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

Commit 83a86c5c authored by Alex Klyubin's avatar Alex Klyubin
Browse files

Always mix in additional entropy into keymaster.

This makes AndroidKeyStore Cipher and KeyGenerator implementations mix
in additional entropy into keymaster's RNG regardless of whether they
were provided with a SecureRandom instance.

In practice, they are always provided with a SecureRandom instance.
However, to be safe, when no SecureRandom instance is provided the
code now uses a platform-default SecureRandom implementation.

Bug: 18088752
Change-Id: I85bca30d7bdc82c2a342094dcbe6044e48a63dca
parent 6223ec12
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -633,10 +633,9 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
                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);
                    }
                    mAdditionalEntropyForBegin =
                            KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                                    mRng, mBlockSizeBytes);
                }
            }
        }
+28 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.security.keymaster.KeymasterDefs;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;

/**
 * Assorted utility methods for implementing crypto operations on top of KeyStore.
@@ -28,6 +29,9 @@ import java.security.InvalidKeyException;
 * @hide
 */
abstract class KeyStoreCryptoOperationUtils {

    private static volatile SecureRandom sRng;

    private KeyStoreCryptoOperationUtils() {}

    /**
@@ -81,4 +85,28 @@ abstract class KeyStoreCryptoOperationUtils {
        // General cases
        return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode);
    }

    /**
     * Returns the requested number of random bytes to mix into keystore/keymaster RNG.
     *
     * @param rng RNG from which to obtain the random bytes or {@code null} for the platform-default
     *        RNG.
     */
    static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) {
        if (rng == null) {
            rng = getRng();
        }
        byte[] result = new byte[sizeBytes];
        rng.nextBytes(result);
        return result;
    }

    private static SecureRandom getRng() {
        // IMPLEMENTATION NOTE: It's OK to share a SecureRandom instance because SecureRandom is
        // required to be thread-safe.
        if (sRng == null) {
            sRng = new SecureRandom();
        }
        return sRng;
    }
}
+3 −6
Original line number Diff line number Diff line
@@ -174,12 +174,9 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
            args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
        }

        byte[] additionalEntropy = null;
        SecureRandom rng = mRng;
        if (rng != null) {
            additionalEntropy = new byte[(keySizeBits + 7) / 8];
            rng.nextBytes(additionalEntropy);
        }
        byte[] additionalEntropy =
                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                        mRng, (keySizeBits + 7) / 8);

        int flags = spec.getFlags();
        String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();