am ada70be8: Merge "Add KM_MIN_MAC_LENGTH tag to HMAC and AES-GCM keys." into mnc-dev
* commit 'ada70be897fb7541129f1ab1f6faa94a80fca986': Add KM_MIN_MAC_LENGTH tag to HMAC and AES-GCM keys.
This commit is contained in:
@@ -51,6 +51,7 @@ public final class KeymasterDefs {
|
||||
public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
|
||||
public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
|
||||
public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
|
||||
public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8;
|
||||
|
||||
public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
|
||||
public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
|
||||
@@ -194,6 +195,9 @@ public final class KeymasterDefs {
|
||||
public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
|
||||
public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
|
||||
public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
|
||||
public static final int KM_ERROR_INVALID_MAC_LENGTH = -57;
|
||||
public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
|
||||
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
|
||||
public static final int KM_ERROR_UNIMPLEMENTED = -100;
|
||||
public static final int KM_ERROR_VERSION_MISMATCH = -101;
|
||||
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
|
||||
@@ -237,6 +241,8 @@ public final class KeymasterDefs {
|
||||
sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV");
|
||||
sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
|
||||
"Caller-provided IV not permitted");
|
||||
sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
|
||||
"Invalid MAC or authentication tag length");
|
||||
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
|
||||
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ import javax.crypto.spec.GCMParameterSpec;
|
||||
abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
|
||||
|
||||
abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
|
||||
private static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
|
||||
static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
|
||||
private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
|
||||
private static final int DEFAULT_TAG_LENGTH_BITS = 128;
|
||||
private static final int IV_LENGTH_BYTES = 12;
|
||||
|
||||
@@ -171,7 +171,7 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
"Key size must be positive: " + mKeySizeBits);
|
||||
} else if ((mKeySizeBits % 8) != 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Key size in must be a multiple of 8: " + mKeySizeBits);
|
||||
"Key size must be a multiple of 8: " + mKeySizeBits);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -272,6 +272,11 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds());
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
mKeymasterAlgorithm,
|
||||
mKeymasterBlockModes,
|
||||
mKeymasterDigests);
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
spec.getKeyValidityForOriginationEnd());
|
||||
|
||||
@@ -672,6 +672,11 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
params.isUserAuthenticationRequired(),
|
||||
params.getUserAuthenticationValidityDurationSeconds());
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
keymasterAlgorithm,
|
||||
keymasterBlockModes,
|
||||
keymasterDigests);
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
|
||||
params.getKeyValidityStart());
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.security.KeyStore;
|
||||
import android.security.keymaster.KeymasterArguments;
|
||||
import android.security.keymaster.KeymasterDefs;
|
||||
|
||||
import java.security.ProviderException;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -133,4 +135,45 @@ public abstract class KeymasterUtils {
|
||||
userAuthenticationValidityDurationSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code KM_TAG_MIN_MAC_LENGTH} tag, if necessary, to the keymaster arguments for
|
||||
* generating or importing a key. This tag may only be needed for symmetric keys (e.g., HMAC,
|
||||
* AES-GCM).
|
||||
*/
|
||||
public static void addMinMacLengthAuthorizationIfNecessary(KeymasterArguments args,
|
||||
int keymasterAlgorithm,
|
||||
int[] keymasterBlockModes,
|
||||
int[] keymasterDigests) {
|
||||
switch (keymasterAlgorithm) {
|
||||
case KeymasterDefs.KM_ALGORITHM_AES:
|
||||
if (com.android.internal.util.ArrayUtils.contains(
|
||||
keymasterBlockModes, KeymasterDefs.KM_MODE_GCM)) {
|
||||
// AES GCM key needs the minimum length of AEAD tag specified.
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH,
|
||||
AndroidKeyStoreAuthenticatedAESCipherSpi.GCM
|
||||
.MIN_SUPPORTED_TAG_LENGTH_BITS);
|
||||
}
|
||||
break;
|
||||
case KeymasterDefs.KM_ALGORITHM_HMAC:
|
||||
// HMAC key needs the minimum length of MAC set to the output size of the associated
|
||||
// digest. This is because we do not offer a way to generate shorter MACs and
|
||||
// don't offer a way to verify MACs (other than by generating them).
|
||||
if (keymasterDigests.length != 1) {
|
||||
throw new ProviderException(
|
||||
"Unsupported number of authorized digests for HMAC key: "
|
||||
+ keymasterDigests.length
|
||||
+ ". Exactly one digest must be authorized");
|
||||
}
|
||||
int keymasterDigest = keymasterDigests[0];
|
||||
int digestOutputSizeBits = getDigestOutputSizeBits(keymasterDigest);
|
||||
if (digestOutputSizeBits == -1) {
|
||||
throw new ProviderException(
|
||||
"HMAC key authorized for unsupported digest: "
|
||||
+ KeyProperties.Digest.fromKeymaster(keymasterDigest));
|
||||
}
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH, digestOutputSizeBits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user