Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 58 additions & 27 deletions .classpath
Original file line number Diff line number Diff line change
@@ -1,27 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
2 changes: 2 additions & 0 deletions .settings/org.eclipse.jdt.apt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=false
10 changes: 7 additions & 3 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
Expand All @@ -45,7 +45,7 @@
<Import-Package>javax.net.ssl;version="0.0.0",javax.net;version="0.0.0",javax.crypto;version="0.0.0"</Import-Package>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment>
<Bundle-RequiredExecutionEnvironment>JavaSE-1.8</Bundle-RequiredExecutionEnvironment>
<_removeheaders>Bnd-LastModified,Private-Package</_removeheaders>
</instructions>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ public boolean matches(final CipherSuite cipher, final Set<CipherSuite> defaults
* <em>Filter spec usage:</em> <code>FS</code>.
*/
public static CipherFilter forwardSecrecy() {
return or(keyExchange("DHE"), keyExchange("ECDHE"));
return or(keyExchange("DHE"), keyExchange("ECDHE"), keyExchange("TLSv1.3_PROTOCOL_DECIDED"));
}

/**
Expand Down Expand Up @@ -501,8 +501,8 @@ public boolean matches(final CipherSuite cipher, final Set<CipherSuite> defaults
public static CipherFilter fips() {
// http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf
// http://csrc.nist.gov/publications/nistpubs/800-52/SP800-52.pdf
return and(or(keyExchange("DH"), keyExchange("DHE"), keyExchange("RSA"), keyExchange("ECDH"), keyExchange("ECDHE")),
or(authentication("DSS"), authentication("RSA"), authentication("ECDSA")),
return and(or(keyExchange("DH"), keyExchange("DHE"), keyExchange("RSA"), keyExchange("ECDH"), keyExchange("ECDHE"), keyExchange("TLSv1.3_PROTOCOL_DECIDED")),
or(authentication("DSS"), authentication("RSA"), authentication("ECDSA"), authentication("TLSv1.3_PROTOCOL_DECIDED")),
or(encryption("AES"), encryption("3DES")),
or(encryptionMode("CBC"), encryptionMode("GCM"), encryptionMode("CCM")),
or(mac("SHA"), mac("SHA256"), mac("SHA384"), mac("SHA512")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package org.archie.groktls.impl.cipher;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
Expand All @@ -35,6 +37,18 @@ public class CipherSuiteParserImpl implements ItemParser<CipherSuite> {
private static final Pattern PATTERN_DUAL_KEY_EXCHANGE = Pattern.compile("(RSA_FIPS|SRP_SHA|[^_]+)_([^_]+)(_EXPORT.*)?");
private static final Pattern PATTERN_SINGLE_KEY_EXCHANGE = Pattern.compile("(RSA_FIPS|SRP_SHA|[^_]+)(_EXPORT.*)?");

private static final Set<String> TLS_1_3_CIPHERS;

static {
final Set<String> tls13Ciphers = new HashSet<>();
tls13Ciphers.add("TLS_AES_128_GCM_SHA256");
tls13Ciphers.add("TLS_AES_256_GCM_SHA384");
tls13Ciphers.add("TLS_CHACHA20_POLY1305_SHA256");
tls13Ciphers.add("TLS_AES_128_CCM_SHA256");
tls13Ciphers.add("TLS_AES_128_CCM_8_SHA256");
TLS_1_3_CIPHERS = Collections.unmodifiableSet(tls13Ciphers);
}

private static final String PREFIX_SSLV2 = "SSL_CK_";
private static final String PREFIX_SSL = "SSL_";
private static final String PREFIX_TLS = "TLS_";
Expand All @@ -50,6 +64,11 @@ public CipherSuite parse(final String cipherSuite) {
if (cipherSuite.endsWith(SCSV_SUFFIX)) {
return new CipherSuiteImpl(cipherSuite);
}

if (TLS_1_3_CIPHERS.contains(cipherSuite)) {
return parseTls13(cipherSuite);
}

final String cs = patchSSLv2(cipherSuite);
final int withSplit = cs.indexOf(WITH);
if (withSplit == -1) {
Expand Down Expand Up @@ -85,6 +104,45 @@ public CipherSuite parse(final String cipherSuite) {
return new CipherSuiteImpl(cipherSuite, keyExchange, cipher, hash);
}

/**
* TLS 1.3 redefines how the Cipher Spec is written. The key differences are:
* <p>
* <ul>
* <li>There is no
*
* <pre>
* _WITH_
* </pre>
*
* in the cipher string anymore separating the Key Exchange from the Encryption Algorithm.
* <li>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<CipherSuite> parse(final Collection<String> ciphers) {
return parse(ciphers, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public class KeyExchangeImpl implements KeyExchange {

private static final Map<String, String> ALIASES = new HashMap<String, String>();

/**
* 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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,35 @@ public void testSpacesInFilterSpec() {
"TLS_DH_anon_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_NULL_SHA");
final List<String> expectedCiphers = Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DH_RSA_WITH_AES_128_CBC_SHA");
ItemFilter<CipherSuite> 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<CipherSuite> 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<String> 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<String> expectedFipsCiphers = Arrays.asList("TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_CCM_SHA256");

final ItemFilter<CipherSuite> filter = new CipherSuiteFilterBuilderImpl().add(fips()).build();
checkResult("FIPS", filter, tls13Ciphers, expectedFipsCiphers);
}

@Test
public void testForwardSecrecyIncludes13() {
final List<String> 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<CipherSuite> filter = new CipherSuiteFilterBuilderImpl().add(forwardSecrecy()).build();
checkResult("FS", filter, tls13Ciphers, tls13Ciphers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ public class ProtocolVariantFilterTest extends AbstractItemFilterTest<ProtocolVa
public static final String TLSv1 = "TLSv1";
public static final String TLSv11 = "TLSv1.1";
public static final String TLSv12 = "TLSv1.2";
public static final String TLSv13 = "TLSv1.3";

private static final List<String> ALL_PROTOCOLS = Arrays.asList(TLSv1, TLSv11, TLSv12, SSLv2HELLO, SSLv2, SSLv3);
private static final List<String> ALL_PROTOCOLS = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13, SSLv2HELLO, SSLv2, SSLv3);

@Override
protected ItemFilterSpecParser<ProtocolVariant> createSpecParser() {
Expand All @@ -46,8 +47,8 @@ protected ItemFilterSpecParser<ProtocolVariant> createSpecParser() {
@Test
public void testAll() {
final List<String> supported = ALL_PROTOCOLS;
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12, SSLv3);
ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(all()).build();
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13, SSLv3);
final ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(all()).build();
checkResult("ALL", filter, supported, expected);
}

Expand All @@ -73,16 +74,16 @@ public void testDefault() {
public void testComplementOfDefault() {
final List<String> supported = ALL_PROTOCOLS;
final List<String> defaults = Arrays.asList(TLSv1, TLSv11, SSLv3);
final List<String> expected = Arrays.asList(TLSv12);
ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(complementOfDefaults()).build();
final List<String> expected = Arrays.asList(TLSv12, TLSv13);
final ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(complementOfDefaults()).build();
checkResult("COMPLEMENTOFDEFAULT", filter, supported, expected, defaults);
}

@Test
public void testFamily() {
final List<String> supported = ALL_PROTOCOLS;
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(family("TLS")).build();
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
final ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(family("TLS")).build();
checkResult("fTLS", filter, supported, expected);
}

Expand Down Expand Up @@ -114,16 +115,16 @@ public void testUnsafeAndPseudoProtocols() {
@Test
public void testMinVersion() {
final List<String> supported = ALL_PROTOCOLS;
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(3, 1)).build();
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
final ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(3, 1)).build();
checkResult(">=TLSv1", filter, supported, expected);
}

@Test
public void testMinVersionString() {
final List<String> supported = ALL_PROTOCOLS;
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12);
ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(TLSv1)).build();
final List<String> expected = Arrays.asList(TLSv1, TLSv11, TLSv12, TLSv13);
final ItemFilter<ProtocolVariant> filter = new ProtocolVariantFilterBuilderImpl().add(minimumVersion(TLSv1)).build();
checkResult(">=TLSv1", filter, supported, expected);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}

}