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