Merge "Always mix in additional entropy into keymaster." into mnc-dev
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index 28bc3d2..afa0c8e 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -634,10 +634,9 @@
                 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);
                 }
             }
         }
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
index e5933ad..311278b 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
@@ -21,6 +21,7 @@
 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 @@
  * @hide
  */
 abstract class KeyStoreCryptoOperationUtils {
+
+    private static volatile SecureRandom sRng;
+
     private KeyStoreCryptoOperationUtils() {}
 
     /**
@@ -81,4 +85,28 @@
         // 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;
+    }
 }
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index e69648c..c265c46 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -173,12 +173,9 @@
             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();