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 17package android.security.keystore; 18 19import android.annotation.Nullable; 20import android.security.Credentials; 21import android.security.KeyPairGeneratorSpec; 22import android.security.KeyStore; 23import android.security.keymaster.KeyCharacteristics; 24import android.security.keymaster.KeymasterArguments; 25import android.security.keymaster.KeymasterCertificateChain; 26import android.security.keymaster.KeymasterDefs; 27 28import com.android.org.bouncycastle.asn1.ASN1EncodableVector; 29import com.android.org.bouncycastle.asn1.ASN1InputStream; 30import com.android.org.bouncycastle.asn1.ASN1Integer; 31import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier; 32import com.android.org.bouncycastle.asn1.DERBitString; 33import com.android.org.bouncycastle.asn1.DERInteger; 34import com.android.org.bouncycastle.asn1.DERNull; 35import com.android.org.bouncycastle.asn1.DERSequence; 36import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 37import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 38import com.android.org.bouncycastle.asn1.x509.Certificate; 39import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 40import com.android.org.bouncycastle.asn1.x509.TBSCertificate; 41import com.android.org.bouncycastle.asn1.x509.Time; 42import com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; 43import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 44import com.android.org.bouncycastle.jce.X509Principal; 45import com.android.org.bouncycastle.jce.provider.X509CertificateObject; 46import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; 47 48import libcore.util.EmptyArray; 49 50import java.io.ByteArrayOutputStream; 51import java.io.IOException; 52import java.math.BigInteger; 53import java.security.InvalidAlgorithmParameterException; 54import java.security.KeyPair; 55import java.security.KeyPairGenerator; 56import java.security.KeyPairGeneratorSpi; 57import java.security.PrivateKey; 58import java.security.ProviderException; 59import java.security.PublicKey; 60import java.security.SecureRandom; 61import java.security.UnrecoverableKeyException; 62import java.security.cert.CertificateEncodingException; 63import java.security.cert.CertificateParsingException; 64import java.security.cert.X509Certificate; 65import java.security.spec.AlgorithmParameterSpec; 66import java.security.spec.ECGenParameterSpec; 67import java.security.spec.RSAKeyGenParameterSpec; 68import java.util.ArrayList; 69import java.util.Collection; 70import java.util.Collections; 71import java.util.HashMap; 72import java.util.HashSet; 73import java.util.Iterator; 74import java.util.List; 75import java.util.Locale; 76import java.util.Map; 77import java.util.Set; 78 79/** 80 * Provides a way to create instances of a KeyPair which will be placed in the 81 * Android keystore service usable only by the application that called it. This 82 * can be used in conjunction with 83 * {@link java.security.KeyStore#getInstance(String)} using the 84 * {@code "AndroidKeyStore"} type. 85 * <p> 86 * This class can not be directly instantiated and must instead be used via the 87 * {@link KeyPairGenerator#getInstance(String) 88 * KeyPairGenerator.getInstance("AndroidKeyStore")} API. 89 * 90 * @hide 91 */ 92public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi { 93 94 public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi { 95 public RSA() { 96 super(KeymasterDefs.KM_ALGORITHM_RSA); 97 } 98 } 99 100 public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi { 101 public EC() { 102 super(KeymasterDefs.KM_ALGORITHM_EC); 103 } 104 } 105 106 /* 107 * These must be kept in sync with system/security/keystore/defaults.h 108 */ 109 110 /* EC */ 111 private static final int EC_DEFAULT_KEY_SIZE = 256; 112 113 /* RSA */ 114 private static final int RSA_DEFAULT_KEY_SIZE = 2048; 115 private static final int RSA_MIN_KEY_SIZE = 512; 116 private static final int RSA_MAX_KEY_SIZE = 8192; 117 118 private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE = 119 new HashMap<String, Integer>(); 120 private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>(); 121 private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>(); 122 static { 123 // Aliases for NIST P-224 124 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224); 125 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224); 126 127 128 // Aliases for NIST P-256 129 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256); 130 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256); 131 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256); 132 133 // Aliases for NIST P-384 134 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384); 135 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384); 136 137 // Aliases for NIST P-521 138 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521); 139 SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521); 140 141 SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet()); 142 Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES); 143 144 SUPPORTED_EC_NIST_CURVE_SIZES.addAll( 145 new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values())); 146 Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES); 147 } 148 149 private final int mOriginalKeymasterAlgorithm; 150 151 private KeyStore mKeyStore; 152 153 private KeyGenParameterSpec mSpec; 154 155 private String mEntryAlias; 156 private int mEntryUid; 157 private boolean mEncryptionAtRestRequired; 158 private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm; 159 private int mKeymasterAlgorithm = -1; 160 private int mKeySizeBits; 161 private SecureRandom mRng; 162 163 private int[] mKeymasterPurposes; 164 private int[] mKeymasterBlockModes; 165 private int[] mKeymasterEncryptionPaddings; 166 private int[] mKeymasterSignaturePaddings; 167 private int[] mKeymasterDigests; 168 169 private BigInteger mRSAPublicExponent; 170 171 protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) { 172 mOriginalKeymasterAlgorithm = keymasterAlgorithm; 173 } 174 175 @SuppressWarnings("deprecation") 176 @Override 177 public void initialize(int keysize, SecureRandom random) { 178 throw new IllegalArgumentException( 179 KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName() 180 + " required to initialize this KeyPairGenerator"); 181 } 182 183 @SuppressWarnings("deprecation") 184 @Override 185 public void initialize(AlgorithmParameterSpec params, SecureRandom random) 186 throws InvalidAlgorithmParameterException { 187 resetAll(); 188 189 boolean success = false; 190 try { 191 if (params == null) { 192 throw new InvalidAlgorithmParameterException( 193 "Must supply params of type " + KeyGenParameterSpec.class.getName() 194 + " or " + KeyPairGeneratorSpec.class.getName()); 195 } 196 197 KeyGenParameterSpec spec; 198 boolean encryptionAtRestRequired = false; 199 int keymasterAlgorithm = mOriginalKeymasterAlgorithm; 200 if (params instanceof KeyGenParameterSpec) { 201 spec = (KeyGenParameterSpec) params; 202 } else if (params instanceof KeyPairGeneratorSpec) { 203 // Legacy/deprecated spec 204 KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params; 205 try { 206 KeyGenParameterSpec.Builder specBuilder; 207 String specKeyAlgorithm = legacySpec.getKeyType(); 208 if (specKeyAlgorithm != null) { 209 // Spec overrides the generator's default key algorithm 210 try { 211 keymasterAlgorithm = 212 KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( 213 specKeyAlgorithm); 214 } catch (IllegalArgumentException e) { 215 throw new InvalidAlgorithmParameterException( 216 "Invalid key type in parameters", e); 217 } 218 } 219 switch (keymasterAlgorithm) { 220 case KeymasterDefs.KM_ALGORITHM_EC: 221 specBuilder = new KeyGenParameterSpec.Builder( 222 legacySpec.getKeystoreAlias(), 223 KeyProperties.PURPOSE_SIGN 224 | KeyProperties.PURPOSE_VERIFY); 225 // Authorized to be used with any digest (including no digest). 226 // MD5 was never offered for Android Keystore for ECDSA. 227 specBuilder.setDigests( 228 KeyProperties.DIGEST_NONE, 229 KeyProperties.DIGEST_SHA1, 230 KeyProperties.DIGEST_SHA224, 231 KeyProperties.DIGEST_SHA256, 232 KeyProperties.DIGEST_SHA384, 233 KeyProperties.DIGEST_SHA512); 234 break; 235 case KeymasterDefs.KM_ALGORITHM_RSA: 236 specBuilder = new KeyGenParameterSpec.Builder( 237 legacySpec.getKeystoreAlias(), 238 KeyProperties.PURPOSE_ENCRYPT 239 | KeyProperties.PURPOSE_DECRYPT 240 | KeyProperties.PURPOSE_SIGN 241 | KeyProperties.PURPOSE_VERIFY); 242 // Authorized to be used with any digest (including no digest). 243 specBuilder.setDigests( 244 KeyProperties.DIGEST_NONE, 245 KeyProperties.DIGEST_MD5, 246 KeyProperties.DIGEST_SHA1, 247 KeyProperties.DIGEST_SHA224, 248 KeyProperties.DIGEST_SHA256, 249 KeyProperties.DIGEST_SHA384, 250 KeyProperties.DIGEST_SHA512); 251 // Authorized to be used with any encryption and signature padding 252 // schemes (including no padding). 253 specBuilder.setEncryptionPaddings( 254 KeyProperties.ENCRYPTION_PADDING_NONE, 255 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, 256 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); 257 specBuilder.setSignaturePaddings( 258 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, 259 KeyProperties.SIGNATURE_PADDING_RSA_PSS); 260 // Disable randomized encryption requirement to support encryption 261 // padding NONE above. 262 specBuilder.setRandomizedEncryptionRequired(false); 263 break; 264 default: 265 throw new ProviderException( 266 "Unsupported algorithm: " + mKeymasterAlgorithm); 267 } 268 269 if (legacySpec.getKeySize() != -1) { 270 specBuilder.setKeySize(legacySpec.getKeySize()); 271 } 272 if (legacySpec.getAlgorithmParameterSpec() != null) { 273 specBuilder.setAlgorithmParameterSpec( 274 legacySpec.getAlgorithmParameterSpec()); 275 } 276 specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); 277 specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); 278 specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); 279 specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); 280 encryptionAtRestRequired = legacySpec.isEncryptionRequired(); 281 specBuilder.setUserAuthenticationRequired(false); 282 283 spec = specBuilder.build(); 284 } catch (NullPointerException | IllegalArgumentException e) { 285 throw new InvalidAlgorithmParameterException(e); 286 } 287 } else { 288 throw new InvalidAlgorithmParameterException( 289 "Unsupported params class: " + params.getClass().getName() 290 + ". Supported: " + KeyGenParameterSpec.class.getName() 291 + ", " + KeyPairGeneratorSpec.class.getName()); 292 } 293 294 mEntryAlias = spec.getKeystoreAlias(); 295 mEntryUid = spec.getUid(); 296 mSpec = spec; 297 mKeymasterAlgorithm = keymasterAlgorithm; 298 mEncryptionAtRestRequired = encryptionAtRestRequired; 299 mKeySizeBits = spec.getKeySize(); 300 initAlgorithmSpecificParameters(); 301 if (mKeySizeBits == -1) { 302 mKeySizeBits = getDefaultKeySize(keymasterAlgorithm); 303 } 304 checkValidKeySize(keymasterAlgorithm, mKeySizeBits); 305 306 if (spec.getKeystoreAlias() == null) { 307 throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided"); 308 } 309 310 String jcaKeyAlgorithm; 311 try { 312 jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm( 313 keymasterAlgorithm); 314 mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes()); 315 mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()); 316 mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster( 317 spec.getEncryptionPaddings()); 318 if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) 319 && (spec.isRandomizedEncryptionRequired())) { 320 for (int keymasterPadding : mKeymasterEncryptionPaddings) { 321 if (!KeymasterUtils 322 .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto( 323 keymasterPadding)) { 324 throw new InvalidAlgorithmParameterException( 325 "Randomized encryption (IND-CPA) required but may be violated" 326 + " by padding scheme: " 327 + KeyProperties.EncryptionPadding.fromKeymaster( 328 keymasterPadding) 329 + ". See " + KeyGenParameterSpec.class.getName() 330 + " documentation."); 331 } 332 } 333 } 334 mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster( 335 spec.getSignaturePaddings()); 336 if (spec.isDigestsSpecified()) { 337 mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests()); 338 } else { 339 mKeymasterDigests = EmptyArray.INT; 340 } 341 342 // Check that user authentication related parameters are acceptable. This method 343 // will throw an IllegalStateException if there are issues (e.g., secure lock screen 344 // not set up). 345 KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), 346 mSpec.isUserAuthenticationRequired(), 347 mSpec.getUserAuthenticationValidityDurationSeconds(), 348 mSpec.isUserAuthenticationValidWhileOnBody(), 349 mSpec.isInvalidatedByBiometricEnrollment()); 350 } catch (IllegalArgumentException | IllegalStateException e) { 351 throw new InvalidAlgorithmParameterException(e); 352 } 353 354 mJcaKeyAlgorithm = jcaKeyAlgorithm; 355 mRng = random; 356 mKeyStore = KeyStore.getInstance(); 357 success = true; 358 } finally { 359 if (!success) { 360 resetAll(); 361 } 362 } 363 } 364 365 private void resetAll() { 366 mEntryAlias = null; 367 mEntryUid = KeyStore.UID_SELF; 368 mJcaKeyAlgorithm = null; 369 mKeymasterAlgorithm = -1; 370 mKeymasterPurposes = null; 371 mKeymasterBlockModes = null; 372 mKeymasterEncryptionPaddings = null; 373 mKeymasterSignaturePaddings = null; 374 mKeymasterDigests = null; 375 mKeySizeBits = 0; 376 mSpec = null; 377 mRSAPublicExponent = null; 378 mEncryptionAtRestRequired = false; 379 mRng = null; 380 mKeyStore = null; 381 } 382 383 private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException { 384 AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec(); 385 switch (mKeymasterAlgorithm) { 386 case KeymasterDefs.KM_ALGORITHM_RSA: 387 { 388 BigInteger publicExponent = null; 389 if (algSpecificSpec instanceof RSAKeyGenParameterSpec) { 390 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec; 391 if (mKeySizeBits == -1) { 392 mKeySizeBits = rsaSpec.getKeysize(); 393 } else if (mKeySizeBits != rsaSpec.getKeysize()) { 394 throw new InvalidAlgorithmParameterException("RSA key size must match " 395 + " between " + mSpec + " and " + algSpecificSpec 396 + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize()); 397 } 398 publicExponent = rsaSpec.getPublicExponent(); 399 } else if (algSpecificSpec != null) { 400 throw new InvalidAlgorithmParameterException( 401 "RSA may only use RSAKeyGenParameterSpec"); 402 } 403 if (publicExponent == null) { 404 publicExponent = RSAKeyGenParameterSpec.F4; 405 } 406 if (publicExponent.compareTo(BigInteger.ZERO) < 1) { 407 throw new InvalidAlgorithmParameterException( 408 "RSA public exponent must be positive: " + publicExponent); 409 } 410 if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) { 411 throw new InvalidAlgorithmParameterException( 412 "Unsupported RSA public exponent: " + publicExponent 413 + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE); 414 } 415 mRSAPublicExponent = publicExponent; 416 break; 417 } 418 case KeymasterDefs.KM_ALGORITHM_EC: 419 if (algSpecificSpec instanceof ECGenParameterSpec) { 420 ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec; 421 String curveName = ecSpec.getName(); 422 Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get( 423 curveName.toLowerCase(Locale.US)); 424 if (ecSpecKeySizeBits == null) { 425 throw new InvalidAlgorithmParameterException( 426 "Unsupported EC curve name: " + curveName 427 + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES); 428 } 429 if (mKeySizeBits == -1) { 430 mKeySizeBits = ecSpecKeySizeBits; 431 } else if (mKeySizeBits != ecSpecKeySizeBits) { 432 throw new InvalidAlgorithmParameterException("EC key size must match " 433 + " between " + mSpec + " and " + algSpecificSpec 434 + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits); 435 } 436 } else if (algSpecificSpec != null) { 437 throw new InvalidAlgorithmParameterException( 438 "EC may only use ECGenParameterSpec"); 439 } 440 break; 441 default: 442 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 443 } 444 } 445 446 @Override 447 public KeyPair generateKeyPair() { 448 if (mKeyStore == null || mSpec == null) { 449 throw new IllegalStateException("Not initialized"); 450 } 451 452 final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0; 453 if (((flags & KeyStore.FLAG_ENCRYPTED) != 0) 454 && (mKeyStore.state() != KeyStore.State.UNLOCKED)) { 455 throw new IllegalStateException( 456 "Encryption at rest using secure lock screen credential requested for key pair" 457 + ", but the user has not yet entered the credential"); 458 } 459 460 byte[] additionalEntropy = 461 KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( 462 mRng, (mKeySizeBits + 7) / 8); 463 464 Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid); 465 final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias; 466 boolean success = false; 467 try { 468 generateKeystoreKeyPair( 469 privateKeyAlias, constructKeyGenerationArguments(), additionalEntropy, flags); 470 KeyPair keyPair = loadKeystoreKeyPair(privateKeyAlias); 471 472 storeCertificateChain(flags, createCertificateChain(privateKeyAlias, keyPair)); 473 474 success = true; 475 return keyPair; 476 } finally { 477 if (!success) { 478 Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid); 479 } 480 } 481 } 482 483 private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair) 484 throws ProviderException { 485 byte[] challenge = mSpec.getAttestationChallenge(); 486 if (challenge != null) { 487 KeymasterArguments args = new KeymasterArguments(); 488 args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge); 489 return getAttestationChain(privateKeyAlias, keyPair, args); 490 } 491 492 // Very short certificate chain in the non-attestation case. 493 return Collections.singleton(generateSelfSignedCertificateBytes(keyPair)); 494 } 495 496 private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args, 497 byte[] additionalEntropy, final int flags) throws ProviderException { 498 KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics(); 499 int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy, 500 mEntryUid, flags, resultingKeyCharacteristics); 501 if (errorCode != KeyStore.NO_ERROR) { 502 throw new ProviderException( 503 "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode)); 504 } 505 } 506 507 private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException { 508 try { 509 KeyPair result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore( 510 mKeyStore, privateKeyAlias, mEntryUid); 511 if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) { 512 throw new ProviderException( 513 "Generated key pair algorithm does not match requested algorithm: " 514 + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm); 515 } 516 return result; 517 } catch (UnrecoverableKeyException e) { 518 throw new ProviderException("Failed to load generated key pair from keystore", e); 519 } 520 } 521 522 private KeymasterArguments constructKeyGenerationArguments() { 523 KeymasterArguments args = new KeymasterArguments(); 524 args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits); 525 args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); 526 args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes); 527 args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes); 528 args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings); 529 args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings); 530 args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests); 531 532 KeymasterUtils.addUserAuthArgs(args, 533 mSpec.isUserAuthenticationRequired(), 534 mSpec.getUserAuthenticationValidityDurationSeconds(), 535 mSpec.isUserAuthenticationValidWhileOnBody(), 536 mSpec.isInvalidatedByBiometricEnrollment()); 537 args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart()); 538 args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, 539 mSpec.getKeyValidityForOriginationEnd()); 540 args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, 541 mSpec.getKeyValidityForConsumptionEnd()); 542 addAlgorithmSpecificParameters(args); 543 544 if (mSpec.isUniqueIdIncluded()) 545 args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID); 546 547 return args; 548 } 549 550 private void storeCertificateChain(final int flags, Iterable<byte[]> iterable) 551 throws ProviderException { 552 Iterator<byte[]> iter = iterable.iterator(); 553 storeCertificate( 554 Credentials.USER_CERTIFICATE, iter.next(), flags, "Failed to store certificate"); 555 556 if (!iter.hasNext()) { 557 return; 558 } 559 560 ByteArrayOutputStream certificateConcatenationStream = new ByteArrayOutputStream(); 561 while (iter.hasNext()) { 562 byte[] data = iter.next(); 563 certificateConcatenationStream.write(data, 0, data.length); 564 } 565 566 storeCertificate(Credentials.CA_CERTIFICATE, certificateConcatenationStream.toByteArray(), 567 flags, "Failed to store attestation CA certificate"); 568 } 569 570 private void storeCertificate(String prefix, byte[] certificateBytes, final int flags, 571 String failureMessage) throws ProviderException { 572 int insertErrorCode = mKeyStore.insert( 573 prefix + mEntryAlias, 574 certificateBytes, 575 mEntryUid, 576 flags); 577 if (insertErrorCode != KeyStore.NO_ERROR) { 578 throw new ProviderException(failureMessage, 579 KeyStore.getKeyStoreException(insertErrorCode)); 580 } 581 } 582 583 private byte[] generateSelfSignedCertificateBytes(KeyPair keyPair) throws ProviderException { 584 try { 585 return generateSelfSignedCertificate(keyPair.getPrivate(), keyPair.getPublic()) 586 .getEncoded(); 587 } catch (IOException | CertificateParsingException e) { 588 throw new ProviderException("Failed to generate self-signed certificate", e); 589 } catch (CertificateEncodingException e) { 590 throw new ProviderException( 591 "Failed to obtain encoded form of self-signed certificate", e); 592 } 593 } 594 595 private Iterable<byte[]> getAttestationChain(String privateKeyAlias, 596 KeyPair keyPair, KeymasterArguments args) 597 throws ProviderException { 598 KeymasterCertificateChain outChain = new KeymasterCertificateChain(); 599 int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain); 600 if (errorCode != KeyStore.NO_ERROR) { 601 throw new ProviderException("Failed to generate attestation certificate chain", 602 KeyStore.getKeyStoreException(errorCode)); 603 } 604 Collection<byte[]> chain = outChain.getCertificates(); 605 if (chain.size() < 2) { 606 throw new ProviderException("Attestation certificate chain contained " 607 + chain.size() + " entries. At least two are required."); 608 } 609 return chain; 610 } 611 612 private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) { 613 switch (mKeymasterAlgorithm) { 614 case KeymasterDefs.KM_ALGORITHM_RSA: 615 keymasterArgs.addUnsignedLong( 616 KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent); 617 break; 618 case KeymasterDefs.KM_ALGORITHM_EC: 619 break; 620 default: 621 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 622 } 623 } 624 625 private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey, 626 PublicKey publicKey) throws CertificateParsingException, IOException { 627 String signatureAlgorithm = 628 getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec); 629 if (signatureAlgorithm == null) { 630 // Key cannot be used to sign a certificate 631 return generateSelfSignedCertificateWithFakeSignature(publicKey); 632 } else { 633 // Key can be used to sign a certificate 634 try { 635 return generateSelfSignedCertificateWithValidSignature( 636 privateKey, publicKey, signatureAlgorithm); 637 } catch (Exception e) { 638 // Failed to generate the self-signed certificate with valid signature. Fall back 639 // to generating a self-signed certificate with a fake signature. This is done for 640 // all exception types because we prefer key pair generation to succeed and end up 641 // producing a self-signed certificate with an invalid signature to key pair 642 // generation failing. 643 return generateSelfSignedCertificateWithFakeSignature(publicKey); 644 } 645 } 646 } 647 648 @SuppressWarnings("deprecation") 649 private X509Certificate generateSelfSignedCertificateWithValidSignature( 650 PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception { 651 final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); 652 certGen.setPublicKey(publicKey); 653 certGen.setSerialNumber(mSpec.getCertificateSerialNumber()); 654 certGen.setSubjectDN(mSpec.getCertificateSubject()); 655 certGen.setIssuerDN(mSpec.getCertificateSubject()); 656 certGen.setNotBefore(mSpec.getCertificateNotBefore()); 657 certGen.setNotAfter(mSpec.getCertificateNotAfter()); 658 certGen.setSignatureAlgorithm(signatureAlgorithm); 659 return certGen.generate(privateKey); 660 } 661 662 @SuppressWarnings("deprecation") 663 private X509Certificate generateSelfSignedCertificateWithFakeSignature( 664 PublicKey publicKey) throws IOException, CertificateParsingException { 665 V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator(); 666 ASN1ObjectIdentifier sigAlgOid; 667 AlgorithmIdentifier sigAlgId; 668 byte[] signature; 669 switch (mKeymasterAlgorithm) { 670 case KeymasterDefs.KM_ALGORITHM_EC: 671 sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256; 672 sigAlgId = new AlgorithmIdentifier(sigAlgOid); 673 ASN1EncodableVector v = new ASN1EncodableVector(); 674 v.add(new DERInteger(0)); 675 v.add(new DERInteger(0)); 676 signature = new DERSequence().getEncoded(); 677 break; 678 case KeymasterDefs.KM_ALGORITHM_RSA: 679 sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption; 680 sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE); 681 signature = new byte[1]; 682 break; 683 default: 684 throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm); 685 } 686 687 try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) { 688 tbsGenerator.setSubjectPublicKeyInfo( 689 SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject())); 690 } 691 tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber())); 692 X509Principal subject = 693 new X509Principal(mSpec.getCertificateSubject().getEncoded()); 694 tbsGenerator.setSubject(subject); 695 tbsGenerator.setIssuer(subject); 696 tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore())); 697 tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter())); 698 tbsGenerator.setSignature(sigAlgId); 699 TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate(); 700 701 ASN1EncodableVector result = new ASN1EncodableVector(); 702 result.add(tbsCertificate); 703 result.add(sigAlgId); 704 result.add(new DERBitString(signature)); 705 return new X509CertificateObject(Certificate.getInstance(new DERSequence(result))); 706 } 707 708 private static int getDefaultKeySize(int keymasterAlgorithm) { 709 switch (keymasterAlgorithm) { 710 case KeymasterDefs.KM_ALGORITHM_EC: 711 return EC_DEFAULT_KEY_SIZE; 712 case KeymasterDefs.KM_ALGORITHM_RSA: 713 return RSA_DEFAULT_KEY_SIZE; 714 default: 715 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 716 } 717 } 718 719 private static void checkValidKeySize(int keymasterAlgorithm, int keySize) 720 throws InvalidAlgorithmParameterException { 721 switch (keymasterAlgorithm) { 722 case KeymasterDefs.KM_ALGORITHM_EC: 723 if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) { 724 throw new InvalidAlgorithmParameterException("Unsupported EC key size: " 725 + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES); 726 } 727 break; 728 case KeymasterDefs.KM_ALGORITHM_RSA: 729 if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { 730 throw new InvalidAlgorithmParameterException("RSA key size must be >= " 731 + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); 732 } 733 break; 734 default: 735 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 736 } 737 } 738 739 /** 740 * Returns the {@code Signature} algorithm to be used for signing a certificate using the 741 * specified key or {@code null} if the key cannot be used for signing a certificate. 742 */ 743 @Nullable 744 private static String getCertificateSignatureAlgorithm( 745 int keymasterAlgorithm, 746 int keySizeBits, 747 KeyGenParameterSpec spec) { 748 // Constraints: 749 // 1. Key must be authorized for signing without user authentication. 750 // 2. Signature digest must be one of key's authorized digests. 751 // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead 752 // of RSA PKCS#1 signature padding scheme (about 30 bytes). 753 // 4. For EC keys, the there is no point in using a digest whose output size is longer than 754 // key/field size because the digest will be truncated to that size. 755 756 if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) { 757 // Key not authorized for signing 758 return null; 759 } 760 if (spec.isUserAuthenticationRequired()) { 761 // Key not authorized for use without user authentication 762 return null; 763 } 764 if (!spec.isDigestsSpecified()) { 765 // Key not authorized for any digests -- can't sign 766 return null; 767 } 768 switch (keymasterAlgorithm) { 769 case KeymasterDefs.KM_ALGORITHM_EC: 770 { 771 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 772 spec.getDigests(), 773 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 774 775 int bestKeymasterDigest = -1; 776 int bestDigestOutputSizeBits = -1; 777 for (int keymasterDigest : availableKeymasterDigests) { 778 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 779 if (outputSizeBits == keySizeBits) { 780 // Perfect match -- use this digest 781 bestKeymasterDigest = keymasterDigest; 782 bestDigestOutputSizeBits = outputSizeBits; 783 break; 784 } 785 // Not a perfect match -- check against the best digest so far 786 if (bestKeymasterDigest == -1) { 787 // First digest tested -- definitely the best so far 788 bestKeymasterDigest = keymasterDigest; 789 bestDigestOutputSizeBits = outputSizeBits; 790 } else { 791 // Prefer output size to be as close to key size as possible, with output 792 // sizes larger than key size preferred to those smaller than key size. 793 if (bestDigestOutputSizeBits < keySizeBits) { 794 // Output size of the best digest so far is smaller than key size. 795 // Anything larger is a win. 796 if (outputSizeBits > bestDigestOutputSizeBits) { 797 bestKeymasterDigest = keymasterDigest; 798 bestDigestOutputSizeBits = outputSizeBits; 799 } 800 } else { 801 // Output size of the best digest so far is larger than key size. 802 // Anything smaller is a win, as long as it's not smaller than key size. 803 if ((outputSizeBits < bestDigestOutputSizeBits) 804 && (outputSizeBits >= keySizeBits)) { 805 bestKeymasterDigest = keymasterDigest; 806 bestDigestOutputSizeBits = outputSizeBits; 807 } 808 } 809 } 810 } 811 if (bestKeymasterDigest == -1) { 812 return null; 813 } 814 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 815 bestKeymasterDigest) + "WithECDSA"; 816 } 817 case KeymasterDefs.KM_ALGORITHM_RSA: 818 { 819 // Check whether this key is authorized for PKCS#1 signature padding. 820 // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle 821 // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs 822 // to be authorized for PKCS#1 padding or padding NONE which means any padding. 823 boolean pkcs1SignaturePaddingSupported = 824 com.android.internal.util.ArrayUtils.contains( 825 KeyProperties.SignaturePadding.allToKeymaster( 826 spec.getSignaturePaddings()), 827 KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); 828 if (!pkcs1SignaturePaddingSupported) { 829 // Key not authorized for PKCS#1 signature padding -- can't sign 830 return null; 831 } 832 833 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 834 spec.getDigests(), 835 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 836 837 // The amount of space available for the digest is less than modulus size by about 838 // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00, 839 // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes 840 // overhead (depending the on chosen digest) for encoding digest OID and digest 841 // value in DER. 842 int maxDigestOutputSizeBits = keySizeBits - 30 * 8; 843 int bestKeymasterDigest = -1; 844 int bestDigestOutputSizeBits = -1; 845 for (int keymasterDigest : availableKeymasterDigests) { 846 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 847 if (outputSizeBits > maxDigestOutputSizeBits) { 848 // Digest too long (signature generation will fail) -- skip 849 continue; 850 } 851 if (bestKeymasterDigest == -1) { 852 // First digest tested -- definitely the best so far 853 bestKeymasterDigest = keymasterDigest; 854 bestDigestOutputSizeBits = outputSizeBits; 855 } else { 856 // The longer the better 857 if (outputSizeBits > bestDigestOutputSizeBits) { 858 bestKeymasterDigest = keymasterDigest; 859 bestDigestOutputSizeBits = outputSizeBits; 860 } 861 } 862 } 863 if (bestKeymasterDigest == -1) { 864 return null; 865 } 866 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 867 bestKeymasterDigest) + "WithRSA"; 868 } 869 default: 870 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 871 } 872 } 873 874 private static Set<Integer> getAvailableKeymasterSignatureDigests( 875 @KeyProperties.DigestEnum String[] authorizedKeyDigests, 876 @KeyProperties.DigestEnum String[] supportedSignatureDigests) { 877 Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>(); 878 for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) { 879 authorizedKeymasterKeyDigests.add(keymasterDigest); 880 } 881 Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>(); 882 for (int keymasterDigest 883 : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) { 884 supportedKeymasterSignatureDigests.add(keymasterDigest); 885 } 886 Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests); 887 result.retainAll(authorizedKeymasterKeyDigests); 888 return result; 889 } 890} 891