|
22 | 22 | import android.security.keymaster.KeymasterArguments; |
23 | 23 | import android.security.keymaster.KeymasterDefs; |
24 | 24 |
|
| 25 | +import java.security.ProviderException; |
| 26 | + |
25 | 27 | /** |
26 | 28 | * @hide |
27 | 29 | */ |
@@ -133,4 +135,45 @@ public static void addUserAuthArgs(KeymasterArguments args, |
133 | 135 | userAuthenticationValidityDurationSeconds); |
134 | 136 | } |
135 | 137 | } |
| 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 | + } |
136 | 179 | } |
0 commit comments