Merge "Add KM_MIN_MAC_LENGTH tag to HMAC and AES-GCM keys." into mnc-dev
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_DIGEST = KM_ENUM_REP | 5;
|
||||||
public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
|
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_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_ADD = KM_ENUM_REP | 101;
|
||||||
public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
|
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_KEY_RATE_LIMIT_EXCEEDED = -54;
|
||||||
public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
|
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_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_UNIMPLEMENTED = -100;
|
||||||
public static final int KM_ERROR_VERSION_MISMATCH = -101;
|
public static final int KM_ERROR_VERSION_MISMATCH = -101;
|
||||||
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
|
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_INVALID_NONCE, "Invalid IV");
|
||||||
sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
|
sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
|
||||||
"Caller-provided IV not permitted");
|
"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_UNIMPLEMENTED, "Not implemented");
|
||||||
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
|
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import javax.crypto.spec.GCMParameterSpec;
|
|||||||
abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
|
abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
|
||||||
|
|
||||||
abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
|
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 MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
|
||||||
private static final int DEFAULT_TAG_LENGTH_BITS = 128;
|
private static final int DEFAULT_TAG_LENGTH_BITS = 128;
|
||||||
private static final int IV_LENGTH_BYTES = 12;
|
private static final int IV_LENGTH_BYTES = 12;
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
|||||||
"Key size must be positive: " + mKeySizeBits);
|
"Key size must be positive: " + mKeySizeBits);
|
||||||
} else if ((mKeySizeBits % 8) != 0) {
|
} else if ((mKeySizeBits % 8) != 0) {
|
||||||
throw new InvalidAlgorithmParameterException(
|
throw new InvalidAlgorithmParameterException(
|
||||||
"Key size in must be a multiple of 8: " + mKeySizeBits);
|
"Key size must be a multiple of 8: " + mKeySizeBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -272,6 +272,11 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
|||||||
KeymasterUtils.addUserAuthArgs(args,
|
KeymasterUtils.addUserAuthArgs(args,
|
||||||
spec.isUserAuthenticationRequired(),
|
spec.isUserAuthenticationRequired(),
|
||||||
spec.getUserAuthenticationValidityDurationSeconds());
|
spec.getUserAuthenticationValidityDurationSeconds());
|
||||||
|
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||||
|
args,
|
||||||
|
mKeymasterAlgorithm,
|
||||||
|
mKeymasterBlockModes,
|
||||||
|
mKeymasterDigests);
|
||||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
|
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
|
||||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||||
spec.getKeyValidityForOriginationEnd());
|
spec.getKeyValidityForOriginationEnd());
|
||||||
|
|||||||
@@ -672,6 +672,11 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
|||||||
KeymasterUtils.addUserAuthArgs(args,
|
KeymasterUtils.addUserAuthArgs(args,
|
||||||
params.isUserAuthenticationRequired(),
|
params.isUserAuthenticationRequired(),
|
||||||
params.getUserAuthenticationValidityDurationSeconds());
|
params.getUserAuthenticationValidityDurationSeconds());
|
||||||
|
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||||
|
args,
|
||||||
|
keymasterAlgorithm,
|
||||||
|
keymasterBlockModes,
|
||||||
|
keymasterDigests);
|
||||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
|
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
|
||||||
params.getKeyValidityStart());
|
params.getKeyValidityStart());
|
||||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
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.KeymasterArguments;
|
||||||
import android.security.keymaster.KeymasterDefs;
|
import android.security.keymaster.KeymasterDefs;
|
||||||
|
|
||||||
|
import java.security.ProviderException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -133,4 +135,45 @@ public abstract class KeymasterUtils {
|
|||||||
userAuthenticationValidityDurationSeconds);
|
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