diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index ed690de12ec42..c5b6a68d41dcb 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -512,12 +512,23 @@ public class AndroidKeyStore extends KeyStoreSpi {
}
}
- int purposes = params.getPurposes();
+ @KeyStoreKeyConstraints.PurposeEnum int purposes = params.getPurposes();
+ @KeyStoreKeyConstraints.BlockModeEnum int blockModes = params.getBlockModes();
+ if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
+ && (params.isRandomizedEncryptionRequired())) {
+ @KeyStoreKeyConstraints.BlockModeEnum int incompatibleBlockModes =
+ blockModes & ~KeyStoreKeyConstraints.BlockMode.IND_CPA_COMPATIBLE_MODES;
+ if (incompatibleBlockModes != 0) {
+ throw new KeyStoreException("Randomized encryption (IND-CPA) required but may be"
+ + " violated by block mode(s): "
+ + KeyStoreKeyConstraints.BlockMode.allToString(incompatibleBlockModes)
+ + ". See KeyStoreParameter documentation.");
+ }
+ }
for (int keymasterPurpose : KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) {
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
}
- for (int keymasterBlockMode :
- KeyStoreKeyConstraints.BlockMode.allToKeymaster(params.getBlockModes())) {
+ for (int keymasterBlockMode : KeyStoreKeyConstraints.BlockMode.allToKeymaster(blockModes)) {
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode);
}
for (int keymasterPadding :
@@ -553,8 +564,8 @@ public class AndroidKeyStore extends KeyStoreSpi {
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keyMaterial.length * 8);
if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
- || ((purposes & KeyStoreKeyConstraints.Purpose.DECRYPT) != 0)) {
- // Permit caller-specified IV. This is needed for the Cipher abstraction.
+ && (!params.isRandomizedEncryptionRequired())) {
+ // Permit caller-provided IV when encrypting with this key
args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
}
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java
index 0e490cd7cadb0..29b1209b08054 100644
--- a/keystore/java/android/security/KeyGeneratorSpec.java
+++ b/keystore/java/android/security/KeyGeneratorSpec.java
@@ -22,6 +22,7 @@ import android.text.TextUtils;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Date;
+import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
@@ -51,6 +52,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private final boolean mRandomizedEncryptionRequired;
private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mInvalidatedOnNewFingerprintEnrolled;
@@ -66,6 +68,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
@KeyStoreKeyConstraints.PurposeEnum int purposes,
@KeyStoreKeyConstraints.PaddingEnum int paddings,
@KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+ boolean randomizedEncryptionRequired,
@KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
int userAuthenticationValidityDurationSeconds,
boolean invalidatedOnNewFingerprintEnrolled) {
@@ -89,6 +92,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
mPurposes = purposes;
mPaddings = paddings;
mBlockModes = blockModes;
+ mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticators = userAuthenticators;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
@@ -171,6 +175,19 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
return mBlockModes;
}
+ /**
+ * Returns {@code true} if encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic property
+ * being required is indistinguishability under chosen-plaintext attack ({@code
+ * IND-CPA}). This property is important because it mitigates several classes of
+ * weaknesses due to which ciphertext may leak information about plaintext. For example, if a
+ * given plaintext always produces the same ciphertext, an attacker may see the repeated
+ * ciphertexts and be able to deduce something about the plaintext.
+ */
+ public boolean isRandomizedEncryptionRequired() {
+ return mRandomizedEncryptionRequired;
+ }
+
/**
* Gets the set of user authenticators which protect access to this key. The key can only be
* used iff the user has authenticated to at least one of these user authenticators.
@@ -223,6 +240,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
private @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
private @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private boolean mRandomizedEncryptionRequired = true;
private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mInvalidatedOnNewFingerprintEnrolled;
@@ -362,6 +380,43 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
return this;
}
+ /**
+ * Sets whether encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic
+ * property being required is indistinguishability under chosen-plaintext attack
+ * ({@code IND-CPA}). This property is important because it mitigates several classes
+ * of weaknesses due to which ciphertext may leak information about plaintext. For example,
+ * if a given plaintext always produces the same ciphertext, an attacker may see the
+ * repeated ciphertexts and be able to deduce something about the plaintext.
+ *
+ *
By default, {@code IND-CPA} is required.
+ *
+ *
When {@code IND-CPA} is required:
+ *
+ * - block modes which do not offer {@code IND-CPA}, such as {@code ECB}, are prohibited;
+ *
+ * - in block modes which use an IV, such as {@code CBC}, {@code CTR}, and {@code GCM},
+ * caller-provided IVs are rejected when encrypting, to ensure that only random IVs are
+ * used.
+ *
+ * Before disabling this requirement, consider the following approaches instead:
+ *
+ * - If you are generating a random IV for encryption and then initializing a {@code}
+ * Cipher using the IV, the solution is to let the {@code Cipher} generate a random IV
+ * instead. This will occur if the {@code Cipher} is initialized for encryption without an
+ * IV. The IV can then be queried via {@link Cipher#getIV()}.
+ * - If you are generating a non-random IV (e.g., an IV derived from something not fully
+ * random, such as the name of the file being encrypted, or transaction ID, or password,
+ * or a device identifier), consider changing your design to use a random IV which will then
+ * be provided in addition to the ciphertext to the entities which need to decrypt the
+ * ciphertext.
+ *
+ */
+ public Builder setRandomizedEncryptionRequired(boolean required) {
+ mRandomizedEncryptionRequired = required;
+ return this;
+ }
+
/**
* Sets the user authenticators which protect access to this key. The key can only be used
* iff the user has authenticated to at least one of these user authenticators.
@@ -427,6 +482,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
mPurposes,
mPaddings,
mBlockModes,
+ mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index 52b7097b77c77..1c7e2ce560f95 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -86,6 +86,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private final boolean mRandomizedEncryptionRequired;
+
private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private final int mUserAuthenticationValidityDurationSeconds;
@@ -134,6 +136,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
@KeyStoreKeyConstraints.DigestEnum int digests,
@KeyStoreKeyConstraints.PaddingEnum int paddings,
@KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+ boolean randomizedEncryptionRequired,
@KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
int userAuthenticationValidityDurationSeconds,
boolean invalidatedOnNewFingerprintEnrolled) {
@@ -174,6 +177,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mDigests = digests;
mPaddings = paddings;
mBlockModes = blockModes;
+ mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticators = userAuthenticators;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
@@ -186,8 +190,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize,
AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber,
Date startDate, Date endDate, int flags) {
- this(context, keyStoreAlias, keyType, keySize, spec, subjectDN, serialNumber, startDate,
- endDate, flags, startDate, endDate, endDate, 0, 0, 0, 0, 0, -1, false);
+
+ this(context,
+ keyStoreAlias,
+ keyType,
+ keySize,
+ spec,
+ subjectDN,
+ serialNumber,
+ startDate,
+ endDate,
+ flags,
+ startDate,
+ endDate,
+ endDate,
+ 0,
+ 0,
+ 0,
+ 0,
+ true,
+ 0,
+ -1,
+ false);
}
/**
@@ -346,6 +370,21 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
return mBlockModes;
}
+ /**
+ * Returns {@code true} if encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic property
+ * being required is indistinguishability under chosen-plaintext attack ({@code
+ * IND-CPA}). This property is important because it mitigates several classes of
+ * weaknesses due to which ciphertext may leak information about plaintext. For example, if a
+ * given plaintext always produces the same ciphertext, an attacker may see the repeated
+ * ciphertexts and be able to deduce something about the plaintext.
+ *
+ * @hide
+ */
+ public boolean isRandomizedEncryptionRequired() {
+ return mRandomizedEncryptionRequired;
+ }
+
/**
* Gets the set of user authenticators which protect access to the private key. The key can only
* be used iff the user has authenticated to at least one of these user authenticators.
@@ -446,6 +485,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private boolean mRandomizedEncryptionRequired = true;
+
private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private int mUserAuthenticationValidityDurationSeconds = -1;
@@ -688,6 +729,33 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
return this;
}
+ /**
+ * Sets whether encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic
+ * property being required is indistinguishability under chosen-plaintext attack
+ * ({@code IND-CPA}). This property is important because it mitigates several classes
+ * of weaknesses due to which ciphertext may leak information about plaintext. For example,
+ * if a given plaintext always produces the same ciphertext, an attacker may see the
+ * repeated ciphertexts and be able to deduce something about the plaintext.
+ *
+ * By default, {@code IND-CPA} is required.
+ *
+ *
When {@code IND-CPA} is required, encryption/decryption transformations which do not
+ * offer {@code IND-CPA}, such as RSA without padding, are prohibited.
+ *
+ *
Before disabling this requirement, consider the following approaches instead:
+ *
+ * - If you are using RSA encryption without padding, consider switching to padding
+ * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.
+ *
+ *
+ * @hide
+ */
+ public Builder setRandomizedEncryptionRequired(boolean required) {
+ mRandomizedEncryptionRequired = required;
+ return this;
+ }
+
/**
* Sets the user authenticators which protect access to this key. The key can only be used
* iff the user has authenticated to at least one of these user authenticators.
@@ -771,6 +839,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mDigests,
mPaddings,
mBlockModes,
+ mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);
diff --git a/keystore/java/android/security/KeyStoreKeyConstraints.java b/keystore/java/android/security/KeyStoreKeyConstraints.java
index 097c20faca5fd..d0f02a7e6ec8c 100644
--- a/keystore/java/android/security/KeyStoreKeyConstraints.java
+++ b/keystore/java/android/security/KeyStoreKeyConstraints.java
@@ -591,6 +591,14 @@ public abstract class KeyStoreKeyConstraints {
/** Galois/Counter Mode (GCM) block mode. */
public static final int GCM = 1 << 3;
+ /**
+ * Set of block modes compatible with IND-CPA if used correctly.
+ *
+ * @hide
+ */
+ public static final @BlockModeEnum int IND_CPA_COMPATIBLE_MODES =
+ CBC | CTR | GCM;
+
/**
* @hide
*/
@@ -667,6 +675,24 @@ public abstract class KeyStoreKeyConstraints {
}
}
+ /**
+ * @hide
+ */
+ public static String allToString(@BlockModeEnum int modes) {
+ StringBuilder result = new StringBuilder("[");
+ boolean firstValue = true;
+ for (@BlockModeEnum int mode : getSetFlags(modes)) {
+ if (firstValue) {
+ firstValue = false;
+ } else {
+ result.append(", ");
+ }
+ result.append(toString(mode));
+ }
+ result.append(']');
+ return result.toString();
+ }
+
/**
* @hide
*/
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 279acd66d2940..b39d16d1aa81b 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -138,13 +138,26 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
}
int keySizeBits = (spec.getKeySize() != null) ? spec.getKeySize() : mDefaultKeySizeBits;
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits);
- int purposes = spec.getPurposes();
+ @KeyStoreKeyConstraints.PurposeEnum int purposes = spec.getPurposes();
+ @KeyStoreKeyConstraints.BlockModeEnum int blockModes = spec.getBlockModes();
+ if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
+ && (spec.isRandomizedEncryptionRequired())) {
+ @KeyStoreKeyConstraints.BlockModeEnum int incompatibleBlockModes =
+ blockModes & ~KeyStoreKeyConstraints.BlockMode.IND_CPA_COMPATIBLE_MODES;
+ if (incompatibleBlockModes != 0) {
+ throw new IllegalStateException(
+ "Randomized encryption (IND-CPA) required but may be violated by block"
+ + " mode(s): "
+ + KeyStoreKeyConstraints.BlockMode.allToString(incompatibleBlockModes)
+ + ". See KeyGeneratorSpec documentation.");
+ }
+ }
+
for (int keymasterPurpose :
KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) {
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
}
- for (int keymasterBlockMode :
- KeyStoreKeyConstraints.BlockMode.allToKeymaster(spec.getBlockModes())) {
+ for (int keymasterBlockMode : KeyStoreKeyConstraints.BlockMode.allToKeymaster(blockModes)) {
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode);
}
for (int keymasterPadding :
@@ -177,8 +190,8 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
- || ((purposes & KeyStoreKeyConstraints.Purpose.DECRYPT) != 0)) {
- // Permit caller-specified IV. This is needed due to the Cipher abstraction.
+ && (!spec.isRandomizedEncryptionRequired())) {
+ // Permit caller-provided IV when encrypting with this key
args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
}
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index 0b2f9b69b2f19..13ede1ac523e4 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -23,6 +23,8 @@ import java.security.KeyPairGenerator;
import java.security.KeyStore.ProtectionParameter;
import java.util.Date;
+import javax.crypto.Cipher;
+
/**
* This provides the optional parameters that can be specified for
* {@code KeyStore} entries that work with
@@ -52,6 +54,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
private final @KeyStoreKeyConstraints.DigestEnum Integer mDigests;
private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private final boolean mRandomizedEncryptionRequired;
private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mInvalidatedOnNewFingerprintEnrolled;
@@ -64,6 +67,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
@KeyStoreKeyConstraints.PaddingEnum int paddings,
@KeyStoreKeyConstraints.DigestEnum Integer digests,
@KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+ boolean randomizedEncryptionRequired,
@KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
int userAuthenticationValidityDurationSeconds,
boolean invalidatedOnNewFingerprintEnrolled) {
@@ -81,6 +85,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
mPaddings = paddings;
mDigests = digests;
mBlockModes = blockModes;
+ mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticators = userAuthenticators;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
@@ -187,6 +192,21 @@ public final class KeyStoreParameter implements ProtectionParameter {
return mBlockModes;
}
+ /**
+ * Returns {@code true} if encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic property
+ * being required is indistinguishability under chosen-plaintext attack ({@code
+ * IND-CPA}). This property is important because it mitigates several classes of
+ * weaknesses due to which ciphertext may leak information about plaintext. For example, if a
+ * given plaintext always produces the same ciphertext, an attacker may see the repeated
+ * ciphertexts and be able to deduce something about the plaintext.
+ *
+ * @hide
+ */
+ public boolean isRandomizedEncryptionRequired() {
+ return mRandomizedEncryptionRequired;
+ }
+
/**
* Gets the set of user authenticators which protect access to this key. The key can only be
* used iff the user has authenticated to at least one of these user authenticators.
@@ -251,6 +271,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
private @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
private @KeyStoreKeyConstraints.DigestEnum Integer mDigests;
private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+ private boolean mRandomizedEncryptionRequired = true;
private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mInvalidatedOnNewFingerprintEnrolled;
@@ -397,6 +418,46 @@ public final class KeyStoreParameter implements ProtectionParameter {
return this;
}
+ /**
+ * Sets whether encryption using this key must be sufficiently randomized to produce
+ * different ciphertexts for the same plaintext every time. The formal cryptographic
+ * property being required is indistinguishability under chosen-plaintext attack
+ * ({@code IND-CPA}). This property is important because it mitigates several classes
+ * of weaknesses due to which ciphertext may leak information about plaintext. For example,
+ * if a given plaintext always produces the same ciphertext, an attacker may see the
+ * repeated ciphertexts and be able to deduce something about the plaintext.
+ *
+ * By default, {@code IND-CPA} is required.
+ *
+ *
When {@code IND-CPA} is required:
+ *
+ * - transformation which do not offer {@code IND-CPA}, such as symmetric ciphers using
+ * {@code ECB} mode or RSA encryption without padding, are prohibited;
+ * - in transformations which use an IV, such as symmetric ciphers in {@code CBC},
+ * {@code CTR}, and {@code GCM} block modes, caller-provided IVs are rejected when
+ * encrypting, to ensure that only random IVs are used.
+ *
+ * Before disabling this requirement, consider the following approaches instead:
+ *
+ * - If you are generating a random IV for encryption and then initializing a {@code}
+ * Cipher using the IV, the solution is to let the {@code Cipher} generate a random IV
+ * instead. This will occur if the {@code Cipher} is initialized for encryption without an
+ * IV. The IV can then be queried via {@link Cipher#getIV()}.
+ * - If you are generating a non-random IV (e.g., an IV derived from something not fully
+ * random, such as the name of the file being encrypted, or transaction ID, or password,
+ * or a device identifier), consider changing your design to use a random IV which will then
+ * be provided in addition to the ciphertext to the entities which need to decrypt the
+ * ciphertext.
+ * - If you are using RSA encryption without padding, consider switching to padding
+ * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.
+ *
+ *
+ */
+ public Builder setRandomizedEncryptionRequired(boolean required) {
+ mRandomizedEncryptionRequired = required;
+ return this;
+ }
+
/**
* Sets the user authenticators which protect access to this key. The key can only be used
* iff the user has authenticated to at least one of these user authenticators.
@@ -465,6 +526,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
mPaddings,
mDigests,
mBlockModes,
+ mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);