+ *
+ * in the cipher string anymore separating the Key Exchange from the Encryption Algorithm.
+ *
There is no Key Exchange defined in the suite at all. The Key Exchange has been moved to a separate TLS extension in the
+ * protocol.
+ *
+ * Because of these changes the list of ciphers is now very, very, small and so they are listed explicitly for comparison - this might
+ * not work if this list expands, or if TLS 1.4 comes along and changes more things. For compatibility all TLS 1.3 ciphers are reported
+ * as using DHE key exchange so that previous matching works.
+ */
+ private CipherSuite parseTls13(final String cipherSuite) {
+ final String cs = removeTlsPrefix(cipherSuite);
+ final int lastSep = cs.lastIndexOf(SEPARATOR);
+ if (lastSep == -1) {
+ return null;
+ }
+ final String cipherSpec = cs.substring(0, lastSep);
+ final String hashSpec = cs.substring(lastSep + 1);
+
+ final CipherImpl cipher = parseCipher(cipherSpec);
+ if (cipher == null) {
+ return null;
+ }
+
+ final MacImpl hash = parseHash(hashSpec);
+ if (hash == null) {
+ return null;
+ }
+ return new CipherSuiteImpl(cipherSuite, KeyExchangeImpl.TLSv13_KEY_EXCHANGE, cipher, hash);
+ }
+
@Override
public Set parse(final Collection ciphers) {
return parse(ciphers, null);
diff --git a/src/main/java/org/archie/groktls/impl/cipher/KeyExchangeImpl.java b/src/main/java/org/archie/groktls/impl/cipher/KeyExchangeImpl.java
index 0d0a340..5eea350 100644
--- a/src/main/java/org/archie/groktls/impl/cipher/KeyExchangeImpl.java
+++ b/src/main/java/org/archie/groktls/impl/cipher/KeyExchangeImpl.java
@@ -24,6 +24,14 @@ public class KeyExchangeImpl implements KeyExchange {
private static final Map ALIASES = new HashMap();
+ /**
+ * TLSv1.3 does not have a static key exchange and instead uses a key exchange message elsewhere in the protocol. Returning this should
+ * make other filters work correctly with this while marking that no key exchange is part of the specification. From the Protocol
+ * definition we do know there will be a key exchange so using the {@code NULL} key exchange would not be appropriate.
+ */
+ public static final KeyExchangeImpl TLSv13_KEY_EXCHANGE = new KeyExchangeImpl("TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED",
+ "TLSv1.3_PROTOCOL_DECIDED", false, null);
+
static {
// GOST key exchange from http://tools.ietf.org/html/draft-chudov-cryptopro-cptls-04
ALIASES.put("GOSTR341094", "GOST94");
diff --git a/src/test/java/org/archie/groktls/cipher/CipherSuiteFilterTest.java b/src/test/java/org/archie/groktls/cipher/CipherSuiteFilterTest.java
index 85d3d38..f5ba49c 100644
--- a/src/test/java/org/archie/groktls/cipher/CipherSuiteFilterTest.java
+++ b/src/test/java/org/archie/groktls/cipher/CipherSuiteFilterTest.java
@@ -598,7 +598,35 @@ public void testSpacesInFilterSpec() {
"TLS_DH_anon_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_NULL_SHA");
final List expectedCiphers = Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DH_RSA_WITH_AES_128_CBC_SHA");
- ItemFilter filter = new CipherSuiteFilterBuilderImpl().add(cipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA")).add(cipherSuite("TLS_DH_RSA_WITH_AES_128_CBC_SHA")).build();
+ final ItemFilter filter = new CipherSuiteFilterBuilderImpl().add(cipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA")).add(cipherSuite("TLS_DH_RSA_WITH_AES_128_CBC_SHA")).build();
checkResult("TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DH_RSA_WITH_AES_128_CBC_SHA", filter, supported, expectedCiphers);
}
+
+ @Test
+ public void testFipsIncludes13() {
+ final List tls13Ciphers = Arrays.asList("TLS_AES_128_GCM_SHA256",
+ "TLS_AES_256_GCM_SHA384",
+ "TLS_CHACHA20_POLY1305_SHA256",
+ "TLS_AES_128_CCM_SHA256",
+ "TLS_AES_128_CCM_8_SHA256");
+
+ final List expectedFipsCiphers = Arrays.asList("TLS_AES_128_GCM_SHA256",
+ "TLS_AES_256_GCM_SHA384",
+ "TLS_AES_128_CCM_SHA256");
+
+ final ItemFilter filter = new CipherSuiteFilterBuilderImpl().add(fips()).build();
+ checkResult("FIPS", filter, tls13Ciphers, expectedFipsCiphers);
+ }
+
+ @Test
+ public void testForwardSecrecyIncludes13() {
+ final List tls13Ciphers = Arrays.asList("TLS_AES_128_GCM_SHA256",
+ "TLS_AES_256_GCM_SHA384",
+ "TLS_CHACHA20_POLY1305_SHA256",
+ "TLS_AES_128_CCM_SHA256",
+ "TLS_AES_128_CCM_8_SHA256");
+
+ final ItemFilter filter = new CipherSuiteFilterBuilderImpl().add(forwardSecrecy()).build();
+ checkResult("FS", filter, tls13Ciphers, tls13Ciphers);
+ }
}
diff --git a/src/test/java/org/archie/groktls/cipher/TlsCipherParserTest.java b/src/test/java/org/archie/groktls/cipher/TlsCipherParserTest.java
index 088fc8d..a2ff4ca 100644
--- a/src/test/java/org/archie/groktls/cipher/TlsCipherParserTest.java
+++ b/src/test/java/org/archie/groktls/cipher/TlsCipherParserTest.java
@@ -447,6 +447,15 @@ public void testChaCha_Poly1305_draft_agl_CipherSuites() {
check("TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "DHE", "RSA", false, null, "CHACHA20_POLY1305", null, CipherType.AEAD, 256, "SHA256", 256);
}
+ @Test
+ public void testTls13_RFC8446_CipherSuites() {
+ check("TLS_AES_128_GCM_SHA256", "TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED", false, null, "AES", "GCM", CipherType.AEAD, 128, "SHA256", 256);
+ check("TLS_AES_256_GCM_SHA384", "TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED", false, null, "AES", "GCM", CipherType.AEAD, 256, "SHA384", 384);
+ check("TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED", false, null, "CHACHA20_POLY1305", null, CipherType.AEAD, 256, "SHA256", 256);
+ check("TLS_AES_128_CCM_SHA256", "TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED", false, null, "AES", "CCM", CipherType.AEAD, 128, "SHA256", 256);
+ check("TLS_AES_128_CCM_8_SHA256", "TLSv1.3_PROTOCOL_DECIDED", "TLSv1.3_PROTOCOL_DECIDED", false, null, "AES", "CCM_8", CipherType.AEAD, 128, "SHA256", 256);
+ }
+
private void check(final String cipherSuite,
final String keyExchange,
final String authentication,
diff --git a/src/test/java/org/archie/groktls/protocol/ProtocolVariantFilterTest.java b/src/test/java/org/archie/groktls/protocol/ProtocolVariantFilterTest.java
index 1cb88fb..0bfb5a6 100644
--- a/src/test/java/org/archie/groktls/protocol/ProtocolVariantFilterTest.java
+++ b/src/test/java/org/archie/groktls/protocol/ProtocolVariantFilterTest.java
@@ -35,8 +35,9 @@ public class ProtocolVariantFilterTest extends AbstractItemFilterTest ALL_PROTOCOLS = Arrays.asList(TLSv1, TLSv11, TLSv12, SSLv2HELLO, SSLv2, SSLv3);
+ private static final List ALL_PROTOCOLS = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13, SSLv2HELLO, SSLv2, SSLv3);
@Override
protected ItemFilterSpecParser createSpecParser() {
@@ -46,8 +47,8 @@ protected ItemFilterSpecParser createSpecParser() {
@Test
public void testAll() {
final List supported = ALL_PROTOCOLS;
- final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12, SSLv3);
- ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(all()).build();
+ final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13, SSLv3);
+ final ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(all()).build();
checkResult("ALL", filter, supported, expected);
}
@@ -73,16 +74,16 @@ public void testDefault() {
public void testComplementOfDefault() {
final List supported = ALL_PROTOCOLS;
final List defaults = Arrays.asList(TLSv1, TLSv11, SSLv3);
- final List expected = Arrays.asList(TLSv12);
- ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(complementOfDefaults()).build();
+ final List expected = Arrays.asList(TLSv12, TLSv13);
+ final ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(complementOfDefaults()).build();
checkResult("COMPLEMENTOFDEFAULT", filter, supported, expected, defaults);
}
@Test
public void testFamily() {
final List supported = ALL_PROTOCOLS;
- final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
- ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(family("TLS")).build();
+ final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
+ final ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(family("TLS")).build();
checkResult("fTLS", filter, supported, expected);
}
@@ -114,16 +115,16 @@ public void testUnsafeAndPseudoProtocols() {
@Test
public void testMinVersion() {
final List supported = ALL_PROTOCOLS;
- final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
- ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(3, 1)).build();
+ final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
+ final ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(3, 1)).build();
checkResult(">=TLSv1", filter, supported, expected);
}
@Test
public void testMinVersionString() {
final List supported = ALL_PROTOCOLS;
- final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
- ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(TLSv1)).build();
+ final List expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
+ final ItemFilter filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(TLSv1)).build();
checkResult(">=TLSv1", filter, supported, expected);
}
diff --git a/src/test/java/org/archie/groktls/protocol/ProtocolVariantParserTest.java b/src/test/java/org/archie/groktls/protocol/ProtocolVariantParserTest.java
index af307e6..55fa8b0 100644
--- a/src/test/java/org/archie/groktls/protocol/ProtocolVariantParserTest.java
+++ b/src/test/java/org/archie/groktls/protocol/ProtocolVariantParserTest.java
@@ -32,6 +32,7 @@ public void testVariants() {
check("TLSv1.0", "TLS", 3, 1, null);
check("TLSv1.1", "TLS", 3, 2, null);
check("TLSv1.2", "TLS", 3, 3, null);
+ check("TLSv1.3", "TLS", 3, 4, null);
}
private void check(final String name, final String family, final int major, final int minor, final String pseudo) {
diff --git a/src/test/java/org/archie/groktls/protocol/ProtocolVariantTest.java b/src/test/java/org/archie/groktls/protocol/ProtocolVariantTest.java
index 6a82a29..88304ea 100644
--- a/src/test/java/org/archie/groktls/protocol/ProtocolVariantTest.java
+++ b/src/test/java/org/archie/groktls/protocol/ProtocolVariantTest.java
@@ -24,10 +24,11 @@ public class ProtocolVariantTest {
@Test
public void testOrdering() {
- ProtocolVariant p10 = new ProtocolVariantImpl("TLSv1", "TLS", 3, 1, null);
- ProtocolVariant p10b = new ProtocolVariantImpl("SSLv3.1", "SSL", 3, 1, null);
- ProtocolVariant p11 = new ProtocolVariantImpl("TLSv1.1", "TLS", 3, 2, null);
- ProtocolVariant p12 = new ProtocolVariantImpl("TLSv1.2", "TLS", 3, 3, null);
+ final ProtocolVariant p10 = new ProtocolVariantImpl("TLSv1", "TLS", 3, 1, null);
+ final ProtocolVariant p10b = new ProtocolVariantImpl("SSLv3.1", "SSL", 3, 1, null);
+ final ProtocolVariant p11 = new ProtocolVariantImpl("TLSv1.1", "TLS", 3, 2, null);
+ final ProtocolVariant p12 = new ProtocolVariantImpl("TLSv1.2", "TLS", 3, 3, null);
+ final ProtocolVariant p13 = new ProtocolVariantImpl("TLSv1.3", "TLS", 3, 4, null);
assertTrue(p10.compareTo(p10b) == 0);
assertTrue(p10b.compareTo(p10) == 0);
@@ -40,6 +41,9 @@ public void testOrdering() {
assertTrue(p11.compareTo(p12) < 0);
assertTrue(p12.compareTo(p11) > 0);
+
+ assertTrue(p12.compareTo(p13) < 0);
+ assertTrue(p13.compareTo(p12) > 0);
}
}