Merge "HMAC keys are authorized for exactly one digest." into mnc-dev
This commit is contained in:
@@ -197,48 +197,36 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spec.isDigestsSpecified()) {
|
||||
// Digest(s) explicitly specified in the spec
|
||||
mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
|
||||
if (mKeymasterDigest != -1) {
|
||||
// Key algorithm implies a digest -- ensure it's specified in the spec as
|
||||
// first digest.
|
||||
if (!com.android.internal.util.ArrayUtils.contains(
|
||||
mKeymasterDigests, mKeymasterDigest)) {
|
||||
|
||||
if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
|
||||
// JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
|
||||
// implies SHA-256 digest). Because keymaster HMAC key is authorized only for
|
||||
// one digest, we don't let algorithm parameter spec override the digest implied
|
||||
// by the key. If the spec specifies digests at all, it must specify only one
|
||||
// digest, the only implied by key algorithm.
|
||||
mKeymasterDigests = new int[] {mKeymasterDigest};
|
||||
if (spec.isDigestsSpecified()) {
|
||||
// Digest(s) explicitly specified in the spec. Check that the list
|
||||
// consists of exactly one digest, the one implied by key algorithm.
|
||||
int[] keymasterDigestsFromSpec =
|
||||
KeyProperties.Digest.allToKeymaster(spec.getDigests());
|
||||
if ((keymasterDigestsFromSpec.length != 1)
|
||||
|| (keymasterDigestsFromSpec[0] != mKeymasterDigest)) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Digests specified in algorithm parameters ("
|
||||
+ Arrays.asList(spec.getDigests()) + ") must include "
|
||||
+ " the digest "
|
||||
"Unsupported digests specification: "
|
||||
+ Arrays.asList(spec.getDigests()) + ". Only "
|
||||
+ KeyProperties.Digest.fromKeymaster(mKeymasterDigest)
|
||||
+ " implied by key algorithm");
|
||||
}
|
||||
if (mKeymasterDigests[0] != mKeymasterDigest) {
|
||||
// The first digest is not the one implied by the key algorithm.
|
||||
// Swap the implied digest with the first one.
|
||||
for (int i = 0; i < mKeymasterDigests.length; i++) {
|
||||
if (mKeymasterDigests[i] == mKeymasterDigest) {
|
||||
mKeymasterDigests[i] = mKeymasterDigests[0];
|
||||
mKeymasterDigests[0] = mKeymasterDigest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ " supported for this HMAC key algorithm");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No digest specified in the spec
|
||||
if (mKeymasterDigest != -1) {
|
||||
// Key algorithm implies a digest -- use that digest
|
||||
mKeymasterDigests = new int[] {mKeymasterDigest};
|
||||
// Key algorithm does not imply a digest.
|
||||
if (spec.isDigestsSpecified()) {
|
||||
mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
|
||||
} else {
|
||||
mKeymasterDigests = EmptyArray.INT;
|
||||
}
|
||||
}
|
||||
if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
|
||||
if (mKeymasterDigests.length == 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"At least one digest algorithm must be specified");
|
||||
}
|
||||
}
|
||||
|
||||
// Check that user authentication related parameters are acceptable. This method
|
||||
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.security.KeyStoreException;
|
||||
import java.security.KeyStoreSpi;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.ProviderException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
@@ -605,50 +606,43 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
|
||||
|
||||
int[] keymasterDigests;
|
||||
int keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
|
||||
if (params.isDigestsSpecified()) {
|
||||
// Digest(s) specified in parameters
|
||||
keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
|
||||
if (keymasterDigest != -1) {
|
||||
// Digest also specified in the JCA key algorithm name.
|
||||
if (!com.android.internal.util.ArrayUtils.contains(
|
||||
keymasterDigests, keymasterDigest)) {
|
||||
throw new KeyStoreException("Digest specified in key algorithm "
|
||||
+ key.getAlgorithm() + " not specified in protection parameters: "
|
||||
+ Arrays.asList(params.getDigests()));
|
||||
}
|
||||
// When the key is read back from keystore we reconstruct the JCA key algorithm
|
||||
// name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to
|
||||
// ensure that the digest reflected in the JCA key algorithm name is the first
|
||||
// KM_TAG_DIGEST tag.
|
||||
if (keymasterDigests[0] != keymasterDigest) {
|
||||
// The first digest is not the one implied by the JCA key algorithm name.
|
||||
// Swap the implied digest with the first one.
|
||||
for (int i = 0; i < keymasterDigests.length; i++) {
|
||||
if (keymasterDigests[i] == keymasterDigest) {
|
||||
keymasterDigests[i] = keymasterDigests[0];
|
||||
keymasterDigests[0] = keymasterDigest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
|
||||
// JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
|
||||
// implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
|
||||
// digest, we don't let import parameters override the digest implied by the key.
|
||||
// If the parameters specify digests at all, they must specify only one digest, the
|
||||
// only implied by key algorithm.
|
||||
int keymasterImpliedDigest =
|
||||
KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
|
||||
if (keymasterImpliedDigest == -1) {
|
||||
throw new ProviderException(
|
||||
"HMAC key algorithm digest unknown for key algorithm "
|
||||
+ key.getAlgorithm());
|
||||
}
|
||||
keymasterDigests = new int[] {keymasterImpliedDigest};
|
||||
if (params.isDigestsSpecified()) {
|
||||
// Digest(s) explicitly specified in params -- check that the list consists of
|
||||
// exactly one digest, the one implied by key algorithm.
|
||||
int[] keymasterDigestsFromParams =
|
||||
KeyProperties.Digest.allToKeymaster(params.getDigests());
|
||||
if ((keymasterDigestsFromParams.length != 1)
|
||||
|| (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
|
||||
throw new KeyStoreException(
|
||||
"Unsupported digests specification: "
|
||||
+ Arrays.asList(params.getDigests()) + ". Only "
|
||||
+ KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
|
||||
+ " supported for HMAC key algorithm " + key.getAlgorithm());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No digest specified in parameters
|
||||
if (keymasterDigest != -1) {
|
||||
// Digest specified in the JCA key algorithm name.
|
||||
keymasterDigests = new int[] {keymasterDigest};
|
||||
// Key algorithm does not imply a digest.
|
||||
if (params.isDigestsSpecified()) {
|
||||
keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
|
||||
} else {
|
||||
keymasterDigests = EmptyArray.INT;
|
||||
}
|
||||
}
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
|
||||
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
|
||||
if (keymasterDigests.length == 0) {
|
||||
throw new KeyStoreException("At least one digest algorithm must be specified"
|
||||
+ " for key algorithm " + key.getAlgorithm());
|
||||
}
|
||||
}
|
||||
|
||||
@KeyProperties.PurposeEnum int purposes = params.getPurposes();
|
||||
int[] keymasterBlockModes =
|
||||
|
||||
@@ -642,7 +642,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
* <p>This must be specified for signing/verification keys and RSA encryption/decryption
|
||||
* keys used with RSA OAEP padding scheme because these operations involve a digest. For
|
||||
* HMAC keys, the default is the digest associated with the key algorithm (e.g.,
|
||||
* {@code SHA-256} for key algorithm {@code HmacSHA256}).
|
||||
* {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
|
||||
* for more than one digest.
|
||||
*
|
||||
* <p>For private keys used for TLS/SSL client or server authentication it is usually
|
||||
* necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
|
||||
|
||||
@@ -423,7 +423,8 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
* <p>This must be specified for signing/verification keys and RSA encryption/decryption
|
||||
* keys used with RSA OAEP padding scheme because these operations involve a digest. For
|
||||
* HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()} (e.g.,
|
||||
* {@code SHA-256} for key algorithm {@code HmacSHA256}).
|
||||
* {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
|
||||
* for more than one digest.
|
||||
*
|
||||
* <p>For private keys used for TLS/SSL client or server authentication it is usually
|
||||
* necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
|
||||
|
||||
Reference in New Issue
Block a user