summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/javax/net/ssl/SSLEngine.java5
-rw-r--r--luni/src/main/java/javax/net/ssl/SSLSocket.java5
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java8
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java92
-rw-r--r--support/src/test/java/libcore/java/security/StandardNames.java12
5 files changed, 118 insertions, 4 deletions
diff --git a/luni/src/main/java/javax/net/ssl/SSLEngine.java b/luni/src/main/java/javax/net/ssl/SSLEngine.java
index 3ba3450..cbf02ac 100644
--- a/luni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/luni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -542,6 +542,11 @@ import java.nio.ByteBuffer;
* <td>20+</td>
* </tr>
* <tr>
+ * <td>TLS_FALLBACK_SCSV</td>
+ * <td>21+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
* <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td>
* <td>21+</td>
* <td>21+</td>
diff --git a/luni/src/main/java/javax/net/ssl/SSLSocket.java b/luni/src/main/java/javax/net/ssl/SSLSocket.java
index 33a88b6..dc406e1 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSocket.java
@@ -521,6 +521,11 @@ import java.net.UnknownHostException;
* <td>11+</td>
* </tr>
* <tr>
+ * <td>TLS_FALLBACK_SCSV</td>
+ * <td>21+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
* <td>TLS_PSK_WITH_3DES_EDE_CBC_SHA</td>
* <td>21+</td>
* <td></td>
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index 8e29e71..fb7e0c9 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -154,11 +154,11 @@ public class SSLEngineTest extends TestCase {
continue;
}
/*
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on
- * its own, but instead in conjunction with other
- * cipher suites.
+ * Signaling Cipher Suite Values (SCSV) cannot be used on their own, but instead in
+ * conjunction with other cipher suites.
*/
- if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) {
+ if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)
+ || cipherSuite.equals(StandardNames.CIPHER_SUITE_FALLBACK)) {
continue;
}
/*
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index d24ef0b..10cf159 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -126,6 +126,14 @@ public class SSLSocketTest extends TestCase {
continue;
}
/*
+ * Similarly with the TLS_FALLBACK_SCSV suite, it is not
+ * a selectable suite, but is used in conjunction with
+ * other cipher suites.
+ */
+ if (cipherSuite.equals(StandardNames.CIPHER_SUITE_FALLBACK)) {
+ continue;
+ }
+ /*
* Kerberos cipher suites require external setup. See "Kerberos Requirements" in
* https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
* #KRBRequire
@@ -1562,6 +1570,90 @@ public class SSLSocketTest extends TestCase {
}
}
+ public void test_SSLSocket_sendsTlsFallbackScsv_Fallback_Success() throws Exception {
+ TestSSLContext context = TestSSLContext.create();
+
+ final SSLSocket client = (SSLSocket)
+ context.clientContext.getSocketFactory().createSocket(context.host, context.port);
+ final SSLSocket server = (SSLSocket) context.serverSocket.accept();
+
+ final String[] serverCipherSuites = server.getEnabledCipherSuites();
+ final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
+ System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
+ clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
+
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ Future<Void> s = executor.submit(new Callable<Void>() {
+ public Void call() throws Exception {
+ server.setEnabledProtocols(new String[] { "TLSv1.2" });
+ server.setEnabledCipherSuites(serverCipherSuites);
+ server.startHandshake();
+ return null;
+ }
+ });
+ Future<Void> c = executor.submit(new Callable<Void>() {
+ public Void call() throws Exception {
+ client.setEnabledProtocols(new String[] { "TLSv1.2" });
+ client.setEnabledCipherSuites(clientCipherSuites);
+ client.startHandshake();
+ return null;
+ }
+ });
+ executor.shutdown();
+
+ s.get();
+ c.get();
+ client.close();
+ server.close();
+ context.close();
+ }
+
+ public void test_SSLSocket_sendsTlsFallbackScsv_InappropriateFallback_Failure() throws Exception {
+ TestSSLContext context = TestSSLContext.create();
+
+ final SSLSocket client = (SSLSocket)
+ context.clientContext.getSocketFactory().createSocket(context.host, context.port);
+ final SSLSocket server = (SSLSocket) context.serverSocket.accept();
+
+ final String[] serverCipherSuites = server.getEnabledCipherSuites();
+ final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
+ System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
+ clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
+
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ Future<Void> s = executor.submit(new Callable<Void>() {
+ public Void call() throws Exception {
+ server.setEnabledProtocols(new String[] { "TLSv1", "SSLv3" });
+ server.setEnabledCipherSuites(serverCipherSuites);
+ try {
+ server.startHandshake();
+ fail("Should result in inappropriate fallback");
+ } catch (SSLHandshakeException expected) {
+ }
+ return null;
+ }
+ });
+ Future<Void> c = executor.submit(new Callable<Void>() {
+ public Void call() throws Exception {
+ client.setEnabledProtocols(new String[] { "SSLv3" });
+ client.setEnabledCipherSuites(clientCipherSuites);
+ try {
+ client.startHandshake();
+ fail("Should receive TLS alert inappropriate fallback");
+ } catch (SSLHandshakeException expected) {
+ }
+ return null;
+ }
+ });
+ executor.shutdown();
+
+ s.get();
+ c.get();
+ client.close();
+ server.close();
+ context.close();
+ }
+
/**
* Not run by default by JUnit, but can be run by Vogar by
* specifying it explicitly (or with main method below)
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index a526c2e..528a651 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -82,6 +82,14 @@ public final class StandardNames extends Assert {
= "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
/**
+ * From https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00 it is a
+ * signaling cipher suite value (SCSV) to indicate that this request is a
+ * protocol fallback (e.g., TLS 1.0 -> SSL 3.0) because the server didn't respond
+ * to the first request.
+ */
+ public static final String CIPHER_SUITE_FALLBACK = "TLS_FALLBACK_SCSV";
+
+ /**
* A map from algorithm type (e.g. Cipher) to a set of algorithms (e.g. AES, DES, ...)
*/
public static final Map<String,Set<String>> PROVIDER_ALGORITHMS
@@ -723,6 +731,10 @@ public final class StandardNames extends Assert {
// RFC 5746's Signaling Cipher Suite Value to indicate a request for secure renegotiation
addBoth(CIPHER_SUITE_SECURE_RENEGOTIATION);
+ // From https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00 to indicate
+ // TLS fallback request
+ addOpenSsl(CIPHER_SUITE_FALLBACK);
+
// non-defaultCipherSuites
addBoth( "TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
addBoth( "TLS_DH_anon_WITH_AES_256_CBC_SHA");