summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java92
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java163
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java169
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java20
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java33
-rw-r--r--luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java83
-rw-r--r--luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp181
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java151
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSessionTest.java2
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java10
-rw-r--r--luni/src/test/java/javax/net/ssl/SSLSocketTest.java9
-rw-r--r--luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java9
12 files changed, 457 insertions, 465 deletions
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
index 5c73558..0309838 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
@@ -24,6 +24,8 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import javax.net.ssl.SSLSession;
@@ -45,6 +47,15 @@ abstract class AbstractSessionContext implements SSLSessionContext {
/** Identifies OpenSSL sessions. */
static final int OPEN_SSL = 1;
+ private final Map<ByteArray, SSLSession> sessions
+ = new LinkedHashMap<ByteArray, SSLSession>() {
+ @Override
+ protected boolean removeEldestEntry(
+ Map.Entry<ByteArray, SSLSession> eldest) {
+ return maximumSize > 0 && size() > maximumSize;
+ }
+ };
+
/**
* Constructs a new session context.
*
@@ -57,9 +68,15 @@ abstract class AbstractSessionContext implements SSLSessionContext {
}
/**
- * Returns the collection of sessions ordered by least-recently-used first.
+ * Returns the collection of sessions ordered from oldest to newest
*/
- abstract Iterator<SSLSession> sessionIterator();
+ private Iterator<SSLSession> sessionIterator() {
+ synchronized (sessions) {
+ SSLSession[] array = sessions.values().toArray(
+ new SSLSession[sessions.size()]);
+ return Arrays.asList(array).iterator();
+ }
+ }
public final Enumeration getIds() {
final Iterator<SSLSession> i = sessionIterator();
@@ -101,7 +118,47 @@ abstract class AbstractSessionContext implements SSLSessionContext {
/**
* Makes sure cache size is < maximumSize.
*/
- abstract void trimToSize();
+ protected void trimToSize() {
+ synchronized (sessions) {
+ int size = sessions.size();
+ if (size > maximumSize) {
+ int removals = size - maximumSize;
+ Iterator<SSLSession> i = sessions.values().iterator();
+ do {
+ SSLSession session = i.next();
+ i.remove();
+ sessionRemoved(session);
+ } while (--removals > 0);
+ }
+ }
+ }
+
+ public void setSessionTimeout(int seconds)
+ throws IllegalArgumentException {
+ if (seconds < 0) {
+ throw new IllegalArgumentException("seconds < 0");
+ }
+ timeout = seconds;
+
+ synchronized (sessions) {
+ Iterator<SSLSession> i = sessions.values().iterator();
+ while (i.hasNext()) {
+ SSLSession session = i.next();
+ // SSLSession's know their context and consult the
+ // timeout as part of their validity condition.
+ if (!session.isValid()) {
+ i.remove();
+ sessionRemoved(session);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when a session is removed. Used by ClientSessionContext
+ * to update its host-and-port based cache.
+ */
+ abstract protected void sessionRemoved(SSLSession session);
public final void setSessionCacheSize(int size)
throws IllegalArgumentException {
@@ -201,10 +258,31 @@ abstract class AbstractSessionContext implements SSLSessionContext {
}
}
- /**
- * Puts an SSLSession in the AbstractSessionContext cache
- */
- abstract void putSession(SSLSession session);
+ public SSLSession getSession(byte[] sessionId) {
+ if (sessionId == null) {
+ throw new NullPointerException("sessionId == null");
+ }
+ ByteArray key = new ByteArray(sessionId);
+ SSLSession session;
+ synchronized (sessions) {
+ session = sessions.get(key);
+ }
+ if (session != null && session.isValid()) {
+ return session;
+ }
+ return null;
+ }
+
+ void putSession(SSLSession session) {
+ byte[] id = session.getId();
+ if (id.length == 0) {
+ return;
+ }
+ ByteArray key = new ByteArray(id);
+ synchronized (sessions) {
+ sessions.put(key, session);
+ }
+ }
static void log(Throwable t) {
java.util.logging.Logger.global.log(Level.WARNING,
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
index dac22f0..0b297a3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
@@ -16,42 +16,22 @@
package org.apache.harmony.xnet.provider.jsse;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.Map;
import javax.net.ssl.SSLSession;
/**
* Caches client sessions. Indexes by host and port. Users are typically
- * looking to reuse any session for a given host and port. Users of the
- * standard API are forced to iterate over the sessions semi-linearly as
- * opposed to in constant time.
+ * looking to reuse any session for a given host and port.
*/
public class ClientSessionContext extends AbstractSessionContext {
- /** Sessions indexed by host and port in access order. */
- final Map<HostAndPort, SSLSession> sessions
- = new LinkedHashMap<HostAndPort, SSLSession>() {
- @Override
- protected boolean removeEldestEntry(
- Map.Entry<HostAndPort, SSLSession> eldest) {
- // Called while lock is held on sessions.
- boolean remove = maximumSize > 0 && size() > maximumSize;
- if (remove) {
- // don't just update sessions, but also sessionsById
- removeById(eldest.getValue());
- }
- return remove;
- }
- };
-
/**
- * Sessions indexed by ID. Initialized on demand. Protected from concurrent
- * access by holding a lock on sessions.
+ * Sessions indexed by host and port. Protect from concurrent
+ * access by holding a lock on sessionsByHostAndPort.
*/
- Map<ByteArray, SSLSession> sessionsById;
+ final Map<HostAndPort, SSLSession> sessionsByHostAndPort
+ = new HashMap<HostAndPort, SSLSession>();
private SSLClientSessionCache persistentCache;
@@ -63,106 +43,10 @@ public class ClientSessionContext extends AbstractSessionContext {
this.persistentCache = persistentCache;
}
- public final void setSessionTimeout(int seconds)
- throws IllegalArgumentException {
- if (seconds < 0) {
- throw new IllegalArgumentException("seconds < 0");
- }
- timeout = seconds;
-
- synchronized (sessions) {
- Iterator<SSLSession> i = sessions.values().iterator();
- while (i.hasNext()) {
- SSLSession session = i.next();
- // SSLSession's know their context and consult the
- // timeout as part of their validity condition.
- if (!session.isValid()) {
- i.remove();
- // don't just update sessions, but also sessionsById
- removeById(session);
- }
- }
- }
- }
-
- Iterator<SSLSession> sessionIterator() {
- synchronized (sessions) {
- SSLSession[] array = sessions.values().toArray(
- new SSLSession[sessions.size()]);
- return Arrays.asList(array).iterator();
- }
- }
-
- void trimToSize() {
- synchronized (sessions) {
- int size = sessions.size();
- if (size > maximumSize) {
- int removals = size - maximumSize;
- Iterator<SSLSession> i = sessions.values().iterator();
- do {
- removeById(i.next());
- i.remove();
- } while (--removals > 0);
- }
- }
- }
-
- void removeById(SSLSession session) {
- if (sessionsById != null) {
- sessionsById.remove(new ByteArray(session.getId()));
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #getSession(String, int) for an implementation-specific but more
- * efficient approach
- */
- public SSLSession getSession(byte[] sessionId) {
- if (sessionId == null) {
- throw new NullPointerException("sessionId == null");
- }
- /*
- * This method is typically used in conjunction with getIds() to
- * iterate over the sessions linearly, so it doesn't make sense for
- * it to impact access order.
- *
- * It also doesn't load sessions from the persistent cache as doing
- * so would likely force every session to load.
- */
-
- ByteArray id = new ByteArray(sessionId);
- SSLSession session;
- synchronized (sessions) {
- indexById();
- session = sessionsById.get(id);
- }
- if (session != null && session.isValid()) {
- return session;
- }
- return null;
- }
-
- /**
- * Ensures that the ID-based index is initialized.
- */
- private void indexById() {
- if (sessionsById == null) {
- sessionsById = new HashMap<ByteArray, SSLSession>();
- for (SSLSession session : sessions.values()) {
- sessionsById.put(new ByteArray(session.getId()), session);
- }
- }
- }
-
- /**
- * Adds the given session to the ID-based index if the index has already
- * been initialized.
- */
- private void indexById(byte[] id, SSLSession session) {
- if (sessionsById != null) {
- sessionsById.put(new ByteArray(id), session);
+ protected void sessionRemoved(SSLSession session) {
+ HostAndPort hostAndPortKey = new HostAndPort(session);
+ synchronized (sessionsByHostAndPort) {
+ sessionsByHostAndPort.remove(hostAndPortKey);
}
}
@@ -175,8 +59,9 @@ public class ClientSessionContext extends AbstractSessionContext {
*/
public SSLSession getSession(String host, int port) {
SSLSession session;
- synchronized (sessions) {
- session = sessions.get(new HostAndPort(host, port));
+ HostAndPort hostAndPortKey = new HostAndPort(host, port);
+ synchronized (sessionsByHostAndPort) {
+ session = sessionsByHostAndPort.get(hostAndPortKey);
}
if (session != null && session.isValid()) {
return session;
@@ -188,9 +73,9 @@ public class ClientSessionContext extends AbstractSessionContext {
if (data != null) {
session = toSession(data, host, port);
if (session != null && session.isValid()) {
- synchronized (sessions) {
- sessions.put(new HostAndPort(host, port), session);
- indexById(session.getId(), session);
+ super.putSession(session);
+ synchronized (sessionsByHostAndPort) {
+ sessionsByHostAndPort.put(hostAndPortKey, session);
}
return session;
}
@@ -202,15 +87,11 @@ public class ClientSessionContext extends AbstractSessionContext {
@Override
void putSession(SSLSession session) {
- byte[] id = session.getId();
- if (id.length == 0) {
- return;
- }
- HostAndPort key = new HostAndPort(session.getPeerHost(),
- session.getPeerPort());
- synchronized (sessions) {
- sessions.put(key, session);
- indexById(id, session);
+ super.putSession(session);
+
+ HostAndPort hostAndPortKey = new HostAndPort(session);
+ synchronized (sessionsByHostAndPort) {
+ sessionsByHostAndPort.put(hostAndPortKey, session);
}
// TODO: This in a background thread.
@@ -226,6 +107,10 @@ public class ClientSessionContext extends AbstractSessionContext {
final String host;
final int port;
+ HostAndPort(SSLSession session) {
+ this(session.getPeerHost(), session.getPeerPort());
+ }
+
HostAndPort(String host, int port) {
this.host = host;
this.port = port;
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 6e38cf6..02b015b 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
@@ -25,6 +25,10 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import org.bouncycastle.openssl.PEMWriter;
/**
@@ -104,6 +108,106 @@ public class NativeCrypto {
private static final String SUPPORTED_PROTOCOL_SSLV3 = "SSLv3";
private static final String SUPPORTED_PROTOCOL_TLSV1 = "TLSv1";
+ public static final Map<String, String> OPENSSL_TO_STANDARD = new HashMap<String, String>();
+ public static final Map<String, String> STANDARD_TO_OPENSSL = new LinkedHashMap<String, String>();
+
+ private static void add(String standard, String openssl) {
+ OPENSSL_TO_STANDARD.put(openssl, standard);
+ STANDARD_TO_OPENSSL.put(standard, openssl);
+ }
+
+ static {
+ // Note these are added in priority order
+ add("SSL_RSA_WITH_RC4_128_MD5", "RC4-MD5");
+ add("SSL_RSA_WITH_RC4_128_SHA", "RC4-SHA");
+ add("TLS_RSA_WITH_AES_128_CBC_SHA", "AES128-SHA");
+ add("TLS_RSA_WITH_AES_256_CBC_SHA", "AES256-SHA");
+ add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "ECDH-ECDSA-RC4-SHA");
+ add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", "ECDH-ECDSA-AES128-SHA");
+ add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "ECDH-ECDSA-AES256-SHA");
+ add("TLS_ECDH_RSA_WITH_RC4_128_SHA", "ECDH-RSA-RC4-SHA");
+ add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "ECDH-RSA-AES128-SHA");
+ add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "ECDH-RSA-AES256-SHA");
+ add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "ECDHE-ECDSA-RC4-SHA");
+ add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "ECDHE-ECDSA-AES128-SHA");
+ add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "ECDHE-ECDSA-AES256-SHA");
+ add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", "ECDHE-RSA-RC4-SHA");
+ add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "ECDHE-RSA-AES128-SHA");
+ add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "ECDHE-RSA-AES256-SHA");
+ add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "DHE-RSA-AES128-SHA");
+ add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "DHE-RSA-AES256-SHA");
+ add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "DHE-DSS-AES128-SHA");
+ add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "DHE-DSS-AES256-SHA");
+ add("SSL_RSA_WITH_3DES_EDE_CBC_SHA", "DES-CBC3-SHA");
+ add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDH-ECDSA-DES-CBC3-SHA");
+ add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "ECDH-RSA-DES-CBC3-SHA");
+ add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-ECDSA-DES-CBC3-SHA");
+ add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-RSA-DES-CBC3-SHA");
+ add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "EDH-RSA-DES-CBC3-SHA");
+ add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "EDH-DSS-DES-CBC3-SHA");
+ add("SSL_RSA_WITH_DES_CBC_SHA", "DES-CBC-SHA");
+ add("SSL_DHE_RSA_WITH_DES_CBC_SHA", "EDH-RSA-DES-CBC-SHA");
+ add("SSL_DHE_DSS_WITH_DES_CBC_SHA", "EDH-DSS-DES-CBC-SHA");
+ add("SSL_RSA_EXPORT_WITH_RC4_40_MD5", "EXP-RC4-MD5");
+ add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "EXP-DES-CBC-SHA");
+ add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-RSA-DES-CBC-SHA");
+ add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-DSS-DES-CBC-SHA");
+ add("SSL_RSA_WITH_NULL_MD5", "NULL-MD5");
+ add("SSL_RSA_WITH_NULL_SHA", "NULL-SHA");
+ add("TLS_ECDH_ECDSA_WITH_NULL_SHA", "ECDH-ECDSA-NULL-SHA");
+ add("TLS_ECDH_RSA_WITH_NULL_SHA", "ECDH-RSA-NULL-SHA");
+ add("TLS_ECDHE_ECDSA_WITH_NULL_SHA", "ECDHE-ECDSA-NULL-SHA");
+ add("TLS_ECDHE_RSA_WITH_NULL_SHA", "ECDHE-RSA-NULL-SHA");
+ add("SSL_DH_anon_WITH_RC4_128_MD5", "ADH-RC4-MD5");
+ add("TLS_DH_anon_WITH_AES_128_CBC_SHA", "ADH-AES128-SHA");
+ add("TLS_DH_anon_WITH_AES_256_CBC_SHA", "ADH-AES256-SHA");
+ add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", "ADH-DES-CBC3-SHA");
+ add("SSL_DH_anon_WITH_DES_CBC_SHA", "ADH-DES-CBC-SHA");
+ add("TLS_ECDH_anon_WITH_RC4_128_SHA", "AECDH-RC4-SHA");
+ add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", "AECDH-AES128-SHA");
+ add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", "AECDH-AES256-SHA");
+ add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", "AECDH-DES-CBC3-SHA");
+ add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "EXP-ADH-RC4-MD5");
+ add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "EXP-ADH-DES-CBC-SHA");
+ add("TLS_ECDH_anon_WITH_NULL_SHA", "AECDH-NULL-SHA");
+
+ // No Kerberos in Android
+ //add("TLS_KRB5_WITH_RC4_128_SHA", "KRB5-RC4-SHA");
+ //add("TLS_KRB5_WITH_RC4_128_MD5", "KRB5-RC4-MD5");
+ //add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA", "KRB5-DES-CBC3-SHA");
+ //add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5", "KRB5-DES-CBC3-MD5");
+ //add("TLS_KRB5_WITH_DES_CBC_SHA", "KRB5-DES-CBC-SHA");
+ //add("TLS_KRB5_WITH_DES_CBC_MD5", "KRB5-DES-CBC-MD5");
+ //add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", "EXP-KRB5-RC4-SHA");
+ //add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", "EXP-KRB5-RC4-MD5");
+ //add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", "EXP-KRB5-DES-CBC-SHA");
+ //add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", "EXP-KRB5-DES-CBC-MD5");
+
+ // not implemented by either RI or OpenSSL
+ //add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", null);
+ //add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", null);
+
+ // EXPORT1024 suites were never standardized but were widely implemented.
+ // OpenSSL 0.9.8c and later have disabled TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
+ //add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", "EXP1024-DES-CBC-SHA");
+ //add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", "EXP1024-RC4-SHA");
+
+ // No RC2
+ //add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "EXP-RC2-CBC-MD5");
+ //add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", "EXP-KRB5-RC2-CBC-SHA");
+ //add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", "EXP-KRB5-RC2-CBC-MD5");
+
+ // PSK is Private Shared Key - didn't exist in Froyo's openssl - no JSSE equivalent
+ //add(null, "PSK-3DES-EDE-CBC-SHA");
+ //add(null, "PSK-AES128-CBC-SHA");
+ //add(null, "PSK-AES256-CBC-SHA");
+ //add(null, "PSK-RC4-SHA");
+
+ }
+
+ private static final String[] SUPPORTED_CIPHER_SUITES
+ = STANDARD_TO_OPENSSL.keySet().toArray(new String[0]);
+
// SSL mode
public static long SSL_MODE_HANDSHAKE_CUTTHROUGH = 0x00000040L;
@@ -113,18 +217,28 @@ public class NativeCrypto {
public static native int SSL_CTX_new();
- public static native String[] SSL_CTX_get_ciphers(int ssl_ctx);
-
public static String[] getDefaultCipherSuites() {
- int ssl_ctx = SSL_CTX_new();
- String[] supportedCiphers = SSL_CTX_get_ciphers(ssl_ctx);
- SSL_CTX_free(ssl_ctx);
- return supportedCiphers;
+ return new String[] {
+ "SSL_RSA_WITH_RC4_128_MD5",
+ "SSL_RSA_WITH_RC4_128_SHA",
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "SSL_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
+ };
}
public static String[] getSupportedCipherSuites() {
- // TODO really return full cipher list
- return getDefaultCipherSuites();
+ return SUPPORTED_CIPHER_SUITES.clone();
}
public static native void SSL_CTX_free(int ssl_ctx);
@@ -236,7 +350,7 @@ public class NativeCrypto {
optionsToSet &= ~SSL_OP_NO_TLSv1;
optionsToClear |= SSL_OP_NO_TLSv1;
} else {
- throw new IllegalArgumentException("Protocol " + protocol +
+ throw new IllegalArgumentException("protocol " + protocol +
" is not supported");
}
}
@@ -256,29 +370,25 @@ public class NativeCrypto {
}
if ((!protocol.equals(SUPPORTED_PROTOCOL_SSLV3))
&& (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) {
- throw new IllegalArgumentException("Protocol " + protocol +
+ throw new IllegalArgumentException("protocol " + protocol +
" is not supported");
}
}
return protocols;
}
- public static native String[] SSL_get_ciphers(int ssl);
-
- public static native void SSL_set_cipher_list(int ssl, String ciphers);
+ public static native void SSL_set_cipher_lists(int ssl, String[] ciphers);
public static void setEnabledCipherSuites(int ssl, String[] cipherSuites) {
checkEnabledCipherSuites(cipherSuites);
- String controlString = "";
+ List<String> opensslSuites = new ArrayList<String>();
for (int i = 0; i < cipherSuites.length; i++) {
String cipherSuite = cipherSuites[i];
- if (i == 0) {
- controlString = cipherSuite;
- } else {
- controlString += ":" + cipherSuite;
- }
+ String openssl = STANDARD_TO_OPENSSL.get(cipherSuite);
+ String cs = (openssl == null) ? cipherSuite : openssl;
+ opensslSuites.add(cs);
}
- SSL_set_cipher_list(ssl, controlString);
+ SSL_set_cipher_lists(ssl, opensslSuites.toArray(new String[opensslSuites.size()]));
}
public static String[] checkEnabledCipherSuites(String[] cipherSuites) {
@@ -286,24 +396,21 @@ public class NativeCrypto {
throw new IllegalArgumentException("cipherSuites == null");
}
// makes sure all suites are valid, throwing on error
- String[] supportedCipherSuites = getSupportedCipherSuites();
for (int i = 0; i < cipherSuites.length; i++) {
String cipherSuite = cipherSuites[i];
if (cipherSuite == null) {
throw new IllegalArgumentException("cipherSuites[" + i + "] == null");
}
- findSuite(supportedCipherSuites, cipherSuite);
- }
- return cipherSuites;
- }
-
- private static void findSuite(String[] supportedCipherSuites, String suite) {
- for (String supportedCipherSuite : supportedCipherSuites) {
- if (supportedCipherSuite.equals(suite)) {
- return;
+ if (STANDARD_TO_OPENSSL.containsKey(cipherSuite)) {
+ continue;
}
+ if (OPENSSL_TO_STANDARD.containsKey(cipherSuite)) {
+ // TODO log warning about using backward compatability
+ continue;
+ }
+ throw new IllegalArgumentException("cipherSuite " + cipherSuite + " is not supported.");
}
- throw new IllegalArgumentException("Protocol " + suite + " is not supported.");
+ return cipherSuites;
}
/*
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
index b722a97..b889e7d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
@@ -23,9 +23,8 @@ import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Iterator;
-import java.util.UnknownFormatConversionException;
+import java.util.Map;
import java.util.Vector;
-
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLPermission;
import javax.net.ssl.SSLSession;
@@ -33,7 +32,6 @@ import javax.net.ssl.SSLSessionBindingEvent;
import javax.net.ssl.SSLSessionBindingListener;
import javax.net.ssl.SSLSessionContext;
import javax.security.cert.CertificateEncodingException;
-
import org.apache.harmony.luni.util.TwoKeyHashMap;
import org.apache.harmony.security.provider.cert.X509CertImpl;
@@ -54,6 +52,8 @@ public class OpenSSLSessionImpl implements SSLSession {
protected int sslSessionNativePointer;
private String peerHost;
private int peerPort;
+ private String cipherSuite;
+ private String protocol;
private AbstractSessionContext sessionContext;
private byte[] id;
@@ -310,7 +310,14 @@ public class OpenSSLSessionImpl implements SSLSession {
* actual SSL session.
*/
public String getCipherSuite() {
- return NativeCrypto.SSL_SESSION_cipher(sslSessionNativePointer);
+ if (cipherSuite == null) {
+ String name = NativeCrypto.SSL_SESSION_cipher(sslSessionNativePointer);
+ cipherSuite = NativeCrypto.OPENSSL_TO_STANDARD.get(name);
+ if (cipherSuite == null) {
+ cipherSuite = name;
+ }
+ }
+ return cipherSuite;
}
/**
@@ -322,7 +329,10 @@ public class OpenSSLSessionImpl implements SSLSession {
*
*/
public String getProtocol() {
- return NativeCrypto.SSL_SESSION_get_version(sslSessionNativePointer);
+ if (protocol == null) {
+ protocol = NativeCrypto.SSL_SESSION_get_version(sslSessionNativePointer);
+ }
+ return protocol;
}
/**
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 f643249..acb6098 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
@@ -213,9 +213,38 @@ public class OpenSSLSocketImpl
super.getInetAddress().getHostName() == null) {
return null;
}
- return (OpenSSLSessionImpl) sessionContext.getSession(
+ OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(
super.getInetAddress().getHostName(),
super.getPort());
+ if (session == null) {
+ return null;
+ }
+
+ String protocol = session.getProtocol();
+ boolean protocolFound = false;
+ for (String enabledProtocol : enabledProtocols) {
+ if (protocol.equals(enabledProtocol)) {
+ protocolFound = true;
+ break;
+ }
+ }
+ if (!protocolFound) {
+ return null;
+ }
+
+ String cipherSuite = session.getCipherSuite();
+ boolean cipherSuiteFound = false;
+ for (String enabledCipherSuite : enabledCipherSuites) {
+ if (cipherSuite.equals(enabledCipherSuite)) {
+ cipherSuiteFound = true;
+ break;
+ }
+ }
+ if (!cipherSuiteFound) {
+ return null;
+ }
+
+ return session;
}
/**
@@ -323,7 +352,7 @@ public class OpenSSLSocketImpl
byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId);
if (sslSession != null) {
- session.lastAccessedTime = System.currentTimeMillis();
+ sslSession.lastAccessedTime = System.currentTimeMillis();
LoggerHolder.logger.fine("Reused cached session for "
+ getInetAddress() + ".");
NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
index 6ba82ff..0352ef6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
@@ -16,10 +16,6 @@
package org.apache.harmony.xnet.provider.jsse;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
import javax.net.ssl.SSLSession;
/**
@@ -28,15 +24,6 @@ import javax.net.ssl.SSLSession;
*/
public class ServerSessionContext extends AbstractSessionContext {
- private final Map<ByteArray, SSLSession> sessions
- = new LinkedHashMap<ByteArray, SSLSession>() {
- @Override
- protected boolean removeEldestEntry(
- Map.Entry<ByteArray, SSLSession> eldest) {
- return maximumSize > 0 && size() > maximumSize;
- }
- };
-
private SSLServerSessionCache persistentCache;
public ServerSessionContext() {
@@ -56,58 +43,13 @@ public class ServerSessionContext extends AbstractSessionContext {
this.persistentCache = persistentCache;
}
- Iterator<SSLSession> sessionIterator() {
- synchronized (sessions) {
- SSLSession[] array = sessions.values().toArray(
- new SSLSession[sessions.size()]);
- return Arrays.asList(array).iterator();
- }
- }
-
- void trimToSize() {
- synchronized (sessions) {
- int size = sessions.size();
- if (size > maximumSize) {
- int removals = size - maximumSize;
- Iterator<SSLSession> i = sessions.values().iterator();
- do {
- i.next();
- i.remove();
- } while (--removals > 0);
- }
- }
- }
-
- public void setSessionTimeout(int seconds)
- throws IllegalArgumentException {
- if (seconds < 0) {
- throw new IllegalArgumentException("seconds < 0");
- }
- timeout = seconds;
-
- synchronized (sessions) {
- Iterator<SSLSession> i = sessions.values().iterator();
- while (i.hasNext()) {
- SSLSession session = i.next();
- // SSLSession's know their context and consult the
- // timeout as part of their validity condition.
- if (!session.isValid()) {
- i.remove();
- }
- }
- }
- }
+ protected void sessionRemoved(SSLSession session) {}
- public SSLSession getSession(byte[] sessionId) {
- if (sessionId == null) {
- throw new NullPointerException("sessionId == null");
- }
- ByteArray key = new ByteArray(sessionId);
- SSLSession session;
- synchronized (sessions) {
- session = sessions.get(key);
- }
- if (session != null && session.isValid()) {
+ @Override
+ public SSLSession getSession(byte[] sessionId)
+ {
+ SSLSession session = super.getSession(sessionId);
+ if (session != null) {
return session;
}
@@ -117,9 +59,7 @@ public class ServerSessionContext extends AbstractSessionContext {
if (data != null) {
session = toSession(data, null, -1);
if (session != null && session.isValid()) {
- synchronized (sessions) {
- sessions.put(key, session);
- }
+ super.putSession(session);
return session;
}
}
@@ -130,14 +70,7 @@ public class ServerSessionContext extends AbstractSessionContext {
@Override
void putSession(SSLSession session) {
- byte[] id = session.getId();
- if (id.length == 0) {
- return;
- }
- ByteArray key = new ByteArray(id);
- synchronized (sessions) {
- sessions.put(key, session);
- }
+ super.putSession(session);
// TODO: In background thread.
if (persistentCache != null) {
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index 2c8a02a..0e9d641 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -1340,43 +1340,6 @@ static int NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
return (jint) sslCtx;
}
-static jobjectArray makeCipherList(JNIEnv* env, STACK_OF(SSL_CIPHER)* cipher_list) {
- // Create a String[].
- jclass stringClass = env->FindClass("java/lang/String");
- if (stringClass == NULL) {
- return NULL;
- }
- int cipherCount = sk_SSL_CIPHER_num(cipher_list);
- jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
- if (array == NULL) {
- return NULL;
- }
-
- // Fill in the cipher names.
- for (int i = 0; i < cipherCount; ++i) {
- const char* c = sk_SSL_CIPHER_value(cipher_list, i)->name;
- JNI_TRACE("makeCipherList[i=%d]=%s", i, c);
- env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
- }
- return array;
-}
-
-/**
- * Loads the ciphers suites that are supported by an SSL_CTX
- * and returns them in a string array.
- */
-static jobjectArray NativeCrypto_SSL_CTX_get_ciphers(JNIEnv* env,
- jclass, jint ssl_ctx_address)
-{
- SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
- JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_get_ciphers", ssl_ctx);
- if (ssl_ctx == NULL) {
- jniThrowNullPointerException(env, "SSL_CTX is null");
- return NULL;
- }
- return makeCipherList(env, ssl_ctx->cipher_list);
-}
-
/**
* public static native void SSL_CTX_free(int ssl_ctx)
*/
@@ -1617,34 +1580,50 @@ static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
}
/**
- * Loads the ciphers suites that are enabled in the SSL
- * and returns them in a string array.
+ * Sets the ciphers suites that are enabled in the SSL
*/
-static jobjectArray NativeCrypto_SSL_get_ciphers(JNIEnv* env,
- jclass, jint ssl_address)
+static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
+ jint ssl_address, jobjectArray cipherSuites)
{
SSL* ssl = to_SSL(env, ssl_address, true);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
if (ssl == NULL) {
- return NULL;
+ return;
}
- return makeCipherList(env, SSL_get_ciphers(ssl));
-}
-/**
- * Sets the ciphers suites that are enabled in the SSL
- */
-static void NativeCrypto_SSL_set_cipher_list(JNIEnv* env, jclass,
- jint ssl_address, jstring controlString)
-{
- SSL* ssl = to_SSL(env, ssl_address, true);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_list controlString=%p", ssl, controlString);
- if (ssl == NULL) {
- return;
+ STACK_OF(SSL_CIPHER)* cipherstack = sk_SSL_CIPHER_new_null();
+ if (cipherstack == NULL) {
+ jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
+ return;
}
- ScopedUtfChars str(env, controlString);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_controlString str=%s", ssl, str.c_str());
- int rc = SSL_set_cipher_list(ssl, str.c_str());
+
+ const SSL_METHOD* ssl_method = ssl->method;
+ int num_ciphers = ssl_method->num_ciphers();
+
+ int length = env->GetArrayLength(cipherSuites);
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
+ for (int i = 0; i < length; i++) {
+ jstring cipherSuite = (jstring) env->GetObjectArrayElement(cipherSuites, i);
+ ScopedUtfChars c(env, cipherSuite);
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
+ bool found = false;
+ for (int j = 0; j < num_ciphers; j++) {
+ 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, cipher);
+ found = true;
+ }
+ }
+ if (!found) {
+ sk_SSL_CIPHER_free(cipherstack);
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Could not find cipher suite.");
+ return;
+ }
+ }
+
+ int rc = SSL_set_cipher_lists(ssl, cipherstack);
if (rc == 0) {
freeSslErrorState();
jniThrowException(env, "java/lang/IllegalArgumentException",
@@ -2561,53 +2540,51 @@ static jint NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray bytes,
* (3) pointer to C function.
*/
static JNINativeMethod sNativeCryptoMethods[] = {
- { "clinit", "()V", (void*)NativeCrypto_clinit},
- { "EVP_PKEY_new_DSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_DSA },
- { "EVP_PKEY_new_RSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_RSA },
- { "EVP_PKEY_free", "(I)V", (void*)NativeCrypto_EVP_PKEY_free },
- { "EVP_new", "()I", (void*)NativeCrypto_EVP_new },
- { "EVP_free", "(I)V", (void*)NativeCrypto_EVP_free },
- { "EVP_DigestFinal", "(I[BI)I", (void*)NativeCrypto_EVP_DigestFinal },
- { "EVP_DigestInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_DigestInit },
- { "EVP_DigestBlockSize", "(I)I", (void*)NativeCrypto_EVP_DigestBlockSize },
- { "EVP_DigestSize", "(I)I", (void*)NativeCrypto_EVP_DigestSize },
- { "EVP_DigestUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_DigestUpdate },
- { "EVP_VerifyInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_VerifyInit },
- { "EVP_VerifyUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_VerifyUpdate },
- { "EVP_VerifyFinal", "(I[BIII)I", (void*)NativeCrypto_EVP_VerifyFinal },
- { "verifySignature", "([B[BLjava/lang/String;[B[B)I", (void*)NativeCrypto_verifysignature},
- { "SSL_CTX_new", "()I", (void*)NativeCrypto_SSL_CTX_new },
- { "SSL_CTX_get_ciphers", "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_CTX_get_ciphers},
- { "SSL_CTX_free", "(I)V", (void*)NativeCrypto_SSL_CTX_free },
- { "SSL_new", "(ILjava/lang/String;Ljava/lang/String;[B)I", (void*)NativeCrypto_SSL_new},
- { "SSL_get_mode", "(I)J", (void*)NativeCrypto_SSL_get_mode },
- { "SSL_set_mode", "(IJ)J", (void*)NativeCrypto_SSL_set_mode },
- { "SSL_clear_mode", "(IJ)J", (void*)NativeCrypto_SSL_clear_mode },
- { "SSL_get_options", "(I)J", (void*)NativeCrypto_SSL_get_options },
- { "SSL_set_options", "(IJ)J", (void*)NativeCrypto_SSL_set_options },
- { "SSL_clear_options", "(IJ)J", (void*)NativeCrypto_SSL_clear_options },
- { "SSL_get_ciphers", "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_get_ciphers },
- { "SSL_set_cipher_list", "(ILjava/lang/String;)V", (void*)NativeCrypto_SSL_set_cipher_list },
- { "SSL_set_verify", "(II)V", (void*)NativeCrypto_SSL_set_verify},
- { "SSL_set_session", "(II)V", (void*)NativeCrypto_SSL_set_session },
+ { "clinit", "()V", (void*)NativeCrypto_clinit},
+ { "EVP_PKEY_new_DSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_DSA },
+ { "EVP_PKEY_new_RSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_RSA },
+ { "EVP_PKEY_free", "(I)V", (void*)NativeCrypto_EVP_PKEY_free },
+ { "EVP_new", "()I", (void*)NativeCrypto_EVP_new },
+ { "EVP_free", "(I)V", (void*)NativeCrypto_EVP_free },
+ { "EVP_DigestFinal", "(I[BI)I", (void*)NativeCrypto_EVP_DigestFinal },
+ { "EVP_DigestInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_DigestInit },
+ { "EVP_DigestBlockSize", "(I)I", (void*)NativeCrypto_EVP_DigestBlockSize },
+ { "EVP_DigestSize", "(I)I", (void*)NativeCrypto_EVP_DigestSize },
+ { "EVP_DigestUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_DigestUpdate },
+ { "EVP_VerifyInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_VerifyInit },
+ { "EVP_VerifyUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_VerifyUpdate },
+ { "EVP_VerifyFinal", "(I[BIII)I", (void*)NativeCrypto_EVP_VerifyFinal },
+ { "verifySignature", "([B[BLjava/lang/String;[B[B)I", (void*)NativeCrypto_verifysignature},
+ { "SSL_CTX_new", "()I", (void*)NativeCrypto_SSL_CTX_new },
+ { "SSL_CTX_free", "(I)V", (void*)NativeCrypto_SSL_CTX_free },
+ { "SSL_new", "(ILjava/lang/String;Ljava/lang/String;[B)I", (void*)NativeCrypto_SSL_new},
+ { "SSL_get_mode", "(I)J", (void*)NativeCrypto_SSL_get_mode },
+ { "SSL_set_mode", "(IJ)J", (void*)NativeCrypto_SSL_set_mode },
+ { "SSL_clear_mode", "(IJ)J", (void*)NativeCrypto_SSL_clear_mode },
+ { "SSL_get_options", "(I)J", (void*)NativeCrypto_SSL_get_options },
+ { "SSL_set_options", "(IJ)J", (void*)NativeCrypto_SSL_set_options },
+ { "SSL_clear_options", "(IJ)J", (void*)NativeCrypto_SSL_clear_options },
+ { "SSL_set_cipher_lists", "(I[Ljava/lang/String;)V", (void*)NativeCrypto_SSL_set_cipher_lists },
+ { "SSL_set_verify", "(II)V", (void*)NativeCrypto_SSL_set_verify},
+ { "SSL_set_session", "(II)V", (void*)NativeCrypto_SSL_set_session },
{ "SSL_set_session_creation_enabled", "(IZ)V", (void*)NativeCrypto_SSL_set_session_creation_enabled },
- { "SSL_do_handshake", "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$CertificateChainVerifier;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$HandshakeCompletedCallback;IZ)I",(void*)NativeCrypto_SSL_do_handshake},
- { "SSL_get_certificate", "(I)[[B", (void*)NativeCrypto_SSL_get_certificate},
- { "SSL_read_byte", "(II)I", (void*)NativeCrypto_SSL_read_byte},
- { "SSL_read", "(I[BIII)I", (void*)NativeCrypto_SSL_read},
- { "SSL_write_byte", "(II)V", (void*)NativeCrypto_SSL_write_byte},
- { "SSL_write", "(I[BII)V", (void*)NativeCrypto_SSL_write},
- { "SSL_interrupt", "(I)V", (void*)NativeCrypto_SSL_interrupt},
- { "SSL_shutdown", "(I)V", (void*)NativeCrypto_SSL_shutdown},
- { "SSL_free", "(I)V", (void*)NativeCrypto_SSL_free},
- { "SSL_SESSION_session_id", "(I)[B", (void*)NativeCrypto_SSL_SESSION_session_id },
+ { "SSL_do_handshake", "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$CertificateChainVerifier;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$HandshakeCompletedCallback;IZ)I",(void*)NativeCrypto_SSL_do_handshake},
+ { "SSL_get_certificate", "(I)[[B", (void*)NativeCrypto_SSL_get_certificate},
+ { "SSL_read_byte", "(II)I", (void*)NativeCrypto_SSL_read_byte},
+ { "SSL_read", "(I[BIII)I", (void*)NativeCrypto_SSL_read},
+ { "SSL_write_byte", "(II)V", (void*)NativeCrypto_SSL_write_byte},
+ { "SSL_write", "(I[BII)V", (void*)NativeCrypto_SSL_write},
+ { "SSL_interrupt", "(I)V", (void*)NativeCrypto_SSL_interrupt},
+ { "SSL_shutdown", "(I)V", (void*)NativeCrypto_SSL_shutdown},
+ { "SSL_free", "(I)V", (void*)NativeCrypto_SSL_free},
+ { "SSL_SESSION_session_id", "(I)[B", (void*)NativeCrypto_SSL_SESSION_session_id },
{ "SSL_SESSION_get_peer_cert_chain", "(II)[[B", (void*)NativeCrypto_SSL_SESSION_get_peer_cert_chain },
- { "SSL_SESSION_get_time", "(I)J", (void*)NativeCrypto_SSL_SESSION_get_time },
+ { "SSL_SESSION_get_time", "(I)J", (void*)NativeCrypto_SSL_SESSION_get_time },
{ "SSL_SESSION_get_version", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_get_version },
- { "SSL_SESSION_cipher", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_cipher },
- { "SSL_SESSION_free", "(I)V", (void*)NativeCrypto_SSL_SESSION_free },
- { "i2d_SSL_SESSION", "(I)[B", (void*)NativeCrypto_i2d_SSL_SESSION },
- { "d2i_SSL_SESSION", "([BI)I", (void*)NativeCrypto_d2i_SSL_SESSION },
+ { "SSL_SESSION_cipher", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_cipher },
+ { "SSL_SESSION_free", "(I)V", (void*)NativeCrypto_SSL_SESSION_free },
+ { "i2d_SSL_SESSION", "(I)[B", (void*)NativeCrypto_i2d_SSL_SESSION },
+ { "d2i_SSL_SESSION", "([BI)I", (void*)NativeCrypto_d2i_SSL_SESSION },
};
int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
index 855949d..f8aed75 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
@@ -16,32 +16,44 @@
package javax.net.ssl;
-import dalvik.annotation.KnownFailure;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import junit.framework.TestCase;
public class SSLSessionContextTest extends TestCase {
- public static final void assertSSLSessionContextSize(int expected, SSLSessionContext s) {
- assertEquals(expected, Collections.list(s.getIds()).size());
+ public static final void assertSSLSessionContextSize(int expected, SSLContext sslContext) {
+ assertSSLSessionContextSize(expected,
+ sslContext.getClientSessionContext(),
+ sslContext.getServerSessionContext());
+ }
+
+ public static final void assertSSLSessionContextSize(int expected,
+ SSLSessionContext client,
+ SSLSessionContext server) {
+ assertSSLSessionContextSize(expected, client, false);
+ assertSSLSessionContextSize(expected, server, true);
+ }
+
+ public static final void assertSSLSessionContextSize(int expected, SSLSessionContext s, boolean server) {
+ int size = Collections.list(s.getIds()).size();
+ if (server && TestSSLContext.sslServerSocketSupportsSessionTickets()) {
+ assertEquals(0, size);
+ } else {
+ assertEquals(expected, size);
+ }
}
public void test_SSLSessionContext_getIds() {
TestSSLContext c = TestSSLContext.create();
- assertSSLSessionContextSize(0, c.sslContext.getClientSessionContext());
- assertSSLSessionContextSize(0, c.sslContext.getServerSessionContext());
+ assertSSLSessionContextSize(0, c.sslContext);
TestSSLSocketPair s = TestSSLSocketPair.create();
- assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext());
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
- } else {
- assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext());
- }
+ assertSSLSessionContextSize(1, s.c.sslContext);
Enumeration clientIds = s.c.sslContext.getClientSessionContext().getIds();
Enumeration serverIds = s.c.sslContext.getServerSessionContext().getIds();
byte[] clientId = (byte[]) clientIds.nextElement();
@@ -101,15 +113,15 @@ public class SSLSessionContextTest extends TestCase {
s.c.sslContext.getServerSessionContext().getSessionCacheSize());
}
- public void test_SSLSessionContext_setSessionCacheSize_basic() {
+ public void test_SSLSessionContext_setSessionCacheSize_noConnect() {
TestSSLContext c = TestSSLContext.create();
- assertBasicSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getClientSessionContext());
- assertBasicSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
- c.sslContext.getServerSessionContext());
+ assertNoConnectSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
+ c.sslContext.getClientSessionContext());
+ assertNoConnectSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
+ c.sslContext.getServerSessionContext());
}
- private static void assertBasicSetSessionCacheSizeBehavior(int expectedDefault, SSLSessionContext s) {
+ private static void assertNoConnectSetSessionCacheSizeBehavior(int expectedDefault, SSLSessionContext s) {
try {
s.setSessionCacheSize(-1);
fail();
@@ -120,9 +132,7 @@ public class SSLSessionContextTest extends TestCase {
assertEquals(1, s.getSessionCacheSize());
}
- @KnownFailure("Using OpenSSL cipher suite names")
- public void test_SSLSessionContext_setSessionCacheSize_dynamic() {
-
+ public void test_SSLSessionContext_setSessionCacheSize_oneConnect() {
TestSSLSocketPair s = TestSSLSocketPair.create();
SSLSessionContext client = s.c.sslContext.getClientSessionContext();
SSLSessionContext server = s.c.sslContext.getServerSessionContext();
@@ -130,21 +140,29 @@ public class SSLSessionContextTest extends TestCase {
client.getSessionCacheSize());
assertEquals(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
server.getSessionCacheSize());
- assertSSLSessionContextSize(1, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(1, server);
- }
+ assertSSLSessionContextSize(1, s.c.sslContext);
+ }
- LinkedList<String> uniqueCipherSuites
- = new LinkedList(Arrays.asList(s.server.getEnabledCipherSuites()));
- uniqueCipherSuites.remove(s.client.getSession().getCipherSuite());
+ public void test_SSLSessionContext_setSessionCacheSize_dynamic() {
+ TestSSLContext c = TestSSLContext.create();
+ SSLSessionContext client = c.sslContext.getClientSessionContext();
+ SSLSessionContext server = c.sslContext.getServerSessionContext();
+ String[] supportedCipherSuites = c.serverSocket.getSupportedCipherSuites();
+ c.serverSocket.setEnabledCipherSuites(supportedCipherSuites);
+ LinkedList<String> uniqueCipherSuites
+ = new LinkedList(Arrays.asList(supportedCipherSuites));
// only use RSA cipher suites which will work with our TrustProvider
Iterator<String> i = uniqueCipherSuites.iterator();
while (i.hasNext()) {
String cipherSuite = i.next();
+
+ // Certificate key length too long for export ciphers
+ if (cipherSuite.startsWith("SSL_RSA_EXPORT_")) {
+ i.remove();
+ continue;
+ }
+
if (cipherSuite.startsWith("SSL_RSA_")) {
continue;
}
@@ -161,7 +179,7 @@ public class SSLSessionContextTest extends TestCase {
}
/*
- * having more than 5 uniqueCipherSuites is a test
+ * having more than 3 uniqueCipherSuites is a test
* requirement, not a requirement of the interface or
* implementation. It simply allows us to make sure that we
* will not get a cached session ID since we'll have to
@@ -170,59 +188,32 @@ public class SSLSessionContextTest extends TestCase {
* reused the unique cipher suites every time it resets the
* session cache.
*/
- // TODO Fix Known Failure
- // Need to fix CipherSuites methods to use JSSE names
- assertTrue(uniqueCipherSuites.size() > 5);
-
- TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 1
- assertSSLSessionContextSize(2, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(2, server);
- }
- TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 2
- assertSSLSessionContextSize(3, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(3, server);
- }
+ assertTrue(uniqueCipherSuites.size() >= 3);
+ String cipherSuite1 = uniqueCipherSuites.get(0);
+ String cipherSuite2 = uniqueCipherSuites.get(1);
+ String cipherSuite3 = uniqueCipherSuites.get(2);
+
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite1 });
+ assertSSLSessionContextSize(1, c.sslContext);
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite2 });
+ assertSSLSessionContextSize(2, c.sslContext);
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite3 });
+ assertSSLSessionContextSize(3, c.sslContext);
client.setSessionCacheSize(1);
server.setSessionCacheSize(1);
assertEquals(1, client.getSessionCacheSize());
assertEquals(1, server.getSessionCacheSize());
- assertSSLSessionContextSize(1, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(1, server);
- }
- TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 3
- assertSSLSessionContextSize(1, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(1, server);
- }
+ assertSSLSessionContextSize(1, c.sslContext);
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite1 });
+ assertSSLSessionContextSize(1, c.sslContext);
client.setSessionCacheSize(2);
server.setSessionCacheSize(2);
- TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 4
- assertSSLSessionContextSize(2, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(2, server);
- }
- TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 5
- assertSSLSessionContextSize(2, client);
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, server);
- } else {
- assertSSLSessionContextSize(2, server);
- }
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite2 });
+ assertSSLSessionContextSize(2, c.sslContext);
+ TestSSLSocketPair.connect(c, new String[] { cipherSuite3 });
+ assertSSLSessionContextSize(2, c.sslContext);
}
public void test_SSLSessionContext_getSessionTimeout() {
@@ -262,16 +253,10 @@ public class SSLSessionContextTest extends TestCase {
}
TestSSLSocketPair s = TestSSLSocketPair.create();
- assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext());
- if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
- assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
- } else {
- assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext());
- }
+ assertSSLSessionContextSize(1, s.c.sslContext);
Thread.sleep(1 * 1000);
s.c.sslContext.getClientSessionContext().setSessionTimeout(1);
s.c.sslContext.getServerSessionContext().setSessionTimeout(1);
- assertSSLSessionContextSize(0, s.c.sslContext.getClientSessionContext());
- assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
+ assertSSLSessionContextSize(0, s.c.sslContext);
}
}
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
index 36b565b..eb15e57 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
@@ -47,6 +47,7 @@ public class SSLSessionTest extends TestCase {
assertNotNull(s.client.getCipherSuite());
assertEquals(s.server.getCipherSuite(),
s.client.getCipherSuite());
+ assertTrue(StandardNames.CIPHER_SUITES.contains(s.server.getCipherSuite()));
}
public void test_SSLSession_getCreationTime() {
@@ -199,6 +200,7 @@ public class SSLSessionTest extends TestCase {
assertNotNull(s.client.getProtocol());
assertEquals(s.server.getProtocol(),
s.client.getProtocol());
+ assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(s.server.getProtocol()));
}
public void test_SSLSession_getSessionContext() {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
index bb76390..15e2e71 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
@@ -36,7 +36,6 @@ public class SSLSocketFactoryTest extends TestCase {
assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass()));
}
- @KnownFailure("Using OpenSSL cipher suite names")
public void test_SSLSocketFactory_getDefaultCipherSuites() {
SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
String[] cipherSuites = sf.getDefaultCipherSuites();
@@ -52,13 +51,10 @@ public class SSLSocketFactoryTest extends TestCase {
// Make sure all cipherSuites names are expected
for (String cipherSuite : cipherSuites) {
- // TODO Fix Known Failure
- // Need to fix CipherSuites methods to use JSSE names
assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
}
}
- @KnownFailure("Using OpenSSL cipher suite names")
public void test_SSLSocketFactory_getSupportedCipherSuites() {
SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
String[] cipherSuites = sf.getSupportedCipherSuites();
@@ -75,11 +71,11 @@ public class SSLSocketFactoryTest extends TestCase {
// Make sure all cipherSuites names are expected
Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
for (String cipherSuite : cipherSuites) {
- assertNotNull(remainingCipherSuites.remove(cipherSuite));
+ assertTrue(remainingCipherSuites.remove(cipherSuite));
}
- // TODO Fix Known Failure
- // Need to fix CipherSuites methods to use JSSE names
assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
+
+ assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
}
@KnownFailure("Should not parse bogus port number -1 during createSocket")
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
index f9766a1..3a44510 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
@@ -33,7 +33,6 @@ import junit.framework.TestCase;
public class SSLSocketTest extends TestCase {
- @KnownFailure("Using OpenSSL cipher suite names")
public void test_SSLSocket_getSupportedCipherSuites() throws Exception {
SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket ssl = (SSLSocket) sf.createSocket();
@@ -42,14 +41,12 @@ public class SSLSocketTest extends TestCase {
assertTrue(cipherSuites.length != 0);
Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
for (String cipherSuite : cipherSuites) {
- assertNotNull(remainingCipherSuites.remove(cipherSuite));
+ assertTrue(remainingCipherSuites.remove(cipherSuite));
}
- // TODO Fix Known Failure
- // Need to fix CipherSuites methods to use JSSE names
assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
+ assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
}
- @KnownFailure("Using OpenSSL cipher suite names")
public void test_SSLSocket_getEnabledCipherSuites() throws Exception {
SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket ssl = (SSLSocket) sf.createSocket();
@@ -66,8 +63,6 @@ public class SSLSocketTest extends TestCase {
// Make sure all cipherSuites names are expected
for (String cipherSuite : cipherSuites) {
- // TODO Fix Known Failure
- // Need to fix CipherSuites methods to use JSSE names
assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
}
}
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
index cdad187..bce302a 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
@@ -178,7 +178,7 @@ public class SSLSessionTest extends TestCase {
@AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
public void test_getCipherSuite() {
try {
- assertEquals(cipherSuite, clientSession.getCipherSuite());
+ assertEquals(CIPHER_SUITE, clientSession.getCipherSuite());
} catch (Exception ex) {
fail("Unexpected exception " + ex);
}
@@ -571,9 +571,6 @@ public class SSLSessionTest extends TestCase {
public void valueUnbound(SSLSessionBindingEvent event) {}
}
-
-
- String cipherSuiteBKS = "AES256-SHA";
/**
* Defines the keystore contents for the server, BKS version. Holds just a
* single self-generated key. The subject name is "Test Server".
@@ -634,7 +631,7 @@ public class SSLSessionTest extends TestCase {
"uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef" +
"lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
- String cipherSuiteJKS = "SSL_RSA_WITH_RC4_128_MD5";
+ private static final String CIPHER_SUITE = "SSL_RSA_WITH_RC4_128_MD5";
/**
* Defines the keystore contents for the server, JKS version. Holds just a
* single self-generated key. The subject name is "Test Server".
@@ -707,8 +704,6 @@ public class SSLSessionTest extends TestCase {
private String PASSWORD = "android";
- String cipherSuite = (useBKS ? cipherSuiteBKS : cipherSuiteJKS);
-
/**
* Implements a test SSL socket server. It waits for a connection on a given
* port, requests client authentication (if specified), reads from the socket,