1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.keystore2; 18 19 import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MGF1_DIGEST; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.RequiresPermission; 24 import android.content.Context; 25 import android.hardware.security.keymint.EcCurve; 26 import android.hardware.security.keymint.KeyParameter; 27 import android.hardware.security.keymint.KeyPurpose; 28 import android.hardware.security.keymint.SecurityLevel; 29 import android.hardware.security.keymint.Tag; 30 import android.os.Build; 31 import android.os.StrictMode; 32 import android.security.Flags; 33 import android.security.KeyPairGeneratorSpec; 34 import android.security.KeyStore2; 35 import android.security.KeyStoreException; 36 import android.security.KeyStoreSecurityLevel; 37 import android.security.keymaster.KeymasterArguments; 38 import android.security.keymaster.KeymasterDefs; 39 import android.security.keystore.ArrayUtils; 40 import android.security.keystore.AttestationUtils; 41 import android.security.keystore.DeviceIdAttestationException; 42 import android.security.keystore.KeyGenParameterSpec; 43 import android.security.keystore.KeyProperties; 44 import android.security.keystore.SecureKeyImportUnavailableException; 45 import android.security.keystore.StrongBoxUnavailableException; 46 import android.system.keystore2.Authorization; 47 import android.system.keystore2.Domain; 48 import android.system.keystore2.IKeystoreSecurityLevel; 49 import android.system.keystore2.KeyDescriptor; 50 import android.system.keystore2.KeyEntryResponse; 51 import android.system.keystore2.KeyMetadata; 52 import android.system.keystore2.ResponseCode; 53 import android.telephony.TelephonyManager; 54 import android.text.TextUtils; 55 import android.util.ArraySet; 56 import android.util.Log; 57 58 import libcore.util.EmptyArray; 59 60 import java.math.BigInteger; 61 import java.nio.charset.StandardCharsets; 62 import java.security.InvalidAlgorithmParameterException; 63 import java.security.KeyPair; 64 import java.security.KeyPairGenerator; 65 import java.security.KeyPairGeneratorSpi; 66 import java.security.ProviderException; 67 import java.security.SecureRandom; 68 import java.security.UnrecoverableKeyException; 69 import java.security.spec.AlgorithmParameterSpec; 70 import java.security.spec.ECGenParameterSpec; 71 import java.security.spec.NamedParameterSpec; 72 import java.security.spec.RSAKeyGenParameterSpec; 73 import java.util.ArrayList; 74 import java.util.Arrays; 75 import java.util.Collection; 76 import java.util.Collections; 77 import java.util.HashMap; 78 import java.util.HashSet; 79 import java.util.List; 80 import java.util.Locale; 81 import java.util.Map; 82 import java.util.Set; 83 import java.util.function.Predicate; 84 85 /** 86 * Provides a way to create instances of a KeyPair which will be placed in the 87 * Android keystore service usable only by the application that called it. This 88 * can be used in conjunction with 89 * {@link java.security.KeyStore#getInstance(String)} using the 90 * {@code "AndroidKeyStore"} type. 91 * <p> 92 * This class can not be directly instantiated and must instead be used via the 93 * {@link KeyPairGenerator#getInstance(String) 94 * KeyPairGenerator.getInstance("AndroidKeyStore")} API. 95 * 96 * @hide 97 */ 98 public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi { 99 private static final String TAG = "AndroidKeyStoreKeyPairGeneratorSpi"; 100 101 public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi { RSA()102 public RSA() { 103 super(KeymasterDefs.KM_ALGORITHM_RSA); 104 } 105 } 106 107 public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi { EC()108 public EC() { 109 super(KeymasterDefs.KM_ALGORITHM_EC); 110 } 111 } 112 113 // For curve 25519, KeyMint uses the KM_ALGORITHM_EC constant, but in the Java layer we need 114 // to distinguish between Curve 25519 and other EC algorithms, so we use a different constant 115 // with a value that is outside the range of the enum used for KeyMint algorithms. 116 private static final int ALGORITHM_XDH = KeymasterDefs.KM_ALGORITHM_EC + 1200; 117 private static final int ALGORITHM_ED25519 = ALGORITHM_XDH + 1; 118 119 /** 120 * XDH represents Curve 25519 agreement key provider. 121 */ 122 public static class XDH extends AndroidKeyStoreKeyPairGeneratorSpi { 123 // XDH is treated as EC. XDH()124 public XDH() { 125 super(ALGORITHM_XDH); 126 } 127 } 128 129 /** 130 * ED25519 represents Curve 25519 signing key provider. 131 */ 132 public static class ED25519 extends AndroidKeyStoreKeyPairGeneratorSpi { 133 // ED25519 is treated as EC. ED25519()134 public ED25519() { 135 super(ALGORITHM_ED25519); 136 } 137 } 138 139 /* 140 * These must be kept in sync with system/security/keystore/defaults.h 141 */ 142 143 /* EC */ 144 private static final int EC_DEFAULT_KEY_SIZE = 256; 145 146 /* RSA */ 147 private static final int RSA_DEFAULT_KEY_SIZE = 2048; 148 private static final int RSA_MIN_KEY_SIZE = 512; 149 private static final int RSA_MAX_KEY_SIZE = 8192; 150 151 private static final Map<String, Integer> SUPPORTED_EC_CURVE_NAME_TO_SIZE = 152 new HashMap<String, Integer>(); 153 private static final List<String> SUPPORTED_EC_CURVE_NAMES = new ArrayList<String>(); 154 private static final List<Integer> SUPPORTED_EC_CURVE_SIZES = new ArrayList<Integer>(); 155 private static final String CURVE_X_25519 = NamedParameterSpec.X25519.getName(); 156 private static final String CURVE_ED_25519 = NamedParameterSpec.ED25519.getName(); 157 158 159 static { 160 // Aliases for NIST P-224 161 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-224", 224); 162 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp224r1", 224); 163 164 165 // Aliases for NIST P-256 166 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-256", 256); 167 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp256r1", 256); 168 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("prime256v1", 256); 169 // Aliases for Curve 25519 CURVE_X_25519.toLowerCase(Locale.US)170 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_X_25519.toLowerCase(Locale.US), 256); CURVE_ED_25519.toLowerCase(Locale.US)171 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_ED_25519.toLowerCase(Locale.US), 256); 172 173 // Aliases for NIST P-384 174 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-384", 384); 175 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp384r1", 384); 176 177 // Aliases for NIST P-521 178 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-521", 521); 179 SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp521r1", 521); 180 SUPPORTED_EC_CURVE_NAME_TO_SIZE.keySet()181 SUPPORTED_EC_CURVE_NAMES.addAll(SUPPORTED_EC_CURVE_NAME_TO_SIZE.keySet()); 182 Collections.sort(SUPPORTED_EC_CURVE_NAMES); 183 SUPPORTED_EC_CURVE_SIZES.addAll( new HashSet<Integer>(SUPPORTED_EC_CURVE_NAME_TO_SIZE.values()))184 SUPPORTED_EC_CURVE_SIZES.addAll( 185 new HashSet<Integer>(SUPPORTED_EC_CURVE_NAME_TO_SIZE.values())); 186 Collections.sort(SUPPORTED_EC_CURVE_SIZES); 187 } 188 189 private final int mOriginalKeymasterAlgorithm; 190 191 private KeyStore2 mKeyStore; 192 193 private KeyGenParameterSpec mSpec; 194 195 private String mEntryAlias; 196 private int mEntryNamespace; 197 private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm; 198 private int mKeymasterAlgorithm = -1; 199 private int mKeySizeBits; 200 private SecureRandom mRng; 201 private KeyDescriptor mAttestKeyDescriptor; 202 private String mEcCurveName; 203 204 private int[] mKeymasterPurposes; 205 private int[] mKeymasterBlockModes; 206 private int[] mKeymasterEncryptionPaddings; 207 private int[] mKeymasterSignaturePaddings; 208 private int[] mKeymasterDigests; 209 private int[] mKeymasterMgf1Digests; 210 211 private Long mRSAPublicExponent; 212 AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm)213 protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) { 214 mOriginalKeymasterAlgorithm = keymasterAlgorithm; 215 } 216 keySizeAndNameToEcCurve(int keySizeBits, String ecCurveName)217 private static @EcCurve int keySizeAndNameToEcCurve(int keySizeBits, String ecCurveName) 218 throws InvalidAlgorithmParameterException { 219 switch (keySizeBits) { 220 case 224: 221 return EcCurve.P_224; 222 case 256: 223 if (isCurve25519(ecCurveName)) { 224 return EcCurve.CURVE_25519; 225 } 226 return EcCurve.P_256; 227 case 384: 228 return EcCurve.P_384; 229 case 521: 230 return EcCurve.P_521; 231 default: 232 throw new InvalidAlgorithmParameterException( 233 "Unsupported EC curve keysize: " + keySizeBits); 234 } 235 } 236 237 @SuppressWarnings("deprecation") 238 @Override initialize(int keysize, SecureRandom random)239 public void initialize(int keysize, SecureRandom random) { 240 throw new IllegalArgumentException( 241 KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName() 242 + " required to initialize this KeyPairGenerator"); 243 } 244 245 @SuppressWarnings("deprecation") 246 @Override initialize(AlgorithmParameterSpec params, SecureRandom random)247 public void initialize(AlgorithmParameterSpec params, SecureRandom random) 248 throws InvalidAlgorithmParameterException { 249 resetAll(); 250 251 boolean success = false; 252 try { 253 if (params == null) { 254 throw new InvalidAlgorithmParameterException( 255 "Must supply params of type " + KeyGenParameterSpec.class.getName() 256 + " or " + KeyPairGeneratorSpec.class.getName()); 257 } 258 259 KeyGenParameterSpec spec; 260 boolean encryptionAtRestRequired = false; 261 int keymasterAlgorithm = (mOriginalKeymasterAlgorithm == ALGORITHM_XDH 262 || mOriginalKeymasterAlgorithm == ALGORITHM_ED25519) 263 ? KeymasterDefs.KM_ALGORITHM_EC : mOriginalKeymasterAlgorithm; 264 if (params instanceof KeyGenParameterSpec) { 265 spec = (KeyGenParameterSpec) params; 266 } else if (params instanceof KeyPairGeneratorSpec) { 267 // Legacy/deprecated spec 268 KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params; 269 try { 270 keymasterAlgorithm = getKeymasterAlgorithmFromLegacy(keymasterAlgorithm, 271 legacySpec); 272 spec = buildKeyGenParameterSpecFromLegacy(legacySpec, keymasterAlgorithm); 273 } catch (NullPointerException | IllegalArgumentException e) { 274 throw new InvalidAlgorithmParameterException(e); 275 } 276 } else if (params instanceof NamedParameterSpec) { 277 NamedParameterSpec namedSpec = (NamedParameterSpec) params; 278 // Android Keystore cannot support initialization from a NamedParameterSpec 279 // because an alias for the key is needed (a KeyGenParameterSpec cannot be 280 // constructed). 281 if (namedSpec.getName().equalsIgnoreCase(NamedParameterSpec.X25519.getName()) 282 || namedSpec.getName().equalsIgnoreCase( 283 NamedParameterSpec.ED25519.getName())) { 284 throw new IllegalArgumentException( 285 "This KeyPairGenerator cannot be initialized using NamedParameterSpec." 286 + " use " + KeyGenParameterSpec.class.getName() + " or " 287 + KeyPairGeneratorSpec.class.getName()); 288 } else { 289 throw new InvalidAlgorithmParameterException( 290 "Unsupported algorithm specified via NamedParameterSpec: " 291 + namedSpec.getName()); 292 } 293 } else { 294 throw new InvalidAlgorithmParameterException( 295 "Unsupported params class: " + params.getClass().getName() 296 + ". Supported: " + KeyGenParameterSpec.class.getName() 297 + ", " + KeyPairGeneratorSpec.class.getName()); 298 } 299 300 mEntryAlias = spec.getKeystoreAlias(); 301 mEntryNamespace = spec.getNamespace(); 302 mSpec = spec; 303 mKeymasterAlgorithm = keymasterAlgorithm; 304 mKeySizeBits = spec.getKeySize(); 305 initAlgorithmSpecificParameters(); 306 if (mKeySizeBits == -1) { 307 mKeySizeBits = getDefaultKeySize(keymasterAlgorithm); 308 } 309 checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked(), 310 mEcCurveName); 311 312 if (spec.getKeystoreAlias() == null) { 313 throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided"); 314 } 315 316 String jcaKeyAlgorithm; 317 try { 318 jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm( 319 keymasterAlgorithm); 320 mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes()); 321 mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()); 322 mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster( 323 spec.getEncryptionPaddings()); 324 if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) 325 && (spec.isRandomizedEncryptionRequired())) { 326 for (int keymasterPadding : mKeymasterEncryptionPaddings) { 327 if (!KeymasterUtils 328 .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto( 329 keymasterPadding)) { 330 throw new InvalidAlgorithmParameterException( 331 "Randomized encryption (IND-CPA) required but may be violated" 332 + " by padding scheme: " 333 + KeyProperties.EncryptionPadding.fromKeymaster( 334 keymasterPadding) 335 + ". See " + KeyGenParameterSpec.class.getName() 336 + " documentation."); 337 } 338 } 339 } 340 mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster( 341 spec.getSignaturePaddings()); 342 if (spec.isDigestsSpecified()) { 343 mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests()); 344 } else { 345 mKeymasterDigests = EmptyArray.INT; 346 } 347 if (spec.isMgf1DigestsSpecified()) { 348 // User-specified digests: Add all of them and do _not_ add the SHA-1 349 // digest by default (stick to what the user provided). 350 Set<String> mgfDigests = spec.getMgf1Digests(); 351 mKeymasterMgf1Digests = new int[mgfDigests.size()]; 352 int offset = 0; 353 for (String digest : mgfDigests) { 354 mKeymasterMgf1Digests[offset] = KeyProperties.Digest.toKeymaster(digest); 355 offset++; 356 } 357 } else { 358 // No user-specified digests: Add the SHA-1 default. 359 mKeymasterMgf1Digests = new int[]{ 360 KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)}; 361 } 362 363 // Check that user authentication related parameters are acceptable. This method 364 // will throw an IllegalStateException if there are issues (e.g., secure lock screen 365 // not set up). 366 KeyStore2ParameterUtils.addUserAuthArgs(new ArrayList<>(), mSpec); 367 } catch (IllegalArgumentException | IllegalStateException e) { 368 throw new InvalidAlgorithmParameterException(e); 369 } 370 371 mJcaKeyAlgorithm = jcaKeyAlgorithm; 372 mRng = random; 373 mKeyStore = KeyStore2.getInstance(); 374 375 mAttestKeyDescriptor = buildAndCheckAttestKeyDescriptor(spec); 376 checkAttestKeyPurpose(spec); 377 checkCorrectKeyPurposeForCurve(spec); 378 379 success = true; 380 } finally { 381 if (!success) { 382 resetAll(); 383 } 384 } 385 } 386 checkAttestKeyPurpose(KeyGenParameterSpec spec)387 private void checkAttestKeyPurpose(KeyGenParameterSpec spec) 388 throws InvalidAlgorithmParameterException { 389 if ((spec.getPurposes() & KeyProperties.PURPOSE_ATTEST_KEY) != 0 390 && spec.getPurposes() != KeyProperties.PURPOSE_ATTEST_KEY) { 391 throw new InvalidAlgorithmParameterException( 392 "PURPOSE_ATTEST_KEY may not be specified with any other purposes"); 393 } 394 } 395 checkCorrectKeyPurposeForCurve(KeyGenParameterSpec spec)396 private void checkCorrectKeyPurposeForCurve(KeyGenParameterSpec spec) 397 throws InvalidAlgorithmParameterException { 398 // Validate the key usage purposes against the curve. x25519 should be 399 // key exchange only, ed25519 signing and attesting. 400 401 if (!isCurve25519(mEcCurveName)) { 402 return; 403 } 404 405 if (mEcCurveName.equalsIgnoreCase(CURVE_X_25519) 406 && spec.getPurposes() != KeyProperties.PURPOSE_AGREE_KEY) { 407 throw new InvalidAlgorithmParameterException( 408 "x25519 may only be used for key agreement."); 409 } else if (mEcCurveName.equalsIgnoreCase(CURVE_ED_25519) 410 && !hasOnlyAllowedPurposeForEd25519(spec.getPurposes())) { 411 throw new InvalidAlgorithmParameterException( 412 "ed25519 may not be used for key agreement."); 413 } 414 } 415 isCurve25519(String ecCurveName)416 private static boolean isCurve25519(String ecCurveName) { 417 if (ecCurveName == null) { 418 return false; 419 } 420 return ecCurveName.equalsIgnoreCase(CURVE_X_25519) 421 || ecCurveName.equalsIgnoreCase(CURVE_ED_25519); 422 } 423 hasOnlyAllowedPurposeForEd25519(@eyProperties.PurposeEnum int purpose)424 private static boolean hasOnlyAllowedPurposeForEd25519(@KeyProperties.PurposeEnum int purpose) { 425 final int allowedPurposes = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 426 | KeyProperties.PURPOSE_ATTEST_KEY; 427 boolean hasAllowedPurpose = (purpose & allowedPurposes) != 0; 428 boolean hasDisallowedPurpose = (purpose & ~allowedPurposes) != 0; 429 return hasAllowedPurpose && !hasDisallowedPurpose; 430 } 431 buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec)432 private KeyDescriptor buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec) 433 throws InvalidAlgorithmParameterException { 434 if (spec.getAttestKeyAlias() != null) { 435 KeyDescriptor attestKeyDescriptor = new KeyDescriptor(); 436 attestKeyDescriptor.domain = Domain.APP; 437 attestKeyDescriptor.alias = spec.getAttestKeyAlias(); 438 try { 439 KeyEntryResponse attestKey = mKeyStore.getKeyEntry(attestKeyDescriptor); 440 checkAttestKeyChallenge(spec); 441 checkAttestKeyPurpose(attestKey.metadata.authorizations); 442 checkAttestKeySecurityLevel(spec, attestKey); 443 } catch (KeyStoreException e) { 444 throw new InvalidAlgorithmParameterException("Invalid attestKeyAlias", e); 445 } 446 return attestKeyDescriptor; 447 } 448 return null; 449 } 450 checkAttestKeyChallenge(KeyGenParameterSpec spec)451 private void checkAttestKeyChallenge(KeyGenParameterSpec spec) 452 throws InvalidAlgorithmParameterException { 453 if (spec.getAttestationChallenge() == null) { 454 throw new InvalidAlgorithmParameterException( 455 "AttestKey specified but no attestation challenge provided"); 456 } 457 } 458 checkAttestKeyPurpose(Authorization[] keyAuths)459 private void checkAttestKeyPurpose(Authorization[] keyAuths) 460 throws InvalidAlgorithmParameterException { 461 Predicate<Authorization> isAttestKeyPurpose = x -> x.keyParameter.tag == Tag.PURPOSE 462 && x.keyParameter.value.getKeyPurpose() == KeyPurpose.ATTEST_KEY; 463 464 if (Arrays.stream(keyAuths).noneMatch(isAttestKeyPurpose)) { 465 throw new InvalidAlgorithmParameterException( 466 ("Invalid attestKey, does not have PURPOSE_ATTEST_KEY")); 467 } 468 } 469 checkAttestKeySecurityLevel(KeyGenParameterSpec spec, KeyEntryResponse key)470 private void checkAttestKeySecurityLevel(KeyGenParameterSpec spec, KeyEntryResponse key) 471 throws InvalidAlgorithmParameterException { 472 boolean attestKeyInStrongBox = key.metadata.keySecurityLevel == SecurityLevel.STRONGBOX; 473 if (spec.isStrongBoxBacked() != attestKeyInStrongBox) { 474 if (attestKeyInStrongBox) { 475 throw new InvalidAlgorithmParameterException( 476 "Invalid security level: Cannot sign non-StrongBox key with " 477 + "StrongBox attestKey"); 478 479 } else { 480 throw new InvalidAlgorithmParameterException( 481 "Invalid security level: Cannot sign StrongBox key with " 482 + "non-StrongBox attestKey"); 483 } 484 } 485 } 486 getKeymasterAlgorithmFromLegacy(int keymasterAlgorithm, KeyPairGeneratorSpec legacySpec)487 private int getKeymasterAlgorithmFromLegacy(int keymasterAlgorithm, 488 KeyPairGeneratorSpec legacySpec) throws InvalidAlgorithmParameterException { 489 String specKeyAlgorithm = legacySpec.getKeyType(); 490 if (specKeyAlgorithm != null) { 491 // Spec overrides the generator's default key algorithm 492 try { 493 keymasterAlgorithm = 494 KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( 495 specKeyAlgorithm); 496 } catch (IllegalArgumentException e) { 497 throw new InvalidAlgorithmParameterException( 498 "Invalid key type in parameters", e); 499 } 500 } 501 return keymasterAlgorithm; 502 } 503 buildKeyGenParameterSpecFromLegacy(KeyPairGeneratorSpec legacySpec, int keymasterAlgorithm)504 private KeyGenParameterSpec buildKeyGenParameterSpecFromLegacy(KeyPairGeneratorSpec legacySpec, 505 int keymasterAlgorithm) { 506 KeyGenParameterSpec.Builder specBuilder; 507 switch (keymasterAlgorithm) { 508 case KeymasterDefs.KM_ALGORITHM_EC: 509 specBuilder = new KeyGenParameterSpec.Builder( 510 legacySpec.getKeystoreAlias(), 511 KeyProperties.PURPOSE_SIGN 512 | KeyProperties.PURPOSE_VERIFY); 513 // Authorized to be used with any digest (including no digest). 514 // MD5 was never offered for Android Keystore for ECDSA. 515 specBuilder.setDigests( 516 KeyProperties.DIGEST_NONE, 517 KeyProperties.DIGEST_SHA1, 518 KeyProperties.DIGEST_SHA224, 519 KeyProperties.DIGEST_SHA256, 520 KeyProperties.DIGEST_SHA384, 521 KeyProperties.DIGEST_SHA512); 522 break; 523 case KeymasterDefs.KM_ALGORITHM_RSA: 524 specBuilder = new KeyGenParameterSpec.Builder( 525 legacySpec.getKeystoreAlias(), 526 KeyProperties.PURPOSE_ENCRYPT 527 | KeyProperties.PURPOSE_DECRYPT 528 | KeyProperties.PURPOSE_SIGN 529 | KeyProperties.PURPOSE_VERIFY); 530 // Authorized to be used with any digest (including no digest). 531 specBuilder.setDigests( 532 KeyProperties.DIGEST_NONE, 533 KeyProperties.DIGEST_MD5, 534 KeyProperties.DIGEST_SHA1, 535 KeyProperties.DIGEST_SHA224, 536 KeyProperties.DIGEST_SHA256, 537 KeyProperties.DIGEST_SHA384, 538 KeyProperties.DIGEST_SHA512); 539 // Authorized to be used with any encryption and signature padding 540 // schemes (including no padding). 541 specBuilder.setEncryptionPaddings( 542 KeyProperties.ENCRYPTION_PADDING_NONE, 543 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, 544 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); 545 specBuilder.setSignaturePaddings( 546 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, 547 KeyProperties.SIGNATURE_PADDING_RSA_PSS); 548 // Disable randomized encryption requirement to support encryption 549 // padding NONE above. 550 specBuilder.setRandomizedEncryptionRequired(false); 551 break; 552 default: 553 throw new ProviderException( 554 "Unsupported algorithm: " + mKeymasterAlgorithm); 555 } 556 557 if (legacySpec.getKeySize() != -1) { 558 specBuilder.setKeySize(legacySpec.getKeySize()); 559 } 560 if (legacySpec.getAlgorithmParameterSpec() != null) { 561 specBuilder.setAlgorithmParameterSpec( 562 legacySpec.getAlgorithmParameterSpec()); 563 } 564 specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); 565 specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); 566 specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); 567 specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); 568 specBuilder.setUserAuthenticationRequired(false); 569 570 return specBuilder.build(); 571 } 572 resetAll()573 private void resetAll() { 574 mEntryAlias = null; 575 mEntryNamespace = KeyProperties.NAMESPACE_APPLICATION; 576 mJcaKeyAlgorithm = null; 577 mKeymasterAlgorithm = -1; 578 mKeymasterPurposes = null; 579 mKeymasterBlockModes = null; 580 mKeymasterEncryptionPaddings = null; 581 mKeymasterSignaturePaddings = null; 582 mKeymasterDigests = null; 583 mKeymasterMgf1Digests = null; 584 mKeySizeBits = 0; 585 mSpec = null; 586 mRSAPublicExponent = null; 587 mRng = null; 588 mKeyStore = null; 589 mEcCurveName = null; 590 } 591 initAlgorithmSpecificParameters()592 private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException { 593 AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec(); 594 switch (mKeymasterAlgorithm) { 595 case KeymasterDefs.KM_ALGORITHM_RSA: { 596 BigInteger publicExponent = null; 597 if (algSpecificSpec instanceof RSAKeyGenParameterSpec) { 598 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec; 599 if (mKeySizeBits == -1) { 600 mKeySizeBits = rsaSpec.getKeysize(); 601 } else if (mKeySizeBits != rsaSpec.getKeysize()) { 602 throw new InvalidAlgorithmParameterException("RSA key size must match " 603 + " between " + mSpec + " and " + algSpecificSpec 604 + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize()); 605 } 606 publicExponent = rsaSpec.getPublicExponent(); 607 } else if (algSpecificSpec != null) { 608 throw new InvalidAlgorithmParameterException( 609 "RSA may only use RSAKeyGenParameterSpec"); 610 } 611 if (publicExponent == null) { 612 publicExponent = RSAKeyGenParameterSpec.F4; 613 } 614 if (publicExponent.compareTo(BigInteger.ZERO) < 1) { 615 throw new InvalidAlgorithmParameterException( 616 "RSA public exponent must be positive: " + publicExponent); 617 } 618 if ((publicExponent.signum() == -1) 619 || (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0)) { 620 throw new InvalidAlgorithmParameterException( 621 "Unsupported RSA public exponent: " + publicExponent 622 + ". Maximum supported value: " 623 + KeymasterArguments.UINT64_MAX_VALUE); 624 } 625 mRSAPublicExponent = publicExponent.longValue(); 626 break; 627 } 628 case KeymasterDefs.KM_ALGORITHM_EC: 629 if (algSpecificSpec instanceof ECGenParameterSpec) { 630 ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec; 631 mEcCurveName = ecSpec.getName(); 632 if (mOriginalKeymasterAlgorithm == ALGORITHM_XDH 633 && !mEcCurveName.equalsIgnoreCase("x25519")) { 634 throw new InvalidAlgorithmParameterException("XDH algorithm only supports" 635 + " x25519 curve."); 636 } else if (mOriginalKeymasterAlgorithm == ALGORITHM_ED25519 637 && !mEcCurveName.equalsIgnoreCase("ed25519")) { 638 throw new InvalidAlgorithmParameterException("Ed25519 algorithm only" 639 + " supports ed25519 curve."); 640 } 641 final Integer ecSpecKeySizeBits = SUPPORTED_EC_CURVE_NAME_TO_SIZE.get( 642 mEcCurveName.toLowerCase(Locale.US)); 643 if (ecSpecKeySizeBits == null) { 644 throw new InvalidAlgorithmParameterException( 645 "Unsupported EC curve name: " + mEcCurveName 646 + ". Supported: " + SUPPORTED_EC_CURVE_NAMES); 647 } 648 if (mKeySizeBits == -1) { 649 mKeySizeBits = ecSpecKeySizeBits; 650 } else if (mKeySizeBits != ecSpecKeySizeBits) { 651 throw new InvalidAlgorithmParameterException("EC key size must match " 652 + " between " + mSpec + " and " + algSpecificSpec 653 + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits); 654 } 655 } else if (algSpecificSpec != null) { 656 throw new InvalidAlgorithmParameterException( 657 "EC may only use ECGenParameterSpec"); 658 } 659 break; 660 default: 661 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 662 } 663 } 664 665 @Override generateKeyPair()666 public KeyPair generateKeyPair() { 667 StrictMode.noteSlowCall("generateKeyPair"); 668 if (mKeyStore == null || mSpec == null) { 669 throw new IllegalStateException("Not initialized"); 670 } 671 672 final @SecurityLevel int securityLevel = 673 mSpec.isStrongBoxBacked() 674 ? SecurityLevel.STRONGBOX 675 : SecurityLevel.TRUSTED_ENVIRONMENT; 676 677 final int flags = 678 mSpec.isCriticalToDeviceEncryption() 679 ? IKeystoreSecurityLevel 680 .KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING 681 : 0; 682 683 byte[] additionalEntropy = 684 KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( 685 mRng, (mKeySizeBits + 7) / 8); 686 687 KeyDescriptor descriptor = new KeyDescriptor(); 688 descriptor.alias = mEntryAlias; 689 descriptor.domain = mEntryNamespace == KeyProperties.NAMESPACE_APPLICATION 690 ? Domain.APP 691 : Domain.SELINUX; 692 descriptor.nspace = mEntryNamespace; 693 descriptor.blob = null; 694 695 boolean success = false; 696 try { 697 KeyStoreSecurityLevel iSecurityLevel = mKeyStore.getSecurityLevel(securityLevel); 698 699 KeyMetadata metadata = iSecurityLevel.generateKey(descriptor, mAttestKeyDescriptor, 700 constructKeyGenerationArguments(), flags, additionalEntropy); 701 702 AndroidKeyStorePublicKey publicKey = 703 AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse( 704 descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm); 705 success = true; 706 return new KeyPair(publicKey, publicKey.getPrivateKey()); 707 } catch (KeyStoreException e) { 708 switch (e.getErrorCode()) { 709 case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE: 710 throw new StrongBoxUnavailableException("Failed to generated key pair.", e); 711 default: 712 ProviderException p = new ProviderException("Failed to generate key pair.", e); 713 if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) { 714 throw new SecureKeyImportUnavailableException(p); 715 } 716 throw p; 717 } 718 } catch (UnrecoverableKeyException | IllegalArgumentException 719 | DeviceIdAttestationException | InvalidAlgorithmParameterException e) { 720 throw new ProviderException( 721 "Failed to construct key object from newly generated key pair.", e); 722 } finally { 723 if (!success) { 724 try { 725 mKeyStore.deleteKey(descriptor); 726 } catch (KeyStoreException e) { 727 if (e.getErrorCode() != ResponseCode.KEY_NOT_FOUND) { 728 Log.e(TAG, "Failed to delete newly generated key after " 729 + "generation failed unexpectedly.", e); 730 } 731 } 732 } 733 } 734 } 735 736 @RequiresPermission(value = android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 737 conditional = true) addAttestationParameters(@onNull List<KeyParameter> params)738 private void addAttestationParameters(@NonNull List<KeyParameter> params) 739 throws ProviderException, IllegalArgumentException, DeviceIdAttestationException { 740 byte[] challenge = mSpec.getAttestationChallenge(); 741 742 if (challenge != null) { 743 params.add(KeyStore2ParameterUtils.makeBytes( 744 KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge 745 )); 746 747 if (mSpec.isDevicePropertiesAttestationIncluded()) { 748 final String platformReportedBrand = 749 isPropertyEmptyOrUnknown(Build.BRAND_FOR_ATTESTATION) 750 ? Build.BRAND : Build.BRAND_FOR_ATTESTATION; 751 params.add(KeyStore2ParameterUtils.makeBytes( 752 KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND, 753 platformReportedBrand.getBytes(StandardCharsets.UTF_8) 754 )); 755 final String platformReportedDevice = 756 isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION) 757 ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION; 758 params.add(KeyStore2ParameterUtils.makeBytes( 759 KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE, 760 platformReportedDevice.getBytes(StandardCharsets.UTF_8) 761 )); 762 final String platformReportedProduct = 763 isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION) 764 ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION; 765 params.add(KeyStore2ParameterUtils.makeBytes( 766 KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT, 767 platformReportedProduct.getBytes(StandardCharsets.UTF_8) 768 )); 769 final String platformReportedManufacturer = 770 isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION) 771 ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION; 772 params.add(KeyStore2ParameterUtils.makeBytes( 773 KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER, 774 platformReportedManufacturer.getBytes(StandardCharsets.UTF_8) 775 )); 776 final String platformReportedModel = 777 isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION) 778 ? Build.MODEL : Build.MODEL_FOR_ATTESTATION; 779 params.add(KeyStore2ParameterUtils.makeBytes( 780 KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL, 781 platformReportedModel.getBytes(StandardCharsets.UTF_8) 782 )); 783 } 784 785 int[] idTypes = mSpec.getAttestationIds(); 786 if (idTypes.length == 0) { 787 return; 788 } 789 final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length); 790 for (int idType : idTypes) { 791 idTypesSet.add(idType); 792 } 793 TelephonyManager telephonyService = null; 794 if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI) 795 || idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) { 796 telephonyService = 797 (TelephonyManager) android.app.AppGlobals.getInitialApplication() 798 .getSystemService(Context.TELEPHONY_SERVICE); 799 if (telephonyService == null) { 800 throw new DeviceIdAttestationException("Unable to access telephony service"); 801 } 802 } 803 for (final Integer idType : idTypesSet) { 804 switch (idType) { 805 case AttestationUtils.ID_TYPE_SERIAL: 806 params.add(KeyStore2ParameterUtils.makeBytes( 807 KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL, 808 Build.getSerial().getBytes(StandardCharsets.UTF_8) 809 )); 810 break; 811 case AttestationUtils.ID_TYPE_IMEI: { 812 final String imei = telephonyService.getImei(0); 813 if (imei == null) { 814 throw new DeviceIdAttestationException("Unable to retrieve IMEI"); 815 } 816 params.add(KeyStore2ParameterUtils.makeBytes( 817 KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI, 818 imei.getBytes(StandardCharsets.UTF_8) 819 )); 820 final String secondImei = telephonyService.getImei(1); 821 if (!TextUtils.isEmpty(secondImei)) { 822 params.add(KeyStore2ParameterUtils.makeBytes( 823 KeymasterDefs.KM_TAG_ATTESTATION_ID_SECOND_IMEI, 824 secondImei.getBytes(StandardCharsets.UTF_8) 825 )); 826 } 827 break; 828 } 829 case AttestationUtils.ID_TYPE_MEID: { 830 String meid; 831 try { 832 meid = telephonyService.getMeid(0); 833 } catch (UnsupportedOperationException e) { 834 Log.e(TAG, "Unable to retrieve MEID", e); 835 meid = null; 836 } 837 if (meid == null) { 838 throw new DeviceIdAttestationException("Unable to retrieve MEID"); 839 } 840 params.add(KeyStore2ParameterUtils.makeBytes( 841 KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID, 842 meid.getBytes(StandardCharsets.UTF_8) 843 )); 844 break; 845 } 846 case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: { 847 params.add(KeyStore2ParameterUtils.makeBool( 848 KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION)); 849 break; 850 } 851 default: 852 throw new IllegalArgumentException("Unknown device ID type " + idType); 853 } 854 } 855 } 856 } 857 constructKeyGenerationArguments()858 private Collection<KeyParameter> constructKeyGenerationArguments() 859 throws DeviceIdAttestationException, IllegalArgumentException, 860 InvalidAlgorithmParameterException { 861 List<KeyParameter> params = new ArrayList<>(); 862 params.add(KeyStore2ParameterUtils.makeInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits)); 863 params.add(KeyStore2ParameterUtils.makeEnum( 864 KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm 865 )); 866 867 if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) { 868 params.add(KeyStore2ParameterUtils.makeEnum( 869 Tag.EC_CURVE, keySizeAndNameToEcCurve(mKeySizeBits, mEcCurveName) 870 )); 871 } 872 873 ArrayUtils.forEach(mKeymasterPurposes, (purpose) -> { 874 params.add(KeyStore2ParameterUtils.makeEnum( 875 KeymasterDefs.KM_TAG_PURPOSE, purpose 876 )); 877 }); 878 ArrayUtils.forEach(mKeymasterBlockModes, (blockMode) -> { 879 params.add(KeyStore2ParameterUtils.makeEnum( 880 KeymasterDefs.KM_TAG_BLOCK_MODE, blockMode 881 )); 882 }); 883 ArrayUtils.forEach(mKeymasterEncryptionPaddings, (padding) -> { 884 params.add(KeyStore2ParameterUtils.makeEnum( 885 KeymasterDefs.KM_TAG_PADDING, padding 886 )); 887 if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) { 888 ArrayUtils.forEach(mKeymasterMgf1Digests, (mgf1Digest) -> { 889 params.add(KeyStore2ParameterUtils.makeEnum( 890 KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest 891 )); 892 }); 893 894 /* If the MGF1 Digest setter is not set, fall back to the previous behaviour: 895 * Add, as MGF1 Digest function, all the primary digests. 896 * Avoid adding the default MGF1 digest as it will have been included in the 897 * mKeymasterMgf1Digests field. 898 */ 899 if (!getMgf1DigestSetterFlag()) { 900 final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster( 901 DEFAULT_MGF1_DIGEST); 902 ArrayUtils.forEach(mKeymasterDigests, (digest) -> { 903 if (digest != defaultMgf1Digest) { 904 params.add(KeyStore2ParameterUtils.makeEnum( 905 KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest)); 906 } 907 }); 908 } 909 } 910 }); 911 ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> { 912 params.add(KeyStore2ParameterUtils.makeEnum( 913 KeymasterDefs.KM_TAG_PADDING, padding 914 )); 915 }); 916 ArrayUtils.forEach(mKeymasterDigests, (digest) -> { 917 params.add(KeyStore2ParameterUtils.makeEnum( 918 KeymasterDefs.KM_TAG_DIGEST, digest 919 )); 920 }); 921 922 KeyStore2ParameterUtils.addUserAuthArgs(params, mSpec); 923 924 if (mSpec.getKeyValidityStart() != null) { 925 params.add(KeyStore2ParameterUtils.makeDate( 926 KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart() 927 )); 928 } 929 if (mSpec.getKeyValidityForOriginationEnd() != null) { 930 params.add(KeyStore2ParameterUtils.makeDate( 931 KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, 932 mSpec.getKeyValidityForOriginationEnd() 933 )); 934 } 935 if (mSpec.getKeyValidityForConsumptionEnd() != null) { 936 params.add(KeyStore2ParameterUtils.makeDate( 937 KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, 938 mSpec.getKeyValidityForConsumptionEnd() 939 )); 940 } 941 if (mSpec.getCertificateNotAfter() != null) { 942 params.add(KeyStore2ParameterUtils.makeDate( 943 KeymasterDefs.KM_TAG_CERTIFICATE_NOT_AFTER, 944 mSpec.getCertificateNotAfter() 945 )); 946 } 947 if (mSpec.getCertificateNotBefore() != null) { 948 params.add(KeyStore2ParameterUtils.makeDate( 949 KeymasterDefs.KM_TAG_CERTIFICATE_NOT_BEFORE, 950 mSpec.getCertificateNotBefore() 951 )); 952 } 953 if (mSpec.getCertificateSerialNumber() != null) { 954 params.add(KeyStore2ParameterUtils.makeBignum( 955 KeymasterDefs.KM_TAG_CERTIFICATE_SERIAL, 956 mSpec.getCertificateSerialNumber() 957 )); 958 } 959 if (mSpec.getCertificateSubject() != null) { 960 params.add(KeyStore2ParameterUtils.makeBytes( 961 KeymasterDefs.KM_TAG_CERTIFICATE_SUBJECT, 962 mSpec.getCertificateSubject().getEncoded() 963 )); 964 } 965 966 if (mSpec.getMaxUsageCount() != KeyProperties.UNRESTRICTED_USAGE_COUNT) { 967 params.add(KeyStore2ParameterUtils.makeInt( 968 KeymasterDefs.KM_TAG_USAGE_COUNT_LIMIT, 969 mSpec.getMaxUsageCount() 970 )); 971 } 972 973 addAlgorithmSpecificParameters(params); 974 975 if (mSpec.isUniqueIdIncluded()) { 976 params.add(KeyStore2ParameterUtils.makeBool(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID)); 977 } 978 979 addAttestationParameters(params); 980 981 return params; 982 } 983 getMgf1DigestSetterFlag()984 private static boolean getMgf1DigestSetterFlag() { 985 try { 986 return Flags.mgf1DigestSetterV2(); 987 } catch (SecurityException e) { 988 Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e); 989 return false; 990 } 991 } 992 993 addAlgorithmSpecificParameters(List<KeyParameter> params)994 private void addAlgorithmSpecificParameters(List<KeyParameter> params) { 995 switch (mKeymasterAlgorithm) { 996 case KeymasterDefs.KM_ALGORITHM_RSA: 997 params.add(KeyStore2ParameterUtils.makeLong( 998 KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent 999 )); 1000 break; 1001 case KeymasterDefs.KM_ALGORITHM_EC: 1002 break; 1003 default: 1004 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 1005 } 1006 } 1007 getDefaultKeySize(int keymasterAlgorithm)1008 private static int getDefaultKeySize(int keymasterAlgorithm) { 1009 switch (keymasterAlgorithm) { 1010 case KeymasterDefs.KM_ALGORITHM_EC: 1011 return EC_DEFAULT_KEY_SIZE; 1012 case KeymasterDefs.KM_ALGORITHM_RSA: 1013 return RSA_DEFAULT_KEY_SIZE; 1014 default: 1015 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 1016 } 1017 } 1018 checkValidKeySize( int keymasterAlgorithm, int keySize, boolean isStrongBoxBacked, String mEcCurveName)1019 private static void checkValidKeySize( 1020 int keymasterAlgorithm, 1021 int keySize, 1022 boolean isStrongBoxBacked, 1023 String mEcCurveName) 1024 throws InvalidAlgorithmParameterException { 1025 switch (keymasterAlgorithm) { 1026 case KeymasterDefs.KM_ALGORITHM_EC: 1027 if (isStrongBoxBacked && keySize != 256) { 1028 throw new InvalidAlgorithmParameterException( 1029 "Unsupported StrongBox EC key size: " 1030 + keySize + " bits. Supported: 256"); 1031 } 1032 if (isStrongBoxBacked && isCurve25519(mEcCurveName)) { 1033 throw new InvalidAlgorithmParameterException( 1034 "Unsupported StrongBox EC: " + mEcCurveName); 1035 } 1036 if (!SUPPORTED_EC_CURVE_SIZES.contains(keySize)) { 1037 throw new InvalidAlgorithmParameterException("Unsupported EC key size: " 1038 + keySize + " bits. Supported: " + SUPPORTED_EC_CURVE_SIZES); 1039 } 1040 break; 1041 case KeymasterDefs.KM_ALGORITHM_RSA: 1042 if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { 1043 throw new InvalidAlgorithmParameterException("RSA key size must be >= " 1044 + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); 1045 } 1046 break; 1047 default: 1048 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 1049 } 1050 } 1051 1052 /** 1053 * Returns the {@code Signature} algorithm to be used for signing a certificate using the 1054 * specified key or {@code null} if the key cannot be used for signing a certificate. 1055 */ 1056 @Nullable getCertificateSignatureAlgorithm( int keymasterAlgorithm, int keySizeBits, KeyGenParameterSpec spec)1057 private static String getCertificateSignatureAlgorithm( 1058 int keymasterAlgorithm, 1059 int keySizeBits, 1060 KeyGenParameterSpec spec) { 1061 // Constraints: 1062 // 1. Key must be authorized for signing without user authentication. 1063 // 2. Signature digest must be one of key's authorized digests. 1064 // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead 1065 // of RSA PKCS#1 signature padding scheme (about 30 bytes). 1066 // 4. For EC keys, the there is no point in using a digest whose output size is longer than 1067 // key/field size because the digest will be truncated to that size. 1068 1069 if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) { 1070 // Key not authorized for signing 1071 return null; 1072 } 1073 if (spec.isUserAuthenticationRequired()) { 1074 // Key not authorized for use without user authentication 1075 return null; 1076 } 1077 if (!spec.isDigestsSpecified()) { 1078 // Key not authorized for any digests -- can't sign 1079 return null; 1080 } 1081 switch (keymasterAlgorithm) { 1082 case KeymasterDefs.KM_ALGORITHM_EC: { 1083 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 1084 spec.getDigests(), 1085 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 1086 1087 int bestKeymasterDigest = -1; 1088 int bestDigestOutputSizeBits = -1; 1089 for (int keymasterDigest : availableKeymasterDigests) { 1090 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 1091 if (outputSizeBits == keySizeBits) { 1092 // Perfect match -- use this digest 1093 bestKeymasterDigest = keymasterDigest; 1094 bestDigestOutputSizeBits = outputSizeBits; 1095 break; 1096 } 1097 // Not a perfect match -- check against the best digest so far 1098 if (bestKeymasterDigest == -1) { 1099 // First digest tested -- definitely the best so far 1100 bestKeymasterDigest = keymasterDigest; 1101 bestDigestOutputSizeBits = outputSizeBits; 1102 } else { 1103 // Prefer output size to be as close to key size as possible, with output 1104 // sizes larger than key size preferred to those smaller than key size. 1105 if (bestDigestOutputSizeBits < keySizeBits) { 1106 // Output size of the best digest so far is smaller than key size. 1107 // Anything larger is a win. 1108 if (outputSizeBits > bestDigestOutputSizeBits) { 1109 bestKeymasterDigest = keymasterDigest; 1110 bestDigestOutputSizeBits = outputSizeBits; 1111 } 1112 } else { 1113 // Output size of the best digest so far is larger than key size. 1114 // Anything smaller is a win, as long as it's not smaller than key size. 1115 if ((outputSizeBits < bestDigestOutputSizeBits) 1116 && (outputSizeBits >= keySizeBits)) { 1117 bestKeymasterDigest = keymasterDigest; 1118 bestDigestOutputSizeBits = outputSizeBits; 1119 } 1120 } 1121 } 1122 } 1123 if (bestKeymasterDigest == -1) { 1124 return null; 1125 } 1126 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 1127 bestKeymasterDigest) + "WithECDSA"; 1128 } 1129 case KeymasterDefs.KM_ALGORITHM_RSA: { 1130 // Check whether this key is authorized for PKCS#1 signature padding. 1131 // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle 1132 // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs 1133 // to be authorized for PKCS#1 padding or padding NONE which means any padding. 1134 boolean pkcs1SignaturePaddingSupported = 1135 com.android.internal.util.ArrayUtils.contains( 1136 KeyProperties.SignaturePadding.allToKeymaster( 1137 spec.getSignaturePaddings()), 1138 KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); 1139 if (!pkcs1SignaturePaddingSupported) { 1140 // Key not authorized for PKCS#1 signature padding -- can't sign 1141 return null; 1142 } 1143 1144 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 1145 spec.getDigests(), 1146 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 1147 1148 // The amount of space available for the digest is less than modulus size by about 1149 // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00, 1150 // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes 1151 // overhead (depending the on chosen digest) for encoding digest OID and digest 1152 // value in DER. 1153 int maxDigestOutputSizeBits = keySizeBits - 30 * 8; 1154 int bestKeymasterDigest = -1; 1155 int bestDigestOutputSizeBits = -1; 1156 for (int keymasterDigest : availableKeymasterDigests) { 1157 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 1158 if (outputSizeBits > maxDigestOutputSizeBits) { 1159 // Digest too long (signature generation will fail) -- skip 1160 continue; 1161 } 1162 if (bestKeymasterDigest == -1) { 1163 // First digest tested -- definitely the best so far 1164 bestKeymasterDigest = keymasterDigest; 1165 bestDigestOutputSizeBits = outputSizeBits; 1166 } else { 1167 // The longer the better 1168 if (outputSizeBits > bestDigestOutputSizeBits) { 1169 bestKeymasterDigest = keymasterDigest; 1170 bestDigestOutputSizeBits = outputSizeBits; 1171 } 1172 } 1173 } 1174 if (bestKeymasterDigest == -1) { 1175 return null; 1176 } 1177 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 1178 bestKeymasterDigest) + "WithRSA"; 1179 } 1180 default: 1181 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 1182 } 1183 } 1184 getAvailableKeymasterSignatureDigests( @eyProperties.DigestEnum String[] authorizedKeyDigests, @KeyProperties.DigestEnum String[] supportedSignatureDigests)1185 private static Set<Integer> getAvailableKeymasterSignatureDigests( 1186 @KeyProperties.DigestEnum String[] authorizedKeyDigests, 1187 @KeyProperties.DigestEnum String[] supportedSignatureDigests) { 1188 Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>(); 1189 for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) { 1190 authorizedKeymasterKeyDigests.add(keymasterDigest); 1191 } 1192 Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>(); 1193 for (int keymasterDigest 1194 : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) { 1195 supportedKeymasterSignatureDigests.add(keymasterDigest); 1196 } 1197 Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests); 1198 result.retainAll(authorizedKeymasterKeyDigests); 1199 return result; 1200 } 1201 isPropertyEmptyOrUnknown(String property)1202 private boolean isPropertyEmptyOrUnknown(String property) { 1203 return TextUtils.isEmpty(property) || property.equals(Build.UNKNOWN); 1204 } 1205 } 1206