1/* 2 * Copyright (C) 2010 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 libcore.java.security; 18 19import com.android.org.bouncycastle.asn1.DEROctetString; 20import com.android.org.bouncycastle.asn1.x509.BasicConstraints; 21import com.android.org.bouncycastle.asn1.x509.CRLReason; 22import com.android.org.bouncycastle.asn1.x509.ExtendedKeyUsage; 23import com.android.org.bouncycastle.asn1.x509.GeneralName; 24import com.android.org.bouncycastle.asn1.x509.GeneralNames; 25import com.android.org.bouncycastle.asn1.x509.GeneralSubtree; 26import com.android.org.bouncycastle.asn1.x509.KeyPurposeId; 27import com.android.org.bouncycastle.asn1.x509.KeyUsage; 28import com.android.org.bouncycastle.asn1.x509.NameConstraints; 29import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 30import com.android.org.bouncycastle.asn1.x509.X509Extensions; 31import com.android.org.bouncycastle.cert.X509CertificateHolder; 32import com.android.org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; 33import com.android.org.bouncycastle.cert.ocsp.BasicOCSPResp; 34import com.android.org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder; 35import com.android.org.bouncycastle.cert.ocsp.CertificateID; 36import com.android.org.bouncycastle.cert.ocsp.CertificateStatus; 37import com.android.org.bouncycastle.cert.ocsp.OCSPException; 38import com.android.org.bouncycastle.cert.ocsp.OCSPResp; 39import com.android.org.bouncycastle.cert.ocsp.OCSPRespBuilder; 40import com.android.org.bouncycastle.cert.ocsp.RevokedStatus; 41import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider; 42import com.android.org.bouncycastle.operator.DigestCalculatorProvider; 43import com.android.org.bouncycastle.operator.OperatorCreationException; 44import com.android.org.bouncycastle.operator.bc.BcDigestCalculatorProvider; 45import com.android.org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 46import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; 47import java.io.ByteArrayInputStream; 48import java.io.IOException; 49import java.io.PrintStream; 50import java.math.BigInteger; 51import java.security.KeyPair; 52import java.security.KeyPairGenerator; 53import java.security.KeyStore; 54import java.security.KeyStore.PasswordProtection; 55import java.security.KeyStore.PrivateKeyEntry; 56import java.security.KeyStore.TrustedCertificateEntry; 57import java.security.KeyStoreException; 58import java.security.NoSuchAlgorithmException; 59import java.security.Principal; 60import java.security.PrivateKey; 61import java.security.PublicKey; 62import java.security.SecureRandom; 63import java.security.Security; 64import java.security.UnrecoverableEntryException; 65import java.security.UnrecoverableKeyException; 66import java.security.cert.Certificate; 67import java.security.cert.CertificateEncodingException; 68import java.security.cert.CertificateException; 69import java.security.cert.CertificateFactory; 70import java.security.cert.X509Certificate; 71import java.security.spec.AlgorithmParameterSpec; 72import java.util.ArrayList; 73import java.util.Collections; 74import java.util.Date; 75import java.util.List; 76import javax.crypto.spec.DHParameterSpec; 77import javax.net.ssl.KeyManager; 78import javax.net.ssl.KeyManagerFactory; 79import javax.net.ssl.TrustManager; 80import javax.net.ssl.TrustManagerFactory; 81import javax.security.auth.x500.X500Principal; 82import junit.framework.Assert; 83import libcore.javax.net.ssl.TestKeyManager; 84import libcore.javax.net.ssl.TestTrustManager; 85 86/** 87 * TestKeyStore is a convenience class for other tests that 88 * want a canned KeyStore with a variety of key pairs. 89 * 90 * Creating a key store is relatively slow, so a singleton instance is 91 * accessible via TestKeyStore.get(). 92 */ 93public final class TestKeyStore extends Assert { 94 /** Size of DSA keys to generate for testing. */ 95 private static final int DSA_KEY_SIZE_BITS = 1024; 96 97 /** Size of EC keys to generate for testing. */ 98 private static final int EC_KEY_SIZE_BITS = 256; 99 100 /** Size of RSA keys to generate for testing. */ 101 private static final int RSA_KEY_SIZE_BITS = 1024; 102 103 // Generated with: openssl dhparam -C 1024 104 private static final BigInteger DH_PARAMS_P = new BigInteger(1, new byte[] { 105 (byte) 0xA2, (byte) 0x31, (byte) 0xB4, (byte) 0xB3, (byte) 0x6D, (byte) 0x9B, 106 (byte) 0x7E, (byte) 0xF4, (byte) 0xE7, (byte) 0x21, (byte) 0x51, (byte) 0x40, 107 (byte) 0xEB, (byte) 0xC6, (byte) 0xB6, (byte) 0xD6, (byte) 0x54, (byte) 0x56, 108 (byte) 0x72, (byte) 0xBE, (byte) 0x43, (byte) 0x18, (byte) 0x30, (byte) 0x5C, 109 (byte) 0x15, (byte) 0x5A, (byte) 0xF9, (byte) 0x19, (byte) 0x62, (byte) 0xAD, 110 (byte) 0xF4, (byte) 0x29, (byte) 0xCB, (byte) 0xC6, (byte) 0xF6, (byte) 0x64, 111 (byte) 0x0B, (byte) 0x9D, (byte) 0x23, (byte) 0x80, (byte) 0xF9, (byte) 0x5B, 112 (byte) 0x1C, (byte) 0x1C, (byte) 0x6A, (byte) 0xB4, (byte) 0xEA, (byte) 0xB9, 113 (byte) 0x80, (byte) 0x98, (byte) 0x8B, (byte) 0xAF, (byte) 0x15, (byte) 0xA8, 114 (byte) 0x5C, (byte) 0xC4, (byte) 0xB0, (byte) 0x41, (byte) 0x29, (byte) 0x66, 115 (byte) 0x9F, (byte) 0x9F, (byte) 0x1F, (byte) 0x88, (byte) 0x50, (byte) 0x97, 116 (byte) 0x38, (byte) 0x0B, (byte) 0x01, (byte) 0x16, (byte) 0xD6, (byte) 0x84, 117 (byte) 0x1D, (byte) 0x48, (byte) 0x6F, (byte) 0x7C, (byte) 0x06, (byte) 0x8C, 118 (byte) 0x6E, (byte) 0x68, (byte) 0xCD, (byte) 0x38, (byte) 0xE6, (byte) 0x22, 119 (byte) 0x30, (byte) 0x61, (byte) 0x37, (byte) 0x02, (byte) 0x3D, (byte) 0x47, 120 (byte) 0x62, (byte) 0xCE, (byte) 0xB9, (byte) 0x1A, (byte) 0x69, (byte) 0x9D, 121 (byte) 0xA1, (byte) 0x9F, (byte) 0x10, (byte) 0xA1, (byte) 0xAA, (byte) 0x70, 122 (byte) 0xF7, (byte) 0x27, (byte) 0x9C, (byte) 0xD4, (byte) 0xA5, (byte) 0x15, 123 (byte) 0xE2, (byte) 0x15, (byte) 0x0C, (byte) 0x20, (byte) 0x90, (byte) 0x08, 124 (byte) 0xB6, (byte) 0xF5, (byte) 0xDF, (byte) 0x1C, (byte) 0xCB, (byte) 0x82, 125 (byte) 0x6D, (byte) 0xC0, (byte) 0xE1, (byte) 0xBD, (byte) 0xCC, (byte) 0x4A, 126 (byte) 0x76, (byte) 0xE3, 127 }); 128 129 // generator of 2 130 private static final BigInteger DH_PARAMS_G = BigInteger.valueOf(2); 131 132 private static TestKeyStore ROOT_CA; 133 private static TestKeyStore INTERMEDIATE_CA; 134 private static TestKeyStore INTERMEDIATE_CA_2; 135 136 private static TestKeyStore SERVER; 137 private static TestKeyStore CLIENT; 138 private static TestKeyStore CLIENT_CERTIFICATE; 139 140 private static TestKeyStore CLIENT_2; 141 142 static { 143 if (StandardNames.IS_RI) { 144 // Needed to create BKS keystore but add at end so most 145 // algorithm come from the default providers 146 Security.insertProviderAt(new BouncyCastleProvider(), 147 Security.getProviders().length+1); 148 } 149 } 150 151 private static final boolean TEST_MANAGERS = true; 152 private static final byte[] LOCAL_HOST_ADDRESS = { 127, 0, 0, 1 }; 153 private static final String LOCAL_HOST_NAME = "localhost"; 154 155 156 public final KeyStore keyStore; 157 public final char[] storePassword; 158 public final char[] keyPassword; 159 public final KeyManager[] keyManagers; 160 public final TrustManager[] trustManagers; 161 public final TestTrustManager trustManager; 162 163 private TestKeyStore(KeyStore keyStore, char[] storePassword, char[] keyPassword) { 164 this.keyStore = keyStore; 165 this.storePassword = storePassword; 166 this.keyPassword = keyPassword; 167 this.keyManagers = createKeyManagers(keyStore, storePassword); 168 this.trustManagers = createTrustManagers(keyStore); 169 this.trustManager = (TestTrustManager)trustManagers[0]; 170 } 171 172 public static KeyManager[] createKeyManagers(KeyStore keyStore, char[] storePassword) { 173 try { 174 String kmfa = KeyManagerFactory.getDefaultAlgorithm(); 175 KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa); 176 kmf.init(keyStore, storePassword); 177 return TestKeyManager.wrap(kmf.getKeyManagers()); 178 } catch (Exception e) { 179 throw new RuntimeException(e); 180 } 181 } 182 183 public static TrustManager[] createTrustManagers(final KeyStore keyStore) { 184 try { 185 String tmfa = TrustManagerFactory.getDefaultAlgorithm(); 186 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); 187 tmf.init(keyStore); 188 return TestTrustManager.wrap(tmf.getTrustManagers()); 189 } catch (Exception e) { 190 throw new RuntimeException(e); 191 } 192 } 193 194 /** 195 * Lazily create shared test certificates. 196 */ 197 private static synchronized void initCerts() { 198 if (ROOT_CA != null) { 199 return; 200 } 201 ROOT_CA = new Builder() 202 .aliasPrefix("RootCA") 203 .subject("CN=Test Root Certificate Authority") 204 .ca(true) 205 .certificateSerialNumber(BigInteger.valueOf(1)) 206 .build(); 207 INTERMEDIATE_CA = new Builder() 208 .aliasPrefix("IntermediateCA") 209 .subject("CN=Test Intermediate Certificate Authority") 210 .ca(true) 211 .signer(ROOT_CA.getPrivateKey("RSA", "RSA")) 212 .rootCa(ROOT_CA.getRootCertificate("RSA")) 213 .certificateSerialNumber(BigInteger.valueOf(2)) 214 .build(); 215 SERVER = new Builder() 216 .aliasPrefix("server") 217 .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA")) 218 .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA")) 219 .addSubjectAltNameIpAddress(LOCAL_HOST_ADDRESS) 220 .certificateSerialNumber(BigInteger.valueOf(3)) 221 .build(); 222 CLIENT = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null); 223 CLIENT_CERTIFICATE = new Builder() 224 .aliasPrefix("client") 225 .subject("emailAddress=test@user") 226 .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA")) 227 .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA")) 228 .build(); 229 TestKeyStore rootCa2 = new Builder() 230 .aliasPrefix("RootCA2") 231 .subject("CN=Test Root Certificate Authority 2") 232 .ca(true) 233 .build(); 234 INTERMEDIATE_CA_2 = new Builder() 235 .aliasPrefix("IntermediateCA") 236 .subject("CN=Test Intermediate Certificate Authority") 237 .ca(true) 238 .signer(rootCa2.getPrivateKey("RSA", "RSA")) 239 .rootCa(rootCa2.getRootCertificate("RSA")) 240 .build(); 241 CLIENT_2 = new TestKeyStore(createClient(rootCa2.keyStore), null, null); 242 } 243 244 /** 245 * Return an root CA that can be used to issue new certificates. 246 */ 247 public static TestKeyStore getRootCa() { 248 initCerts(); 249 return ROOT_CA; 250 } 251 252 /** 253 * Return an intermediate CA that can be used to issue new certificates. 254 */ 255 public static TestKeyStore getIntermediateCa() { 256 initCerts(); 257 return INTERMEDIATE_CA; 258 } 259 260 /** 261 * Return an intermediate CA that can be used to issue new certificates. 262 */ 263 public static TestKeyStore getIntermediateCa2() { 264 initCerts(); 265 return INTERMEDIATE_CA_2; 266 } 267 268 /** 269 * Return a server keystore with a matched RSA certificate and 270 * private key as well as a CA certificate. 271 */ 272 public static TestKeyStore getServer() { 273 initCerts(); 274 return SERVER; 275 } 276 277 /** 278 * Return a keystore with a CA certificate 279 */ 280 public static TestKeyStore getClient() { 281 initCerts(); 282 return CLIENT; 283 } 284 285 /** 286 * Return a client keystore with a matched RSA certificate and 287 * private key as well as a CA certificate. 288 */ 289 public static TestKeyStore getClientCertificate() { 290 initCerts(); 291 return CLIENT_CERTIFICATE; 292 } 293 294 /** 295 * Return a keystore with a second CA certificate that does not 296 * trust the server certificate returned by getServer for negative 297 * testing. 298 */ 299 public static TestKeyStore getClientCA2() { 300 initCerts(); 301 return CLIENT_2; 302 } 303 304 /** 305 * Creates KeyStores containing the requested key types. Since key 306 * generation can be expensive, most tests should reuse the RSA-only 307 * singleton instance returned by TestKeyStore.get. 308 */ 309 public static class Builder { 310 private String[] keyAlgorithms = { "RSA" }; 311 private char[] storePassword; 312 private char[] keyPassword; 313 private String aliasPrefix; 314 private X500Principal subject; 315 private int keyUsage; 316 private boolean ca; 317 private PrivateKeyEntry privateEntry; 318 private PrivateKeyEntry signer; 319 private Certificate rootCa; 320 private final List<KeyPurposeId> extendedKeyUsages = new ArrayList<KeyPurposeId>(); 321 private final List<Boolean> criticalExtendedKeyUsages = new ArrayList<Boolean>(); 322 private final List<GeneralName> subjectAltNames = new ArrayList<GeneralName>(); 323 private final List<GeneralSubtree> permittedNameConstraints 324 = new ArrayList<GeneralSubtree>(); 325 private final List<GeneralSubtree> excludedNameConstraints 326 = new ArrayList<GeneralSubtree>(); 327 // Generated randomly if not set 328 private BigInteger certificateSerialNumber = null; 329 330 public Builder() { 331 subject = localhost(); 332 } 333 334 /** 335 * Sets the requested key types to generate and include. The default is 336 * RSA only. 337 */ 338 public Builder keyAlgorithms(String... keyAlgorithms) { 339 this.keyAlgorithms = keyAlgorithms; 340 return this; 341 } 342 343 /** A unique prefix to identify the key aliases */ 344 public Builder aliasPrefix(String aliasPrefix) { 345 this.aliasPrefix = aliasPrefix; 346 return this; 347 } 348 349 /** 350 * Sets the subject common name. The default is the local host's 351 * canonical name. 352 */ 353 public Builder subject(X500Principal subject) { 354 this.subject = subject; 355 return this; 356 } 357 358 public Builder subject(String commonName) { 359 return subject(new X500Principal(commonName)); 360 } 361 362 /** {@link KeyUsage} bit mask for 2.5.29.15 extension */ 363 public Builder keyUsage(int keyUsage) { 364 this.keyUsage = keyUsage; 365 return this; 366 } 367 368 /** true If the keys being created are for a CA */ 369 public Builder ca(boolean ca) { 370 this.ca = ca; 371 return this; 372 } 373 374 /** a private key entry to use for the generation of the certificate */ 375 public Builder privateEntry(PrivateKeyEntry privateEntry) { 376 this.privateEntry = privateEntry; 377 return this; 378 } 379 380 /** a private key entry to be used for signing, otherwise self-sign */ 381 public Builder signer(PrivateKeyEntry signer) { 382 this.signer = signer; 383 return this; 384 } 385 386 /** a root CA to include in the final store */ 387 public Builder rootCa(Certificate rootCa) { 388 this.rootCa = rootCa; 389 return this; 390 } 391 392 public Builder addExtendedKeyUsage(KeyPurposeId keyPurposeId, boolean critical) { 393 extendedKeyUsages.add(keyPurposeId); 394 criticalExtendedKeyUsages.add(critical); 395 return this; 396 } 397 398 public Builder addSubjectAltName(GeneralName generalName) { 399 subjectAltNames.add(generalName); 400 return this; 401 } 402 403 public Builder addSubjectAltNameIpAddress(byte[] ipAddress) { 404 return addSubjectAltName( 405 new GeneralName(GeneralName.iPAddress, new DEROctetString(ipAddress))); 406 } 407 408 private Builder addNameConstraint(boolean permitted, GeneralName generalName) { 409 if (permitted) { 410 permittedNameConstraints.add(new GeneralSubtree(generalName)); 411 } else { 412 excludedNameConstraints.add(new GeneralSubtree(generalName)); 413 } 414 return this; 415 } 416 417 public Builder addNameConstraint(boolean permitted, byte[] ipAddress) { 418 return addNameConstraint(permitted, 419 new GeneralName(GeneralName.iPAddress, new DEROctetString(ipAddress))); 420 } 421 422 public Builder certificateSerialNumber(BigInteger certificateSerialNumber) { 423 this.certificateSerialNumber = certificateSerialNumber; 424 return this; 425 } 426 427 public TestKeyStore build() { 428 try { 429 if (StandardNames.IS_RI) { 430 // JKS does not allow null password 431 if (storePassword == null) { 432 storePassword = "password".toCharArray(); 433 } 434 if (keyPassword == null) { 435 keyPassword = "password".toCharArray(); 436 } 437 } 438 439 /* 440 * This is not implemented for other key types because the logic 441 * would be long to write and it's not needed currently. 442 */ 443 if (privateEntry != null 444 && (keyAlgorithms.length != 1 || !"RSA".equals(keyAlgorithms[0]))) { 445 throw new IllegalStateException( 446 "Only reusing an existing key is implemented for RSA"); 447 } 448 449 KeyStore keyStore = createKeyStore(); 450 for (String keyAlgorithm : keyAlgorithms) { 451 String publicAlias = aliasPrefix + "-public-" + keyAlgorithm; 452 String privateAlias = aliasPrefix + "-private-" + keyAlgorithm; 453 if ((keyAlgorithm.equals("EC_RSA") || keyAlgorithm.equals("DH_RSA")) 454 && signer == null && rootCa == null) { 455 createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, null, 456 privateKey(keyStore, keyPassword, "RSA", "RSA")); 457 continue; 458 } else if (keyAlgorithm.equals("DH_DSA") && signer == null && rootCa == null) { 459 createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, null, 460 privateKey(keyStore, keyPassword, "DSA", "DSA")); 461 continue; 462 } 463 createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, privateEntry, 464 signer); 465 } 466 if (rootCa != null) { 467 keyStore.setCertificateEntry(aliasPrefix 468 + "-root-ca-" 469 + rootCa.getPublicKey().getAlgorithm(), 470 rootCa); 471 } 472 return new TestKeyStore(keyStore, storePassword, keyPassword); 473 } catch (Exception e) { 474 throw new RuntimeException(e); 475 } 476 } 477 478 /** 479 * Add newly generated keys of a given key type to an existing 480 * KeyStore. The PrivateKey will be stored under the specified 481 * private alias name. The X509Certificate will be stored on the 482 * public alias name and have the given subject distinguished 483 * name. 484 * 485 * If a CA is provided, it will be used to sign the generated 486 * certificate and OCSP responses. Otherwise, the certificate 487 * will be self signed. The certificate will be valid for one 488 * day before and one day after the time of creation. 489 * 490 * Based on: 491 * org.bouncycastle.jce.provider.test.SigTest 492 * org.bouncycastle.jce.provider.test.CertTest 493 */ 494 private KeyStore createKeys(KeyStore keyStore, 495 String keyAlgorithm, 496 String publicAlias, 497 String privateAlias, 498 PrivateKeyEntry privateEntry, 499 PrivateKeyEntry signer) throws Exception { 500 PrivateKey caKey; 501 X509Certificate caCert; 502 X509Certificate[] caCertChain; 503 if (signer == null) { 504 caKey = null; 505 caCert = null; 506 caCertChain = null; 507 } else { 508 caKey = signer.getPrivateKey(); 509 caCert = (X509Certificate)signer.getCertificate(); 510 caCertChain = (X509Certificate[])signer.getCertificateChain(); 511 } 512 513 final PrivateKey privateKey; 514 final PublicKey publicKey; 515 X509Certificate x509c; 516 if (publicAlias == null && privateAlias == null) { 517 // don't want anything apparently 518 privateKey = null; 519 publicKey = null; 520 x509c = null; 521 } else { 522 if (privateEntry == null) { 523 // 1a.) we make the keys 524 int keySize = -1; 525 AlgorithmParameterSpec spec = null; 526 if (keyAlgorithm.equals("RSA")) { 527 keySize = RSA_KEY_SIZE_BITS; 528 } else if (keyAlgorithm.equals("DH_RSA")) { 529 spec = new DHParameterSpec(DH_PARAMS_P, DH_PARAMS_G); 530 keyAlgorithm = "DH"; 531 } else if (keyAlgorithm.equals("DSA")) { 532 keySize = DSA_KEY_SIZE_BITS; 533 } else if (keyAlgorithm.equals("DH_DSA")) { 534 spec = new DHParameterSpec(DH_PARAMS_P, DH_PARAMS_G); 535 keyAlgorithm = "DH"; 536 } else if (keyAlgorithm.equals("EC")) { 537 keySize = EC_KEY_SIZE_BITS; 538 } else if (keyAlgorithm.equals("EC_RSA")) { 539 keySize = EC_KEY_SIZE_BITS; 540 keyAlgorithm = "EC"; 541 } else { 542 throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm); 543 } 544 545 KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm); 546 if (spec != null) { 547 kpg.initialize(spec); 548 } else if (keySize != -1) { 549 kpg.initialize(keySize); 550 } else { 551 throw new AssertionError("Must either have set algorithm parameters or key size!"); 552 } 553 554 KeyPair kp = kpg.generateKeyPair(); 555 privateKey = kp.getPrivate(); 556 publicKey = kp.getPublic(); 557 } else { 558 // 1b.) we use the previous keys 559 privateKey = privateEntry.getPrivateKey(); 560 publicKey = privateEntry.getCertificate().getPublicKey(); 561 } 562 563 // 2.) use keys to make certificate 564 X500Principal issuer = ((caCert != null) 565 ? caCert.getSubjectX500Principal() 566 : subject); 567 PrivateKey signingKey = (caKey == null) ? privateKey : caKey; 568 x509c = createCertificate(publicKey, signingKey, subject, issuer, keyUsage, ca, 569 extendedKeyUsages, criticalExtendedKeyUsages, 570 subjectAltNames, 571 permittedNameConstraints, excludedNameConstraints, 572 certificateSerialNumber); 573 } 574 575 X509Certificate[] x509cc; 576 if (privateAlias == null) { 577 // don't need certificate chain 578 x509cc = null; 579 } else if (caCertChain == null) { 580 x509cc = new X509Certificate[] { x509c }; 581 } else { 582 x509cc = new X509Certificate[caCertChain.length+1]; 583 x509cc[0] = x509c; 584 System.arraycopy(caCertChain, 0, x509cc, 1, caCertChain.length); 585 } 586 587 // 3.) put certificate and private key into the key store 588 if (privateAlias != null) { 589 keyStore.setKeyEntry(privateAlias, privateKey, keyPassword, x509cc); 590 } 591 if (publicAlias != null) { 592 keyStore.setCertificateEntry(publicAlias, x509c); 593 } 594 return keyStore; 595 } 596 597 private X500Principal localhost() { 598 return new X500Principal("CN=" + LOCAL_HOST_NAME); 599 } 600 } 601 602 public static X509Certificate createCa(PublicKey publicKey, 603 PrivateKey privateKey, 604 String subject) { 605 try { 606 X500Principal principal = new X500Principal(subject); 607 return createCertificate(publicKey, privateKey, 608 principal, principal, 609 0, true, 610 new ArrayList<KeyPurposeId>(), 611 new ArrayList<Boolean>(), 612 new ArrayList<GeneralName>(), 613 new ArrayList<GeneralSubtree>(), 614 new ArrayList<GeneralSubtree>(), 615 null /* serialNumber, generated randomly */); 616 } catch (Exception e) { 617 throw new RuntimeException(e); 618 } 619 } 620 621 private static X509Certificate createCertificate( 622 PublicKey publicKey, 623 PrivateKey privateKey, 624 X500Principal subject, 625 X500Principal issuer, 626 int keyUsage, 627 boolean ca, 628 List<KeyPurposeId> extendedKeyUsages, 629 List<Boolean> criticalExtendedKeyUsages, 630 List<GeneralName> subjectAltNames, 631 List<GeneralSubtree> permittedNameConstraints, 632 List<GeneralSubtree> excludedNameConstraints, 633 BigInteger serialNumber) throws Exception { 634 // Note that there is no way to programmatically make a 635 // Certificate using java.* or javax.* APIs. The 636 // CertificateFactory interface assumes you want to read 637 // in a stream of bytes, typically the X.509 factory would 638 // allow ASN.1 DER encoded bytes and optionally some PEM 639 // formats. Here we use Bouncy Castle's 640 // X509V3CertificateGenerator and related classes. 641 642 long millisPerDay = 24 * 60 * 60 * 1000; 643 long now = System.currentTimeMillis(); 644 Date start = new Date(now - millisPerDay); 645 Date end = new Date(now + millisPerDay); 646 647 String keyAlgorithm = privateKey.getAlgorithm(); 648 String signatureAlgorithm; 649 if (keyAlgorithm.equals("RSA")) { 650 signatureAlgorithm = "sha1WithRSA"; 651 } else if (keyAlgorithm.equals("DSA")) { 652 signatureAlgorithm = "sha1WithDSA"; 653 } else if (keyAlgorithm.equals("EC")) { 654 signatureAlgorithm = "sha1WithECDSA"; 655 } else if (keyAlgorithm.equals("EC_RSA")) { 656 signatureAlgorithm = "sha1WithRSA"; 657 } else { 658 throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm); 659 } 660 661 X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator(); 662 x509cg.setSubjectDN(subject); 663 x509cg.setIssuerDN(issuer); 664 x509cg.setNotBefore(start); 665 x509cg.setNotAfter(end); 666 x509cg.setPublicKey(publicKey); 667 x509cg.setSignatureAlgorithm(signatureAlgorithm); 668 if (serialNumber == null) { 669 byte[] serialBytes = new byte[16]; 670 new SecureRandom().nextBytes(serialBytes); 671 serialNumber = new BigInteger(1, serialBytes); 672 } 673 x509cg.setSerialNumber(serialNumber); 674 if (keyUsage != 0) { 675 x509cg.addExtension(X509Extensions.KeyUsage, 676 true, 677 new KeyUsage(keyUsage)); 678 } 679 if (ca) { 680 x509cg.addExtension(X509Extensions.BasicConstraints, 681 true, 682 new BasicConstraints(true)); 683 } 684 for (int i = 0; i < extendedKeyUsages.size(); i++) { 685 KeyPurposeId keyPurposeId = extendedKeyUsages.get(i); 686 boolean critical = criticalExtendedKeyUsages.get(i); 687 x509cg.addExtension(X509Extensions.ExtendedKeyUsage, 688 critical, 689 new ExtendedKeyUsage(keyPurposeId)); 690 } 691 for (GeneralName subjectAltName : subjectAltNames) { 692 x509cg.addExtension(X509Extensions.SubjectAlternativeName, 693 false, 694 new GeneralNames(subjectAltName).getEncoded()); 695 } 696 if (!permittedNameConstraints.isEmpty() || !excludedNameConstraints.isEmpty()) { 697 x509cg.addExtension(X509Extensions.NameConstraints, 698 true, 699 new NameConstraints(permittedNameConstraints.toArray( 700 new GeneralSubtree[ 701 permittedNameConstraints.size()]), 702 excludedNameConstraints.toArray( 703 new GeneralSubtree[ 704 excludedNameConstraints.size()]))); 705 } 706 707 X509Certificate x509c = x509cg.generateX509Certificate(privateKey); 708 if (StandardNames.IS_RI) { 709 /* 710 * The RI can't handle the BC EC signature algorithm 711 * string of "ECDSA", since it expects "...WITHEC...", 712 * so convert from BC to RI X509Certificate 713 * implementation via bytes. 714 */ 715 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 716 ByteArrayInputStream bais = new ByteArrayInputStream(x509c.getEncoded()); 717 Certificate c = cf.generateCertificate(bais); 718 x509c = (X509Certificate) c; 719 } 720 return x509c; 721 } 722 723 /** 724 * Return the key algorithm for a possible compound algorithm 725 * identifier containing an underscore. If not underscore is 726 * present, the argument is returned unmodified. However for an 727 * algorithm such as EC_RSA, return EC. 728 */ 729 public static String keyAlgorithm(String algorithm) { 730 int index = algorithm.indexOf('_'); 731 if (index == -1) { 732 return algorithm; 733 } 734 return algorithm.substring(0, index); 735 } 736 737 738 /** 739 * Return the signature algorithm for a possible compound 740 * algorithm identifier containing an underscore. If not 741 * underscore is present, the argument is returned 742 * unmodified. However for an algorithm such as EC_RSA, return 743 * RSA. 744 */ 745 public static String signatureAlgorithm(String algorithm) { 746 int index = algorithm.indexOf('_'); 747 if (index == -1) { 748 return algorithm; 749 } 750 return algorithm.substring(index+1, algorithm.length()); 751 } 752 753 /** 754 * Create an empty KeyStore 755 */ 756 public static KeyStore createKeyStore() { 757 try { 758 KeyStore keyStore = KeyStore.getInstance(StandardNames.KEY_STORE_ALGORITHM); 759 keyStore.load(null, null); 760 return keyStore; 761 } catch (Exception e) { 762 throw new RuntimeException(e); 763 } 764 } 765 766 /** 767 * Return the only private key in a TestKeyStore for the given 768 * algorithms. Throws IllegalStateException if there are are more 769 * or less than one. 770 */ 771 public PrivateKeyEntry getPrivateKey(String keyAlgorithm, String signatureAlgorithm) { 772 return privateKey(keyStore, keyPassword, keyAlgorithm, signatureAlgorithm); 773 } 774 775 /** 776 * Return the only private key in a keystore for the given 777 * algorithms. Throws IllegalStateException if there are are more 778 * or less than one. 779 */ 780 public static PrivateKeyEntry privateKey(KeyStore keyStore, char[] keyPassword, 781 String keyAlgorithm, String signatureAlgorithm) { 782 try { 783 PrivateKeyEntry found = null; 784 PasswordProtection password = new PasswordProtection(keyPassword); 785 for (String alias : Collections.list(keyStore.aliases())) { 786 if (!keyStore.entryInstanceOf(alias, PrivateKeyEntry.class)) { 787 continue; 788 } 789 PrivateKeyEntry privateKey = (PrivateKeyEntry) keyStore.getEntry(alias, password); 790 if (!privateKey.getPrivateKey().getAlgorithm().equals(keyAlgorithm)) { 791 continue; 792 } 793 X509Certificate certificate = (X509Certificate) privateKey.getCertificate(); 794 if (!certificate.getSigAlgName().contains(signatureAlgorithm)) { 795 continue; 796 } 797 if (found != null) { 798 throw new IllegalStateException("KeyStore has more than one private key for" 799 + " keyAlgorithm: " + keyAlgorithm 800 + " signatureAlgorithm: " + signatureAlgorithm 801 + "\nfirst: " + found.getPrivateKey() 802 + "\nsecond: " + privateKey.getPrivateKey() ); 803 } 804 found = privateKey; 805 } 806 if (found == null) { 807 throw new IllegalStateException("KeyStore contained no private key for" 808 + " keyAlgorithm: " + keyAlgorithm 809 + " signatureAlgorithm: " + signatureAlgorithm); 810 } 811 return found; 812 } catch (Exception e) { 813 throw new RuntimeException("Problem getting key for " + keyAlgorithm 814 + " and signature " + signatureAlgorithm, e); 815 } 816 } 817 818 /** 819 * Return the issuing CA certificate of the given 820 * certificate. Throws IllegalStateException if there are are more 821 * or less than one. 822 */ 823 public Certificate getIssuer(Certificate cert) throws Exception { 824 return issuer(keyStore, cert); 825 } 826 827 /** 828 * Return the issuing CA certificate of the given 829 * certificate. Throws IllegalStateException if there are are more 830 * or less than one. 831 */ 832 public static Certificate issuer(KeyStore keyStore, Certificate c) 833 throws Exception { 834 if (!(c instanceof X509Certificate)) { 835 throw new IllegalStateException("issuer requires an X509Certificate, found " + c); 836 } 837 X509Certificate cert = (X509Certificate) c; 838 839 Certificate found = null; 840 for (String alias : Collections.list(keyStore.aliases())) { 841 if (!keyStore.entryInstanceOf(alias, TrustedCertificateEntry.class)) { 842 continue; 843 } 844 TrustedCertificateEntry certificateEntry = 845 (TrustedCertificateEntry) keyStore.getEntry(alias, null); 846 Certificate certificate = certificateEntry.getTrustedCertificate(); 847 if (!(certificate instanceof X509Certificate)) { 848 continue; 849 } 850 X509Certificate x = (X509Certificate) certificate; 851 if (!cert.getIssuerDN().equals(x.getSubjectDN())) { 852 continue; 853 } 854 if (found != null) { 855 throw new IllegalStateException("KeyStore has more than one issuing CA for " 856 + cert 857 + "\nfirst: " + found 858 + "\nsecond: " + certificate ); 859 } 860 found = certificate; 861 } 862 if (found == null) { 863 throw new IllegalStateException("KeyStore contained no issuing CA for " + cert); 864 } 865 return found; 866 } 867 868 /** 869 * Return the only self-signed root certificate in a TestKeyStore 870 * for the given algorithm. Throws IllegalStateException if there 871 * are are more or less than one. 872 */ 873 public X509Certificate getRootCertificate(String algorithm) { 874 return rootCertificate(keyStore, algorithm); 875 } 876 877 private static OCSPResp generateOCSPResponse(PrivateKeyEntry server, PrivateKeyEntry issuer, 878 CertificateStatus status) throws CertificateException { 879 try { 880 X509Certificate serverCertJca = (X509Certificate) server.getCertificate(); 881 X509Certificate caCertJca = (X509Certificate) issuer.getCertificate(); 882 883 X509CertificateHolder caCert = new JcaX509CertificateHolder(caCertJca); 884 885 DigestCalculatorProvider digCalcProv = new BcDigestCalculatorProvider(); 886 BasicOCSPRespBuilder basicBuilder = new BasicOCSPRespBuilder( 887 SubjectPublicKeyInfo.getInstance(caCertJca.getPublicKey().getEncoded()), 888 digCalcProv.get(CertificateID.HASH_SHA1)); 889 890 CertificateID certId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), 891 caCert, serverCertJca.getSerialNumber()); 892 893 basicBuilder.addResponse(certId, status); 894 895 BasicOCSPResp resp = basicBuilder.build( 896 new JcaContentSignerBuilder("SHA256withRSA").build(issuer.getPrivateKey()), 897 null, new Date()); 898 899 OCSPRespBuilder builder = new OCSPRespBuilder(); 900 return builder.build(OCSPRespBuilder.SUCCESSFUL, resp); 901 } catch (Exception e) { 902 throw new CertificateException("cannot generate OCSP response", e); 903 } 904 } 905 906 public static byte[] getOCSPResponseForGood(PrivateKeyEntry server, PrivateKeyEntry issuer) throws CertificateException { 907 try { 908 return generateOCSPResponse(server, issuer, CertificateStatus.GOOD).getEncoded(); 909 } catch (IOException e) { 910 throw new CertificateException(e); 911 } 912 } 913 914 public static byte[] getOCSPResponseForRevoked(PrivateKeyEntry server, PrivateKeyEntry issuer) 915 throws CertificateException { 916 try { 917 return generateOCSPResponse(server, issuer, 918 new RevokedStatus(new Date(), CRLReason.keyCompromise)).getEncoded(); 919 } catch (IOException e) { 920 throw new CertificateException(e); 921 } 922 } 923 924 /** 925 * Return the only self-signed root certificate in a keystore for 926 * the given algorithm. Throws IllegalStateException if there are 927 * are more or less than one. 928 */ 929 public static X509Certificate rootCertificate(KeyStore keyStore, String algorithm) { 930 try { 931 X509Certificate found = null; 932 for (String alias : Collections.list(keyStore.aliases())) { 933 if (!keyStore.entryInstanceOf(alias, TrustedCertificateEntry.class)) { 934 continue; 935 } 936 TrustedCertificateEntry certificateEntry = 937 (TrustedCertificateEntry) keyStore.getEntry(alias, null); 938 Certificate certificate = certificateEntry.getTrustedCertificate(); 939 if (!certificate.getPublicKey().getAlgorithm().equals(algorithm)) { 940 continue; 941 } 942 if (!(certificate instanceof X509Certificate)) { 943 continue; 944 } 945 X509Certificate x = (X509Certificate) certificate; 946 if (!x.getIssuerDN().equals(x.getSubjectDN())) { 947 continue; 948 } 949 if (found != null) { 950 throw new IllegalStateException("KeyStore has more than one root CA for " 951 + algorithm 952 + "\nfirst: " + found 953 + "\nsecond: " + certificate ); 954 } 955 found = x; 956 } 957 if (found == null) { 958 throw new IllegalStateException("KeyStore contained no root CA for " + algorithm); 959 } 960 return found; 961 } catch (Exception e) { 962 throw new RuntimeException(e); 963 } 964 } 965 966 /** 967 * Return an {@code X509Certificate that matches the given {@code alias}. 968 */ 969 public KeyStore.Entry getEntryByAlias(String alias) { 970 return entryByAlias(keyStore, alias); 971 } 972 973 /** 974 * Finds an entry in the keystore by the given alias. 975 */ 976 public static KeyStore.Entry entryByAlias(KeyStore keyStore, String alias) { 977 try { 978 return keyStore.getEntry(alias, null); 979 } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) { 980 throw new RuntimeException(e); 981 } 982 } 983 984 /** 985 * Create a client key store that only contains self-signed certificates but no private keys 986 */ 987 public static KeyStore createClient(KeyStore caKeyStore) { 988 KeyStore clientKeyStore = createKeyStore(); 989 copySelfSignedCertificates(clientKeyStore, caKeyStore); 990 return clientKeyStore; 991 } 992 993 /** 994 * Copy self-signed certificates from one key store to another. 995 * Returns true if successful, false if no match found. 996 */ 997 public static boolean copySelfSignedCertificates(KeyStore dst, KeyStore src) { 998 try { 999 boolean copied = false; 1000 for (String alias : Collections.list(src.aliases())) { 1001 if (!src.isCertificateEntry(alias)) { 1002 continue; 1003 } 1004 X509Certificate cert = (X509Certificate)src.getCertificate(alias); 1005 if (!cert.getSubjectDN().equals(cert.getIssuerDN())) { 1006 continue; 1007 } 1008 dst.setCertificateEntry(alias, cert); 1009 copied = true; 1010 } 1011 return copied; 1012 } catch (Exception e) { 1013 throw new RuntimeException(e); 1014 } 1015 } 1016 1017 /** 1018 * Copy named certificates from one key store to another. 1019 * Returns true if successful, false if no match found. 1020 */ 1021 public static boolean copyCertificate(Principal subject, KeyStore dst, KeyStore src) 1022 throws Exception { 1023 for (String alias : Collections.list(src.aliases())) { 1024 if (!src.isCertificateEntry(alias)) { 1025 continue; 1026 } 1027 X509Certificate cert = (X509Certificate)src.getCertificate(alias); 1028 if (!cert.getSubjectDN().equals(subject)) { 1029 continue; 1030 } 1031 dst.setCertificateEntry(alias, cert); 1032 return true; 1033 } 1034 return false; 1035 } 1036 1037 /** 1038 * Dump a key store for debugging. 1039 */ 1040 public void dump(String context) throws KeyStoreException, NoSuchAlgorithmException { 1041 dump(context, keyStore, keyPassword); 1042 } 1043 1044 /** 1045 * Dump a key store for debugging. 1046 */ 1047 public static void dump(String context, KeyStore keyStore, char[] keyPassword) 1048 throws KeyStoreException, NoSuchAlgorithmException { 1049 PrintStream out = System.out; 1050 out.println("context=" + context); 1051 out.println("\tkeyStore=" + keyStore); 1052 out.println("\tkeyStore.type=" + keyStore.getType()); 1053 out.println("\tkeyStore.provider=" + keyStore.getProvider()); 1054 out.println("\tkeyPassword=" 1055 + ((keyPassword == null) ? null : new String(keyPassword))); 1056 out.println("\tsize=" + keyStore.size()); 1057 for (String alias : Collections.list(keyStore.aliases())) { 1058 out.println("alias=" + alias); 1059 out.println("\tcreationDate=" + keyStore.getCreationDate(alias)); 1060 if (keyStore.isCertificateEntry(alias)) { 1061 out.println("\tcertificate:"); 1062 out.println("=========================================="); 1063 out.println(keyStore.getCertificate(alias)); 1064 out.println("=========================================="); 1065 continue; 1066 } 1067 if (keyStore.isKeyEntry(alias)) { 1068 out.println("\tkey:"); 1069 out.println("=========================================="); 1070 String key; 1071 try { 1072 key = ("Key retrieved using password\n" 1073 + keyStore.getKey(alias, keyPassword)); 1074 } catch (UnrecoverableKeyException e1) { 1075 try { 1076 key = ("Key retrieved without password\n" 1077 + keyStore.getKey(alias, null)); 1078 } catch (UnrecoverableKeyException e2) { 1079 key = "Key could not be retrieved"; 1080 } 1081 } 1082 out.println(key); 1083 out.println("=========================================="); 1084 Certificate[] chain = keyStore.getCertificateChain(alias); 1085 if (chain == null) { 1086 out.println("No certificate chain associated with key"); 1087 out.println("=========================================="); 1088 } else { 1089 for (int i = 0; i < chain.length; i++) { 1090 out.println("Certificate chain element #" + i); 1091 out.println(chain[i]); 1092 out.println("=========================================="); 1093 } 1094 } 1095 continue; 1096 } 1097 out.println("\tunknown entry type"); 1098 } 1099 } 1100 1101 public static void assertChainLength(Object[] chain) { 1102 /* 1103 * Note chain is Object[] to support both 1104 * java.security.cert.X509Certificate and 1105 * javax.security.cert.X509Certificate 1106 */ 1107 assertEquals(3, chain.length); 1108 } 1109} 1110