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