Skip to content

Commit ada70be

Browse files
Alex KlyubinAndroid (Google) Code Review
authored andcommitted
Merge "Add KM_MIN_MAC_LENGTH tag to HMAC and AES-GCM keys." into mnc-dev
2 parents ff21279 + a95550f commit ada70be

5 files changed

Lines changed: 61 additions & 2 deletions

File tree

core/java/android/security/keymaster/KeymasterDefs.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ private KeymasterDefs() {}
5151
public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
5252
public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
5353
public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
54+
public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8;
5455

5556
public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
5657
public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
@@ -194,6 +195,9 @@ private KeymasterDefs() {}
194195
public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
195196
public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
196197
public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
198+
public static final int KM_ERROR_INVALID_MAC_LENGTH = -57;
199+
public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
200+
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
197201
public static final int KM_ERROR_UNIMPLEMENTED = -100;
198202
public static final int KM_ERROR_VERSION_MISMATCH = -101;
199203
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -237,6 +241,8 @@ private KeymasterDefs() {}
237241
sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV");
238242
sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
239243
"Caller-provided IV not permitted");
244+
sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
245+
"Invalid MAC or authentication tag length");
240246
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
241247
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
242248
}

keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
5252

5353
abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
54-
private static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
54+
static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
5555
private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
5656
private static final int DEFAULT_TAG_LENGTH_BITS = 128;
5757
private static final int IV_LENGTH_BYTES = 12;

keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
171171
"Key size must be positive: " + mKeySizeBits);
172172
} else if ((mKeySizeBits % 8) != 0) {
173173
throw new InvalidAlgorithmParameterException(
174-
"Key size in must be a multiple of 8: " + mKeySizeBits);
174+
"Key size must be a multiple of 8: " + mKeySizeBits);
175175
}
176176

177177
try {
@@ -272,6 +272,11 @@ protected SecretKey engineGenerateKey() {
272272
KeymasterUtils.addUserAuthArgs(args,
273273
spec.isUserAuthenticationRequired(),
274274
spec.getUserAuthenticationValidityDurationSeconds());
275+
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
276+
args,
277+
mKeymasterAlgorithm,
278+
mKeymasterBlockModes,
279+
mKeymasterDigests);
275280
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
276281
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
277282
spec.getKeyValidityForOriginationEnd());

keystore/java/android/security/keystore/AndroidKeyStoreSpi.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ private void setSecretKeyEntry(String entryAlias, SecretKey key,
672672
KeymasterUtils.addUserAuthArgs(args,
673673
params.isUserAuthenticationRequired(),
674674
params.getUserAuthenticationValidityDurationSeconds());
675+
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
676+
args,
677+
keymasterAlgorithm,
678+
keymasterBlockModes,
679+
keymasterDigests);
675680
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
676681
params.getKeyValidityStart());
677682
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,

keystore/java/android/security/keystore/KeymasterUtils.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import android.security.keymaster.KeymasterArguments;
2323
import android.security.keymaster.KeymasterDefs;
2424

25+
import java.security.ProviderException;
26+
2527
/**
2628
* @hide
2729
*/
@@ -133,4 +135,45 @@ public static void addUserAuthArgs(KeymasterArguments args,
133135
userAuthenticationValidityDurationSeconds);
134136
}
135137
}
138+
139+
/**
140+
* Adds {@code KM_TAG_MIN_MAC_LENGTH} tag, if necessary, to the keymaster arguments for
141+
* generating or importing a key. This tag may only be needed for symmetric keys (e.g., HMAC,
142+
* AES-GCM).
143+
*/
144+
public static void addMinMacLengthAuthorizationIfNecessary(KeymasterArguments args,
145+
int keymasterAlgorithm,
146+
int[] keymasterBlockModes,
147+
int[] keymasterDigests) {
148+
switch (keymasterAlgorithm) {
149+
case KeymasterDefs.KM_ALGORITHM_AES:
150+
if (com.android.internal.util.ArrayUtils.contains(
151+
keymasterBlockModes, KeymasterDefs.KM_MODE_GCM)) {
152+
// AES GCM key needs the minimum length of AEAD tag specified.
153+
args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH,
154+
AndroidKeyStoreAuthenticatedAESCipherSpi.GCM
155+
.MIN_SUPPORTED_TAG_LENGTH_BITS);
156+
}
157+
break;
158+
case KeymasterDefs.KM_ALGORITHM_HMAC:
159+
// HMAC key needs the minimum length of MAC set to the output size of the associated
160+
// digest. This is because we do not offer a way to generate shorter MACs and
161+
// don't offer a way to verify MACs (other than by generating them).
162+
if (keymasterDigests.length != 1) {
163+
throw new ProviderException(
164+
"Unsupported number of authorized digests for HMAC key: "
165+
+ keymasterDigests.length
166+
+ ". Exactly one digest must be authorized");
167+
}
168+
int keymasterDigest = keymasterDigests[0];
169+
int digestOutputSizeBits = getDigestOutputSizeBits(keymasterDigest);
170+
if (digestOutputSizeBits == -1) {
171+
throw new ProviderException(
172+
"HMAC key authorized for unsupported digest: "
173+
+ KeyProperties.Digest.fromKeymaster(keymasterDigest));
174+
}
175+
args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH, digestOutputSizeBits);
176+
break;
177+
}
178+
}
136179
}

0 commit comments

Comments
 (0)