AndroidKeyStoreKeyPairGeneratorSpi.java revision adef49640d6339e6b4a6ad736c5815e35d9b8803
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 } catch (IllegalArgumentException | IllegalStateException e) { 350 throw new InvalidAlgorithmParameterException(e); 351 } 352 353 mJcaKeyAlgorithm = jcaKeyAlgorithm; 354 mRng = random; 355 mKeyStore = KeyStore.getInstance(); 356 success = true; 357 } finally { 358 if (!success) { 359 resetAll(); 360 } 361 } 362 } 363 364 private void resetAll() { 365 mEntryAlias = null; 366 mEntryUid = KeyStore.UID_SELF; 367 mJcaKeyAlgorithm = null; 368 mKeymasterAlgorithm = -1; 369 mKeymasterPurposes = null; 370 mKeymasterBlockModes = null; 371 mKeymasterEncryptionPaddings = null; 372 mKeymasterSignaturePaddings = null; 373 mKeymasterDigests = null; 374 mKeySizeBits = 0; 375 mSpec = null; 376 mRSAPublicExponent = null; 377 mEncryptionAtRestRequired = false; 378 mRng = null; 379 mKeyStore = null; 380 } 381 382 private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException { 383 AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec(); 384 switch (mKeymasterAlgorithm) { 385 case KeymasterDefs.KM_ALGORITHM_RSA: 386 { 387 BigInteger publicExponent = null; 388 if (algSpecificSpec instanceof RSAKeyGenParameterSpec) { 389 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec; 390 if (mKeySizeBits == -1) { 391 mKeySizeBits = rsaSpec.getKeysize(); 392 } else if (mKeySizeBits != rsaSpec.getKeysize()) { 393 throw new InvalidAlgorithmParameterException("RSA key size must match " 394 + " between " + mSpec + " and " + algSpecificSpec 395 + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize()); 396 } 397 publicExponent = rsaSpec.getPublicExponent(); 398 } else if (algSpecificSpec != null) { 399 throw new InvalidAlgorithmParameterException( 400 "RSA may only use RSAKeyGenParameterSpec"); 401 } 402 if (publicExponent == null) { 403 publicExponent = RSAKeyGenParameterSpec.F4; 404 } 405 if (publicExponent.compareTo(BigInteger.ZERO) < 1) { 406 throw new InvalidAlgorithmParameterException( 407 "RSA public exponent must be positive: " + publicExponent); 408 } 409 if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) { 410 throw new InvalidAlgorithmParameterException( 411 "Unsupported RSA public exponent: " + publicExponent 412 + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE); 413 } 414 mRSAPublicExponent = publicExponent; 415 break; 416 } 417 case KeymasterDefs.KM_ALGORITHM_EC: 418 if (algSpecificSpec instanceof ECGenParameterSpec) { 419 ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec; 420 String curveName = ecSpec.getName(); 421 Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get( 422 curveName.toLowerCase(Locale.US)); 423 if (ecSpecKeySizeBits == null) { 424 throw new InvalidAlgorithmParameterException( 425 "Unsupported EC curve name: " + curveName 426 + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES); 427 } 428 if (mKeySizeBits == -1) { 429 mKeySizeBits = ecSpecKeySizeBits; 430 } else if (mKeySizeBits != ecSpecKeySizeBits) { 431 throw new InvalidAlgorithmParameterException("EC key size must match " 432 + " between " + mSpec + " and " + algSpecificSpec 433 + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits); 434 } 435 } else if (algSpecificSpec != null) { 436 throw new InvalidAlgorithmParameterException( 437 "EC may only use ECGenParameterSpec"); 438 } 439 break; 440 default: 441 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 442 } 443 } 444 445 @Override 446 public KeyPair generateKeyPair() { 447 if (mKeyStore == null || mSpec == null) { 448 throw new IllegalStateException("Not initialized"); 449 } 450 451 final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0; 452 if (((flags & KeyStore.FLAG_ENCRYPTED) != 0) 453 && (mKeyStore.state() != KeyStore.State.UNLOCKED)) { 454 throw new IllegalStateException( 455 "Encryption at rest using secure lock screen credential requested for key pair" 456 + ", but the user has not yet entered the credential"); 457 } 458 459 byte[] additionalEntropy = 460 KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( 461 mRng, (mKeySizeBits + 7) / 8); 462 463 Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid); 464 final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias; 465 boolean success = false; 466 try { 467 generateKeystoreKeyPair( 468 privateKeyAlias, constructKeyGenerationArguments(), additionalEntropy, flags); 469 KeyPair keyPair = loadKeystoreKeyPair(privateKeyAlias); 470 471 storeCertificateChain(flags, createCertificateChain(privateKeyAlias, keyPair)); 472 473 success = true; 474 return keyPair; 475 } finally { 476 if (!success) { 477 Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid); 478 } 479 } 480 } 481 482 private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair) 483 throws ProviderException { 484 byte[] challenge = mSpec.getAttestationChallenge(); 485 if (challenge != null) { 486 KeymasterArguments args = new KeymasterArguments(); 487 args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge); 488 return getAttestationChain(privateKeyAlias, keyPair, args); 489 } 490 491 // Very short certificate chain in the non-attestation case. 492 return Collections.singleton(generateSelfSignedCertificateBytes(keyPair)); 493 } 494 495 private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args, 496 byte[] additionalEntropy, final int flags) throws ProviderException { 497 KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics(); 498 int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy, 499 mEntryUid, flags, resultingKeyCharacteristics); 500 if (errorCode != KeyStore.NO_ERROR) { 501 throw new ProviderException( 502 "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode)); 503 } 504 } 505 506 private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException { 507 try { 508 KeyPair result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore( 509 mKeyStore, privateKeyAlias, mEntryUid); 510 if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) { 511 throw new ProviderException( 512 "Generated key pair algorithm does not match requested algorithm: " 513 + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm); 514 } 515 return result; 516 } catch (UnrecoverableKeyException e) { 517 throw new ProviderException("Failed to load generated key pair from keystore", e); 518 } 519 } 520 521 private KeymasterArguments constructKeyGenerationArguments() { 522 KeymasterArguments args = new KeymasterArguments(); 523 args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits); 524 args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); 525 args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes); 526 args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes); 527 args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings); 528 args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings); 529 args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests); 530 531 KeymasterUtils.addUserAuthArgs(args, 532 mSpec.isUserAuthenticationRequired(), 533 mSpec.getUserAuthenticationValidityDurationSeconds(), 534 mSpec.isUserAuthenticationValidWhileOnBody()); 535 args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart()); 536 args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, 537 mSpec.getKeyValidityForOriginationEnd()); 538 args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, 539 mSpec.getKeyValidityForConsumptionEnd()); 540 addAlgorithmSpecificParameters(args); 541 542 if (mSpec.isUniqueIdIncluded()) 543 args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID); 544 545 return args; 546 } 547 548 private void storeCertificateChain(final int flags, Iterable<byte[]> iterable) 549 throws ProviderException { 550 Iterator<byte[]> iter = iterable.iterator(); 551 storeCertificate( 552 Credentials.USER_CERTIFICATE, iter.next(), flags, "Failed to store certificate"); 553 554 if (!iter.hasNext()) { 555 return; 556 } 557 558 ByteArrayOutputStream certificateConcatenationStream = new ByteArrayOutputStream(); 559 while (iter.hasNext()) { 560 byte[] data = iter.next(); 561 certificateConcatenationStream.write(data, 0, data.length); 562 } 563 564 storeCertificate(Credentials.CA_CERTIFICATE, certificateConcatenationStream.toByteArray(), 565 flags, "Failed to store attestation CA certificate"); 566 } 567 568 private void storeCertificate(String prefix, byte[] certificateBytes, final int flags, 569 String failureMessage) throws ProviderException { 570 int insertErrorCode = mKeyStore.insert( 571 prefix + mEntryAlias, 572 certificateBytes, 573 mEntryUid, 574 flags); 575 if (insertErrorCode != KeyStore.NO_ERROR) { 576 throw new ProviderException(failureMessage, 577 KeyStore.getKeyStoreException(insertErrorCode)); 578 } 579 } 580 581 private byte[] generateSelfSignedCertificateBytes(KeyPair keyPair) throws ProviderException { 582 try { 583 return generateSelfSignedCertificate(keyPair.getPrivate(), keyPair.getPublic()) 584 .getEncoded(); 585 } catch (IOException | CertificateParsingException e) { 586 throw new ProviderException("Failed to generate self-signed certificate", e); 587 } catch (CertificateEncodingException e) { 588 throw new ProviderException( 589 "Failed to obtain encoded form of self-signed certificate", e); 590 } 591 } 592 593 private Iterable<byte[]> getAttestationChain(String privateKeyAlias, 594 KeyPair keyPair, KeymasterArguments args) 595 throws ProviderException { 596 KeymasterCertificateChain outChain = new KeymasterCertificateChain(); 597 int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain); 598 if (errorCode != KeyStore.NO_ERROR) { 599 throw new ProviderException("Failed to generate attestation certificate chain", 600 KeyStore.getKeyStoreException(errorCode)); 601 } 602 Collection<byte[]> chain = outChain.getCertificates(); 603 if (chain.size() < 2) { 604 throw new ProviderException("Attestation certificate chain contained " 605 + chain.size() + " entries. At least two are required."); 606 } 607 return chain; 608 } 609 610 private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) { 611 switch (mKeymasterAlgorithm) { 612 case KeymasterDefs.KM_ALGORITHM_RSA: 613 keymasterArgs.addUnsignedLong( 614 KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent); 615 break; 616 case KeymasterDefs.KM_ALGORITHM_EC: 617 break; 618 default: 619 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 620 } 621 } 622 623 private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey, 624 PublicKey publicKey) throws CertificateParsingException, IOException { 625 String signatureAlgorithm = 626 getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec); 627 if (signatureAlgorithm == null) { 628 // Key cannot be used to sign a certificate 629 return generateSelfSignedCertificateWithFakeSignature(publicKey); 630 } else { 631 // Key can be used to sign a certificate 632 try { 633 return generateSelfSignedCertificateWithValidSignature( 634 privateKey, publicKey, signatureAlgorithm); 635 } catch (Exception e) { 636 // Failed to generate the self-signed certificate with valid signature. Fall back 637 // to generating a self-signed certificate with a fake signature. This is done for 638 // all exception types because we prefer key pair generation to succeed and end up 639 // producing a self-signed certificate with an invalid signature to key pair 640 // generation failing. 641 return generateSelfSignedCertificateWithFakeSignature(publicKey); 642 } 643 } 644 } 645 646 @SuppressWarnings("deprecation") 647 private X509Certificate generateSelfSignedCertificateWithValidSignature( 648 PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception { 649 final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); 650 certGen.setPublicKey(publicKey); 651 certGen.setSerialNumber(mSpec.getCertificateSerialNumber()); 652 certGen.setSubjectDN(mSpec.getCertificateSubject()); 653 certGen.setIssuerDN(mSpec.getCertificateSubject()); 654 certGen.setNotBefore(mSpec.getCertificateNotBefore()); 655 certGen.setNotAfter(mSpec.getCertificateNotAfter()); 656 certGen.setSignatureAlgorithm(signatureAlgorithm); 657 return certGen.generate(privateKey); 658 } 659 660 @SuppressWarnings("deprecation") 661 private X509Certificate generateSelfSignedCertificateWithFakeSignature( 662 PublicKey publicKey) throws IOException, CertificateParsingException { 663 V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator(); 664 ASN1ObjectIdentifier sigAlgOid; 665 AlgorithmIdentifier sigAlgId; 666 byte[] signature; 667 switch (mKeymasterAlgorithm) { 668 case KeymasterDefs.KM_ALGORITHM_EC: 669 sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256; 670 sigAlgId = new AlgorithmIdentifier(sigAlgOid); 671 ASN1EncodableVector v = new ASN1EncodableVector(); 672 v.add(new DERInteger(0)); 673 v.add(new DERInteger(0)); 674 signature = new DERSequence().getEncoded(); 675 break; 676 case KeymasterDefs.KM_ALGORITHM_RSA: 677 sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption; 678 sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE); 679 signature = new byte[1]; 680 break; 681 default: 682 throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm); 683 } 684 685 try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) { 686 tbsGenerator.setSubjectPublicKeyInfo( 687 SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject())); 688 } 689 tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber())); 690 X509Principal subject = 691 new X509Principal(mSpec.getCertificateSubject().getEncoded()); 692 tbsGenerator.setSubject(subject); 693 tbsGenerator.setIssuer(subject); 694 tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore())); 695 tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter())); 696 tbsGenerator.setSignature(sigAlgId); 697 TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate(); 698 699 ASN1EncodableVector result = new ASN1EncodableVector(); 700 result.add(tbsCertificate); 701 result.add(sigAlgId); 702 result.add(new DERBitString(signature)); 703 return new X509CertificateObject(Certificate.getInstance(new DERSequence(result))); 704 } 705 706 private static int getDefaultKeySize(int keymasterAlgorithm) { 707 switch (keymasterAlgorithm) { 708 case KeymasterDefs.KM_ALGORITHM_EC: 709 return EC_DEFAULT_KEY_SIZE; 710 case KeymasterDefs.KM_ALGORITHM_RSA: 711 return RSA_DEFAULT_KEY_SIZE; 712 default: 713 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 714 } 715 } 716 717 private static void checkValidKeySize(int keymasterAlgorithm, int keySize) 718 throws InvalidAlgorithmParameterException { 719 switch (keymasterAlgorithm) { 720 case KeymasterDefs.KM_ALGORITHM_EC: 721 if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) { 722 throw new InvalidAlgorithmParameterException("Unsupported EC key size: " 723 + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES); 724 } 725 break; 726 case KeymasterDefs.KM_ALGORITHM_RSA: 727 if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { 728 throw new InvalidAlgorithmParameterException("RSA key size must be >= " 729 + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); 730 } 731 break; 732 default: 733 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 734 } 735 } 736 737 /** 738 * Returns the {@code Signature} algorithm to be used for signing a certificate using the 739 * specified key or {@code null} if the key cannot be used for signing a certificate. 740 */ 741 @Nullable 742 private static String getCertificateSignatureAlgorithm( 743 int keymasterAlgorithm, 744 int keySizeBits, 745 KeyGenParameterSpec spec) { 746 // Constraints: 747 // 1. Key must be authorized for signing without user authentication. 748 // 2. Signature digest must be one of key's authorized digests. 749 // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead 750 // of RSA PKCS#1 signature padding scheme (about 30 bytes). 751 // 4. For EC keys, the there is no point in using a digest whose output size is longer than 752 // key/field size because the digest will be truncated to that size. 753 754 if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) { 755 // Key not authorized for signing 756 return null; 757 } 758 if (spec.isUserAuthenticationRequired()) { 759 // Key not authorized for use without user authentication 760 return null; 761 } 762 if (!spec.isDigestsSpecified()) { 763 // Key not authorized for any digests -- can't sign 764 return null; 765 } 766 switch (keymasterAlgorithm) { 767 case KeymasterDefs.KM_ALGORITHM_EC: 768 { 769 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 770 spec.getDigests(), 771 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 772 773 int bestKeymasterDigest = -1; 774 int bestDigestOutputSizeBits = -1; 775 for (int keymasterDigest : availableKeymasterDigests) { 776 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 777 if (outputSizeBits == keySizeBits) { 778 // Perfect match -- use this digest 779 bestKeymasterDigest = keymasterDigest; 780 bestDigestOutputSizeBits = outputSizeBits; 781 break; 782 } 783 // Not a perfect match -- check against the best digest so far 784 if (bestKeymasterDigest == -1) { 785 // First digest tested -- definitely the best so far 786 bestKeymasterDigest = keymasterDigest; 787 bestDigestOutputSizeBits = outputSizeBits; 788 } else { 789 // Prefer output size to be as close to key size as possible, with output 790 // sizes larger than key size preferred to those smaller than key size. 791 if (bestDigestOutputSizeBits < keySizeBits) { 792 // Output size of the best digest so far is smaller than key size. 793 // Anything larger is a win. 794 if (outputSizeBits > bestDigestOutputSizeBits) { 795 bestKeymasterDigest = keymasterDigest; 796 bestDigestOutputSizeBits = outputSizeBits; 797 } 798 } else { 799 // Output size of the best digest so far is larger than key size. 800 // Anything smaller is a win, as long as it's not smaller than key size. 801 if ((outputSizeBits < bestDigestOutputSizeBits) 802 && (outputSizeBits >= keySizeBits)) { 803 bestKeymasterDigest = keymasterDigest; 804 bestDigestOutputSizeBits = outputSizeBits; 805 } 806 } 807 } 808 } 809 if (bestKeymasterDigest == -1) { 810 return null; 811 } 812 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 813 bestKeymasterDigest) + "WithECDSA"; 814 } 815 case KeymasterDefs.KM_ALGORITHM_RSA: 816 { 817 // Check whether this key is authorized for PKCS#1 signature padding. 818 // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle 819 // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs 820 // to be authorized for PKCS#1 padding or padding NONE which means any padding. 821 boolean pkcs1SignaturePaddingSupported = 822 com.android.internal.util.ArrayUtils.contains( 823 KeyProperties.SignaturePadding.allToKeymaster( 824 spec.getSignaturePaddings()), 825 KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); 826 if (!pkcs1SignaturePaddingSupported) { 827 // Key not authorized for PKCS#1 signature padding -- can't sign 828 return null; 829 } 830 831 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 832 spec.getDigests(), 833 AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 834 835 // The amount of space available for the digest is less than modulus size by about 836 // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00, 837 // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes 838 // overhead (depending the on chosen digest) for encoding digest OID and digest 839 // value in DER. 840 int maxDigestOutputSizeBits = keySizeBits - 30 * 8; 841 int bestKeymasterDigest = -1; 842 int bestDigestOutputSizeBits = -1; 843 for (int keymasterDigest : availableKeymasterDigests) { 844 int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 845 if (outputSizeBits > maxDigestOutputSizeBits) { 846 // Digest too long (signature generation will fail) -- skip 847 continue; 848 } 849 if (bestKeymasterDigest == -1) { 850 // First digest tested -- definitely the best so far 851 bestKeymasterDigest = keymasterDigest; 852 bestDigestOutputSizeBits = outputSizeBits; 853 } else { 854 // The longer the better 855 if (outputSizeBits > bestDigestOutputSizeBits) { 856 bestKeymasterDigest = keymasterDigest; 857 bestDigestOutputSizeBits = outputSizeBits; 858 } 859 } 860 } 861 if (bestKeymasterDigest == -1) { 862 return null; 863 } 864 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 865 bestKeymasterDigest) + "WithRSA"; 866 } 867 default: 868 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 869 } 870 } 871 872 private static Set<Integer> getAvailableKeymasterSignatureDigests( 873 @KeyProperties.DigestEnum String[] authorizedKeyDigests, 874 @KeyProperties.DigestEnum String[] supportedSignatureDigests) { 875 Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>(); 876 for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) { 877 authorizedKeymasterKeyDigests.add(keymasterDigest); 878 } 879 Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>(); 880 for (int keymasterDigest 881 : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) { 882 supportedKeymasterSignatureDigests.add(keymasterDigest); 883 } 884 Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests); 885 result.retainAll(authorizedKeymasterKeyDigests); 886 return result; 887 } 888} 889