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