Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7513d53c authored by Alex Klyubin's avatar Alex Klyubin Committed by Android Git Automerger
Browse files

am 9be1016b: am c48e8cf0: am edd0e6c0: Merge "Refuse to reuse IV in encryption...

am 9be1016b: am c48e8cf0: am edd0e6c0: Merge "Refuse to reuse IV in encryption mode in AndroidKeyStore."

* commit '9be1016b':
  Refuse to reuse IV in encryption mode in AndroidKeyStore.
parents bd877f26 9be1016b
Loading
Loading
Loading
Loading
+44 −14
Original line number Original line Diff line number Diff line
@@ -111,7 +111,9 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockMode;
    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockMode;
    private final @KeyStoreKeyConstraints.PaddingEnum int mPadding;
    private final @KeyStoreKeyConstraints.PaddingEnum int mPadding;
    private final int mBlockSizeBytes;
    private final int mBlockSizeBytes;
    private final boolean mIvUsed;

    /** 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
    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
    // doFinal finishes.
    // doFinal finishes.
@@ -119,10 +121,13 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
    private KeyStoreSecretKey mKey;
    private KeyStoreSecretKey mKey;
    private SecureRandom mRng;
    private SecureRandom mRng;
    private boolean mFirstOperationInitiated;
    private boolean mFirstOperationInitiated;
    byte[] mIv;
    private byte[] mIv;
    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
    private boolean mIvHasBeenUsed;


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

    /**
    /**
     * Token referencing this operation inside keystore service. It is initialized by
     * Token referencing this operation inside keystore service. It is initialized by
     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and one some
     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and one some
@@ -143,7 +148,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
        mBlockMode = blockMode;
        mBlockMode = blockMode;
        mPadding = padding;
        mPadding = padding;
        mBlockSizeBytes = blockSizeBytes;
        mBlockSizeBytes = blockSizeBytes;
        mIvUsed = ivUsed;
        mIvRequired = ivUsed;
    }
    }


    @Override
    @Override
@@ -170,7 +175,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
    }
    }


    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
        reset();
        resetAll();
        if (!(key instanceof KeyStoreSecretKey)) {
        if (!(key instanceof KeyStoreSecretKey)) {
            throw new InvalidKeyException(
            throw new InvalidKeyException(
                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
@@ -187,7 +192,25 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
        mEncrypting = opmode == Cipher.ENCRYPT_MODE;
        mEncrypting = opmode == Cipher.ENCRYPT_MODE;
    }
    }


    private void reset() {
    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;
        IBinder operationToken = mOperationToken;
        if (operationToken != null) {
        if (operationToken != null) {
            mOperationToken = null;
            mOperationToken = null;
@@ -205,6 +228,12 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
        if (mKey == null) {
        if (mKey == null) {
            throw new IllegalStateException("Not initialized");
            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();
        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mAlgorithm);
        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mAlgorithm);
@@ -234,6 +263,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
        mOperationHandle = opResult.operationHandle;
        mOperationHandle = opResult.operationHandle;
        loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
        loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
        mFirstOperationInitiated = true;
        mFirstOperationInitiated = true;
        mIvHasBeenUsed = true;
        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                        mKeyStore, opResult.token));
                        mKeyStore, opResult.token));
@@ -298,7 +328,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
            }
            }
        }
        }


        reset();
        resetWhilePreservingInitState();
        return output;
        return output;
    }
    }


@@ -376,7 +406,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
     */
     */
    @Override
    @Override
    protected AlgorithmParameters engineGetParameters() {
    protected AlgorithmParameters engineGetParameters() {
        if (!mIvUsed) {
        if (!mIvRequired) {
            return null;
            return null;
        }
        }
        if ((mIv != null) && (mIv.length > 0)) {
        if ((mIv != null) && (mIv.length > 0)) {
@@ -408,7 +438,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
     */
     */
    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
            throws InvalidAlgorithmParameterException {
            throws InvalidAlgorithmParameterException {
        if (!mIvUsed) {
        if (!mIvRequired) {
            if (params != null) {
            if (params != null) {
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
            }
            }
@@ -447,7 +477,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
     */
     */
    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
            throws InvalidAlgorithmParameterException {
            throws InvalidAlgorithmParameterException {
        if (!mIvUsed) {
        if (!mIvRequired) {
            if (params != null) {
            if (params != null) {
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
            }
            }
@@ -492,7 +522,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
     *         and thus {@code Cipher.init} needs to be invoked with explicitly provided parameters.
     *         and thus {@code Cipher.init} needs to be invoked with explicitly provided parameters.
     */
     */
    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
        if (!mIvUsed) {
        if (!mIvRequired) {
            return;
            return;
        }
        }


@@ -515,7 +545,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
        if (!mFirstOperationInitiated) {
        if (!mFirstOperationInitiated) {
            // First begin operation -- see if we need to provide additional entropy for IV
            // First begin operation -- see if we need to provide additional entropy for IV
            // generation.
            // generation.
            if (mIvUsed) {
            if (mIvRequired) {
                // IV is needed
                // IV is needed
                if ((mIv == null) && (mEncrypting)) {
                if ((mIv == null) && (mEncrypting)) {
                    // TODO: Switch to keymaster-generated IV code below once keymaster supports
                    // TODO: Switch to keymaster-generated IV code below once keymaster supports
@@ -534,7 +564,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
            }
            }
        }
        }


        if ((mIvUsed) && (mIv != null)) {
        if ((mIvRequired) && (mIv != null)) {
            keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
            keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
        }
        }
    }
    }
@@ -557,7 +587,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
            returnedIv = null;
            returnedIv = null;
        }
        }


        if (mIvUsed) {
        if (mIvRequired) {
            if (mIv == null) {
            if (mIv == null) {
                mIv = returnedIv;
                mIv = returnedIv;
            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {