summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java152
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java54
-rw-r--r--luni/src/test/java/tests/api/javax/net/ssl/X509TrustManagerTest.java127
-rw-r--r--support/src/test/java/libcore/java/security/TestKeyStore.java81
4 files changed, 277 insertions, 137 deletions
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
index 1682df7..9317966 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
@@ -23,13 +23,18 @@ import java.security.KeyStoreException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
+import java.security.cert.Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
@@ -179,12 +184,12 @@ public final class TrustManagerImpl implements X509TrustManager {
@Override public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
- checkTrusted(chain, authType, null);
+ checkTrusted(chain, authType, null, true);
}
@Override public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
- checkTrusted(chain, authType, null);
+ checkTrusted(chain, authType, null, false);
}
/**
@@ -194,7 +199,7 @@ public final class TrustManagerImpl implements X509TrustManager {
*/
public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,
String host) throws CertificateException {
- return checkTrusted(chain, authType, host);
+ return checkTrusted(chain, authType, host, false);
}
public void handleTrustStorageUpdate() {
@@ -202,10 +207,11 @@ public final class TrustManagerImpl implements X509TrustManager {
trustedCertificateIndex.reset();
} else {
trustedCertificateIndex.reset(trustAnchors(acceptedIssuers));
- }
+ }
}
- private List<X509Certificate> checkTrusted(X509Certificate[] chain, String authType, String host)
+ private List<X509Certificate> checkTrusted(X509Certificate[] chain, String authType,
+ String host, boolean clientAuth)
throws CertificateException {
if (chain == null || chain.length == 0 || authType == null || authType.length() == 0) {
throw new IllegalArgumentException("null or zero-length parameter");
@@ -284,6 +290,8 @@ public final class TrustManagerImpl implements X509TrustManager {
try {
PKIXParameters params = new PKIXParameters(trustAnchor);
params.setRevocationEnabled(false);
+ params.addCertPathChecker(new ExtendedKeyUsagePKIXCertPathChecker(clientAuth,
+ newChain[0]));
validator.validate(certPath, params);
// Add intermediate CAs to the index to tolerate sites
// that assume that the browser will have cached these.
@@ -382,28 +390,101 @@ public final class TrustManagerImpl implements X509TrustManager {
}
/**
- * Check the trustedCertificateIndex for the cert to see if it is
- * already trusted and failing that check the KeyStore if it is
- * available.
+ * If an EKU extension is present in the end-entity certificate,
+ * it MUST contain an appropriate key usage. For servers, this
+ * includes anyExtendedKeyUsage, serverAuth, or the historical
+ * Server Gated Cryptography options of nsSGC or msSGC. For
+ * clients, this includes anyExtendedKeyUsage and clientAuth.
*/
- private TrustAnchor findTrustAnchorBySubjectAndPublicKey(X509Certificate cert) {
- TrustAnchor trustAnchor = trustedCertificateIndex.findBySubjectAndPublicKey(cert);
- if (trustAnchor != null) {
- return trustAnchor;
+ private static class ExtendedKeyUsagePKIXCertPathChecker extends PKIXCertPathChecker {
+
+ private static final String EKU_OID = "2.5.29.37";
+
+ private static final String EKU_anyExtendedKeyUsage = "2.5.29.37.0";
+ private static final String EKU_clientAuth = "1.3.6.1.5.5.7.3.2";
+ private static final String EKU_serverAuth = "1.3.6.1.5.5.7.3.1";
+ private static final String EKU_nsSGC = "2.16.840.1.113730.4.1";
+ private static final String EKU_msSGC = "1.3.6.1.4.1.311.10.3.3";
+
+ private static final Set<String> SUPPORTED_EXTENSIONS
+ = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(EKU_OID)));
+
+ private final boolean clientAuth;
+ private final X509Certificate leaf;
+
+ private ExtendedKeyUsagePKIXCertPathChecker(boolean clientAuth, X509Certificate leaf) {
+ this.clientAuth = clientAuth;
+ this.leaf = leaf;
}
- if (trustedCertificateStore == null) {
- // not trusted and no TrustedCertificateStore to check
- return null;
+
+ @Override public void init(boolean forward) throws CertPathValidatorException {
}
- // probe KeyStore for a cert. AndroidCAStore stores its
- // contents hashed by cert subject on the filesystem to make
- // this faster than scanning all key store entries.
- if (trustedCertificateStore.isTrustAnchor(cert)) {
- // add new TrustAnchor to params index to avoid
- // checking filesystem next time around.
- return trustedCertificateIndex.index(cert);
+
+ @Override public boolean isForwardCheckingSupported() {
+ return true;
+ }
+
+ @Override public Set<String> getSupportedExtensions() {
+ return SUPPORTED_EXTENSIONS;
+ }
+
+ @Override public void check(Certificate c, Collection<String> unresolvedCritExts)
+ throws CertPathValidatorException {
+ // We only want to validate the EKU on the leaf certificate.
+ if (c != leaf) {
+ return;
+ }
+ List<String> ekuOids;
+ try {
+ ekuOids = leaf.getExtendedKeyUsage();
+ } catch (CertificateParsingException e) {
+ // A malformed EKU is bad news, consider it fatal.
+ throw new CertPathValidatorException(e);
+ }
+ // We are here to check EKU, but there is none.
+ if (ekuOids == null) {
+ return;
+ }
+
+ boolean goodExtendedKeyUsage = false;
+ for (String ekuOid : ekuOids) {
+ // anyExtendedKeyUsage for clients and servers
+ if (ekuOid.equals(EKU_anyExtendedKeyUsage)) {
+ goodExtendedKeyUsage = true;
+ break;
+ }
+
+ // clients
+ if (clientAuth) {
+ if (ekuOid.equals(EKU_clientAuth)) {
+ goodExtendedKeyUsage = true;
+ break;
+ }
+ continue;
+ }
+
+ // servers
+ if (ekuOid.equals(EKU_serverAuth)) {
+ goodExtendedKeyUsage = true;
+ break;
+ }
+ if (ekuOid.equals(EKU_nsSGC)) {
+ goodExtendedKeyUsage = true;
+ break;
+ }
+ if (ekuOid.equals(EKU_msSGC)) {
+ goodExtendedKeyUsage = true;
+ break;
+ }
+ }
+ if (goodExtendedKeyUsage) {
+ // Mark extendedKeyUsage as resolved if present.
+ unresolvedCritExts.remove(EKU_OID);
+ } else {
+ throw new CertPathValidatorException("End-entity certificate does not have a valid "
+ + "extendedKeyUsage.");
+ }
}
- return null;
}
private TrustAnchor findTrustAnchorByIssuerAndSignature(X509Certificate lastCert) {
@@ -424,6 +505,31 @@ public final class TrustManagerImpl implements X509TrustManager {
return null;
}
+ /**
+ * Check the trustedCertificateIndex for the cert to see if it is
+ * already trusted and failing that check the KeyStore if it is
+ * available.
+ */
+ private TrustAnchor findTrustAnchorBySubjectAndPublicKey(X509Certificate cert) {
+ TrustAnchor trustAnchor = trustedCertificateIndex.findBySubjectAndPublicKey(cert);
+ if (trustAnchor != null) {
+ return trustAnchor;
+ }
+ if (trustedCertificateStore == null) {
+ // not trusted and no TrustedCertificateStore to check
+ return null;
+ }
+ // probe KeyStore for a cert. AndroidCAStore stores its
+ // contents hashed by cert subject on the filesystem to make
+ // this faster than scanning all key store entries.
+ if (trustedCertificateStore.isTrustAnchor(cert)) {
+ // add new TrustAnchor to params index to avoid
+ // checking filesystem next time around.
+ return trustedCertificateIndex.index(cert);
+ }
+ return null;
+ }
+
@Override public X509Certificate[] getAcceptedIssuers() {
return (acceptedIssuers != null) ? acceptedIssuers.clone() : acceptedIssuers(rootKeyStore);
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java
index ad931af..37d0e07 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java
@@ -16,9 +16,10 @@
package libcore.javax.net.ssl;
+import com.android.org.bouncycastle.asn1.x509.KeyPurposeId;
import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateException;
@@ -257,4 +258,55 @@ public class TrustManagerFactoryTest extends TestCase {
trustManager.checkServerTrusted((X509Certificate[]) pke.getCertificateChain(), "RSA");
}
+ public void test_TrustManagerFactory_extendedKeyUsage() throws Exception {
+ // anyExtendedKeyUsage should work for client or server
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage, false, true, true);
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage, true, true, true);
+
+ // critical clientAuth should work for client
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_clientAuth, false, true, false);
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_clientAuth, true, true, false);
+
+ // critical serverAuth should work for server
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_serverAuth, false, false, true);
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_serverAuth, true, false, true);
+
+ // codeSigning should not work
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_codeSigning, false, false, false);
+ test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId.id_kp_codeSigning, true, false, false);
+ }
+
+ private void test_TrustManagerFactory_extendedKeyUsage(KeyPurposeId keyPurposeId,
+ boolean critical,
+ boolean client,
+ boolean server)
+ throws Exception {
+ String algorithm = "RSA";
+ TestKeyStore intermediateCa = TestKeyStore.getIntermediateCa();
+ TestKeyStore leaf = new TestKeyStore.Builder()
+ .keyAlgorithms(new String[] { algorithm })
+ .aliasPrefix("criticalCodeSigning")
+ .signer(intermediateCa.getPrivateKey("RSA", "RSA"))
+ .rootCa(intermediateCa.getRootCertificate("RSA"))
+ .addExtendedKeyUsage(keyPurposeId, critical)
+ .build();
+ // leaf.dump("test_TrustManagerFactory_criticalCodeSigning");
+ PrivateKeyEntry privateKeyEntry = leaf.getPrivateKey(algorithm, algorithm);
+ X509Certificate[] chain = (X509Certificate[]) privateKeyEntry.getCertificateChain();
+
+ TestKeyStore rootCa = TestKeyStore.getRootCa();
+ X509TrustManager trustManager = (X509TrustManager) rootCa.trustManagers[0];
+ try {
+ trustManager.checkClientTrusted(chain, algorithm);
+ assertTrue(client);
+ } catch (Exception e) {
+ assertFalse(client);
+ }
+ try {
+ trustManager.checkServerTrusted(chain, algorithm);
+ assertTrue(server);
+ } catch (Exception e) {
+ assertFalse(server);
+ }
+ }
}
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/X509TrustManagerTest.java b/luni/src/test/java/tests/api/javax/net/ssl/X509TrustManagerTest.java
index ebe57de..ade0eca 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/X509TrustManagerTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/X509TrustManagerTest.java
@@ -1,210 +1,149 @@
package tests.api.javax.net.ssl;
import java.io.ByteArrayInputStream;
-import java.security.cert.CertificateFactory;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
-
import junit.framework.TestCase;
-
import org.apache.harmony.security.tests.support.cert.TestUtils;
import org.apache.harmony.xnet.tests.support.X509TrustManagerImpl;
-/**
- * Tests for <code>X509TrustManager</code> class constructors and methods.
- */
public class X509TrustManagerTest extends TestCase {
- private X509Certificate[] setX509Certificate() {
- try {
- CertificateFactory certFact = CertificateFactory.getInstance("X.509");
- X509Certificate pemCert = (X509Certificate) certFact
- .generateCertificate(new ByteArrayInputStream(TestUtils
- .getX509Certificate_v3()));
- X509Certificate[] xcert = {pemCert};
- return xcert;
- } catch (Exception ex) {
- fail("Unexpected exception " + ex);
- }
- return null;
+ private X509Certificate[] setX509Certificate() throws Exception {
+ CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+ X509Certificate pemCert = (X509Certificate) certFact.generateCertificate(
+ new ByteArrayInputStream(TestUtils.getX509Certificate_v3()));
+ X509Certificate[] xcert = { pemCert };
+ return xcert;
}
- private X509Certificate[] setInvalid() {
- try {
- CertificateFactory certFact = CertificateFactory.getInstance("X.509");
- X509Certificate pemCert = (X509Certificate) certFact
- .generateCertificate(new ByteArrayInputStream(TestUtils
- .getX509Certificate_v1()));
- X509Certificate[] xcert = {pemCert};
- return xcert;
- } catch (Exception ex) {
- fail("Unexpected exception " + ex);
- }
- return null;
+ private X509Certificate[] setInvalid() throws Exception {
+ CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+ X509Certificate pemCert = (X509Certificate) certFact.generateCertificate(
+ new ByteArrayInputStream(TestUtils.getX509Certificate_v1()));
+ X509Certificate[] xcert = { pemCert };
+ return xcert;
}
- /**
- * javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[] chain, String authType)
- */
- public void test_checkClientTrusted_01() {
+ public void test_checkClientTrusted_01() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = null;
try {
xtm.checkClientTrusted(xcert, "SSL");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
xcert = new X509Certificate[0];
try {
xtm.checkClientTrusted(xcert, "SSL");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
xcert = setX509Certificate();
try {
xtm.checkClientTrusted(xcert, null);
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
try {
xtm.checkClientTrusted(xcert, "");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
}
/**
* javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[] chain, String authType)
*/
- public void test_checkClientTrusted_02() {
+ public void test_checkClientTrusted_02() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = setInvalid();
try {
xtm.checkClientTrusted(xcert, "SSL");
fail("CertificateException wasn't thrown");
- } catch (CertificateException ce) {
- //expected
+ } catch (CertificateException expected) {
}
}
/**
* javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[] chain, String authType)
*/
- public void test_checkClientTrusted_03() {
+ public void test_checkClientTrusted_03() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = setX509Certificate();
-
- try {
- xtm.checkClientTrusted(xcert, "SSL");
- } catch (Exception ex) {
- fail("Unexpected exception " + ex);
- }
+ xtm.checkClientTrusted(xcert, "SSL");
}
/**
* javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[] chain, String authType)
*/
- public void test_checkServerTrusted_01() {
+ public void test_checkServerTrusted_01() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = null;
try {
xtm.checkServerTrusted(xcert, "SSL");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
xcert = new X509Certificate[0];
try {
xtm.checkServerTrusted(xcert, "SSL");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
xcert = setX509Certificate();
try {
xtm.checkServerTrusted(xcert, null);
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
try {
xtm.checkServerTrusted(xcert, "");
fail("IllegalArgumentException wasn't thrown");
- } catch (IllegalArgumentException iae) {
- //expected
- } catch (Exception e) {
- fail(e + " was thrown instead of IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
}
/**
* javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[] chain, String authType)
*/
- public void test_checkServerTrusted_02() {
+ public void test_checkServerTrusted_02() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = setInvalid();
try {
xtm.checkServerTrusted(xcert, "SSL");
fail("CertificateException wasn't thrown");
- } catch (CertificateException ce) {
- //expected
+ } catch (CertificateException expected) {
}
}
/**
* javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[] chain, String authType)
*/
- public void test_checkServerTrusted_03() {
+ public void test_checkServerTrusted_03() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
X509Certificate[] xcert = setX509Certificate();
-
- try {
- xtm.checkServerTrusted(xcert, "SSL");
- } catch (Exception ex) {
- fail("Unexpected exception " + ex);
- }
+ xtm.checkServerTrusted(xcert, "SSL");
}
/**
* javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
- public void test_getAcceptedIssuers() {
+ public void test_getAcceptedIssuers() throws Exception {
X509TrustManagerImpl xtm = new X509TrustManagerImpl();
-
- try {
- assertNotNull(xtm.getAcceptedIssuers());
- } catch (Exception ex) {
- fail("Unexpected exception " + ex);
- }
+ assertNotNull(xtm.getAcceptedIssuers());
}
}
diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java
index 74c2840..aee7f8a 100644
--- a/support/src/test/java/libcore/java/security/TestKeyStore.java
+++ b/support/src/test/java/libcore/java/security/TestKeyStore.java
@@ -18,9 +18,11 @@ package libcore.java.security;
import com.android.org.bouncycastle.asn1.DEROctetString;
import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
+import com.android.org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import com.android.org.bouncycastle.asn1.x509.GeneralName;
import com.android.org.bouncycastle.asn1.x509.GeneralNames;
import com.android.org.bouncycastle.asn1.x509.GeneralSubtree;
+import com.android.org.bouncycastle.asn1.x509.KeyPurposeId;
import com.android.org.bouncycastle.asn1.x509.KeyUsage;
import com.android.org.bouncycastle.asn1.x509.NameConstraints;
import com.android.org.bouncycastle.asn1.x509.X509Extensions;
@@ -75,6 +77,7 @@ import libcore.javax.net.ssl.TestTrustManager;
public final class TestKeyStore extends Assert {
private static TestKeyStore ROOT_CA;
+ private static TestKeyStore INTERMEDIATE_CA;
private static TestKeyStore SERVER;
private static TestKeyStore CLIENT;
@@ -145,7 +148,7 @@ public final class TestKeyStore extends Assert {
.subject("CN=Test Root Certificate Authority")
.ca(true)
.build();
- TestKeyStore intermediateCa = new Builder()
+ INTERMEDIATE_CA = new Builder()
.aliasPrefix("IntermediateCA")
.subject("CN=Test Intermediate Certificate Authority")
.ca(true)
@@ -154,15 +157,15 @@ public final class TestKeyStore extends Assert {
.build();
SERVER = new Builder()
.aliasPrefix("server")
- .signer(intermediateCa.getPrivateKey("RSA", "RSA"))
- .rootCa(intermediateCa.getRootCertificate("RSA"))
+ .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"))
+ .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA"))
.build();
- CLIENT = new TestKeyStore(createClient(intermediateCa.keyStore), null, null);
+ CLIENT = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null);
CLIENT_CERTIFICATE = new Builder()
.aliasPrefix("client")
.subject("emailAddress=test@user")
- .signer(intermediateCa.getPrivateKey("RSA", "RSA"))
- .rootCa(intermediateCa.getRootCertificate("RSA"))
+ .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"))
+ .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA"))
.build();
TestKeyStore rootCa2 = new Builder()
.aliasPrefix("RootCA2")
@@ -173,6 +176,22 @@ public final class TestKeyStore extends Assert {
}
/**
+ * Return an root CA that can be used to issue new certificates.
+ */
+ public static TestKeyStore getRootCa() {
+ initCerts();
+ return ROOT_CA;
+ }
+
+ /**
+ * Return an intermediate CA that can be used to issue new certificates.
+ */
+ public static TestKeyStore getIntermediateCa() {
+ initCerts();
+ return INTERMEDIATE_CA;
+ }
+
+ /**
* Return a server keystore with a matched RSA certificate and
* private key as well as a CA certificate.
*/
@@ -223,10 +242,13 @@ public final class TestKeyStore extends Assert {
private boolean ca;
private PrivateKeyEntry signer;
private Certificate rootCa;
+ private final List<KeyPurposeId> extendedKeyUsages = new ArrayList<KeyPurposeId>();
+ private final List<Boolean> criticalExtendedKeyUsages = new ArrayList<Boolean>();
private final List<GeneralName> subjectAltNames = new ArrayList<GeneralName>();
- private final Vector<GeneralSubtree> permittedNameConstraints
- = new Vector<GeneralSubtree>();
- private final Vector<GeneralSubtree> excludedNameConstraints = new Vector<GeneralSubtree>();
+ private final List<GeneralSubtree> permittedNameConstraints
+ = new ArrayList<GeneralSubtree>();
+ private final List<GeneralSubtree> excludedNameConstraints
+ = new ArrayList<GeneralSubtree>();
public Builder() {
subject = localhost();
@@ -284,7 +306,13 @@ public final class TestKeyStore extends Assert {
return this;
}
- private Builder addSubjectAltName(GeneralName generalName) {
+ public Builder addExtendedKeyUsage(KeyPurposeId keyPurposeId, boolean critical) {
+ extendedKeyUsages.add(keyPurposeId);
+ criticalExtendedKeyUsages.add(critical);
+ return this;
+ }
+
+ public Builder addSubjectAltName(GeneralName generalName) {
subjectAltNames.add(generalName);
return this;
}
@@ -413,6 +441,7 @@ public final class TestKeyStore extends Assert {
: subject);
PrivateKey signingKey = (caKey == null) ? privateKey : caKey;
x509c = createCertificate(publicKey, signingKey, subject, issuer, keyUsage, ca,
+ extendedKeyUsages, criticalExtendedKeyUsages,
subjectAltNames,
permittedNameConstraints, excludedNameConstraints);
}
@@ -456,9 +485,11 @@ public final class TestKeyStore extends Assert {
return createCertificate(publicKey, privateKey,
principal, principal,
0, true,
- new Vector<GeneralName>(),
- new Vector<GeneralSubtree>(),
- new Vector<GeneralSubtree>());
+ new ArrayList<KeyPurposeId>(),
+ new ArrayList<Boolean>(),
+ new ArrayList<GeneralName>(),
+ new ArrayList<GeneralSubtree>(),
+ new ArrayList<GeneralSubtree>());
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -471,9 +502,11 @@ public final class TestKeyStore extends Assert {
X500Principal issuer,
int keyUsage,
boolean ca,
+ List<KeyPurposeId> extendedKeyUsages,
+ List<Boolean> criticalExtendedKeyUsages,
List<GeneralName> subjectAltNames,
- Vector<GeneralSubtree> permittedNameConstraints,
- Vector<GeneralSubtree> excludedNameConstraints) throws Exception {
+ List<GeneralSubtree> permittedNameConstraints,
+ List<GeneralSubtree> excludedNameConstraints) throws Exception {
// Note that there is no way to programmatically make a
// Certificate using java.* or javax.* APIs. The
// CertificateFactory interface assumes you want to read
@@ -520,6 +553,13 @@ public final class TestKeyStore extends Assert {
true,
new BasicConstraints(true));
}
+ for (int i = 0; i < extendedKeyUsages.size(); i++) {
+ KeyPurposeId keyPurposeId = extendedKeyUsages.get(i);
+ boolean critical = criticalExtendedKeyUsages.get(i);
+ x509cg.addExtension(X509Extensions.ExtendedKeyUsage,
+ critical,
+ new ExtendedKeyUsage(keyPurposeId));
+ }
for (GeneralName subjectAltName : subjectAltNames) {
x509cg.addExtension(X509Extensions.SubjectAlternativeName,
false,
@@ -592,10 +632,6 @@ public final class TestKeyStore extends Assert {
/**
* Create an empty KeyStore
- *
- * The KeyStore is optionally password protected by the
- * keyStorePassword argument, which can be null if a password is
- * not desired.
*/
public static KeyStore createKeyStore() {
try {
@@ -815,6 +851,13 @@ public final class TestKeyStore extends Assert {
/**
* Dump a key store for debugging.
*/
+ public void dump(String context) throws KeyStoreException, NoSuchAlgorithmException {
+ dump(context, keyStore, keyPassword);
+ }
+
+ /**
+ * Dump a key store for debugging.
+ */
public static void dump(String context, KeyStore keyStore, char[] keyPassword)
throws KeyStoreException, NoSuchAlgorithmException {
PrintStream out = System.out;