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