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