diff options
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() { |