/*
 * 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.keystore;

import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.security.KeyStore;
import android.security.KeyStoreException;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;

import libcore.util.EmptyArray;

import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

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.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;

/**
 * Base class for {@link CipherSpi} implementations of Android KeyStore backed ciphers.
 *
 * @hide
 */
abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
    private final KeyStore mKeyStore;

    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
    // doFinal finishes.
    private boolean mEncrypting;
    private int mKeymasterPurposeOverride = -1;
    private AndroidKeyStoreKey mKey;
    private SecureRandom mRng;

    /**
     * Token referencing this operation inside keystore service. It is initialized by
     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and on some error
     * conditions in between.
     */
    private IBinder mOperationToken;
    private long mOperationHandle;
    private KeyStoreCryptoOperationStreamer mMainDataStreamer;
    private KeyStoreCryptoOperationStreamer mAdditionalAuthenticationDataStreamer;
    private boolean mAdditionalAuthenticationDataStreamerClosed;

    /**
     * Encountered exception which could not be immediately thrown because it was encountered inside
     * a method that does not throw checked exception. This exception will be thrown from
     * {@code engineDoFinal}. Once such an exception is encountered, {@code engineUpdate} and
     * {@code engineDoFinal} start ignoring input data.
     */
    private Exception mCachedException;

    AndroidKeyStoreCipherSpiBase() {
        mKeyStore = KeyStore.getInstance();
    }

    @Override
    protected final void engineInit(int opmode, Key key, SecureRandom random)
            throws InvalidKeyException {
        resetAll();

        boolean success = false;
        try {
            init(opmode, key, random);
            initAlgorithmSpecificParameters();
            try {
                ensureKeystoreOperationInitialized();
            } catch (InvalidAlgorithmParameterException e) {
                throw new InvalidKeyException(e);
            }
            success = true;
        } finally {
            if (!success) {
                resetAll();
            }
        }
    }

    @Override
    protected final void engineInit(int opmode, Key key, AlgorithmParameters params,
            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
        resetAll();

        boolean success = false;
        try {
            init(opmode, key, random);
            initAlgorithmSpecificParameters(params);
            ensureKeystoreOperationInitialized();
            success = true;
        } finally {
            if (!success) {
                resetAll();
            }
        }
    }

    @Override
    protected final void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
        resetAll();

        boolean success = false;
        try {
            init(opmode, key, random);
            initAlgorithmSpecificParameters(params);
            ensureKeystoreOperationInitialized();
            success = true;
        } finally {
            if (!success) {
                resetAll();
            }
        }
    }

    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
        switch (opmode) {
            case Cipher.ENCRYPT_MODE:
            case Cipher.WRAP_MODE:
                mEncrypting = true;
                break;
            case Cipher.DECRYPT_MODE:
            case Cipher.UNWRAP_MODE:
                mEncrypting = false;
                break;
            default:
                throw new InvalidParameterException("Unsupported opmode: " + opmode);
        }
        initKey(opmode, key);
        if (mKey == null) {
            throw new ProviderException("initKey did not initialize the key");
        }
        mRng = random;
    }

    /**
     * Resets this cipher to its pristine pre-init state. This must be equivalent to obtaining a new
     * cipher instance.
     *
     * <p>Subclasses storing additional state should override this method, reset the additional
     * state, and then chain to superclass.
     */
    @CallSuper
    protected void resetAll() {
        IBinder operationToken = mOperationToken;
        if (operationToken != null) {
            mKeyStore.abort(operationToken);
        }
        mEncrypting = false;
        mKeymasterPurposeOverride = -1;
        mKey = null;
        mRng = null;
        mOperationToken = null;
        mOperationHandle = 0;
        mMainDataStreamer = null;
        mAdditionalAuthenticationDataStreamer = null;
        mAdditionalAuthenticationDataStreamerClosed = false;
        mCachedException = null;
    }

    /**
     * Resets this cipher while preserving the initialized state. This must be equivalent to
     * rolling back the cipher's state to just after the most recent {@code engineInit} completed
     * successfully.
     *
     * <p>Subclasses storing additional post-init state should override this method, reset the
     * additional state, and then chain to superclass.
     */
    @CallSuper
    protected void resetWhilePreservingInitState() {
        IBinder operationToken = mOperationToken;
        if (operationToken != null) {
            mKeyStore.abort(operationToken);
        }
        mOperationToken = null;
        mOperationHandle = 0;
        mMainDataStreamer = null;
        mAdditionalAuthenticationDataStreamer = null;
        mAdditionalAuthenticationDataStreamerClosed = false;
        mCachedException = null;
    }

    private void ensureKeystoreOperationInitialized() throws InvalidKeyException,
            InvalidAlgorithmParameterException {
        if (mMainDataStreamer != null) {
            return;
        }
        if (mCachedException != null) {
            return;
        }
        if (mKey == null) {
            throw new IllegalStateException("Not initialized");
        }

        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
        addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
        byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                mRng, getAdditionalEntropyAmountForBegin());

        int purpose;
        if (mKeymasterPurposeOverride != -1) {
            purpose = mKeymasterPurposeOverride;
        } else {
            purpose = mEncrypting
                    ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT;
        }
        OperationResult opResult = mKeyStore.begin(
                mKey.getAlias(),
                purpose,
                true, // permit aborting this operation if keystore runs out of resources
                keymasterInputArgs,
                additionalEntropy);
        if (opResult == null) {
            throw new KeyStoreConnectException();
        }

        // Store operation token and handle regardless of the error code returned by KeyStore to
        // ensure that the operation gets aborted immediately if the code below throws an exception.
        mOperationToken = opResult.token;
        mOperationHandle = opResult.operationHandle;

        // If necessary, throw an exception due to KeyStore operation having failed.
        GeneralSecurityException e = KeyStoreCryptoOperationUtils.getExceptionForCipherInit(
                mKeyStore, mKey, opResult.resultCode);
        if (e != null) {
            if (e instanceof InvalidKeyException) {
                throw (InvalidKeyException) e;
            } else if (e instanceof InvalidAlgorithmParameterException) {
                throw (InvalidAlgorithmParameterException) e;
            } else {
                throw new ProviderException("Unexpected exception type", e);
            }
        }

        if (mOperationToken == null) {
            throw new ProviderException("Keystore returned null operation token");
        }
        if (mOperationHandle == 0) {
            throw new ProviderException("Keystore returned invalid operation handle");
        }

        loadAlgorithmSpecificParametersFromBeginResult(opResult.outParams);
        mMainDataStreamer = createMainDataStreamer(mKeyStore, opResult.token);
        mAdditionalAuthenticationDataStreamer =
                createAdditionalAuthenticationDataStreamer(mKeyStore, opResult.token);
        mAdditionalAuthenticationDataStreamerClosed = false;
    }

    /**
     * Creates a streamer which sends plaintext/ciphertext into the provided KeyStore and receives
     * the corresponding ciphertext/plaintext from the KeyStore.
     *
     * <p>This implementation returns a working streamer.
     */
    @NonNull
    protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
            KeyStore keyStore, IBinder operationToken) {
        return new KeyStoreCryptoOperationChunkedStreamer(
                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                        keyStore, operationToken));
    }

    /**
     * Creates a streamer which sends Additional Authentication Data (AAD) into the KeyStore.
     *
     * <p>This implementation returns {@code null}.
     *
     * @returns stream or {@code null} if AAD is not supported by this cipher.
     */
    @Nullable
    protected KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
            @SuppressWarnings("unused") KeyStore keyStore,
            @SuppressWarnings("unused") IBinder operationToken) {
        return null;
    }

    @Override
    protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
        if (mCachedException != null) {
            return null;
        }
        try {
            ensureKeystoreOperationInitialized();
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            mCachedException = e;
            return null;
        }

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

        byte[] output;
        try {
            flushAAD();
            output = mMainDataStreamer.update(input, inputOffset, inputLen);
        } catch (KeyStoreException e) {
            mCachedException = e;
            return null;
        }

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

        return output;
    }

    private void flushAAD() throws KeyStoreException {
        if ((mAdditionalAuthenticationDataStreamer != null)
                && (!mAdditionalAuthenticationDataStreamerClosed)) {
            byte[] output;
            try {
                output = mAdditionalAuthenticationDataStreamer.doFinal(
                        EmptyArray.BYTE, 0, 0,
                        null // no additional entropy needed flushing AAD
                        );
            } finally {
                mAdditionalAuthenticationDataStreamerClosed = true;
            }
            if ((output != null) && (output.length > 0)) {
                throw new ProviderException(
                        "AAD update unexpectedly returned data: " + output.length + " bytes");
            }
        }
    }

    @Override
    protected final 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 final int engineUpdate(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException {
        return super.engineUpdate(input, output);
    }

    @Override
    protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
        if (mCachedException != null) {
            return;
        }

        try {
            ensureKeystoreOperationInitialized();
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            mCachedException = e;
            return;
        }

        if (mAdditionalAuthenticationDataStreamerClosed) {
            throw new IllegalStateException(
                    "AAD can only be provided before Cipher.update is invoked");
        }

        if (mAdditionalAuthenticationDataStreamer == null) {
            throw new IllegalStateException("This cipher does not support AAD");
        }

        byte[] output;
        try {
            output = mAdditionalAuthenticationDataStreamer.update(input, inputOffset, inputLen);
        } catch (KeyStoreException e) {
            mCachedException = e;
            return;
        }

        if ((output != null) && (output.length > 0)) {
            throw new ProviderException("AAD update unexpectedly produced output: "
                    + output.length + " bytes");
        }
    }

    @Override
    protected final void engineUpdateAAD(ByteBuffer src) {
        if (src == null) {
            throw new IllegalArgumentException("src == null");
        }
        if (!src.hasRemaining()) {
            return;
        }

        byte[] input;
        int inputOffset;
        int inputLen;
        if (src.hasArray()) {
            input = src.array();
            inputOffset = src.arrayOffset() + src.position();
            inputLen = src.remaining();
            src.position(src.limit());
        } else {
            input = new byte[src.remaining()];
            inputOffset = 0;
            inputLen = input.length;
            src.get(input);
        }
        super.engineUpdateAAD(input, inputOffset, inputLen);
    }

    @Override
    protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
            throws IllegalBlockSizeException, BadPaddingException {
        if (mCachedException != null) {
            throw (IllegalBlockSizeException)
                    new IllegalBlockSizeException().initCause(mCachedException);
        }

        try {
            ensureKeystoreOperationInitialized();
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
        }

        byte[] output;
        try {
            flushAAD();
            byte[] additionalEntropy =
                    KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                            mRng, getAdditionalEntropyAmountForFinish());
            output = mMainDataStreamer.doFinal(input, inputOffset, inputLen, additionalEntropy);
        } catch (KeyStoreException e) {
            switch (e.getErrorCode()) {
                case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
                    throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
                case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT:
                    throw (BadPaddingException) new BadPaddingException().initCause(e);
                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
                    throw (AEADBadTagException) new AEADBadTagException().initCause(e);
                default:
                    throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
            }
        }

        resetWhilePreservingInitState();
        return output;
    }

    @Override
    protected final 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 final int engineDoFinal(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
        return super.engineDoFinal(input, output);
    }

    @Override
    protected final byte[] engineWrap(Key key)
            throws IllegalBlockSizeException, InvalidKeyException {
        if (mKey == null) {
            throw new IllegalStateException("Not initilized");
        }

        if (!isEncrypting()) {
            throw new IllegalStateException(
                    "Cipher must be initialized in Cipher.WRAP_MODE to wrap keys");
        }

        if (key == null) {
            throw new NullPointerException("key == null");
        }
        byte[] encoded = null;
        if (key instanceof SecretKey) {
            if ("RAW".equalsIgnoreCase(key.getFormat())) {
                encoded = key.getEncoded();
            }
            if (encoded == null) {
                try {
                    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(key.getAlgorithm());
                    SecretKeySpec spec =
                            (SecretKeySpec) keyFactory.getKeySpec(
                                    (SecretKey) key, SecretKeySpec.class);
                    encoded = spec.getEncoded();
                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
                    throw new InvalidKeyException(
                            "Failed to wrap key because it does not export its key material",
                            e);
                }
            }
        } else if (key instanceof PrivateKey) {
            if ("PKCS8".equalsIgnoreCase(key.getFormat())) {
                encoded = key.getEncoded();
            }
            if (encoded == null) {
                try {
                    KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
                    PKCS8EncodedKeySpec spec =
                            keyFactory.getKeySpec(key, PKCS8EncodedKeySpec.class);
                    encoded = spec.getEncoded();
                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
                    throw new InvalidKeyException(
                            "Failed to wrap key because it does not export its key material",
                            e);
                }
            }
        } else if (key instanceof PublicKey) {
            if ("X.509".equalsIgnoreCase(key.getFormat())) {
                encoded = key.getEncoded();
            }
            if (encoded == null) {
                try {
                    KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
                    X509EncodedKeySpec spec =
                            keyFactory.getKeySpec(key, X509EncodedKeySpec.class);
                    encoded = spec.getEncoded();
                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
                    throw new InvalidKeyException(
                            "Failed to wrap key because it does not export its key material",
                            e);
                }
            }
        } else {
            throw new InvalidKeyException("Unsupported key type: " + key.getClass().getName());
        }

        if (encoded == null) {
            throw new InvalidKeyException(
                    "Failed to wrap key because it does not export its key material");
        }

        try {
            return engineDoFinal(encoded, 0, encoded.length);
        } catch (BadPaddingException e) {
            throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
        }
    }

    @Override
    protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
            int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
        if (mKey == null) {
            throw new IllegalStateException("Not initilized");
        }

        if (isEncrypting()) {
            throw new IllegalStateException(
                    "Cipher must be initialized in Cipher.WRAP_MODE to wrap keys");
        }

        if (wrappedKey == null) {
            throw new NullPointerException("wrappedKey == null");
        }

        byte[] encoded;
        try {
            encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new InvalidKeyException("Failed to unwrap key", e);
        }

        switch (wrappedKeyType) {
            case Cipher.SECRET_KEY:
            {
                return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
                // break;
            }
            case Cipher.PRIVATE_KEY:
            {
                KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
                try {
                    return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded));
                } catch (InvalidKeySpecException e) {
                    throw new InvalidKeyException(
                            "Failed to create private key from its PKCS#8 encoded form", e);
                }
                // break;
            }
            case Cipher.PUBLIC_KEY:
            {
                KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
                try {
                    return keyFactory.generatePublic(new X509EncodedKeySpec(encoded));
                } catch (InvalidKeySpecException e) {
                    throw new InvalidKeyException(
                            "Failed to create public key from its X.509 encoded form", e);
                }
                // break;
            }
            default:
                throw new InvalidParameterException(
                        "Unsupported wrappedKeyType: " + wrappedKeyType);
        }
    }

    @Override
    protected final 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 final 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
    protected final int engineGetKeySize(Key key) throws InvalidKeyException {
        throw new UnsupportedOperationException();
    }

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

    @Override
    public final long getOperationHandle() {
        return mOperationHandle;
    }

    protected final void setKey(@NonNull AndroidKeyStoreKey key) {
        mKey = key;
    }

    /**
     * Overrides the default purpose/type of the crypto operation.
     */
    protected final void setKeymasterPurposeOverride(int keymasterPurpose) {
        mKeymasterPurposeOverride = keymasterPurpose;
    }

    protected final int getKeymasterPurposeOverride() {
        return mKeymasterPurposeOverride;
    }

    /**
     * Returns {@code true} if this cipher is initialized for encryption, {@code false} if this
     * cipher is initialized for decryption.
     */
    protected final boolean isEncrypting() {
        return mEncrypting;
    }

    @NonNull
    protected final KeyStore getKeyStore() {
        return mKeyStore;
    }

    protected final long getConsumedInputSizeBytes() {
        if (mMainDataStreamer == null) {
            throw new IllegalStateException("Not initialized");
        }
        return mMainDataStreamer.getConsumedInputSizeBytes();
    }

    protected final long getProducedOutputSizeBytes() {
        if (mMainDataStreamer == null) {
            throw new IllegalStateException("Not initialized");
        }
        return mMainDataStreamer.getProducedOutputSizeBytes();
    }

    // The methods below need to be implemented by subclasses.

    /**
     * Initializes this cipher with the provided key.
     *
     * @throws InvalidKeyException if the {@code key} is not suitable for this cipher in the
     *         specified {@code opmode}.
     *
     * @see #setKey(AndroidKeyStoreKey)
     */
    protected abstract void initKey(int opmode, @Nullable Key key) throws InvalidKeyException;

    /**
     * Returns algorithm-specific parameters used by this cipher or {@code null} if no
     * algorithm-specific parameters are used.
     */
    @Nullable
    @Override
    protected abstract AlgorithmParameters engineGetParameters();

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when no additional
     * initialization parameters were provided.
     *
     * @throws InvalidKeyException if this cipher cannot be configured based purely on the provided
     *         key and needs additional parameters to be provided to {@code Cipher.init}.
     */
    protected abstract void initAlgorithmSpecificParameters() throws InvalidKeyException;

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when additional
     * parameters were provided.
     *
     * @param params additional algorithm parameters or {@code null} if not specified.
     *
     * @throws InvalidAlgorithmParameterException if there is insufficient information to configure
     *         this cipher or if the provided parameters are not suitable for this cipher.
     */
    protected abstract void initAlgorithmSpecificParameters(
            @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException;

    /**
     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when additional
     * parameters were provided.
     *
     * @param params additional algorithm parameters or {@code null} if not specified.
     *
     * @throws InvalidAlgorithmParameterException if there is insufficient information to configure
     *         this cipher or if the provided parameters are not suitable for this cipher.
     */
    protected abstract void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
            throws InvalidAlgorithmParameterException;

    /**
     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
     * {@code begin} operation. This amount of entropy is typically what's consumed to generate
     * random parameters, such as IV.
     *
     * <p>For decryption, the return value should be {@code 0} because decryption should not be
     * consuming any entropy. For encryption, the value combined with
     * {@link #getAdditionalEntropyAmountForFinish()} should match (or exceed) the amount of Shannon
     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
     * explicitly provided parameters to {@code Cipher.init} are known. For example, for AES CBC
     * encryption with an explicitly provided IV the return value should be {@code 0}, whereas for
     * the case where IV is generated by the KeyStore's {@code begin} operation it should be
     * {@code 16}.
     */
    protected abstract int getAdditionalEntropyAmountForBegin();

    /**
     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
     * {@code finish} operation. This amount of entropy is typically what's consumed by encryption
     * padding scheme.
     *
     * <p>For decryption, the return value should be {@code 0} because decryption should not be
     * consuming any entropy. For encryption, the value combined with
     * {@link #getAdditionalEntropyAmountForBegin()} should match (or exceed) the amount of Shannon
     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
     * explicitly provided parameters to {@code Cipher.init} are known. For example, for RSA with
     * OAEP the return value should be the size of the OAEP hash output. For RSA with PKCS#1 padding
     * the return value should be the size of the padding string or could be raised (for simplicity)
     * to the size of the modulus.
     */
    protected abstract int getAdditionalEntropyAmountForFinish();

    /**
     * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
     *
     * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
     *        parameters.
     */
    protected abstract void addAlgorithmSpecificParametersToBegin(
            @NonNull KeymasterArguments keymasterArgs);

    /**
     * Invoked to obtain algorithm-specific parameters from the result of the KeyStore's
     * {@code begin} operation.
     *
     * <p>Some parameters, such as IV, are not required to be provided to {@code Cipher.init}. Such
     * parameters, if not provided, must be generated by KeyStore and returned to the user of
     * {@code Cipher} and potentially reused after {@code doFinal}.
     *
     * @param keymasterArgs keystore/keymaster arguments returned by KeyStore {@code begin}
     *        operation.
     */
    protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
            @NonNull KeymasterArguments keymasterArgs);
}
