From 2536ac98e00057c9acc6e2c2be4109a93eaa6efc Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 25 Mar 2013 08:53:54 +0000
Subject: [PATCH] OPENDJ-816 (CR-1460) ssf bug in ACI evaluation?

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/TLSByteChannel.java                                 |  102 ++++++--
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TLSByteChannelTestCase.java |  544 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 614 insertions(+), 32 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSByteChannel.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
index 1525187..1a7a5ed 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
@@ -23,25 +23,29 @@
  *
  *
  *      Copyright 2008-2009 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
+ *      Portions copyright 2012-2013 ForgeRock AS
  */
 package org.opends.server.extensions;
 
 
 
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.loggers.debug.DebugLogger.*;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.ClosedChannelException;
 import java.security.cert.Certificate;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-import javax.net.ssl.*;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
 
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.DebugLogLevel;
@@ -62,6 +66,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void close() throws IOException
     {
       synchronized (readLock)
@@ -114,6 +119,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isOpen()
     {
       return !sslEngine.isOutboundDone() || !sslEngine.isInboundDone();
@@ -124,6 +130,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int read(final ByteBuffer unwrappedData) throws IOException
     {
       synchronized (readLock)
@@ -165,6 +172,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int write(final ByteBuffer unwrappedData) throws IOException
     {
       // This method will block until the entire message is sent.
@@ -405,30 +413,37 @@
 
 
 
-  // Map of cipher phrases to effective key size (bits). Taken from the
-  // following RFCs: 5289, 4346, 3268,4132 and 4162.
-  private static final Map<String, Integer> CIPHER_MAP;
+  /**
+   * Map of cipher phrases to effective key size (bits). Taken from the
+   * following RFCs: 5289, 4346, 3268,4132 and 4162.
+   *
+   * @see <a
+   *      href="http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-3">Transport
+   *      Layer Security (TLS) Parameters, TLS Cipher Suite Registry</a>
+   */
+  static final Map<String, Integer> CIPHER_MAP;
   static
   {
-    CIPHER_MAP = new LinkedHashMap<String, Integer>();
-    CIPHER_MAP.put("_WITH_AES_256_CBC_", new Integer(256));
-    CIPHER_MAP.put("_WITH_CAMELLIA_256_CBC_", new Integer(256));
-    CIPHER_MAP.put("_WITH_AES_256_GCM_", new Integer(256));
-    CIPHER_MAP.put("_WITH_3DES_EDE_CBC_", new Integer(112));
-    CIPHER_MAP.put("_WITH_AES_128_GCM_", new Integer(128));
-    CIPHER_MAP.put("_WITH_SEED_CBC_", new Integer(128));
-    CIPHER_MAP.put("_WITH_CAMELLIA_128_CBC_", new Integer(128));
-    CIPHER_MAP.put("_WITH_AES_128_CBC_", new Integer(128));
-    CIPHER_MAP.put("_WITH_IDEA_CBC_", new Integer(128));
-    CIPHER_MAP.put("_WITH_RC4_128_", new Integer(128));
-    CIPHER_MAP.put("_WITH_FORTEZZA_CBC_", new Integer(96));
-    CIPHER_MAP.put("_WITH_DES_CBC_", new Integer(56));
-    CIPHER_MAP.put("_WITH_RC4_56_", new Integer(56));
-    CIPHER_MAP.put("_WITH_DES_CBC_40_", new Integer(40));
-    CIPHER_MAP.put("_WITH_RC2_CBC_40_", new Integer(40));
-    CIPHER_MAP.put("_WITH_RC4_40_", new Integer(40));
-    CIPHER_MAP.put("_WITH_DES40_CBC_", new Integer(40));
-    CIPHER_MAP.put("_WITH_NULL_", new Integer(0));
+    final Map<String, Integer> map = new LinkedHashMap<String, Integer>();
+    map.put("_WITH_AES_256_", 256);
+    map.put("_WITH_ARIA_256_", 256);
+    map.put("_WITH_CAMELLIA_256_", 256);
+    map.put("_WITH_AES_128_", 128);
+    map.put("_WITH_ARIA_128_", 128);
+    map.put("_WITH_SEED_", 128);
+    map.put("_WITH_CAMELLIA_128_", 128);
+    map.put("_WITH_IDEA_", 128);
+    map.put("_WITH_RC4_128_", 128);
+    map.put("_WITH_3DES_EDE_", 112);
+    map.put("_WITH_FORTEZZA_", 96);
+    map.put("_WITH_RC4_56_", 56);
+    map.put("_WITH_DES_CBC_40_", 40);
+    map.put("_WITH_RC2_CBC_40_", 40);
+    map.put("_WITH_RC4_40_", 40);
+    map.put("_WITH_DES40_", 40);
+    map.put("_WITH_DES_", 56);
+    map.put("_WITH_NULL_", 0);
+    CIPHER_MAP = Collections.unmodifiableMap(map);
   }
 
   private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
@@ -485,6 +500,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public ByteChannel getChannel()
   {
     return pimpl;
@@ -495,6 +511,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public Certificate[] getClientCertificateChain()
   {
     try
@@ -516,6 +533,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public String getName()
   {
     return "TLS";
@@ -526,24 +544,44 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int getSSF()
   {
-    final String cipherString = sslEngine.getSession().getCipherSuite();
-    for (final Map.Entry<String, Integer> mapEntry : CIPHER_MAP.entrySet())
+    final Integer ssf = getSSF(sslEngine.getSession().getCipherSuite());
+    if (ssf != null)
     {
-      if (cipherString.indexOf(mapEntry.getKey()) >= 0)
-      {
-        return mapEntry.getValue().intValue();
-      }
+      return ssf.intValue();
     }
     return 0;
   }
 
+  /**
+   * Returns the Security Strength Factor corresponding to the supplied cipher
+   * string.
+   *
+   * @param cipherString
+   *          the cipher to test for SSF
+   * @return the Security Strength Factor corresponding to the supplied cipher
+   *         string, null if the cipher cannot be recognized.
+   */
+  static Integer getSSF(final String cipherString)
+  {
+    for (final Map.Entry<String, Integer> mapEntry : CIPHER_MAP.entrySet())
+    {
+      if (cipherString.contains(mapEntry.getKey()))
+      {
+        return mapEntry.getValue();
+      }
+    }
+    return null;
+  }
+
 
 
   /**
    * {@inheritDoc}
    */
+  @Override
   public boolean isSecure()
   {
     return true;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TLSByteChannelTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TLSByteChannelTestCase.java
new file mode 100644
index 0000000..1fad68e
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TLSByteChannelTestCase.java
@@ -0,0 +1,544 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2012-2013 ForgeRock AS
+ */
+package org.opends.server.extensions;
+
+import static org.testng.Assert.*;
+
+import java.io.BufferedInputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import com.forgerock.opendj.util.StaticUtils;
+
+@Test(groups = { "slow" })
+public class TLSByteChannelTestCase
+{
+
+  /**
+   * Cipher suite hardcoded from the IANA registry on internet
+   */
+  static final String[][] HARDCODED_CIPHER_SUITE = new String[][] {
+        { "TLS_NULL_WITH_NULL_NULL" },
+        { "TLS_RSA_WITH_NULL_MD5" },
+        { "TLS_RSA_WITH_NULL_SHA" },
+        { "TLS_RSA_EXPORT_WITH_RC4_40_MD5" },
+        { "TLS_RSA_WITH_RC4_128_MD5" },
+        { "TLS_RSA_WITH_RC4_128_SHA" },
+        { "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5" },
+        { "TLS_RSA_WITH_IDEA_CBC_SHA" },
+        { "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_RSA_WITH_DES_CBC_SHA" },
+        { "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_DES_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_DES_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_DES_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_DES_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5" },
+        { "TLS_DH_anon_WITH_RC4_128_MD5" },
+        { "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA" },
+        { "TLS_DH_anon_WITH_DES_CBC_SHA" },
+        { "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_KRB5_WITH_DES_CBC_SHA" },
+        { "TLS_KRB5_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_KRB5_WITH_RC4_128_SHA" },
+        { "TLS_KRB5_WITH_IDEA_CBC_SHA" },
+        { "TLS_KRB5_WITH_DES_CBC_MD5" },
+        { "TLS_KRB5_WITH_3DES_EDE_CBC_MD5" },
+        { "TLS_KRB5_WITH_RC4_128_MD5" },
+        { "TLS_KRB5_WITH_IDEA_CBC_MD5" },
+        { "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA" },
+        { "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA" },
+        { "TLS_KRB5_EXPORT_WITH_RC4_40_SHA" },
+        { "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5" },
+        { "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5" },
+        { "TLS_KRB5_EXPORT_WITH_RC4_40_MD5" },
+        { "TLS_PSK_WITH_NULL_SHA" },
+        { "TLS_DHE_PSK_WITH_NULL_SHA" },
+        { "TLS_RSA_PSK_WITH_NULL_SHA" },
+        { "TLS_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_AES_128_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_DH_anon_WITH_AES_128_CBC_SHA" },
+        { "TLS_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_AES_256_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_DH_anon_WITH_AES_256_CBC_SHA" },
+        { "TLS_RSA_WITH_NULL_SHA256" },
+        { "TLS_RSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_RSA_WITH_AES_256_CBC_SHA256" },
+        { "TLS_DH_DSS_WITH_AES_128_CBC_SHA256" },
+        { "TLS_DH_RSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256" },
+        { "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_DH_DSS_WITH_AES_256_CBC_SHA256" },
+        { "TLS_DH_RSA_WITH_AES_256_CBC_SHA256" },
+        { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" },
+        { "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
+        { "TLS_DH_anon_WITH_AES_128_CBC_SHA256" },
+        { "TLS_DH_anon_WITH_AES_256_CBC_SHA256" },
+        { "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" },
+        { "TLS_PSK_WITH_RC4_128_SHA" },
+        { "TLS_PSK_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_PSK_WITH_AES_128_CBC_SHA" },
+        { "TLS_PSK_WITH_AES_256_CBC_SHA" },
+        { "TLS_DHE_PSK_WITH_RC4_128_SHA" },
+        { "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_DHE_PSK_WITH_AES_128_CBC_SHA" },
+        { "TLS_DHE_PSK_WITH_AES_256_CBC_SHA" },
+        { "TLS_RSA_PSK_WITH_RC4_128_SHA" },
+        { "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_RSA_PSK_WITH_AES_128_CBC_SHA" },
+        { "TLS_RSA_PSK_WITH_AES_256_CBC_SHA" },
+        { "TLS_RSA_WITH_SEED_CBC_SHA" },
+        { "TLS_DH_DSS_WITH_SEED_CBC_SHA" },
+        { "TLS_DH_RSA_WITH_SEED_CBC_SHA" },
+        { "TLS_DHE_DSS_WITH_SEED_CBC_SHA" },
+        { "TLS_DHE_RSA_WITH_SEED_CBC_SHA" },
+        { "TLS_DH_anon_WITH_SEED_CBC_SHA" },
+        { "TLS_RSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_RSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DH_RSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DH_RSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DH_DSS_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DH_DSS_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DH_anon_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DH_anon_WITH_AES_256_GCM_SHA384" },
+        { "TLS_PSK_WITH_AES_128_GCM_SHA256" },
+        { "TLS_PSK_WITH_AES_256_GCM_SHA384" },
+        { "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256" },
+        { "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384" },
+        { "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256" },
+        { "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384" },
+        { "TLS_PSK_WITH_AES_128_CBC_SHA256" },
+        { "TLS_PSK_WITH_AES_256_CBC_SHA384" },
+        { "TLS_PSK_WITH_NULL_SHA256" },
+        { "TLS_PSK_WITH_NULL_SHA384" },
+        { "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256" },
+        { "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384" },
+        { "TLS_DHE_PSK_WITH_NULL_SHA256" },
+        { "TLS_DHE_PSK_WITH_NULL_SHA384" },
+        { "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256" },
+        { "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384" },
+        { "TLS_RSA_PSK_WITH_NULL_SHA256" },
+        { "TLS_RSA_PSK_WITH_NULL_SHA384" },
+        { "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_NULL_SHA" },
+        { "TLS_ECDH_ECDSA_WITH_RC4_128_SHA" },
+        { "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_NULL_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDH_RSA_WITH_NULL_SHA" },
+        { "TLS_ECDH_RSA_WITH_RC4_128_SHA" },
+        { "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDHE_RSA_WITH_NULL_SHA" },
+        { "TLS_ECDHE_RSA_WITH_RC4_128_SHA" },
+        { "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDH_anon_WITH_NULL_SHA" },
+        { "TLS_ECDH_anon_WITH_RC4_128_SHA" },
+        { "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDH_anon_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" },
+        { "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_SRP_SHA_WITH_AES_128_CBC_SHA" },
+        { "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA" },
+        { "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA" },
+        { "TLS_SRP_SHA_WITH_AES_256_CBC_SHA" },
+        { "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA" },
+        { "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
+        { "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" },
+        { "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" },
+        { "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" },
+        { "TLS_ECDHE_PSK_WITH_RC4_128_SHA" },
+        { "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA" },
+        { "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
+        { "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA" },
+        { "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256" },
+        { "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384" },
+        { "TLS_ECDHE_PSK_WITH_NULL_SHA" },
+        { "TLS_ECDHE_PSK_WITH_NULL_SHA256" },
+        { "TLS_ECDHE_PSK_WITH_NULL_SHA384" },
+        { "TLS_RSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_RSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_RSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_RSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_PSK_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_PSK_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_PSK_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_PSK_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256" },
+        { "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384" },
+        { "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384" },
+        { "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
+        { "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
+        { "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
+        { "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
+        { "TLS_RSA_WITH_AES_128_CCM" },
+        { "TLS_RSA_WITH_AES_256_CCM" },
+        { "TLS_DHE_RSA_WITH_AES_128_CCM" },
+        { "TLS_DHE_RSA_WITH_AES_256_CCM" },
+        { "TLS_RSA_WITH_AES_128_CCM_8" },
+        { "TLS_RSA_WITH_AES_256_CCM_8" },
+        { "TLS_DHE_RSA_WITH_AES_128_CCM_8" },
+        { "TLS_DHE_RSA_WITH_AES_256_CCM_8" },
+        { "TLS_PSK_WITH_AES_128_CCM" },
+        { "TLS_PSK_WITH_AES_256_CCM" },
+        { "TLS_DHE_PSK_WITH_AES_128_CCM" },
+        { "TLS_DHE_PSK_WITH_AES_256_CCM" },
+        { "TLS_PSK_WITH_AES_128_CCM_8" },
+        { "TLS_PSK_WITH_AES_256_CCM_8" },
+        { "TLS_PSK_DHE_WITH_AES_128_CCM_8" },
+        { "TLS_PSK_DHE_WITH_AES_256_CCM_8" },
+        };
+
+  /**
+   * Retrieves the IANA TLS Cipher Suites Registry from internet.
+   *
+   * @return the IANA TLS Cipher Suites Registry
+   */
+  private String[][] retrieveIanaTlsCipherSuitesRegistryFromInternet()
+      throws Exception
+  {
+    String url =
+        "http://www.iana.org/assignments/tls-parameters/tls-parameters.xml";
+    URLConnection conn = new URL(url).openConnection();
+    BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
+
+    try
+    {
+      // JAXP boilerplate
+      DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+      DocumentBuilder builder = dbFactory.newDocumentBuilder();
+      Document doc = builder.parse(bis);
+      XPathFactory xpathFactory = XPathFactory.newInstance();
+      XPath xpath = xpathFactory.newXPath();
+
+      // Collect cipher suite
+      String xPathExpr =
+          "//registry[@id='tls-parameters-4']/record/description/text()";
+      List<String> realCiphers = retrieveRealCiphers(doc, xpath, xPathExpr);
+      return toDataProviderResult(realCiphers);
+    }
+    finally
+    {
+      StaticUtils.closeSilently(bis);
+    }
+  }
+
+  private String[][] toDataProviderResult(List<String> realCiphers)
+  {
+    String[][] results = new String[realCiphers.size()][1];
+    for (ListIterator<String> iter = realCiphers.listIterator(); iter.hasNext();)
+    {
+      final String cipherString = iter.next();
+      int i = iter.nextIndex();
+      results[i][0] = cipherString;
+    }
+    return results;
+  }
+
+  private List<String> retrieveRealCiphers(Document doc, XPath xpath,
+      String xPathExpr) throws XPathExpressionException
+  {
+    NodeList nodes =
+        (NodeList) xpath.evaluate(xPathExpr, doc, XPathConstants.NODESET);
+    List<String> cipherStrings = new ArrayList<String>(nodes.getLength());
+    for (int i = 0; i < nodes.getLength(); i++)
+    {
+      String cipherString = nodes.item(i).getNodeValue();
+      // ignore things like "unknown", "reserved", etc.
+      // also ignore the TLS Secure Renegotiation protocol message
+      if (cipherString.startsWith("TLS_")
+          && !"TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipherString))
+      {
+        cipherStrings.add(cipherString);
+      }
+    }
+    return cipherStrings;
+  }
+
+  @DataProvider(name = "ianaTlsCipherSuitesRegistry")
+  public String[][] getIanaTlsCipherSuitesRegistry() throws Exception
+  {
+    try
+    {
+      return retrieveIanaTlsCipherSuitesRegistryFromInternet();
+    }
+    catch (Exception e)
+    {
+      // we could not get access to the internet registry,
+      // return the hardcoded registry
+      return HARDCODED_CIPHER_SUITE;
+    }
+  }
+
+  /**
+   * Checks that all the IANA registered ciphers are supported by
+   * {@link TLSByteChannel#getSSF()}.
+   *
+   * @param cipherString
+   *          cipher to be tested
+   */
+  @Test(dataProvider = "ianaTlsCipherSuitesRegistry")
+  public void getSsfForIanaRegistryCipherSuites(String cipherString)
+  {
+    assertNotNull(TLSByteChannel.getSSF(cipherString));
+  }
+
+  /**
+   * Checks that the IANA cipher suite registry on internet and the hardcoded
+   * cipher suite in this class have not diverged.
+   */
+  @Test
+  public void compareInternetAndHardcodedRegistry() throws Exception
+  {
+    Set<String> internetCiphers = toSet(getIanaTlsCipherSuitesRegistry());
+    Set<String> hardcodedCiphers = toSet(HARDCODED_CIPHER_SUITE);
+    assertEquals(internetCiphers, hardcodedCiphers);
+  }
+
+  private Set<String> toSet(String[][] data)
+  {
+    Set<String> set = new HashSet<String>();
+    for (String[] array : data)
+    {
+      for (String s : array)
+      {
+        set.add(s);
+      }
+    }
+    return set;
+  }
+
+  /**
+   * Ensures that there is no overlapping in the DES ciphers strings and that
+   * the expected Security Strength Factor are returned.
+   */
+  @Test
+  public void checkDesSSFAreAsExpected()
+  {
+    assertEquals((Integer) 56, TLSByteChannel
+        .getSSF("TLS_KRB5_WITH_DES_CBC_SHA"));
+    assertEquals((Integer) 40, TLSByteChannel
+        .getSSF("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"));
+  }
+
+  /**
+   * Ensures that no new overlapping cipher strings are added to the cipher map.
+   */
+  @Test
+  public void checkNoUnknownOverlappingCiphers()
+  {
+    List<String> ciphers = new ArrayList(TLSByteChannel.CIPHER_MAP.keySet());
+    for (int i = 0; i < ciphers.size(); i++)
+    {
+      for (int j = 0; j < i; j++)
+      {
+        String s1 = ciphers.get(i);
+        String s2 = ciphers.get(j);
+        if (s1.contains(s2) || s2.contains(s1))
+        {
+          if (not(s1, s2, "_WITH_DES_", "_WITH_DES_CBC_40_"))
+          {
+            fail("Overlapping cipher strings" + s1 + "\t" + s2);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Ensure the set (cipher1, cipher2) is different from the set (match1,
+   * match2).
+   */
+  private boolean not(String cipher1, String cipher2, String match1,
+      String match2)
+  {
+    return (!cipher1.equals(match1) || !cipher2.equals(match2))
+        && (!cipher2.equals(match1) || !cipher1.equals(match2));
+  }
+
+}

--
Gitblit v1.10.0