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:
Alex Klyubin
2015-07-22 20:24:21 +00:00
committed by Android Git Automerger
5 changed files with 61 additions and 2 deletions

View File

@@ -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");
}

View File

@@ -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;

View File

@@ -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());

View File

@@ -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,

View File

@@ -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;
}
}
}