diff options
author | Nick Hudson <nick.hudson@isode.com> | 2013-04-03 10:54:02 (GMT) |
---|---|---|
committer | Nick Hudson <nick.hudson@isode.com> | 2013-04-11 09:19:22 (GMT) |
commit | b50d3949d81d8cece6c71c2b094297317e584308 (patch) | |
tree | 81837d7a977700f590a2ccace53166564b70a4a6 | |
parent | 00a381a2121fe68d318cddceed32d8bb230935ea (diff) | |
download | stroke-b50d3949d81d8cece6c71c2b094297317e584308.zip stroke-b50d3949d81d8cece6c71c2b094297317e584308.tar.bz2 |
Provide mechanism to allow clients to restrict available ciphersuites
By default, when a TLS connection is established, the SSLContext will
enable all available ciphersuites. This may not be appropriate in
situations where export restrictions apply and higher grade
ciphersuites are prohibitied.
This change allows a caller to configure a restricted set of
ciphersuites to be used when establishing TLS connections.
Callers use the JSSEContextFactory.setRestrictedCipherSuites() method
to configure a list of ciphersuites. Any ciphersuites which are not
included in the list will be excluded in subsequent TLS connections.
If the JSSEContextFactory.setRestrictedCipherSuites() is never called,
or called with a null parameter, then no restriction will apply.
Test-information:
Validated that by calling the new method to restrict the available
ciphers, TLS connections initiated by Stroke only propose ciphersuites
in the restricted list, and connections fail when the server fails to
find an acceptable cipher.
Change-Id: Id0b4b19553a6f386cda27a71f0172410d899218e
Signed-off-by: Nick Hudson <nick.hudson@isode.com>
-rw-r--r-- | src/com/isode/stroke/tls/PlatformTLSFactories.java | 6 | ||||
-rw-r--r-- | src/com/isode/stroke/tls/java/JSSEContext.java | 37 | ||||
-rw-r--r-- | src/com/isode/stroke/tls/java/JSSEContextFactory.java | 35 |
3 files changed, 70 insertions, 8 deletions
diff --git a/src/com/isode/stroke/tls/PlatformTLSFactories.java b/src/com/isode/stroke/tls/PlatformTLSFactories.java index 6b98a95..cbfcfe2 100644 --- a/src/com/isode/stroke/tls/PlatformTLSFactories.java +++ b/src/com/isode/stroke/tls/PlatformTLSFactories.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Isode Limited, London, England. + * Copyright (c) 2012-2013 Isode Limited, London, England. * All rights reserved. */ /* @@ -11,8 +11,10 @@ package com.isode.stroke.tls; import com.isode.stroke.tls.java.JSSEContextFactory; public class PlatformTLSFactories { + private JSSEContextFactory contextFactory = new JSSEContextFactory(); + public TLSContextFactory getTLSContextFactory() { - return new JSSEContextFactory(); + return contextFactory; } public CertificateFactory getCertificateFactory() { diff --git a/src/com/isode/stroke/tls/java/JSSEContext.java b/src/com/isode/stroke/tls/java/JSSEContext.java index 9cb0109..257a70c 100644 --- a/src/com/isode/stroke/tls/java/JSSEContext.java +++ b/src/com/isode/stroke/tls/java/JSSEContext.java @@ -26,6 +26,8 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; +import java.util.HashSet; +import java.util.Set; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; @@ -117,13 +119,14 @@ public class JSSEContext extends TLSContext { @Override public void connect() { try { - doSetup(); + doSetup(); } catch (SSLException e) { emitError(e,"doSetup() failed"); } } + private void doSetup() throws SSLException { SSLContext sslContext = getSSLContext(); @@ -143,6 +146,23 @@ public class JSSEContext extends TLSContext { /* "the SSLContextImpl requires initialization and init() has not been called" */ throw new SSLException(e); } + + /* Restrict cipher suites if necessary */ + if (restrictedCipherSuites != null) { + String[] supportedSuites = sslEngine.getSupportedCipherSuites(); + Set<String> matchedSuites = new HashSet<String>(); + for (String suite:supportedSuites) { + if (restrictedCipherSuites.contains(suite)) { + matchedSuites.add(suite); + } + } + String[] suitesToEnable = new String[]{}; + if (!matchedSuites.isEmpty()) { + suitesToEnable = (String[])matchedSuites.toArray(); + } + + sslEngine.setEnabledCipherSuites(suitesToEnable); + } sslEngine.setUseClientMode(true); /* I am a client */ sslEngine.setEnableSessionCreation(true); /* can create new sessions */ @@ -1018,10 +1038,21 @@ public class JSSEContext extends TLSContext { /** * Construct a new JSSEContext object. + * @param restrictedCipherSuites a list of cipher suites that are to be + * enabled for this context. Null means no restriction */ - public JSSEContext() { - /* */ + public JSSEContext(Set<String> restrictedCipherSuites) { + if (restrictedCipherSuites != null) { + this.restrictedCipherSuites = new HashSet<String>(restrictedCipherSuites); + } } + + + /** + * Specific list of suites to allow - null (the default) means + * no restriction. + */ + private Set<String> restrictedCipherSuites = null; /** * Reference to the SSLEngine being used diff --git a/src/com/isode/stroke/tls/java/JSSEContextFactory.java b/src/com/isode/stroke/tls/java/JSSEContextFactory.java index 0ddb4fd..63b184d 100644 --- a/src/com/isode/stroke/tls/java/JSSEContextFactory.java +++ b/src/com/isode/stroke/tls/java/JSSEContextFactory.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, Isode Limited, London, England. +/* Copyright (c) 2012-2013, Isode Limited, London, England. * All rights reserved. * * Acquisition and use of this software and related materials for any @@ -10,12 +10,19 @@ package com.isode.stroke.tls.java; +import java.util.HashSet; +import java.util.Set; + import com.isode.stroke.tls.TLSContext; import com.isode.stroke.tls.TLSContextFactory; /** * Concrete implementation of a TLSContextFactory which uses SSLEngine - * and maybe other stuff? ..tbs... + * + * <p>Ciphersuite names recognised by this class correspond to the standard + * names as described in + * <a href=http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#ciphersuites> + * Oracle's "Java Cryptography Architecture Standard Algorithm Name Documentation"</a>. * */ public class JSSEContextFactory implements TLSContextFactory { @@ -27,7 +34,29 @@ public class JSSEContextFactory implements TLSContextFactory { @Override public TLSContext createTLSContext() { - return new JSSEContext(); + return new JSSEContext(restrictedCipherSuites); } + + private static Set<String> restrictedCipherSuites = null; + + /** + * Restrict which cipher suites are to be enabled for any TLSContexts + * returned by this factory from now on. Any name which is + * not recognised, or not available is ignored: this method cannot be + * used to enable otherwise unavailable ciphersuites. + * + * @param cipherSuites a set of cipher suite names. If this parameter is + * null, then no restriction on cipher suites applies (all suites available + * to the implementation will be enabled). + * + */ + public static void setRestrictedCipherSuites(Set<String> cipherSuites) { + if (cipherSuites == null) { + restrictedCipherSuites = null; + return; + } + + restrictedCipherSuites = new HashSet<String>(cipherSuites); + } } |