/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.locksettings;

import android.content.Context;
import android.hardware.weaver.V1_0.IWeaver;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.ArrayMap;

import junit.framework.AssertionFailedError;

import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class MockSyntheticPasswordManager extends SyntheticPasswordManager {

    private FakeGateKeeperService mGateKeeper;
    private IWeaver mWeaverService;

    public MockSyntheticPasswordManager(Context context, LockSettingsStorage storage,
            FakeGateKeeperService gatekeeper, UserManager userManager) {
        super(context, storage, userManager);
        mGateKeeper = gatekeeper;
    }

    private ArrayMap<String, byte[]> mBlobs = new ArrayMap<>();

    @Override
    protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) {
        if (mBlobs.containsKey(blobKeyName) && !Arrays.equals(mBlobs.get(blobKeyName), blob)) {
            throw new AssertionFailedError("blobKeyName content is overwritten: " + blobKeyName);
        }
        ByteBuffer buffer = ByteBuffer.allocate(blob.length);
        buffer.put(blob, 0, blob.length);
        buffer.flip();
        int len;
        len = buffer.getInt();
        byte[] data = new byte[len];
        buffer.get(data);
        len = buffer.getInt();
        byte[] appId = new byte[len];
        buffer.get(appId);
        long sid = buffer.getLong();
        if (!Arrays.equals(appId, applicationId)) {
            throw new AssertionFailedError("Invalid application id");
        }
        if (sid != 0 && mGateKeeper.getAuthTokenForSid(sid) == null) {
            throw new AssertionFailedError("No valid auth token");
        }
        return data;
    }

    @Override
    protected byte[] createSPBlob(String blobKeyName, byte[] data, byte[] applicationId, long sid) {
        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + data.length + Integer.BYTES
                + applicationId.length + Long.BYTES);
        buffer.putInt(data.length);
        buffer.put(data);
        buffer.putInt(applicationId.length);
        buffer.put(applicationId);
        buffer.putLong(sid);
        byte[] result = buffer.array();
        mBlobs.put(blobKeyName, result);
        return result;
    }

    @Override
    protected void destroySPBlobKey(String keyAlias) {
    }

    @Override
    protected long sidFromPasswordHandle(byte[] handle) {
        return new FakeGateKeeperService.VerifyHandle(handle).sid;
    }

    @Override
    protected byte[] scrypt(byte[] password, byte[] salt, int n, int r, int p, int outLen) {
        try {
            char[] passwordChars = new char[password.length];
            for (int i = 0; i < password.length; i++) {
                passwordChars[i] = (char) password[i];
            }
            PBEKeySpec spec = new PBEKeySpec(passwordChars, salt, 10, outLen * 8);
            SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            return f.generateSecret(spec).getEncoded();
        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected IWeaver getWeaverService() throws RemoteException {
        return mWeaverService;
    }

    public void enableWeaver() {
        mWeaverService = new MockWeaverService();
        initWeaverService();
    }

}
