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