/*
 * 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.BufferOverflowException;
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,
                mKey.getUid());
        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 signature
                        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 {
        if (input == null) {
            throw new NullPointerException("input == null");
        }
        if (output == null) {
            throw new NullPointerException("output == null");
        }

        int inputSize = input.remaining();
        byte[] outputArray;
        if (input.hasArray()) {
            outputArray =
                    engineUpdate(
                            input.array(), input.arrayOffset() + input.position(), inputSize);
            input.position(input.position() + inputSize);
        } else {
            byte[] inputArray = new byte[inputSize];
            input.get(inputArray);
            outputArray = engineUpdate(inputArray, 0, inputSize);
        }

        int outputSize = (outputArray != null) ? outputArray.length : 0;
        if (outputSize > 0) {
            int outputBufferAvailable = output.remaining();
            try {
                output.put(outputArray);
            } catch (BufferOverflowException e) {
                throw new ShortBufferException(
                        "Output buffer too small. Produced: " + outputSize + ", available: "
                                + outputBufferAvailable);
            }
        }
        return outputSize;
    }

    @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);
        }
        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,
                    null, // no signature involved
                    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 {
        if (input == null) {
            throw new NullPointerException("input == null");
        }
        if (output == null) {
            throw new NullPointerException("output == null");
        }

        int inputSize = input.remaining();
        byte[] outputArray;
        if (input.hasArray()) {
            outputArray =
                    engineDoFinal(
                            input.array(), input.arrayOffset() + input.position(), inputSize);
            input.position(input.position() + inputSize);
        } else {
            byte[] inputArray = new byte[inputSize];
            input.get(inputArray);
            outputArray = engineDoFinal(inputArray, 0, inputSize);
        }

        int outputSize = (outputArray != null) ? outputArray.length : 0;
        if (outputSize > 0) {
            int outputBufferAvailable = output.remaining();
            try {
                output.put(outputArray);
            } catch (BufferOverflowException e) {
                throw new ShortBufferException(
                        "Output buffer too small. Produced: " + outputSize + ", available: "
                                + outputBufferAvailable);
            }
        }
        return outputSize;
    }

    @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();
    }

    static String opmodeToString(int opmode) {
        switch (opmode) {
            case Cipher.ENCRYPT_MODE:
                return "ENCRYPT_MODE";
            case Cipher.DECRYPT_MODE:
                return "DECRYPT_MODE";
            case Cipher.WRAP_MODE:
                return "WRAP_MODE";
            case Cipher.UNWRAP_MODE:
                return "UNWRAP_MODE";
            default:
                return String.valueOf(opmode);
        }
    }

    // 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);
}
