* commit 'f7e7f744e193e027afde5c071889bde1c5882cfd': Require IND-CPA by default for new AndroidKeyStore keys.
This commit is contained in:
@@ -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 :
|
||||
@@ -549,8 +560,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -65,6 +67,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) {
|
||||
if (context == null) {
|
||||
@@ -87,6 +90,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
|
||||
mPurposes = purposes;
|
||||
mPaddings = paddings;
|
||||
mBlockModes = blockModes;
|
||||
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
|
||||
mUserAuthenticators = userAuthenticators;
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
}
|
||||
@@ -168,6 +172,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 <em>indistinguishability under chosen-plaintext attack ({@code
|
||||
* IND-CPA})</em>. 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.
|
||||
@@ -207,6 +224,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;
|
||||
|
||||
@@ -345,6 +363,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 <em>indistinguishability under chosen-plaintext attack
|
||||
* ({@code IND-CPA})</em>. 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.
|
||||
*
|
||||
* <p>By default, {@code IND-CPA} is required.
|
||||
*
|
||||
* <p>When {@code IND-CPA} is required:
|
||||
* <ul>
|
||||
* <li>block modes which do not offer {@code IND-CPA}, such as {@code ECB}, are prohibited;
|
||||
* </li>
|
||||
* <li>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.</li>
|
||||
*
|
||||
* <p>Before disabling this requirement, consider the following approaches instead:
|
||||
* <ul>
|
||||
* <li>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()}.</li>
|
||||
* <li>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.</li>
|
||||
* </ul>
|
||||
*/
|
||||
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.
|
||||
@@ -394,6 +449,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
|
||||
mPurposes,
|
||||
mPaddings,
|
||||
mBlockModes,
|
||||
mRandomizedEncryptionRequired,
|
||||
mUserAuthenticators,
|
||||
mUserAuthenticationValidityDurationSeconds);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -132,6 +134,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) {
|
||||
if (context == null) {
|
||||
@@ -171,6 +174,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
|
||||
mDigests = digests;
|
||||
mPaddings = paddings;
|
||||
mBlockModes = blockModes;
|
||||
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
|
||||
mUserAuthenticators = userAuthenticators;
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
}
|
||||
@@ -182,8 +186,26 @@ 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);
|
||||
this(context,
|
||||
keyStoreAlias,
|
||||
keyType,
|
||||
keySize,
|
||||
spec,
|
||||
subjectDN,
|
||||
serialNumber,
|
||||
startDate,
|
||||
endDate,
|
||||
flags,
|
||||
startDate,
|
||||
endDate,
|
||||
endDate,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
-1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,6 +364,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 <em>indistinguishability under chosen-plaintext attack ({@code
|
||||
* IND-CPA})</em>. 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.
|
||||
@@ -429,6 +466,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;
|
||||
@@ -669,6 +708,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 <em>indistinguishability under chosen-plaintext attack
|
||||
* ({@code IND-CPA})</em>. 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.
|
||||
*
|
||||
* <p>By default, {@code IND-CPA} is required.
|
||||
*
|
||||
* <p>When {@code IND-CPA} is required, encryption/decryption transformations which do not
|
||||
* offer {@code IND-CPA}, such as RSA without padding, are prohibited.
|
||||
*
|
||||
* <p>Before disabling this requirement, consider the following approaches instead:
|
||||
* <ul>
|
||||
* <li>If you are using RSA encryption without padding, consider switching to padding
|
||||
* schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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.
|
||||
@@ -736,6 +802,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
|
||||
mDigests,
|
||||
mPaddings,
|
||||
mBlockModes,
|
||||
mRandomizedEncryptionRequired,
|
||||
mUserAuthenticators,
|
||||
mUserAuthenticationValidityDurationSeconds);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 :
|
||||
@@ -173,8 +186,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -63,6 +66,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) {
|
||||
if ((userAuthenticationValidityDurationSeconds < 0)
|
||||
@@ -79,6 +83,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
|
||||
mPaddings = paddings;
|
||||
mDigests = digests;
|
||||
mBlockModes = blockModes;
|
||||
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
|
||||
mUserAuthenticators = userAuthenticators;
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
}
|
||||
@@ -184,6 +189,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 <em>indistinguishability under chosen-plaintext attack ({@code
|
||||
* IND-CPA})</em>. 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.
|
||||
@@ -235,6 +255,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;
|
||||
|
||||
@@ -380,6 +401,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 <em>indistinguishability under chosen-plaintext attack
|
||||
* ({@code IND-CPA})</em>. 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.
|
||||
*
|
||||
* <p>By default, {@code IND-CPA} is required.
|
||||
*
|
||||
* <p>When {@code IND-CPA} is required:
|
||||
* <ul>
|
||||
* <li>transformation which do not offer {@code IND-CPA}, such as symmetric ciphers using
|
||||
* {@code ECB} mode or RSA encryption without padding, are prohibited;</li>
|
||||
* <li>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.</li>
|
||||
*
|
||||
* <p>Before disabling this requirement, consider the following approaches instead:
|
||||
* <ul>
|
||||
* <li>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()}.</li>
|
||||
* <li>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.</li>
|
||||
* <li>If you are using RSA encryption without padding, consider switching to padding
|
||||
* schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li>
|
||||
*
|
||||
* </ul>
|
||||
*/
|
||||
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.
|
||||
@@ -432,6 +493,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
|
||||
mPaddings,
|
||||
mDigests,
|
||||
mBlockModes,
|
||||
mRandomizedEncryptionRequired,
|
||||
mUserAuthenticators,
|
||||
mUserAuthenticationValidityDurationSeconds);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user