/*
 * Copyright (C) 2015 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 android.security;

import android.os.IBinder;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;

import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;

import javax.crypto.AEADBadTagException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;

/**
 * Base class for {@link CipherSpi} providing Android KeyStore backed ciphers.
 *
 * @hide
 */
public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCryptoOperation {

    public abstract static class AES extends KeyStoreCipherSpi {
        protected AES(int keymasterBlockMode, int keymasterPadding, boolean ivUsed) {
            super(KeymasterDefs.KM_ALGORITHM_AES,
                    keymasterBlockMode,
                    keymasterPadding,
                    16,
                    ivUsed);
        }

        public abstract static class ECB extends AES {
            protected ECB(int keymasterPadding) {
                super(KeymasterDefs.KM_MODE_ECB, keymasterPadding, false);
            }

            public static class NoPadding extends ECB {
                public NoPadding() {
                    super(KeymasterDefs.KM_PAD_NONE);
                }
            }

            public static class PKCS7Padding extends ECB {
                public PKCS7Padding() {
                    super(KeymasterDefs.KM_PAD_PKCS7);
                }
            }
        }

        public abstract static class CBC extends AES {
            protected CBC(int keymasterPadding) {
                super(KeymasterDefs.KM_MODE_CBC, keymasterPadding, true);
            }

            public static class NoPadding extends CBC {
                public NoPadding() {
                    super(KeymasterDefs.KM_PAD_NONE);
                }
            }

            public static class PKCS7Padding extends CBC {
                public PKCS7Padding() {
                    super(KeymasterDefs.KM_PAD_PKCS7);
                }
            }
        }

        public abstract static class CTR extends AES {
            protected CTR(int keymasterPadding) {
                super(KeymasterDefs.KM_MODE_CTR, keymasterPadding, true);
            }

            public static class NoPadding extends CTR {
                public NoPadding() {
                    super(KeymasterDefs.KM_PAD_NONE);
                }
            }
        }
    }

    private final KeyStore mKeyStore;
    private final int mKeymasterAlgorithm;
    private final int mKeymasterBlockMode;
    private final int mKeymasterPadding;
    private final int mBlockSizeBytes;

    /** Whether this transformation requires an IV. */
    private final boolean mIvRequired;

    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
    // doFinal finishes.
    protected boolean mEncrypting;
    private KeyStoreSecretKey mKey;
    private SecureRandom mRng;
    private boolean mFirstOperationInitiated;
    private byte[] mIv;
    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
    private boolean mIvHasBeenUsed;

    // Fields below must be reset after doFinal
    private byte[] mAdditionalEntropyForBegin;

    /**
     * Token referencing this operation inside keystore service. It is initialized by
     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and one some
     * error conditions in between.
     */
    private IBinder mOperationToken;
    private Long mOperationHandle;
    private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;

    protected KeyStoreCipherSpi(
            int keymasterAlgorithm,
            int keymasterBlockMode,
            int keymasterPadding,
            int blockSizeBytes,
            boolean ivUsed) {
        mKeyStore = KeyStore.getInstance();
        mKeymasterAlgorithm = keymasterAlgorithm;
        mKeymasterBlockMode = keymasterBlockMode;
        mKeymasterPadding = keymasterPadding;
        mBlockSizeBytes = blockSizeBytes;
        mIvRequired = ivUsed;
    }

    @Override
    protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
        init(opmode, key, random);
        initAlgorithmSpecificParameters();
        ensureKeystoreOperationInitialized();
    }

    @Override
    protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        init(opmode, key, random);
        initAlgorithmSpecificParameters(params);
        ensureKeystoreOperationInitialized();
    }

    @Override
    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
        init(opmode, key, random);
        initAlgorithmSpecificParameters(params);
        ensureKeystoreOperationInitialized();
    }

    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
        resetAll();
        if (!(key instanceof KeyStoreSecretKey)) {
            throw new InvalidKeyException(
                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
        }
        mKey = (KeyStoreSecretKey) key;
        mRng = random;
        mIv = null;
        mFirstOperationInitiated = false;

        if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) {
            throw new UnsupportedOperationException(
                    "Only ENCRYPT and DECRYPT modes supported. Mode: " + opmode);
        }
        mEncrypting = opmode == Cipher.ENCRYPT_MODE;
    }

    private void resetAll() {
        IBinder operationToken = mOperationToken;
        if (operationToken != null) {
            mOperationToken = null;
            mKeyStore.abort(operationToken);
        }
        mEncrypting = false;
        mKey = null;
        mRng = null;
        mFirstOperationInitiated = false;
        mIv = null;
        mIvHasBeenUsed = false;
        mAdditionalEntropyForBegin = null;
        mOperationToken = null;
        mOperationHandle = null;
        mMainDataStreamer = null;
    }

    private void resetWhilePreservingInitState() {
        IBinder operationToken = mOperationToken;
        if (operationToken != null) {
            mOperationToken = null;
            mKeyStore.abort(operationToken);
        }
        mOperationHandle = null;
        mMainDataStreamer = null;
        mAdditionalEntropyForBegin = null;
    }

    private void ensureKeystoreOperationInitialized() {
        if (mMainDataStreamer != null) {
            return;
        }
        if (mKey == null) {
            throw new IllegalStateException("Not initialized");
        }
        if ((mEncrypting) && (mIvRequired) && (mIvHasBeenUsed)) {
            // IV is being reused for encryption: this violates security best practices.
            throw new IllegalStateException(
                    "IV has already been used. Reusing IV in encryption mode violates security best"
                    + " practices.");
        }

        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
        addAlgorithmSpecificParametersToBegin(keymasterInputArgs);

        KeymasterArguments keymasterOutputArgs = new KeymasterArguments();
        OperationResult opResult = mKeyStore.begin(
                mKey.getAlias(),
                mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT,
                true, // permit aborting this operation if keystore runs out of resources
                keymasterInputArgs,
                mAdditionalEntropyForBegin,
                keymasterOutputArgs);
        mAdditionalEntropyForBegin = null;
        if (opResult == null) {
            throw new KeyStoreConnectException();
        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
            throw KeyStore.getCryptoOperationException(opResult.resultCode);
        }

        if (opResult.token == null) {
            throw new CryptoOperationException("Keystore returned null operation token");
        }
        mOperationToken = opResult.token;
        mOperationHandle = opResult.operationHandle;
        loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
        mFirstOperationInitiated = true;
        mIvHasBeenUsed = true;
        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                        mKeyStore, opResult.token));
    }

    @Override
    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
        ensureKeystoreOperationInitialized();

        if (inputLen == 0) {
            return null;
        }

        byte[] output;
        try {
            output = mMainDataStreamer.update(input, inputOffset, inputLen);
        } catch (KeyStoreException e) {
            throw KeyStore.getCryptoOperationException(e);
        }

        if (output.length == 0) {
            return null;
        }

        return output;
    }

    @Override
    protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
            int outputOffset) throws ShortBufferException {
        byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
        if (outputCopy == null) {
            return 0;
        }
        int outputAvailable = output.length - outputOffset;
        if (outputCopy.length > outputAvailable) {
            throw new ShortBufferException("Output buffer too short. Produced: "
                    + outputCopy.length + ", available: " + outputAvailable);
        }
        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
        return outputCopy.length;
    }

    @Override
    protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
            throws IllegalBlockSizeException, BadPaddingException {
        ensureKeystoreOperationInitialized();

        byte[] output;
        try {
            output = mMainDataStreamer.doFinal(input, inputOffset, inputLen);
        } catch (KeyStoreException e) {
            switch (e.getErrorCode()) {
                case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
                    throw new IllegalBlockSizeException();
                case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT:
                    throw new BadPaddingException();
                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
                    throw new AEADBadTagException();
                default:
                    throw KeyStore.getCryptoOperationException(e);
            }
        }

        resetWhilePreservingInitState();
        return output;
    }

    @Override
    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
            int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
        if (outputCopy == null) {
            return 0;
        }
        int outputAvailable = output.length - outputOffset;
        if (outputCopy.length > outputAvailable) {
            throw new ShortBufferException("Output buffer too short. Produced: "
                    + outputCopy.length + ", available: " + outputAvailable);
        }
        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
        return outputCopy.length;
    }

    @Override
    protected int engineGetBlockSize() {
        return mBlockSizeBytes;
    }

    @Override
    protected byte[] engineGetIV() {
        return (mIv != null) ? mIv.clone() : null;
    }

    @Override
    protected int engineGetOutputSize(int inputLen) {
        return inputLen + 3 * engineGetBlockSize();
    }

    @Override
    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
        // This should never be invoked because all algorithms registered with the AndroidKeyStore
        // provide explicitly specify block mode.
        throw new UnsupportedOperationException();
    }

    @Override
    protected void engineSetPadding(String arg0) throws NoSuchPaddingException {
        // This should never be invoked because all algorithms registered with the AndroidKeyStore
        // provide explicitly specify padding mode.
        throw new UnsupportedOperationException();
    }

    @Override
    public void finalize() throws Throwable {
        try {
            IBinder operationToken = mOperationToken;
            if (operationToken != null) {
                mKeyStore.abort(operationToken);
            }
        } finally {
            super.finalize();
        }
    }

    @Override
    public Long getOperationHandle() {
        return mOperationHandle;
    }

    // The methods below may need to be overridden by subclasses that use algorithm-specific
    // parameters.

    /**
     * Returns algorithm-specific parameters used by this {@code CipherSpi} instance or {@code null}
     * if no algorithm-specific parameters are used.
     *
     * <p>This implementation only handles the IV parameter.
     */
    @Override
    protected AlgorithmParameters engineGetParameters() {
        if (!mIvRequired) {
            return null;
        }
        if ((mIv != null) && (mIv.length > 0)) {
            try {
                AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
                params.init(new IvParameterSpec(mIv));
                return params;
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("Failed to obtain AES AlgorithmParameters", e);
            } catch (InvalidParameterSpecException e) {
                throw new RuntimeException(
                        "Failed to initialize AES AlgorithmParameters with an IV", e);
            }
        }
        return null;
    }

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
     * may need to be stored to be reused after {@code doFinal}.
     *
     * <p>The default implementation only handles the IV parameters.
     *
     * @param params algorithm parameters.
     *
     * @throws InvalidAlgorithmParameterException if some/all of the parameters cannot be
     *         automatically configured and thus {@code Cipher.init} needs to be invoked with
     *         explicitly provided parameters.
     */
    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
            throws InvalidAlgorithmParameterException {
        if (!mIvRequired) {
            if (params != null) {
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
            }
            return;
        }

        // IV is used
        if (params == null) {
            if (!mEncrypting) {
                // IV must be provided by the caller
                throw new InvalidAlgorithmParameterException(
                        "IvParameterSpec must be provided when decrypting");
            }
            return;
        }
        if (!(params instanceof IvParameterSpec)) {
            throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
        }
        mIv = ((IvParameterSpec) params).getIV();
        if (mIv == null) {
            throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
        }
    }

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
     * may need to be stored to be reused after {@code doFinal}.
     *
     * <p>The default implementation only handles the IV parameters.
     *
     * @param params algorithm parameters.
     *
     * @throws InvalidAlgorithmParameterException if some/all of the parameters cannot be
     *         automatically configured and thus {@code Cipher.init} needs to be invoked with
     *         explicitly provided parameters.
     */
    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
            throws InvalidAlgorithmParameterException {
        if (!mIvRequired) {
            if (params != null) {
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
            }
            return;
        }

        // IV is used
        if (params == null) {
            if (!mEncrypting) {
                // IV must be provided by the caller
                throw new InvalidAlgorithmParameterException("IV required when decrypting"
                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
            }
            return;
        }

        IvParameterSpec ivSpec;
        try {
            ivSpec = params.getParameterSpec(IvParameterSpec.class);
        } catch (InvalidParameterSpecException e) {
            if (!mEncrypting) {
                // IV must be provided by the caller
                throw new InvalidAlgorithmParameterException("IV required when decrypting"
                        + ", but not found in parameters: " + params, e);
            }
            mIv = null;
            return;
        }
        mIv = ivSpec.getIV();
        if (mIv == null) {
            throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
        }
    }

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
     * may need to be stored to be reused after {@code doFinal}.
     *
     * <p>The default implementation only handles the IV parameter.
     *
     * @throws InvalidKeyException if some/all of the parameters cannot be automatically configured
     *         and thus {@code Cipher.init} needs to be invoked with explicitly provided parameters.
     */
    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
        if (!mIvRequired) {
            return;
        }

        // IV is used
        if (!mEncrypting) {
            throw new InvalidKeyException("IV required when decrypting"
                    + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
        }
    }

    /**
     * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
     *
     * <p>The default implementation takes care of the IV.
     *
     * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
     *        parameters.
     */
    protected void addAlgorithmSpecificParametersToBegin(KeymasterArguments keymasterArgs) {
        if (!mFirstOperationInitiated) {
            // First begin operation -- see if we need to provide additional entropy for IV
            // generation.
            if (mIvRequired) {
                // IV is needed
                if ((mIv == null) && (mEncrypting)) {
                    // IV was not provided by the caller and thus will be generated by keymaster.
                    // Mix in some additional entropy from the provided SecureRandom.
                    if (mRng != null) {
                        mAdditionalEntropyForBegin = new byte[mBlockSizeBytes];
                        mRng.nextBytes(mAdditionalEntropyForBegin);
                    }
                }
            }
        }

        if ((mIvRequired) && (mIv != null)) {
            keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
        }
    }

    /**
     * Invoked by {@code engineInit} to obtain algorithm-specific parameters from the result of the
     * Keymaster's {@code begin} operation. Some of these parameters may need to be reused after
     * {@code doFinal} by {@link #addAlgorithmSpecificParametersToBegin(KeymasterArguments)}.
     *
     * <p>The default implementation only takes care of the IV.
     *
     * @param keymasterArgs keystore/keymaster arguments returned by KeyStore {@code begin}
     *        operation.
     */
    protected void loadAlgorithmSpecificParametersFromBeginResult(
            KeymasterArguments keymasterArgs) {
        // NOTE: Keymaster doesn't always return an IV, even if it's used.
        byte[] returnedIv = keymasterArgs.getBlob(KeymasterDefs.KM_TAG_NONCE, null);
        if ((returnedIv != null) && (returnedIv.length == 0)) {
            returnedIv = null;
        }

        if (mIvRequired) {
            if (mIv == null) {
                mIv = returnedIv;
            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
                throw new CryptoOperationException("IV in use differs from provided IV");
            }
        } else {
            if (returnedIv != null) {
                throw new CryptoOperationException(
                        "IV in use despite IV not being used by this transformation");
            }
        }
    }
}
