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