summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java2
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java10
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java38
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java52
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java6
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java55
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java6
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java29
-rw-r--r--luni/src/main/native/NativeCrypto.cpp181
-rw-r--r--luni/src/test/java/java/net/URLConnectionTest.java22
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLContextTest.java17
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLEngineTest.java73
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java101
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSessionTest.java27
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSocketTest.java93
-rw-r--r--support/src/test/java/java/security/StandardNames.java7
-rw-r--r--support/src/test/java/javax/net/ssl/TestKeyStore.java295
-rw-r--r--support/src/test/java/javax/net/ssl/TestSSLContext.java156
-rw-r--r--support/src/test/java/javax/net/ssl/TestSSLEnginePair.java16
-rw-r--r--support/src/test/java/javax/net/ssl/TestSSLSocketPair.java2
20 files changed, 854 insertions, 334 deletions
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
index 609a448..5057518 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
@@ -34,7 +34,7 @@ import javax.net.ssl.TrustManagerFactory;
/**
* Support class for this package.
*/
-public final class DefaultSSLContextImpl extends SSLContextImpl {
+public final class DefaultSSLContextImpl extends OpenSSLContextImpl {
/**
* Accessed by SSLContextImpl(DefaultSSLContextImpl) holding the
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
index 35cac53..62b6560 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
@@ -110,15 +110,13 @@ public final class JSSEProvider extends Provider {
super("HarmonyJSSE", 1.0, "Harmony JSSE Provider");
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
+ put("SSLContext.SSL", SSLContextImpl.class.getName());
+ put("SSLContext.SSLv3", SSLContextImpl.class.getName());
put("SSLContext.TLS", SSLContextImpl.class.getName());
- put("Alg.Alias.SSLContext.TLSv1", "TLS");
+ put("SSLContext.TLSv1", SSLContextImpl.class.getName());
+
put("KeyManagerFactory.X509", KeyManagerFactoryImpl.class.getName());
put("TrustManagerFactory.X509", TrustManagerFactoryImpl.class.getName());
- // BEGIN android-added
- put("SSLContext.Default", DefaultSSLContextImpl.class.getName());
- put("SSLContext.SSL", SSLContextImpl.class.getName());
- put("Alg.Alias.SSLContext.SSLv3", "SSL");
- // END android-added
return null;
}
});
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
index 63275f0..5de1e8e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
@@ -254,7 +254,30 @@ public final class NativeCrypto {
public static native int SSL_new(int ssl_ctx) throws IOException;
- public static final String[] KEY_TYPES = new String[] { "RSA", "DSA", "DH_RSA" , "DH_DSA" };
+ public static final String[] KEY_TYPES = new String[] {
+ "RSA",
+ "DSA",
+ "DH_RSA",
+ "DH_DSA",
+ "EC"
+ };
+
+ public static String keyType(int keyType) {
+ switch (keyType) {
+ case 1: // TLS_CT_RSA_SIGN
+ return "RSA";
+ case 2: // TLS_CT_DSS_SIGN
+ return "DSA";
+ case 3: // TLS_CT_RSA_FIXED_DH
+ return "DH_RSA";
+ case 4: // TLS_CT_DSS_FIXED_DH
+ return "DH_DSA";
+ case 64: // TLS_CT_ECDSA_SIGN
+ return "EC";
+ default:
+ return null;
+ }
+ }
public static native void SSL_use_certificate(int ssl, byte[][] asn1DerEncodedCertificate);
@@ -414,7 +437,7 @@ public final class NativeCrypto {
public static native byte[] SSL_SESSION_session_id(int sslSessionNativePointer);
/**
- * Returns the X509 certificates of the peer in the PEM format.
+ * Returns the ASN.1 DER encoded X509 certificates of the peer.
*/
public static native byte[][] SSL_SESSION_get_peer_cert_chain(int sslCtxNativePointer,
int sslSessionNativePointer);
@@ -439,12 +462,12 @@ public final class NativeCrypto {
/**
* Verify that we trust the certificate chain is trusted.
*
- * @param bytes An array of certficates in PEM encode bytes
+ * @param asn1DerEncodedCertificate An array of ASN.1 DER encoded certficates
* @param authMethod auth algorithm name
*
* @throws CertificateException if the certificate is untrusted
*/
- public void verifyCertificateChain(byte[][] bytes, String authMethod)
+ public void verifyCertificateChain(byte[][] asn1DerEncodedCertificate, String authMethod)
throws CertificateException;
/**
@@ -454,9 +477,12 @@ public final class NativeCrypto {
* certificate if has an appropriate one available, similar to
* how the server provides its certificate.
*
- * @param keyType One of KEY_TYPES such as RSA or DSA
+ * @param keyTypes key types supported by the server,
+ * convertible to strings with #keyType
+ * @param asn1DerEncodedX500Principals CAs known to the server
*/
- public void clientCertificateRequested(String keyType)
+ public void clientCertificateRequested(byte[] keyTypes,
+ byte[][] asn1DerEncodedX500Principals)
throws IOException;
/**
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
new file mode 100644
index 0000000..b4e4a46
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.xnet.provider.jsse;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * Overrides the original SSLContextImpl to provide OpenSSL-based
+ * SSLSocketFactory and SSLServerSocketFactory instances.
+ */
+public class OpenSSLContextImpl extends SSLContextImpl {
+
+ public OpenSSLContextImpl() {}
+
+ protected OpenSSLContextImpl(DefaultSSLContextImpl dummy)
+ throws GeneralSecurityException, IOException {
+ super(dummy);
+ }
+
+ @Override
+ public SSLSocketFactory engineGetSocketFactory() {
+ if (sslParameters == null) {
+ throw new IllegalStateException("SSLContext is not initialized.");
+ }
+ return new OpenSSLSocketFactoryImpl(sslParameters);
+ }
+
+ @Override
+ public SSLServerSocketFactory engineGetServerSocketFactory() {
+ if (sslParameters == null) {
+ throw new IllegalStateException("SSLContext is not initialized.");
+ }
+ return new OpenSSLServerSocketFactoryImpl(sslParameters);
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
index 01681f1..4c8ad3a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
@@ -23,6 +23,12 @@ public final class OpenSSLProvider extends Provider {
public OpenSSLProvider() {
super("AndroidOpenSSL", 1.0, "Android's OpenSSL-backed security provider");
+ put("SSLContext.SSL", OpenSSLContextImpl.class.getName());
+ put("SSLContext.SSLv3", OpenSSLContextImpl.class.getName());
+ put("SSLContext.TLS", OpenSSLContextImpl.class.getName());
+ put("SSLContext.TLSv1", OpenSSLContextImpl.class.getName());
+ put("SSLContext.Default", DefaultSSLContextImpl.class.getName());
+
put("MessageDigest.SHA-1",
"org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1");
put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
index 0435717..3349926 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
@@ -35,6 +35,7 @@ import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
+import javax.security.auth.x500.X500Principal;
import org.apache.harmony.security.provider.cert.X509CertImpl;
/**
@@ -308,7 +309,7 @@ public class OpenSSLSocketImpl
for (String keyType : NativeCrypto.KEY_TYPES) {
setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType,
null,
- null));
+ this));
}
}
@@ -354,6 +355,18 @@ public class OpenSSLSocketImpl
NativeCrypto.SSL_VERIFY_CLIENT_ONCE);
}
// ... and it defaults properly so we don't need call SSL_set_verify in the common case.
+
+ // TODO Need to call SSL_CTX_set_client_CA_list to notify trusted issuers to client
+ //
+ // From SSL_CTX_load_verify_locations(3SSL)
+ // In server mode, when requesting a client
+ // certificate, the server must send the list of CAs
+ // of which it will accept client certificates. This
+ // list is not influenced by the contents of CAfile or
+ // CApath and must explicitly be set using the
+ // SSL_CTX_set_client_CA_list(3) family of functions.
+ //
+ // We can get the list from sslParameters.getTrustManager().getAcceptedIssuers()
}
if (client && full) {
@@ -398,15 +411,7 @@ public class OpenSSLSocketImpl
} else {
localCertificates = new X509Certificate[localCertificatesBytes.length];
for (int i = 0; i < localCertificatesBytes.length; i++) {
- try {
- // TODO do not go through PEM decode, DER encode, DER decode
- localCertificates[i]
- = new X509CertImpl(
- javax.security.cert.X509Certificate.getInstance(
- localCertificatesBytes[i]).getEncoded());
- } catch (javax.security.cert.CertificateException e) {
- throw new IOException("Problem decoding local certificate", e);
- }
+ localCertificates[i] = new X509CertImpl(localCertificatesBytes[i]);
}
}
@@ -441,7 +446,7 @@ public class OpenSSLSocketImpl
}
- private void setCertificate (String alias) throws IOException {
+ private void setCertificate(String alias) throws IOException {
if (alias == null) {
return;
}
@@ -459,9 +464,6 @@ public class OpenSSLSocketImpl
throw new IOException("Problem encoding certificate " + certificates[i], e);
}
}
- // TODO SSL_use_certificate only looks at the first certificate in the chain.
- // It would be better to use a custom version of SSL_CTX_use_certificate_chain_file
- // to set the whole chain. Note there is no SSL_ equivalent of this SSL_CTX_ function.
NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
// checks the last installed private key and certificate,
@@ -473,10 +475,25 @@ public class OpenSSLSocketImpl
* Implementation of NativeCrypto.SSLHandshakeCallbacks
* invoked via JNI from client_cert_cb
*/
- public void clientCertificateRequested(String keyType) throws IOException {
- setCertificate(sslParameters.getKeyManager().chooseClientAlias(new String[] { keyType },
- null,
- null));
+ public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
+ throws IOException {
+
+ String[] keyTypes = new String[keyTypeBytes.length];
+ for (int i = 0; i < keyTypeBytes.length; i++) {
+ keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
+ }
+
+ X500Principal[] issuers;
+ if (asn1DerEncodedPrincipals == null) {
+ issuers = null;
+ } else {
+ issuers = new X500Principal[asn1DerEncodedPrincipals.length];
+ for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) {
+ issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]);
+ }
+ }
+
+ setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this));
}
/**
@@ -533,7 +550,7 @@ public class OpenSSLSocketImpl
/**
* Implementation of NativeCrypto.SSLHandshakeCallbacks
*
- * @param bytes An array of certficates in PEM encode bytes
+ * @param bytes An array of ASN.1 DER encoded certficates
* @param authMethod auth algorithm name
*
* @throws CertificateException if the certificate is untrusted
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
index 06f569b..44f6c7f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
@@ -56,6 +56,7 @@ public class SSLContextImpl extends SSLContextSpi {
clientSessionContext = new ClientSessionContext();
serverSessionContext = new ServerSessionContext();
}
+
/**
* Constuctor for the DefaultSSLContextImpl.
* @param dummy is null, used to distinguish this case from the
@@ -110,11 +111,12 @@ public class SSLContextImpl extends SSLContextSpi {
engineGetServerSessionContext().setPersistentCache(serverCache);
}
+ @Override
public SSLSocketFactory engineGetSocketFactory() {
if (sslParameters == null) {
throw new IllegalStateException("SSLContext is not initialized.");
}
- return new OpenSSLSocketFactoryImpl(sslParameters);
+ return new SSLSocketFactoryImpl(sslParameters);
}
@Override
@@ -122,7 +124,7 @@ public class SSLContextImpl extends SSLContextSpi {
if (sslParameters == null) {
throw new IllegalStateException("SSLContext is not initialized.");
}
- return new OpenSSLServerSocketFactoryImpl(sslParameters);
+ return new SSLServerSocketFactoryImpl(sslParameters);
}
@Override
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 502396e..8ccf085 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
@@ -20,8 +20,10 @@ package org.apache.harmony.xnet.provider.jsse;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
+import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
@@ -32,15 +34,8 @@ import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-
import javax.net.ssl.X509TrustManager;
-// BEGIN android-added
-import java.lang.reflect.Method;
-import java.security.cert.CertPath;
-import java.security.cert.CertificateEncodingException;
-// END android-added
-
/**
*
* TrustManager implementation. The implementation is based on CertPathValidator
@@ -109,7 +104,7 @@ public class TrustManagerImpl implements X509TrustManager {
throw new CertificateException(err);
}
// BEGIN android-added
- // Cater for degenerate special case where we can't
+ // Caters to degenerate special case where we can't
// establish an actual certificate chain the usual way,
// but have the peer certificate in our trust store.
if (isDirectlyTrustedCert(chain)) {
@@ -122,7 +117,8 @@ public class TrustManagerImpl implements X509TrustManager {
if (!Arrays.equals(chain[0].getEncoded(),
((X509Certificate)certPath.getCertificates().get(0))
.getEncoded())) {
- // sanity check failed (shouldn't ever happen, but we are using pretty remote code)
+ // Sanity check failed (shouldn't ever happen, but we
+ // are using pretty remote code)
throw new CertificateException("Certificate chain error");
}
validator.validate(certPath, params);
@@ -142,29 +138,29 @@ public class TrustManagerImpl implements X509TrustManager {
throws CertificateException {
if (chain == null || chain.length == 0 || authType == null
|| authType.length() == 0) {
- throw new IllegalArgumentException(
- "null or zero-length parameter");
+ throw new IllegalArgumentException("null or zero-length parameter");
}
if (err != null) {
throw new CertificateException(err);
}
-// BEGIN android-changed
+ // BEGIN android-changed
CertificateException ce = null;
try {
- CertPath certPath = factory.generateCertPath(
- Arrays.asList(chain));
+ CertPath certPath = factory.generateCertPath(Arrays.asList(chain));
if (!Arrays.equals(chain[0].getEncoded(),
certPath.getCertificates().get(0).getEncoded())) {
- // Sanity check failed (shouldn't ever happen, but we are
- // using pretty remote code)
+ // Sanity check failed (shouldn't ever happen, but we
+ // are using pretty remote code)
throw new CertificateException("Certificate chain error");
}
validator.validate(certPath, params);
+ // END android-changed
} catch (InvalidAlgorithmParameterException e) {
ce = new CertificateException(e);
} catch (CertPathValidatorException e) {
ce = new CertificateException(e);
}
+ // BEGIN android-added
if (ce != null) {
// Caters to degenerate special case where we can't
// establish an actual certificate chain the usual way
@@ -173,6 +169,7 @@ public class TrustManagerImpl implements X509TrustManager {
throw ce;
}
}
+ // END android-added
}
/**
diff --git a/luni/src/main/native/NativeCrypto.cpp b/luni/src/main/native/NativeCrypto.cpp
index c3c4a91..3f1825b 100644
--- a/luni/src/main/native/NativeCrypto.cpp
+++ b/luni/src/main/native/NativeCrypto.cpp
@@ -151,6 +151,11 @@ static void freeSslErrorState(void) {
ERR_remove_state(0);
}
+// FIXME: move to JNIHelp.h
+static void jniThrowOutOfMemoryError(JNIEnv* env, const char* message) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", message);
+}
+
/*
* Checks this thread's OpenSSL error queue and throws a RuntimeException if
* necessary.
@@ -1035,37 +1040,74 @@ static jobjectArray getCertificateBytes(JNIEnv* env, const STACK_OF(X509)* chain
return NULL;
}
- Unique_BIO bio(BIO_new(BIO_s_mem()));
- if (bio.get() == NULL) {
- jniThrowRuntimeException(env, "BIO_new failed");
+ for (int i = 0; i < count; i++) {
+ X509* cert = sk_X509_value(chain, i);
+
+ int len = i2d_X509(cert, NULL);
+ if (len < 0) {
+ return NULL;
+ }
+ ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
+ if (byteArray.get() == NULL) {
+ return NULL;
+ }
+ ScopedByteArrayRW bytes(env, byteArray.get());
+ if (bytes.get() == NULL) {
+ return NULL;
+ }
+ unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
+ int n = i2d_X509(cert, &p);
+ if (n < 0) {
+ return NULL;
+ }
+ env->SetObjectArrayElement(joa, i, byteArray.get());
+ }
+
+ return joa;
+}
+
+/**
+ * Returns an array containing all the X500 principal's bytes.
+ */
+static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
+{
+ if (names == NULL) {
return NULL;
}
- // LOGD("Start fetching the certificates");
- for (int i = 0; i < count; i++) {
- X509* cert = sk_X509_value(chain, i);
+ int count = sk_X509_NAME_num(names);
+ if (count <= 0) {
+ return NULL;
+ }
- BIO_reset(bio.get());
- PEM_write_bio_X509(bio.get(), cert);
+ jobjectArray joa = env->NewObjectArray(count, JniConstants::byteArrayClass, NULL);
+ if (joa == NULL) {
+ return NULL;
+ }
- BUF_MEM* bptr;
- BIO_get_mem_ptr(bio.get(), &bptr);
- jbyteArray bytes = env->NewByteArray(bptr->length);
+ for (int i = 0; i < count; i++) {
+ X509_NAME* principal = sk_X509_NAME_value(names, i);
- if (bytes == NULL) {
- /*
- * Indicate an error by resetting joa to NULL. It will
- * eventually get gc'ed.
- */
- joa = NULL;
- break;
+ int len = i2d_X509_NAME(principal, NULL);
+ if (len < 0) {
+ return NULL;
+ }
+ ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
+ if (byteArray.get() == NULL) {
+ return NULL;
+ }
+ ScopedByteArrayRW bytes(env, byteArray.get());
+ if (bytes.get() == NULL) {
+ return NULL;
+ }
+ unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
+ int n = i2d_X509_NAME(principal, &p);
+ if (n < 0) {
+ return NULL;
}
- jbyte* src = reinterpret_cast<jbyte*>(bptr->data);
- env->SetByteArrayRegion(bytes, 0, bptr->length, src);
- env->SetObjectArrayElement(joa, i, bytes);
+ env->SetObjectArrayElement(joa, i, byteArray.get());
}
- // LOGD("Certificate fetching complete");
return joa;
}
@@ -1492,14 +1534,37 @@ static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
jmethodID methodID
- = env->GetMethodID(cls, "clientCertificateRequested", "(Ljava/lang/String;)V");
+ = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
// Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
- const char* authMethod = SSL_authentication_method(ssl);
- JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested authMethod=%s",
- ssl, authMethod);
- jstring authMethodString = env->NewStringUTF(authMethod);
- env->CallVoidMethod(sslHandshakeCallbacks, methodID, authMethodString);
+ char ssl2_ctype = SSL3_CT_RSA_SIGN;
+ const char* ctype = NULL;
+ int ctype_num = 0;
+ jobjectArray issuers = NULL;
+ switch (ssl->version) {
+ case SSL2_VERSION:
+ ctype = &ssl2_ctype;
+ ctype_num = 1;
+ break;
+ case SSL3_VERSION:
+ case TLS1_VERSION:
+ case DTLS1_VERSION:
+ ctype = ssl->s3->tmp.ctype;
+ ctype_num = ssl->s3->tmp.ctype_num;
+ issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
+ break;
+ }
+
+ jbyteArray keyTypes = env->NewByteArray(ctype_num);
+ if (keyTypes == NULL) {
+ JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
+ return 0;
+ }
+ env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
+
+ JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
+ "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
+ env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
if (env->ExceptionCheck()) {
JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
@@ -1812,6 +1877,29 @@ static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
return;
}
+ Unique_sk_X509 chain(sk_X509_new_null());
+ if (chain.get() == NULL) {
+ jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
+ return;
+ }
+ for (int i = 1; i < length; i++) {
+ if (!sk_X509_push(chain.get(), certificatesX509[i].release())) {
+ jniThrowOutOfMemoryError(env, "Unable to push certificate");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
+ return;
+ }
+ }
+ int chainResult = SSL_use_certificate_chain(ssl, chain.get());
+ if (chainResult == 0) {
+ throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
+ ssl);
+ return;
+ } else {
+ chain.release();
+ }
+
JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
}
@@ -1957,7 +2045,11 @@ static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
if ((strcmp(c.c_str(), cipher->name) == 0)
&& (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
- sk_SSL_CIPHER_push(cipherstack.get(), cipher);
+ if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
+ jniThrowOutOfMemoryError(env, "Unable to push cipher");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
+ return;
+ }
found = true;
}
}
@@ -2228,17 +2320,27 @@ static jobjectArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jint s
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
return NULL;
}
- // TODO convert from single certificate to chain properly. One
- // option would be to have the chain remembered where
- // SSL_use_certificate is used. Another would be to save the
- // intermediate CAs with SSL_CTX SSL_CTX_add_extra_chain_cert.
+
Unique_sk_X509 chain(sk_X509_new_null());
if (chain.get() == NULL) {
- jniThrowRuntimeException(env, "Unable to allocate local certificate chain");
+ jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
return NULL;
}
- sk_X509_push(chain.get(), certificate);
+ if (!sk_X509_push(chain.get(), certificate)) {
+ jniThrowOutOfMemoryError(env, "Unable to push local certificate");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
+ return NULL;
+ }
+ STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
+ for (int i=0; i<sk_X509_num(cert_chain); i++) {
+ if (!sk_X509_push(chain.get(), sk_X509_value(cert_chain,i))) {
+ jniThrowOutOfMemoryError(env, "Unable to push local certificate chain");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
+ return NULL;
+ }
+ }
+
jobjectArray objectArray = getCertificateBytes(env, chain.get());
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, objectArray);
return objectArray;
@@ -2438,7 +2540,7 @@ static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint
// See sslRead() regarding improper failure to handle normal cases.
throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Read error");
result = -1;
- } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
+ } else if (ret == THROW_SOCKETTIMEOUTEXCEPTION) {
throwSocketTimeoutException(env, "Read timed out");
result = -1;
} else {
@@ -2593,7 +2695,7 @@ static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address, j
if (ret == THROW_EXCEPTION) {
// See sslWrite() regarding improper failure to handle normal cases.
throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
- } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
+ } else if (ret == THROW_SOCKETTIMEOUTEXCEPTION) {
throwSocketTimeoutException(env, "Write timed out");
}
}
@@ -2627,7 +2729,7 @@ static void NativeCrypto_SSL_write(JNIEnv* env, jclass,
if (ret == THROW_EXCEPTION) {
// See sslWrite() regarding improper failure to handle normal cases.
throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
- } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
+ } else if (ret == THROW_SOCKETTIMEOUTEXCEPTION) {
throwSocketTimeoutException(env, "Write timed out");
}
}
@@ -2880,7 +2982,8 @@ static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jint ssl_ses
if (bytes != NULL) {
ScopedByteArrayRW tmp(env, bytes);
if (tmp.get() == NULL) {
- JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => threw exception");
+ JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => threw exception",
+ ssl_session);
return NULL;
}
unsigned char* ucp = reinterpret_cast<unsigned char*>(tmp.get());
diff --git a/luni/src/test/java/java/net/URLConnectionTest.java b/luni/src/test/java/java/net/URLConnectionTest.java
index 87de3b5..4c6bd83 100644
--- a/luni/src/test/java/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/java/net/URLConnectionTest.java
@@ -261,12 +261,12 @@ public class URLConnectionTest extends junit.framework.TestCase {
public void testConnectViaHttps() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), false);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
server.play();
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/foo").openConnection();
- connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory());
+ connection.setSSLSocketFactory(testSSLContext.serverContext.getSocketFactory());
assertContent("this response comes via HTTPS", connection);
@@ -277,14 +277,14 @@ public class URLConnectionTest extends junit.framework.TestCase {
public void testConnectViaHttpsReusingConnections() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), false);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
server.enqueue(new MockResponse().setBody("another response via HTTPS"));
server.play();
// install a custom SSL socket factory so the server can be authorized
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory());
+ connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
assertContent("this response comes via HTTPS", connection);
// without an SSL socket factory, the connection should fail
@@ -339,7 +339,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
public void testConnectViaHttpProxyToHttps() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), true);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
server.enqueue(new MockResponse().clearHeaders()); // for CONNECT
server.enqueue(new MockResponse().setBody("this response comes via a secure proxy"));
server.play();
@@ -347,7 +347,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(
server.toProxyAddress());
- connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory());
+ connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
connection.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
@@ -841,7 +841,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
public void testRedirectedOnHttps() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), false);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
server.enqueue(new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
.addHeader("Location: /foo")
@@ -850,7 +850,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
server.play();
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory());
+ connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
assertEquals("This is the new location!",
readAscii(connection.getInputStream(), Integer.MAX_VALUE));
@@ -863,7 +863,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
public void testNotRedirectedFromHttpsToHttp() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), false);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
server.enqueue(new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
.addHeader("Location: http://anyhost/foo")
@@ -871,7 +871,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
server.play();
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory());
+ connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
assertEquals("This page has moved!",
readAscii(connection.getInputStream(), Integer.MAX_VALUE));
}
@@ -931,7 +931,7 @@ public class URLConnectionTest extends junit.framework.TestCase {
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
try {
TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.sslContext.getSocketFactory(), false);
+ server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
server.enqueue(new MockResponse().setBody("ABC"));
server.enqueue(new MockResponse().setBody("DEF"));
server.enqueue(new MockResponse().setBody("GHI"));
diff --git a/luni/src/test/java/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/javax/net/ssl/SSLContextTest.java
index 9ed372b..104ceee 100644
--- a/luni/src/test/java/javax/net/ssl/SSLContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLContextTest.java
@@ -83,7 +83,7 @@ public class SSLContextTest extends TestCase {
}
}
try {
- SSLContext.getInstance(null, StandardNames.PROVIDER_NAME);
+ SSLContext.getInstance(null, StandardNames.JSSE_PROVIDER_NAME);
fail();
} catch (NullPointerException expected) {
}
@@ -100,7 +100,7 @@ public class SSLContextTest extends TestCase {
public void test_SSLContext_getProvider() throws Exception {
Provider provider = SSLContext.getDefault().getProvider();
assertNotNull(provider);
- assertEquals(StandardNames.PROVIDER_NAME, provider.getName());
+ assertEquals(StandardNames.JSSE_PROVIDER_NAME, provider.getName());
}
public void test_SSLContext_init() throws Exception {
@@ -286,9 +286,16 @@ public class SSLContextTest extends TestCase {
public void test_SSLContextTest_TestSSLContext_create() {
TestSSLContext testContext = TestSSLContext.create();
assertNotNull(testContext);
- assertNotNull(testContext.keyStore);
- assertNull(testContext.keyStorePassword);
- assertNotNull(testContext.sslContext);
+ assertNotNull(testContext.clientKeyStore);
+ assertNull(testContext.clientKeyStorePassword);
+ assertNotNull(testContext.serverKeyStore);
+ assertNull(testContext.serverKeyStorePassword);
+ assertNotNull(testContext.clientKeyManager);
+ assertNotNull(testContext.serverKeyManager);
+ assertNotNull(testContext.clientTrustManager);
+ assertNotNull(testContext.serverTrustManager);
+ assertNotNull(testContext.clientContext);
+ assertNotNull(testContext.serverContext);
assertNotNull(testContext.serverSocket);
assertNotNull(testContext.host);
assertTrue(testContext.port != 0);
diff --git a/luni/src/test/java/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/javax/net/ssl/SSLEngineTest.java
index 2aa43dd..e731345 100644
--- a/luni/src/test/java/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLEngineTest.java
@@ -53,7 +53,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getSupportedCipherSuites_names() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
String[] cipherSuites = e.getSupportedCipherSuites();
StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE,
cipherSuites);
@@ -62,8 +62,15 @@ public class SSLEngineTest extends TestCase {
@KnownFailure("No *_WITH_NULL_* ciphers work because of 'Invalid transformation: null'")
public void test_SSLEngine_getSupportedCipherSuites_connect() throws Exception {
- String[] cipherSuites
- = SSLContext.getDefault().createSSLEngine().getSupportedCipherSuites();
+ // note the rare usage of DSA keys here in addition to RSA
+ TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" },
+ null,
+ "rsa-dsa",
+ TestKeyStore.localhost(),
+ true,
+ null);
+ TestSSLContext c = TestSSLContext.create(testKeyStore, testKeyStore);
+ String[] cipherSuites = c.clientContext.createSSLEngine().getSupportedCipherSuites();
for (String cipherSuite : cipherSuites) {
/*
* Kerberos cipher suites require external setup. See "Kerberos Requirements" in
@@ -72,9 +79,9 @@ public class SSLEngineTest extends TestCase {
if (cipherSuite.startsWith("TLS_KRB5_")) {
continue;
}
- System.out.println("Trying to connect cipher suite " + cipherSuite);
+ // System.out.println("Trying to connect cipher suite " + cipherSuite);
final String[] cipherSuiteArray = new String[] { cipherSuite };
- assertConnected(TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+ assertConnected(TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
client.setEnabledCipherSuites(cipherSuiteArray);
@@ -86,7 +93,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getEnabledCipherSuites() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
String[] cipherSuites = e.getEnabledCipherSuites();
StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE,
cipherSuites);
@@ -95,7 +102,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_setEnabledCipherSuites() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
try {
e.setEnabledCipherSuites(null);
@@ -120,7 +127,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getSupportedProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
String[] protocols = e.getSupportedProtocols();
StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
assertNotSame(protocols, e.getSupportedProtocols());
@@ -128,7 +135,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getEnabledProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
String[] protocols = e.getEnabledProtocols();
StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
assertNotSame(protocols, e.getEnabledProtocols());
@@ -136,7 +143,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_setEnabledProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
try {
e.setEnabledProtocols(null);
@@ -160,7 +167,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getSession() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
SSLSession session = e.getSession();
assertNotNull(session);
assertFalse(session.isValid());
@@ -170,7 +177,7 @@ public class SSLEngineTest extends TestCase {
TestSSLContext c = TestSSLContext.create();
try {
- c.sslContext.createSSLEngine().beginHandshake();
+ c.clientContext.createSSLEngine().beginHandshake();
fail();
} catch (IllegalStateException expected) {
}
@@ -180,27 +187,26 @@ public class SSLEngineTest extends TestCase {
@KnownFailure("NO SERVER CERTIFICATE FOUND")
public void test_SSLEngine_beginHandshake_noKeyStore() throws Exception {
- TestSSLContext c = TestSSLContext.create(null, null);
+ TestSSLContext c = TestSSLContext.create(null, null, null, null);
try {
// TODO Fix KnownFailure AlertException "NO SERVER CERTIFICATE FOUND"
// ServerHandshakeImpl.selectSuite should not select a suite without a required cert
- TestSSLEnginePair.connect(c, c, null);
+ TestSSLEnginePair.connect(c, null);
fail();
} catch (SSLHandshakeException expected) {
}
}
public void test_SSLEngine_beginHandshake_noClientCertificate() throws Exception {
- TestSSLContext serverContext = TestSSLContext.create();
- TestSSLContext clientContext = TestSSLContext.createClient(serverContext);
- SSLEngine[] engines = TestSSLEnginePair.connect(clientContext, serverContext, null);
+ TestSSLContext c = TestSSLContext.create();
+ SSLEngine[] engines = TestSSLEnginePair.connect(c, null);
assertConnected(engines[0], engines[1]);
}
public void test_SSLEngine_getUseClientMode() throws Exception {
TestSSLContext c = TestSSLContext.create();
- assertFalse(c.sslContext.createSSLEngine().getUseClientMode());
- assertFalse(c.sslContext.createSSLEngine(null, -1).getUseClientMode());
+ assertFalse(c.clientContext.createSSLEngine().getUseClientMode());
+ assertFalse(c.clientContext.createSSLEngine(null, -1).getUseClientMode());
}
@KnownFailure("SSLHandshakeException instead assertNotConnected")
@@ -221,7 +227,14 @@ public class SSLEngineTest extends TestCase {
private TestSSLEnginePair test_SSLEngine_setUseClientMode(final boolean clientClientMode,
final boolean serverClientMode)
throws Exception {
- return TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+ TestSSLContext c;
+ if (!clientClientMode && serverClientMode) {
+ c = TestSSLContext.create(TestKeyStore.getServer(), TestKeyStore.getClient());
+ } else {
+ c = TestSSLContext.create();
+ }
+
+ return TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
client.setUseClientMode(clientClientMode);
@@ -233,7 +246,7 @@ public class SSLEngineTest extends TestCase {
@KnownFailure("init - invalid private key")
public void test_SSLEngine_clientAuth() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
assertFalse(e.getWantClientAuth());
assertFalse(e.getNeedClientAuth());
@@ -254,20 +267,26 @@ public class SSLEngineTest extends TestCase {
assertFalse(e.getNeedClientAuth());
// TODO Fix KnownFailure "init - invalid private key"
- TestSSLEnginePair p = TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+ TestSSLContext clientAuthContext
+ = TestSSLContext.create(TestKeyStore.getClientCertificate(),
+ TestKeyStore.getServer());
+ TestSSLEnginePair p = TestSSLEnginePair.create(clientAuthContext,
+ new TestSSLEnginePair.Hooks() {
@Override
- void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+ void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
server.setWantClientAuth(true);
}
});
assertConnected(p);
assertNotNull(p.client.getSession().getLocalCertificates());
- assertEquals(1, p.client.getSession().getLocalCertificates().length);
+ TestKeyStore.assertChainLength(p.client.getSession().getLocalCertificates());
+ TestSSLContext.assertClientCertificateChain(clientAuthContext.clientTrustManager,
+ p.client.getSession().getLocalCertificates());
}
public void test_SSLEngine_getEnableSessionCreation() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
assertTrue(e.getEnableSessionCreation());
}
@@ -298,7 +317,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_getSSLParameters() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
SSLParameters p = e.getSSLParameters();
assertNotNull(p);
@@ -320,7 +339,7 @@ public class SSLEngineTest extends TestCase {
public void test_SSLEngine_setSSLParameters() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLEngine e = c.sslContext.createSSLEngine();
+ SSLEngine e = c.clientContext.createSSLEngine();
String[] defaultCipherSuites = e.getEnabledCipherSuites();
String[] defaultProtocols = e.getEnabledProtocols();
String[] supportedCipherSuites = e.getSupportedCipherSuites();
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
index 7e2cbd0..0b258b5 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
@@ -25,10 +25,13 @@ import junit.framework.TestCase;
public class SSLSessionContextTest extends TestCase {
- public static final void assertSSLSessionContextSize(int expected, SSLContext sslContext) {
+ public static final void assertSSLSessionContextSize(int expected, TestSSLContext c) {
assertSSLSessionContextSize(expected,
- sslContext.getClientSessionContext(),
- sslContext.getServerSessionContext());
+ c.clientContext.getClientSessionContext(),
+ c.serverContext.getServerSessionContext());
+ assertSSLSessionContextSize(0,
+ c.serverContext.getClientSessionContext(),
+ c.clientContext.getServerSessionContext());
}
public static final void assertSSLSessionContextSize(int expected,
@@ -51,12 +54,12 @@ public class SSLSessionContextTest extends TestCase {
public void test_SSLSessionContext_getIds() {
TestSSLContext c = TestSSLContext.create();
- assertSSLSessionContextSize(0, c.sslContext);
+ assertSSLSessionContextSize(0, c);
TestSSLSocketPair s = TestSSLSocketPair.create();
- assertSSLSessionContextSize(1, s.c.sslContext);
- Enumeration clientIds = s.c.sslContext.getClientSessionContext().getIds();
- Enumeration serverIds = s.c.sslContext.getServerSessionContext().getIds();
+ assertSSLSessionContextSize(1, s.c);
+ Enumeration clientIds = s.c.clientContext.getClientSessionContext().getIds();
+ Enumeration serverIds = s.c.serverContext.getServerSessionContext().getIds();
byte[] clientId = (byte[]) clientIds.nextElement();
assertEquals(32, clientId.length);
if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
@@ -71,23 +74,23 @@ public class SSLSessionContextTest extends TestCase {
public void test_SSLSessionContext_getSession() {
TestSSLContext c = TestSSLContext.create();
try {
- c.sslContext.getClientSessionContext().getSession(null);
+ c.clientContext.getClientSessionContext().getSession(null);
fail();
} catch (NullPointerException expected) {
}
- assertNull(c.sslContext.getClientSessionContext().getSession(new byte[0]));
- assertNull(c.sslContext.getClientSessionContext().getSession(new byte[1]));
+ assertNull(c.clientContext.getClientSessionContext().getSession(new byte[0]));
+ assertNull(c.clientContext.getClientSessionContext().getSession(new byte[1]));
try {
- c.sslContext.getServerSessionContext().getSession(null);
+ c.serverContext.getServerSessionContext().getSession(null);
fail();
} catch (NullPointerException expected) {
}
- assertNull(c.sslContext.getServerSessionContext().getSession(new byte[0]));
- assertNull(c.sslContext.getServerSessionContext().getSession(new byte[1]));
+ assertNull(c.serverContext.getServerSessionContext().getSession(new byte[0]));
+ assertNull(c.serverContext.getServerSessionContext().getSession(new byte[1]));
TestSSLSocketPair s = TestSSLSocketPair.create();
- SSLSessionContext client = s.c.sslContext.getClientSessionContext();
- SSLSessionContext server = s.c.sslContext.getServerSessionContext();
+ SSLSessionContext client = s.c.clientContext.getClientSessionContext();
+ SSLSessionContext server = s.c.serverContext.getServerSessionContext();
byte[] clientId = (byte[]) client.getIds().nextElement();
assertNotNull(client.getSession(clientId));
assertTrue(Arrays.equals(clientId, client.getSession(clientId).getId()));
@@ -103,25 +106,25 @@ public class SSLSessionContextTest extends TestCase {
public void test_SSLSessionContext_getSessionCacheSize() {
TestSSLContext c = TestSSLContext.create();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getClientSessionContext().getSessionCacheSize());
+ c.clientContext.getClientSessionContext().getSessionCacheSize());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getServerSessionContext().getSessionCacheSize());
+ c.serverContext.getServerSessionContext().getSessionCacheSize());
TestSSLSocketPair s = TestSSLSocketPair.create();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
- s.c.sslContext.getClientSessionContext().getSessionCacheSize());
+ s.c.clientContext.getClientSessionContext().getSessionCacheSize());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
- s.c.sslContext.getServerSessionContext().getSessionCacheSize());
+ s.c.serverContext.getServerSessionContext().getSessionCacheSize());
}
public void test_SSLSessionContext_setSessionCacheSize_noConnect() {
TestSSLContext c = TestSSLContext.create();
assertNoConnectSetSessionCacheSizeBehavior(
TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getClientSessionContext());
+ c.clientContext.getClientSessionContext());
assertNoConnectSetSessionCacheSizeBehavior(
TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getServerSessionContext());
+ c.serverContext.getServerSessionContext());
}
private static void assertNoConnectSetSessionCacheSizeBehavior(int expectedDefault,
@@ -138,19 +141,19 @@ public class SSLSessionContextTest extends TestCase {
public void test_SSLSessionContext_setSessionCacheSize_oneConnect() {
TestSSLSocketPair s = TestSSLSocketPair.create();
- SSLSessionContext client = s.c.sslContext.getClientSessionContext();
- SSLSessionContext server = s.c.sslContext.getServerSessionContext();
+ SSLSessionContext client = s.c.clientContext.getClientSessionContext();
+ SSLSessionContext server = s.c.serverContext.getServerSessionContext();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
client.getSessionCacheSize());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
server.getSessionCacheSize());
- assertSSLSessionContextSize(1, s.c.sslContext);
+ assertSSLSessionContextSize(1, s.c);
}
public void test_SSLSessionContext_setSessionCacheSize_dynamic() {
TestSSLContext c = TestSSLContext.create();
- SSLSessionContext client = c.sslContext.getClientSessionContext();
- SSLSessionContext server = c.sslContext.getServerSessionContext();
+ SSLSessionContext client = c.clientContext.getClientSessionContext();
+ SSLSessionContext server = c.serverContext.getServerSessionContext();
String[] supportedCipherSuites = c.serverSocket.getSupportedCipherSuites();
c.serverSocket.setEnabledCipherSuites(supportedCipherSuites);
@@ -198,69 +201,69 @@ public class SSLSessionContextTest extends TestCase {
String cipherSuite3 = uniqueCipherSuites.get(2);
TestSSLSocketPair.connect(c, new String[] { cipherSuite1 }, null);
- assertSSLSessionContextSize(1, c.sslContext);
+ assertSSLSessionContextSize(1, c);
TestSSLSocketPair.connect(c, new String[] { cipherSuite2 }, null);
- assertSSLSessionContextSize(2, c.sslContext);
+ assertSSLSessionContextSize(2, c);
TestSSLSocketPair.connect(c, new String[] { cipherSuite3 }, null);
- assertSSLSessionContextSize(3, c.sslContext);
+ assertSSLSessionContextSize(3, c);
client.setSessionCacheSize(1);
server.setSessionCacheSize(1);
assertEquals(1, client.getSessionCacheSize());
assertEquals(1, server.getSessionCacheSize());
- assertSSLSessionContextSize(1, c.sslContext);
+ assertSSLSessionContextSize(1, c);
TestSSLSocketPair.connect(c, new String[] { cipherSuite1 }, null);
- assertSSLSessionContextSize(1, c.sslContext);
+ assertSSLSessionContextSize(1, c);
client.setSessionCacheSize(2);
server.setSessionCacheSize(2);
TestSSLSocketPair.connect(c, new String[] { cipherSuite2 }, null);
- assertSSLSessionContextSize(2, c.sslContext);
+ assertSSLSessionContextSize(2, c);
TestSSLSocketPair.connect(c, new String[] { cipherSuite3 }, null);
- assertSSLSessionContextSize(2, c.sslContext);
+ assertSSLSessionContextSize(2, c);
}
public void test_SSLSessionContext_getSessionTimeout() {
TestSSLContext c = TestSSLContext.create();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- c.sslContext.getClientSessionContext().getSessionTimeout());
+ c.clientContext.getClientSessionContext().getSessionTimeout());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- c.sslContext.getServerSessionContext().getSessionTimeout());
+ c.serverContext.getServerSessionContext().getSessionTimeout());
TestSSLSocketPair s = TestSSLSocketPair.create();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- s.c.sslContext.getClientSessionContext().getSessionTimeout());
+ s.c.clientContext.getClientSessionContext().getSessionTimeout());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- s.c.sslContext.getServerSessionContext().getSessionTimeout());
+ s.c.serverContext.getServerSessionContext().getSessionTimeout());
}
public void test_SSLSessionContext_setSessionTimeout() throws Exception {
TestSSLContext c = TestSSLContext.create();
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- c.sslContext.getClientSessionContext().getSessionTimeout());
+ c.clientContext.getClientSessionContext().getSessionTimeout());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT,
- c.sslContext.getServerSessionContext().getSessionTimeout());
- c.sslContext.getClientSessionContext().setSessionTimeout(0);
- c.sslContext.getServerSessionContext().setSessionTimeout(0);
- assertEquals(0, c.sslContext.getClientSessionContext().getSessionTimeout());
- assertEquals(0, c.sslContext.getServerSessionContext().getSessionTimeout());
+ c.serverContext.getServerSessionContext().getSessionTimeout());
+ c.clientContext.getClientSessionContext().setSessionTimeout(0);
+ c.serverContext.getServerSessionContext().setSessionTimeout(0);
+ assertEquals(0, c.clientContext.getClientSessionContext().getSessionTimeout());
+ assertEquals(0, c.serverContext.getServerSessionContext().getSessionTimeout());
try {
- c.sslContext.getClientSessionContext().setSessionTimeout(-1);
+ c.clientContext.getClientSessionContext().setSessionTimeout(-1);
fail();
} catch (IllegalArgumentException expected) {
}
try {
- c.sslContext.getServerSessionContext().setSessionTimeout(-1);
+ c.serverContext.getServerSessionContext().setSessionTimeout(-1);
fail();
} catch (IllegalArgumentException expected) {
}
TestSSLSocketPair s = TestSSLSocketPair.create();
- assertSSLSessionContextSize(1, s.c.sslContext);
+ assertSSLSessionContextSize(1, s.c);
Thread.sleep(1 * 1000);
- s.c.sslContext.getClientSessionContext().setSessionTimeout(1);
- s.c.sslContext.getServerSessionContext().setSessionTimeout(1);
- assertSSLSessionContextSize(0, s.c.sslContext);
+ s.c.clientContext.getClientSessionContext().setSessionTimeout(1);
+ s.c.serverContext.getServerSessionContext().setSessionTimeout(1);
+ assertSSLSessionContextSize(0, s.c);
}
}
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
index 6435af6..f05b04c 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
@@ -89,9 +89,11 @@ public class SSLSessionTest extends TestCase {
assertNull(s.invalid.getLocalCertificates());
assertNull(s.client.getLocalCertificates());
assertNotNull(s.server.getLocalCertificates());
- assertEquals(1, s.server.getLocalCertificates().length);
+ TestKeyStore.assertChainLength(s.server.getLocalCertificates());
+ TestSSLContext.assertServerCertificateChain(s.s.c.serverTrustManager,
+ s.server.getLocalCertificates());
TestSSLContext.assertCertificateInKeyStore(s.server.getLocalCertificates()[0],
- s.s.c.keyStore);
+ s.s.c.serverKeyStore);
}
public void test_SSLSession_getLocalPrincipal() throws Exception {
@@ -101,7 +103,7 @@ public class SSLSessionTest extends TestCase {
assertNotNull(s.server.getLocalPrincipal());
assertNotNull(s.server.getLocalPrincipal().getName());
TestSSLContext.assertCertificateInKeyStore(s.server.getLocalPrincipal(),
- s.s.c.keyStore);
+ s.s.c.serverKeyStore);
}
public void test_SSLSession_getPacketBufferSize() {
@@ -119,12 +121,9 @@ public class SSLSessionTest extends TestCase {
} catch (SSLPeerUnverifiedException expected) {
}
assertNotNull(s.client.getPeerCertificates());
- assertEquals(1, s.client.getPeerCertificates().length);
- TestSSLContext.assertCertificateInKeyStore(s.client.getPeerCertificates()[0],
- s.s.c.keyStore);
-
+ TestKeyStore.assertChainLength(s.client.getPeerCertificateChain());
try {
- assertNull(s.server.getPeerCertificates());
+ assertNull(s.server.getPeerCertificateChain());
fail();
} catch (SSLPeerUnverifiedException expected) {
}
@@ -138,9 +137,11 @@ public class SSLSessionTest extends TestCase {
} catch (SSLPeerUnverifiedException expected) {
}
assertNotNull(s.client.getPeerCertificates());
- assertEquals(1, s.client.getPeerCertificates().length);
+ TestKeyStore.assertChainLength(s.client.getPeerCertificates());
+ TestSSLContext.assertServerCertificateChain(s.s.c.serverTrustManager,
+ s.client.getPeerCertificates());
TestSSLContext.assertCertificateInKeyStore(s.client.getPeerCertificates()[0],
- s.s.c.keyStore);
+ s.s.c.serverKeyStore);
try {
s.server.getPeerCertificates();
fail();
@@ -177,7 +178,7 @@ public class SSLSessionTest extends TestCase {
assertNotNull(s.client.getPeerPrincipal());
assertNotNull(s.client.getPeerPrincipal().getName());
TestSSLContext.assertCertificateInKeyStore(s.client.getPeerPrincipal(),
- s.s.c.keyStore);
+ s.s.c.serverKeyStore);
}
public void test_SSLSession_getProtocol() {
@@ -196,9 +197,9 @@ public class SSLSessionTest extends TestCase {
assertNull(s.invalid.getSessionContext());
assertNotNull(s.server.getSessionContext());
assertNotNull(s.client.getSessionContext());
- assertEquals(s.s.c.sslContext.getServerSessionContext(),
+ assertEquals(s.s.c.serverContext.getServerSessionContext(),
s.server.getSessionContext());
- assertEquals(s.s.c.sslContext.getClientSessionContext(),
+ assertEquals(s.s.c.clientContext.getClientSessionContext(),
s.client.getSessionContext());
assertNotSame(s.server.getSessionContext(),
s.client.getSessionContext());
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
index ca318f3..225358d 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
@@ -37,10 +37,14 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception {
// note the rare usage of DSA keys here in addition to RSA
- TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" } );
- TestSSLContext c = TestSSLContext.create(testKeyStore.keyStore,
- testKeyStore.keyStorePassword);
- String[] cipherSuites = c.sslContext.getSocketFactory().getSupportedCipherSuites();
+ TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" },
+ null,
+ "rsa-dsa",
+ TestKeyStore.localhost(),
+ true,
+ null);
+ TestSSLContext c = TestSSLContext.create(testKeyStore, testKeyStore);
+ String[] cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
for (String cipherSuite : cipherSuites) {
/*
* Kerberos cipher suites require external setup. See "Kerberos Requirements" in
@@ -138,7 +142,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_startHandshake() throws Exception {
final TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
@@ -152,9 +157,12 @@ public class SSLSocketTest extends TestCase {
}
Certificate[] localCertificates = server.getSession().getLocalCertificates();
assertNotNull(localCertificates);
- assertEquals(1, localCertificates.length);
+ TestKeyStore.assertChainLength(localCertificates);
assertNotNull(localCertificates[0]);
- TestSSLContext.assertCertificateInKeyStore(localCertificates[0], c.keyStore);
+ TestSSLContext.assertServerCertificateChain(c.serverTrustManager,
+ localCertificates);
+ TestSSLContext.assertCertificateInKeyStore(localCertificates[0],
+ c.serverKeyStore);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -168,15 +176,18 @@ public class SSLSocketTest extends TestCase {
assertNull(client.getSession().getLocalCertificates());
Certificate[] peerCertificates = client.getSession().getPeerCertificates();
assertNotNull(peerCertificates);
- assertEquals(1, peerCertificates.length);
+ TestKeyStore.assertChainLength(peerCertificates);
assertNotNull(peerCertificates[0]);
- TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.keyStore);
+ TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
+ peerCertificates);
+ TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
thread.join();
}
public void test_SSLSocket_startHandshake_noKeyStore() throws Exception {
- TestSSLContext c = TestSSLContext.create(null, null);
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ TestSSLContext c = TestSSLContext.create(null, null, null, null);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
try {
SSLSocket server = (SSLSocket) c.serverSocket.accept();
fail();
@@ -185,12 +196,12 @@ public class SSLSocketTest extends TestCase {
}
public void test_SSLSocket_startHandshake_noClientCertificate() throws Exception {
- TestSSLContext serverContext = TestSSLContext.create();
- TestSSLContext clientContext = TestSSLContext.createClient(serverContext);
+ TestSSLContext c = TestSSLContext.create();
+ SSLContext serverContext = c.serverContext;
+ SSLContext clientContext = c.clientContext;
SSLSocket client = (SSLSocket)
- clientContext.sslContext.getSocketFactory().createSocket(serverContext.host,
- serverContext.port);
- final SSLSocket server = (SSLSocket) serverContext.serverSocket.accept();
+ clientContext.getSocketFactory().createSocket(c.host, c.port);
+ final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
try {
@@ -209,8 +220,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_HandshakeCompletedListener() throws Exception {
final TestSSLContext c = TestSSLContext.create();
- final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host,
- c.port);
+ final SSLSocket client = (SSLSocket)
+ c.clientContext.getSocketFactory().createSocket(c.host, c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
@@ -253,7 +264,7 @@ public class SSLSocketTest extends TestCase {
byte[] id = session.getId();
assertNotNull(id);
assertEquals(32, id.length);
- assertNotNull(c.sslContext.getClientSessionContext().getSession(id));
+ assertNotNull(c.clientContext.getClientSessionContext().getSession(id));
assertNotNull(cipherSuite);
assertTrue(Arrays.asList(
@@ -264,18 +275,21 @@ public class SSLSocketTest extends TestCase {
assertNull(localCertificates);
assertNotNull(peerCertificates);
- assertEquals(1, peerCertificates.length);
+ TestKeyStore.assertChainLength(peerCertificates);
assertNotNull(peerCertificates[0]);
- TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.keyStore);
+ TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
+ peerCertificates);
+ TestSSLContext.assertCertificateInKeyStore(peerCertificates[0],
+ c.serverKeyStore);
assertNotNull(peerCertificateChain);
- assertEquals(1, peerCertificateChain.length);
+ TestKeyStore.assertChainLength(peerCertificateChain);
assertNotNull(peerCertificateChain[0]);
TestSSLContext.assertCertificateInKeyStore(
- peerCertificateChain[0].getSubjectDN(), c.keyStore);
+ peerCertificateChain[0].getSubjectDN(), c.serverKeyStore);
assertNotNull(peerPrincipal);
- TestSSLContext.assertCertificateInKeyStore(peerPrincipal, c.keyStore);
+ TestSSLContext.assertCertificateInKeyStore(peerPrincipal, c.serverKeyStore);
assertNull(localPrincipal);
@@ -297,7 +311,7 @@ public class SSLSocketTest extends TestCase {
client.startHandshake();
thread.join();
if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertNotNull(c.sslContext.getServerSessionContext().getSession(
+ assertNotNull(c.serverContext.getServerSessionContext().getSession(
client.getSession().getId()));
}
synchronized (handshakeCompletedListenerCalled) {
@@ -309,8 +323,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_HandshakeCompletedListener_RuntimeException() throws Exception {
final TestSSLContext c = TestSSLContext.create();
- final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host,
- c.port);
+ final SSLSocket client = (SSLSocket)
+ c.clientContext.getSocketFactory().createSocket(c.host, c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
@@ -335,7 +349,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_getUseClientMode() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
SSLSocket server = (SSLSocket) c.serverSocket.accept();
assertTrue(client.getUseClientMode());
assertFalse(server.getUseClientMode());
@@ -365,7 +380,8 @@ public class SSLSocketTest extends TestCase {
final boolean serverClientMode)
throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
final SSLProtocolException[] sslProtocolException = new SSLProtocolException[1];
@@ -405,8 +421,10 @@ public class SSLSocketTest extends TestCase {
}
public void test_SSLSocket_clientAuth() throws Exception {
- TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCertificate(),
+ TestKeyStore.getServer());
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
@@ -441,13 +459,16 @@ public class SSLSocketTest extends TestCase {
thread.start();
client.startHandshake();
assertNotNull(client.getSession().getLocalCertificates());
- assertEquals(1, client.getSession().getLocalCertificates().length);
+ TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
+ TestSSLContext.assertClientCertificateChain(c.clientTrustManager,
+ client.getSession().getLocalCertificates());
thread.join();
}
public void test_SSLSocket_getEnableSessionCreation() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
SSLSocket server = (SSLSocket) c.serverSocket.accept();
assertTrue(client.getEnableSessionCreation());
assertTrue(server.getEnableSessionCreation());
@@ -455,7 +476,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_setEnableSessionCreation_server() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
@@ -484,7 +506,8 @@ public class SSLSocketTest extends TestCase {
public void test_SSLSocket_setEnableSessionCreation_client() throws Exception {
TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
+ c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {
diff --git a/support/src/test/java/java/security/StandardNames.java b/support/src/test/java/java/security/StandardNames.java
index 4b278b6..1e4355e 100644
--- a/support/src/test/java/java/security/StandardNames.java
+++ b/support/src/test/java/java/security/StandardNames.java
@@ -49,7 +49,7 @@ public final class StandardNames extends Assert {
public static final boolean IS_RI
= !"Dalvik Core Library".equals(System.getProperty("java.specification.name"));
- public static final String PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "HarmonyJSSE";
+ public static final String JSSE_PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "AndroidOpenSSL";
/**
* A map from algorithm type (e.g. Cipher) to a set of algorithms (e.g. AES, DES, ...)
@@ -277,11 +277,6 @@ public final class StandardNames extends Assert {
// TODO remove one, probably Harmony's
provide("CertificateFactory", "X509");
- // Harmony JSSEProvider is missing these
- // TODO add them
- unprovide("SSLContext", "SSLv3");
- unprovide("SSLContext", "TLSv1");
-
// not just different names, but different binary formats
unprovide("KeyStore", "JKS");
provide("KeyStore", "BKS");
diff --git a/support/src/test/java/javax/net/ssl/TestKeyStore.java b/support/src/test/java/javax/net/ssl/TestKeyStore.java
index 72a76de..fbbd4db 100644
--- a/support/src/test/java/javax/net/ssl/TestKeyStore.java
+++ b/support/src/test/java/javax/net/ssl/TestKeyStore.java
@@ -16,18 +16,29 @@
package javax.net.ssl;
+import java.io.PrintStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.KeyStore.PasswordProtection;
+import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.Security;
+import java.security.StandardNames;
+import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
+import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
+import junit.framework.Assert;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;
/**
@@ -37,8 +48,14 @@ import org.bouncycastle.x509.X509V3CertificateGenerator;
* Creating a key store is relatively slow, so a singleton instance is
* accessible via TestKeyStore.get().
*/
-public final class TestKeyStore {
+public final class TestKeyStore extends Assert {
+ static {
+ if (StandardNames.IS_RI) {
+ // Needed to create BKS keystore
+ Security.addProvider(new BouncyCastleProvider());
+ }
+ }
public final KeyStore keyStore;
public final char[] keyStorePassword;
@@ -48,28 +65,91 @@ public final class TestKeyStore {
this.keyStorePassword = keyStorePassword;
}
- private static final TestKeyStore SINGLETON = create(new String[] { "RSA" } );
+ private static final TestKeyStore ROOT_CA
+ = create(new String[] { "RSA" },
+ null,
+ "RootCA",
+ x509Principal("Test Root Certificate Authority"),
+ true,
+ null);
+ private static final TestKeyStore INTERMEDIATE_CA
+ = create(new String[] { "RSA" },
+ null,
+ "IntermediateCA",
+ x509Principal("Test Intermediate Certificate Authority"),
+ true,
+ ROOT_CA);
+ private static final TestKeyStore SERVER
+ = create(new String[] { "RSA" },
+ null,
+ "server",
+ localhost(),
+ false,
+ INTERMEDIATE_CA);
+ private static final TestKeyStore CLIENT
+ = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null);
+ private static final TestKeyStore CLIENT_CERTIFICATE
+ = create(new String[] { "RSA" },
+ null,
+ "client",
+ x509Principal("test@user"),
+ false,
+ INTERMEDIATE_CA);
+
+ /**
+ * Return a server keystore with a matched RSA certificate and
+ * private key as well as a CA certificate.
+ */
+ public static TestKeyStore getServer() {
+ return SERVER;
+ }
+
+ /**
+ * Return a keystore with a CA certificate
+ */
+ public static TestKeyStore getClient() {
+ return CLIENT;
+ }
/**
- * Return a keystore with an RSA keypair
+ * Return a client keystore with a matched RSA certificate and
+ * private key as well as a CA certificate.
*/
- public static TestKeyStore get() {
- return SINGLETON;
+ public static TestKeyStore getClientCertificate() {
+ return CLIENT_CERTIFICATE;
}
/**
* Create a new KeyStore containing the requested key types.
* Since key generation can be expensive, most tests should reuse
* the RSA-only singleton instance returned by TestKeyStore.get
+ *
+ * @param keyAlgorithms The requested key types to generate and include
+ * @param keyStorePassword Password used to protect the private key
+ * @param aliasPrefix A unique prefix to identify the key aliases
+ * @param ca true If the keys being created are for a CA
+ * @param signer If non-null, key store used for signing key, otherwise self-signed
*/
- public static TestKeyStore create(String[] keyAlgorithms) {
+ public static TestKeyStore create(String[] keyAlgorithms,
+ char[] keyStorePassword,
+ String aliasPrefix,
+ X509Principal subject,
+ boolean ca,
+ TestKeyStore signer) {
try {
- char[] keyStorePassword = null;
KeyStore keyStore = createKeyStore();
for (String keyAlgorithm : keyAlgorithms) {
- String publicAlias = "public-" + keyAlgorithm;
- String privateAlias = "private-" + keyAlgorithm;
- createKeys(keyStore, keyStorePassword, keyAlgorithm, publicAlias, privateAlias);
+ String publicAlias = aliasPrefix + "-public-" + keyAlgorithm;
+ String privateAlias = aliasPrefix + "-private-" + keyAlgorithm;
+ createKeys(keyStore, keyStorePassword,
+ keyAlgorithm,
+ publicAlias, privateAlias,
+ subject,
+ ca,
+ signer);
+ }
+ if (signer != null) {
+ copySelfSignedCertificates(keyStore, signer.keyStore);
}
return new TestKeyStore(keyStore, keyStorePassword);
} catch (RuntimeException e) {
@@ -95,15 +175,14 @@ public final class TestKeyStore {
/**
* Add newly generated keys of a given key type to an existing
* KeyStore. The PrivateKey will be stored under the specified
- * private alias name and a X509Certificate based on the matching
- * PublicKey stored under the given public alias name.
+ * private alias name. The X509Certificate will be stored on the
+ * public alias name and have the given subject distiguished
+ * name.
*
- * The private key will have a certificate chain including the
- * certificate stored under the alias name privateAlias. The
- * certificate will be signed by the private key. The certificate
- * Subject and Issuer Common-Name will be the local host's
- * canonical hostname. The certificate will be valid for one day
- * before and one day after the time of creation.
+ * If a CA is provided, it will be used to sign the generated
+ * certificate. Otherwise, the certificate will be self
+ * signed. The certificate will be valid for one day before and
+ * one day after the time of creation.
*
* Based on:
* org.bouncycastle.jce.provider.test.SigTest
@@ -113,7 +192,25 @@ public final class TestKeyStore {
char[] keyStorePassword,
String keyAlgorithm,
String publicAlias,
- String privateAlias) throws Exception {
+ String privateAlias,
+ X509Principal subject,
+ boolean ca,
+ TestKeyStore signer) throws Exception {
+ PrivateKey caKey;
+ X509Certificate caCert;
+ X509Certificate[] caCertChain;
+ if (signer == null) {
+ caKey = null;
+ caCert = null;
+ caCertChain = null;
+ } else {
+ PrivateKeyEntry privateKeyEntry
+ = privateKey(signer.keyStore, signer.keyStorePassword, keyAlgorithm);
+ caKey = privateKeyEntry.getPrivateKey();
+ caCert = (X509Certificate)privateKeyEntry.getCertificate();
+ caCertChain = (X509Certificate[])privateKeyEntry.getCertificateChain();
+ }
+
PrivateKey privateKey;
X509Certificate x509c;
if (publicAlias == null && privateAlias == null) {
@@ -135,10 +232,12 @@ public final class TestKeyStore {
// interface assumes you want to read in a stream of bytes a
// factory specific format. So here we use Bouncy Castle's
// X509V3CertificateGenerator and related classes.
-
- Hashtable attributes = new Hashtable();
- attributes.put(X509Principal.CN, InetAddress.getLocalHost().getCanonicalHostName());
- X509Principal dn = new X509Principal(attributes);
+ X509Principal issuer;
+ if (caCert == null) {
+ issuer = subject;
+ } else {
+ issuer = (X509Principal) caCert.getSubjectDN();
+ }
long millisPerDay = 24 * 60 * 60 * 1000;
long now = System.currentTimeMillis();
@@ -147,22 +246,32 @@ public final class TestKeyStore {
BigInteger serial = BigInteger.valueOf(1);
X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator();
- x509cg.setSubjectDN(dn);
- x509cg.setIssuerDN(dn);
+ x509cg.setSubjectDN(subject);
+ x509cg.setIssuerDN(issuer);
x509cg.setNotBefore(start);
x509cg.setNotAfter(end);
x509cg.setPublicKey(publicKey);
x509cg.setSignatureAlgorithm("sha1With" + keyAlgorithm);
x509cg.setSerialNumber(serial);
- x509c = x509cg.generateX509Certificate(privateKey);
+ if (ca) {
+ x509cg.addExtension(X509Extensions.BasicConstraints,
+ true,
+ new BasicConstraints(true));
+ }
+ PrivateKey signingKey = (caKey == null) ? privateKey : caKey;
+ x509c = x509cg.generateX509Certificate(signingKey);
}
X509Certificate[] x509cc;
if (privateAlias == null) {
// don't need certificate chain
x509cc = null;
- } else {
+ } else if (caCertChain == null) {
x509cc = new X509Certificate[] { x509c };
+ } else {
+ x509cc = new X509Certificate[caCertChain.length+1];
+ x509cc[0] = x509c;
+ System.arraycopy(caCertChain, 0, x509cc, 1, caCertChain.length);
}
// 3.) put certificate and private key into the key store
@@ -174,4 +283,136 @@ public final class TestKeyStore {
}
return keyStore;
}
+
+ /**
+ * Create an X509Principal with the given attributes
+ */
+ public static X509Principal localhost() {
+ try {
+ return x509Principal(InetAddress.getLocalHost().getCanonicalHostName());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Create an X509Principal with the given attributes
+ */
+ public static X509Principal x509Principal(String commonName) {
+ Hashtable attributes = new Hashtable();
+ attributes.put(X509Principal.CN, commonName);
+ return new X509Principal(attributes);
+ }
+
+ /**
+ * Return the only private key in a keystore for the given
+ * algorithm. Throws IllegalStateException if there are are more
+ * or less than one.
+ */
+ public static PrivateKeyEntry privateKey(KeyStore keyStore,
+ char[] keyStorePassword,
+ String algorithm) {
+ try {
+ PrivateKeyEntry found = null;
+ PasswordProtection password = new PasswordProtection(keyStorePassword);
+ for (String alias: Collections.list(keyStore.aliases())) {
+ if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
+ continue;
+ }
+ PrivateKeyEntry privateKey = (PrivateKeyEntry) keyStore.getEntry(alias, password);
+ if (!privateKey.getPrivateKey().getAlgorithm().equals(algorithm)) {
+ continue;
+ }
+ if (found != null) {
+ throw new IllegalStateException("keyStore has more than one private key");
+ }
+ found = privateKey;
+ }
+ if (found == null) {
+ throw new IllegalStateException("keyStore contained no private key");
+ }
+ return found;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Create a client key store that only contains self-signed certificates but no private keys
+ */
+ public static KeyStore createClient(KeyStore caKeyStore) {
+ try {
+ KeyStore clientKeyStore = clientKeyStore = KeyStore.getInstance("BKS");
+ clientKeyStore.load(null, null);
+ copySelfSignedCertificates(clientKeyStore, caKeyStore);
+ return clientKeyStore;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Copy self-signed certifcates from one key store to another
+ */
+ public static void copySelfSignedCertificates(KeyStore dst, KeyStore src) throws Exception {
+ for (String alias: Collections.list(src.aliases())) {
+ if (!src.isCertificateEntry(alias)) {
+ continue;
+ }
+ X509Certificate cert = (X509Certificate)src.getCertificate(alias);
+ if (!cert.getSubjectDN().equals(cert.getIssuerDN())) {
+ continue;
+ }
+ dst.setCertificateEntry(alias, cert);
+ }
+ }
+
+ /**
+ * Dump a key store for debugging.
+ */
+ public static void dump(String context,
+ KeyStore keyStore,
+ char[] keyStorePassword) {
+ try {
+ PrintStream out = System.out;
+ out.println("context=" + context);
+ out.println("\tkeyStore=" + keyStore);
+ out.println("\tpassword="
+ + ((keyStorePassword == null) ? null : new String(keyStorePassword)));
+ for (String alias: Collections.list(keyStore.aliases())) {
+ out.println("\talias=" + alias);
+ if (keyStore.isCertificateEntry(alias)) {
+ out.println("\tcertificate:");
+ out.println("==========================================");
+ out.println(keyStore.getCertificate(alias));
+ out.println("==========================================");
+ continue;
+ }
+ if (keyStore.isKeyEntry(alias)) {
+ out.println("\tkey:");
+ out.println("==========================================");
+ out.println(keyStore.getKey(alias, keyStorePassword));
+ out.println("==========================================");
+ continue;
+ }
+ out.println("\tunknown entry type");
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void assertChainLength(Object[] chain) {
+ /*
+ * Note chain is Object[] to support both
+ * java.security.cert.X509Certificate and
+ * javax.security.cert.X509Certificate
+ */
+ assertEquals(3, chain.length);
+ }
+
}
diff --git a/support/src/test/java/javax/net/ssl/TestSSLContext.java b/support/src/test/java/javax/net/ssl/TestSSLContext.java
index 8d759ee..5174b15 100644
--- a/support/src/test/java/javax/net/ssl/TestSSLContext.java
+++ b/support/src/test/java/javax/net/ssl/TestSSLContext.java
@@ -21,13 +21,12 @@ import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.Principal;
import java.security.SecureRandom;
-import java.security.Security;
import java.security.StandardNames;
import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import junit.framework.Assert;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* TestSSLContext is a convenience class for other tests that
@@ -45,11 +44,6 @@ public final class TestSSLContext extends Assert {
public static final int EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 10;
public static final int EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 100;
public static final int EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT = (IS_RI) ? 86400 : 0;
- static {
- if (IS_RI) {
- Security.addProvider(new BouncyCastleProvider());
- }
- }
/**
* The Android SSLSocket and SSLServerSocket implementations are
@@ -72,22 +66,43 @@ public final class TestSSLContext extends Assert {
return false;
}
- public final KeyStore keyStore;
- public final char[] keyStorePassword;
- public final SSLContext sslContext;
+ public final KeyStore clientKeyStore;
+ public final char[] clientKeyStorePassword;
+ public final KeyStore serverKeyStore;
+ public final char[] serverKeyStorePassword;
+ public final X509ExtendedKeyManager clientKeyManager;
+ public final X509ExtendedKeyManager serverKeyManager;
+ public final X509TrustManager clientTrustManager;
+ public final X509TrustManager serverTrustManager;
+ public final SSLContext clientContext;
+ public final SSLContext serverContext;
public final SSLServerSocket serverSocket;
public final InetAddress host;
public final int port;
- private TestSSLContext(KeyStore keyStore,
- char[] keyStorePassword,
- SSLContext sslContext,
+ private TestSSLContext(KeyStore clientKeyStore,
+ char[] clientKeyStorePassword,
+ KeyStore serverKeyStore,
+ char[] serverKeyStorePassword,
+ X509ExtendedKeyManager clientKeyManager,
+ X509ExtendedKeyManager serverKeyManager,
+ X509TrustManager clientTrustManager,
+ X509TrustManager serverTrustManager,
+ SSLContext clientContext,
+ SSLContext serverContext,
SSLServerSocket serverSocket,
InetAddress host,
int port) {
- this.keyStore = keyStore;
- this.keyStorePassword = keyStorePassword;
- this.sslContext = sslContext;
+ this.clientKeyStore = clientKeyStore;
+ this.clientKeyStorePassword = clientKeyStorePassword;
+ this.serverKeyStore = serverKeyStore;
+ this.serverKeyStorePassword = serverKeyStorePassword;
+ this.clientKeyManager = clientKeyManager;
+ this.serverKeyManager = serverKeyManager;
+ this.clientTrustManager = clientTrustManager;
+ this.serverTrustManager = serverTrustManager;
+ this.clientContext = clientContext;
+ this.serverContext = serverContext;
this.serverSocket = serverSocket;
this.host = host;
this.port = port;
@@ -99,60 +114,51 @@ public final class TestSSLContext extends Assert {
* listening provided host and port.
*/
public static TestSSLContext create() {
- TestKeyStore testKeyStore = TestKeyStore.get();
- return create(testKeyStore.keyStore, testKeyStore.keyStorePassword);
+ return create(TestKeyStore.getClient(),
+ TestKeyStore.getServer());
}
/**
- * TestSSLContext creation method that allows separate creation of key store
+ * TestSSLContext creation method that allows separate creation of server key store
*/
- public static TestSSLContext create(KeyStore keyStore, char[] keyStorePassword) {
- try {
- SSLContext sslContext = createSSLContext(keyStore, keyStorePassword);
-
- SSLServerSocket serverSocket = (SSLServerSocket)
- sslContext.getServerSocketFactory().createServerSocket(0);
- InetSocketAddress sa = (InetSocketAddress) serverSocket.getLocalSocketAddress();
- InetAddress host = sa.getAddress();
- int port = sa.getPort();
-
- return new TestSSLContext(keyStore, keyStorePassword,
- sslContext, serverSocket, host, port);
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ public static TestSSLContext create(TestKeyStore client, TestKeyStore server) {
+ return create(client.keyStore, client.keyStorePassword,
+ server.keyStore, server.keyStorePassword);
}
/**
- * Create a client version of the server TestSSLContext. The
- * client will trust the server's certificate, but not contain any
- * keys of its own.
+ * TestSSLContext creation method that allows separate creation of client and server key store
*/
- public static TestSSLContext createClient(TestSSLContext server) {
+ public static TestSSLContext create(KeyStore clientKeyStore, char[] clientKeyStorePassword,
+ KeyStore serverKeyStore, char[] serverKeyStorePassword) {
try {
- KeyStore keyStore = KeyStore.getInstance("BKS");
- keyStore.load(null, null);
- for (String alias: Collections.list(server.keyStore.aliases())) {
- if (!server.keyStore.isCertificateEntry(alias)) {
- continue;
- }
- Certificate cert = server.keyStore.getCertificate(alias);
- keyStore.setCertificateEntry(alias, cert);
- }
+ KeyManager[] clientKeyManagers = createKeyManagers(clientKeyStore,
+ clientKeyStorePassword);
+ KeyManager[] serverKeyManagers = createKeyManagers(serverKeyStore,
+ serverKeyStorePassword);
- char[] keyStorePassword = server.keyStorePassword;
+ TrustManager[] clientTrustManagers = createTrustManagers(clientKeyStore,
+ clientKeyStorePassword);
+ TrustManager[] serverTrustManagers = createTrustManagers(serverKeyStore,
+ serverKeyStorePassword);
- String tmfa = TrustManagerFactory.getDefaultAlgorithm();
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa);
- tmf.init(keyStore);
+ SSLContext clientContext = createSSLContext(clientKeyManagers, clientTrustManagers);
+ SSLContext serverContext = createSSLContext(serverKeyManagers, serverTrustManagers);
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
+ SSLServerSocket serverSocket = (SSLServerSocket)
+ serverContext.getServerSocketFactory().createServerSocket(0);
+ InetSocketAddress sa = (InetSocketAddress) serverSocket.getLocalSocketAddress();
+ InetAddress host = sa.getAddress();
+ int port = sa.getPort();
- return new TestSSLContext(keyStore, keyStorePassword,
- sslContext, null, null, -1);
+ return new TestSSLContext(clientKeyStore, clientKeyStorePassword,
+ serverKeyStore, serverKeyStorePassword,
+ (X509ExtendedKeyManager) clientKeyManagers[0],
+ (X509ExtendedKeyManager) serverKeyManagers[0],
+ (X509TrustManager) clientTrustManagers[0],
+ (X509TrustManager) serverTrustManagers[0],
+ clientContext, serverContext,
+ serverSocket, host, port);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -165,20 +171,28 @@ public final class TestSSLContext extends Assert {
* certificate chain from the given KeyStore and a TrustManager
* using the certificates authorities from the same KeyStore.
*/
- public static final SSLContext createSSLContext(final KeyStore keyStore,
- final char[] keyStorePassword)
- throws Exception {
+ public static final SSLContext createSSLContext(final KeyManager[] keyManagers,
+ final TrustManager[] trustManagers)
+ throws Exception {
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(keyManagers, trustManagers, new SecureRandom());
+ return context;
+ }
+
+ public static KeyManager[] createKeyManagers(final KeyStore keyStore,
+ final char[] keyStorePassword) throws Exception {
String kmfa = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa);
kmf.init(keyStore, keyStorePassword);
+ return kmf.getKeyManagers();
+ }
+ public static TrustManager[] createTrustManagers(final KeyStore keyStore,
+ final char[] keyStorePassword) throws Exception {
String tmfa = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa);
tmf.init(keyStore);
-
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
- return context;
+ return tmf.getTrustManagers();
}
public static void assertCertificateInKeyStore(Principal principal,
@@ -213,4 +227,18 @@ public final class TestSSLContext extends Assert {
}
assertTrue(found);
}
+
+ public static void assertServerCertificateChain(X509TrustManager trustManager,
+ Certificate[] serverChain)
+ throws CertificateException {
+ X509Certificate[] chain = (X509Certificate[]) serverChain;
+ trustManager.checkServerTrusted(chain, chain[0].getPublicKey().getAlgorithm());
+ }
+
+ public static void assertClientCertificateChain(X509TrustManager trustManager,
+ Certificate[] clientChain)
+ throws CertificateException {
+ X509Certificate[] chain = (X509Certificate[]) clientChain;
+ trustManager.checkClientTrusted(chain, chain[0].getPublicKey().getAlgorithm());
+ }
}
diff --git a/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java b/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java
index f3250e6..1ed2a92 100644
--- a/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java
+++ b/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java
@@ -40,8 +40,11 @@ public final class TestSSLEnginePair extends Assert {
}
public static TestSSLEnginePair create(Hooks hooks) throws IOException {
- TestSSLContext c = TestSSLContext.create();
- SSLEngine[] engines = connect(c, c, hooks);
+ return create(TestSSLContext.create(), hooks);
+ }
+
+ public static TestSSLEnginePair create(TestSSLContext c, Hooks hooks) throws IOException {
+ SSLEngine[] engines = connect(c, hooks);
return new TestSSLEnginePair(c, engines[0], engines[1]);
}
@@ -52,14 +55,13 @@ public final class TestSSLEnginePair extends Assert {
* caching. Optionally specify serverCipherSuites for testing
* cipher suite negotiation.
*/
- public static SSLEngine[] connect(final TestSSLContext clientContext,
- final TestSSLContext serverContext,
+ public static SSLEngine[] connect(final TestSSLContext c,
Hooks hooks) throws IOException {
if (hooks == null) {
hooks = new Hooks();
}
- SSLSession session = clientContext.sslContext.createSSLEngine().getSession();
+ SSLSession session = c.clientContext.createSSLEngine().getSession();
int packetBufferSize = session.getPacketBufferSize();
ByteBuffer clientToServer = ByteBuffer.allocate(packetBufferSize);
@@ -68,8 +70,8 @@ public final class TestSSLEnginePair extends Assert {
int applicationBufferSize = session.getApplicationBufferSize();
ByteBuffer scratch = ByteBuffer.allocate(applicationBufferSize);
- SSLEngine client = clientContext.sslContext.createSSLEngine();
- SSLEngine server = serverContext.sslContext.createSSLEngine();
+ SSLEngine client = c.clientContext.createSSLEngine();
+ SSLEngine server = c.serverContext.createSSLEngine();
client.setUseClientMode(true);
server.setUseClientMode(false);
hooks.beforeBeginHandshake(client, server);
diff --git a/support/src/test/java/javax/net/ssl/TestSSLSocketPair.java b/support/src/test/java/javax/net/ssl/TestSSLSocketPair.java
index cda664c..1d0345f 100644
--- a/support/src/test/java/javax/net/ssl/TestSSLSocketPair.java
+++ b/support/src/test/java/javax/net/ssl/TestSSLSocketPair.java
@@ -55,7 +55,7 @@ public final class TestSSLSocketPair {
final String[] serverCipherSuites) {
try {
SSLSocket client = (SSLSocket)
- c.sslContext.getSocketFactory().createSocket(c.host, c.port);
+ c.clientContext.getSocketFactory().createSocket(c.host, c.port);
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
Thread thread = new Thread(new Runnable () {
public void run() {