Blame SOURCES/mod_nss-cipher-logical_and.patch

b7538d
From 63eb1f4c6ef8c1bb68afbfc5fba8762d50c1a0a8 Mon Sep 17 00:00:00 2001
b7538d
From: Rob Crittenden <rcritten@redhat.com>
b7538d
Date: Wed, 17 Jun 2015 11:12:40 -0400
b7538d
Subject: [PATCH] Fix logical AND support in OpenSSL cipher compatibility
b7538d
b7538d
The + operator didn't perform properly at all. It is supposed
b7538d
to be used either for logical AND to combine two cipher suites
b7538d
or to move ciphers to the end of the list. Given that NSS
b7538d
doesn't support cipher ordering + is a no-op in this case.
b7538d
b7538d
Also add in a slew of missing aliases: kRSA, aRSA, EDH,
b7538d
ECDH, kECDHe, kECDHr, kEECDH, aECDH, aNULL, AESGCM, AES128,
b7538d
AES256, CAMELLIA, CAMELLIA128, CAMELLIA256.
b7538d
b7538d
Fix the definition of TLSv1.2.
b7538d
b7538d
Define some ciphers as unimplemented in NSS.
b7538d
b7538d
Renumber the mask/protocol/strength values to ensure uniqueness.
b7538d
b7538d
Replace the existing cipher test to one that compares the output
b7538d
of the NSS-generated cipher string with the openssl generated
b7538d
string.  There are a lot of restrictions on the openssl string
b7538d
since so much isn't either implemented or needed for mod_nss.
b7538d
b7538d
Add a new openssl-compatible cipher request test to the server
b7538d
tests.
b7538d
---
b7538d
 nss_engine_cipher.c    | 196 +++++++++++++++++++++++++++++++-------
b7538d
 nss_engine_cipher.h    |  61 ++++++------
b7538d
 test/createinstance.sh |   1 +
b7538d
 test/suite1.tmpl       |   6 ++
b7538d
 test/test.py           |   6 ++
b7538d
 test/test_cipher.py    | 254 ++++++++++++++++++++++++++++++++-----------------
b7538d
 test_cipher.c          |  32 +++++--
b7538d
 7 files changed, 401 insertions(+), 155 deletions(-)
b7538d
b7538d
diff --git a/nss_engine_cipher.c b/nss_engine_cipher.c
b7538d
index 9110d57..37ef338 100644
b7538d
--- a/nss_engine_cipher.c
b7538d
+++ b/nss_engine_cipher.c
b7538d
@@ -29,10 +29,11 @@ cipher_properties ciphers_def[ciphernum] =
b7538d
     {"rsa_rc4_128_md5", TLS_RSA_WITH_RC4_128_MD5, "RC4-MD5", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSLV3, SSL_MEDIUM, 128, 128},
b7538d
     {"rsa_rc4_128_sha", TLS_RSA_WITH_RC4_128_SHA, "RC4-SHA", SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSLV3, SSL_MEDIUM, 128, 128},
b7538d
     {"rsa_rc2_40_md5", TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "EXP-RC2-CBC-MD5", SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSLV3, SSL_EXPORT40, 40, 128},
b7538d
+    /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA not implemented 0x0008 */
b7538d
     {"rsa_des_sha", TLS_RSA_WITH_DES_CBC_SHA, "DES-CBC-SHA", SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSLV3, SSL_LOW, 56, 56},
b7538d
-    {"rsa_3des_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA, "DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_HIGH, 112, 168},
b7538d
+    {"rsa_3des_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA, "DES-CBC3-SHA", SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSLV3, SSL_HIGH, 168, 168},
b7538d
     {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, "AES128-SHA", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA1, TLSV1, SSL_HIGH, 128, 128},
b7538d
-    {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, "AES256-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
b7538d
+    {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, "AES256-SHA", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA1, TLSV1, SSL_HIGH, 256, 256},
b7538d
     {"null_sha_256", TLS_RSA_WITH_NULL_SHA256, "NULL-SHA256", SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA256, TLSV1_2, SSL_STRONG_NONE, 0, 0},
b7538d
     {"aes_128_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256, "AES128-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128},
b7538d
     {"aes_256_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256, "AES256-SHA256", SSL_kRSA|SSL_aRSA|SSL_AES256|SSL_SHA256, TLSV1_2, SSL_HIGH, 256, 256},
b7538d
@@ -73,9 +74,25 @@ cipher_properties ciphers_def[ciphernum] =
b7538d
     {"ecdhe_rsa_aes_128_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "ECDHE-RSA-AES128-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128|SSL_SHA256, TLSV1_2, SSL_HIGH, 128, 128},
b7538d
     {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aECDSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128},
b7538d
     {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "ECDHE-RSA-AES128-GCM-SHA256", SSL_kEECDH|SSL_aRSA|SSL_AES128GCM|SSL_AEAD, TLSV1_2, SSL_HIGH, 128, 128},
b7538d
+    /* TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 is not implemented */
b7538d
+    /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 is not implemented */
b7538d
+    /* TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 is not implemented */
b7538d
+    /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 is not implemented */
b7538d
 #endif
b7538d
 };
b7538d
 
b7538d
+
b7538d
+/* Some ciphers are optionally enabled in OpenSSL. For safety sake assume
b7538d
+ * they are not available.
b7538d
+ */
b7538d
+static int skip_ciphers = 4;
b7538d
+static int ciphers_not_in_openssl[] = {
b7538d
+    SSL_RSA_FIPS_WITH_DES_CBC_SHA,
b7538d
+    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
b7538d
+    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
b7538d
+    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
b7538d
+};
b7538d
+
b7538d
 static int parse_nss_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
b7538d
 static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum]);
b7538d
 
b7538d
@@ -107,19 +124,48 @@ int nss_parse_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum
b7538d
         rv = parse_nss_ciphers(s, ciphers, cipher_list);
b7538d
     } else {
b7538d
         rv = parse_openssl_ciphers(s, ciphers, cipher_list);
b7538d
-        if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {
b7538d
+        if (rv == 0 && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {
b7538d
             rv = parse_nss_ciphers(s, ciphers, cipher_list);
b7538d
         }
b7538d
     }
b7538d
+    if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {
b7538d
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
b7538d
+                     "no cipher match");
b7538d
+    }
b7538d
 
b7538d
     return rv;
b7538d
 }
b7538d
 
b7538d
 
b7538d
+/* Given a set of ciphers perform a given action on the indexed value.
b7538d
+ * 
b7538d
+ * This is needed because the + action doesn't do anything in the NSS
b7538d
+ * context. In OpenSSL it will re-order the cipher list.
b7538d
+ */
b7538d
+static int set_cipher_value(PRBool cipher_list[ciphernum], int index, int action)
b7538d
+{
b7538d
+    int i;
b7538d
+
b7538d
+    for (i = 0; i < skip_ciphers; i++) {
b7538d
+        if (ciphers_def[index].num == ciphers_not_in_openssl[i]) {
b7538d
+            cipher_list[index] = -1;
b7538d
+            return;
b7538d
+        }
b7538d
+    }
b7538d
+
b7538d
+    if (cipher_list[index] == -1) /* cipher is disabled */
b7538d
+        return;
b7538d
+    else
b7538d
+        cipher_list[index] = action;
b7538d
+}
b7538d
+
b7538d
+
b7538d
 static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_list[ciphernum])
b7538d
 {
b7538d
     char * cipher;
b7538d
     int i, action;
b7538d
+    PRBool merge = PR_FALSE;
b7538d
+    PRBool found = PR_FALSE;
b7538d
 
b7538d
     cipher = ciphers;
b7538d
     while (ciphers && (strlen(ciphers)))
b7538d
@@ -127,12 +173,12 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
         while ((*cipher) && (isspace(*cipher)))
b7538d
             ++cipher;
b7538d
 
b7538d
-        action = 1;
b7538d
+        action = 1; /* default to enable */
b7538d
         switch(*cipher)
b7538d
         {
b7538d
             case '+': /* Add something */
b7538d
-                action = 1;
b7538d
-                cipher++;
b7538d
+                /* Cipher ordering is not supported in NSS */
b7538d
+                return 0;
b7538d
                 break;
b7538d
             case '-': /* Subtract something */
b7538d
                 action = 0;
b7538d
@@ -149,34 +195,58 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
 
b7538d
         if ((ciphers = strchr(cipher, ':'))) {
b7538d
             *ciphers++ = '\0';
b7538d
+            merge = PR_FALSE;
b7538d
+            found = PR_FALSE;
b7538d
         }
b7538d
 
b7538d
         if (!strcmp(cipher, "ALL")) {
b7538d
+            found = PR_TRUE;
b7538d
             for (i=0; i
b7538d
                 if (!(ciphers_def[i].attr & SSL_eNULL))
b7538d
-                    if (cipher_list[i] != -1)
b7538d
-                        cipher_list[i] = action;
b7538d
+                    set_cipher_value(cipher_list, i, action);
b7538d
             }
b7538d
         } else if (!strcmp(cipher, "COMPLEMENTOFALL")) {
b7538d
+            found = PR_TRUE;
b7538d
             for (i=0; i
b7538d
                 if ((ciphers_def[i].attr & SSL_eNULL))
b7538d
-                    if (cipher_list[i] != -1)
b7538d
-                        cipher_list[i] = action;
b7538d
+                    set_cipher_value(cipher_list, i, action);
b7538d
             }
b7538d
         } else if (!strcmp(cipher, "DEFAULT")) {
b7538d
+            found = PR_TRUE;
b7538d
             for (i=0; i < ciphernum; i++) {
b7538d
                 if (cipher_list[i] != -1)
b7538d
                     SSL_CipherPrefGetDefault(ciphers_def[i].num,
b7538d
                                              &cipher_list[i]);
b7538d
             }
b7538d
+        } else if (!strcmp(cipher, "COMPLEMENTOFDEFAULT")) {
b7538d
+            found = PR_TRUE;
b7538d
+            /* no-op. In OpenSSL this is the ADH ciphers */
b7538d
+        } else if (!strcmp(cipher, "@STRENGTH")) {
b7538d
+            /* No cipher ordering in NSS */
b7538d
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
b7538d
+                         "Cipher ordering is not supported in NSS");
b7538d
+            return -1;
b7538d
         } else {
b7538d
             int mask = 0;
b7538d
             int strength = 0;
b7538d
             int protocol = 0;
b7538d
             char *c;
b7538d
+            int i;
b7538d
+            PRBool candidate_list[ciphernum];
b7538d
+            PRBool temp_list[ciphernum];
b7538d
+
b7538d
+            for (i = 0; i < ciphernum; i++) {
b7538d
+                candidate_list[i] = 1;
b7538d
+            }
b7538d
 
b7538d
             c = cipher;
b7538d
             while (c && (strlen(c))) {
b7538d
+                mask = 0;
b7538d
+                strength = 0;
b7538d
+                protocol = 0;
b7538d
+                for (i = 0; i < ciphernum; i++) {
b7538d
+                    temp_list[i] = 0;
b7538d
+                }
b7538d
 
b7538d
                 if ((c = strchr(cipher, '+'))) {
b7538d
                     *c++ = '\0';
b7538d
@@ -184,12 +254,44 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
 
b7538d
                 if (!strcmp(cipher, "RSA")) {
b7538d
                     mask |= SSL_RSA;
b7538d
+                } else if (!strcmp(cipher, "kRSA")) {
b7538d
+                    mask |= SSL_kRSA;
b7538d
+                } else if (!strcmp(cipher, "aRSA")) {
b7538d
+                    mask |= SSL_aRSA;
b7538d
                 } else if (!strcmp(cipher, "EDH")) {
b7538d
                     mask |= SSL_EDH;
b7538d
+#if 0
b7538d
+                } else if (!strcmp(cipher, "ADH")) {
b7538d
+                    mask |= SSL_ADH;
b7538d
+#endif
b7538d
+                } else if (!strcmp(cipher, "ECDH")) {
b7538d
+                    mask |= SSL_ECDH;
b7538d
+                } else if (!strcmp(cipher, "kECDHe")) {
b7538d
+                    mask |= SSL_kECDHe;
b7538d
+                } else if (!strcmp(cipher, "kECDHr")) {
b7538d
+                    mask |= SSL_kECDHr;
b7538d
+                } else if (!strcmp(cipher, "kEECDH")) {
b7538d
+                    mask |= SSL_kEECDH;
b7538d
+                } else if (!strcmp(cipher, "aECDH")) {
b7538d
+                    mask |= SSL_aECDH;
b7538d
                 } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) {
b7538d
                     mask |= SSL_eNULL;
b7538d
+                } else if (!strcmp(cipher, "aNULL")) {
b7538d
+                    mask |= SSL_aNULL;
b7538d
                 } else if (!strcmp(cipher, "AES")) {
b7538d
                     mask |= SSL_AES;
b7538d
+                } else if (!strcmp(cipher, "AESGCM")) {
b7538d
+                    mask |= SSL_AES128GCM|SSL_AES256GCM;
b7538d
+                } else if (!strcmp(cipher, "AES128")) {
b7538d
+                    mask |= SSL_AES128|SSL_AES128GCM;
b7538d
+                } else if (!strcmp(cipher, "AES256")) {
b7538d
+                    mask |= SSL_AES256|SSL_AES256GCM;
b7538d
+                } else if (!strcmp(cipher, "CAMELLIA")) {
b7538d
+                    mask |= SSL_CAMELLIA128|SSL_CAMELLIA256;
b7538d
+                } else if (!strcmp(cipher, "CAMELLIA128")) {
b7538d
+                    mask |= SSL_CAMELLIA128;
b7538d
+                } else if (!strcmp(cipher, "CAMELLIA256")) {
b7538d
+                    mask |= SSL_CAMELLIA256;
b7538d
                 } else if (!strcmp(cipher, "3DES")) {
b7538d
                     mask |= SSL_3DES;
b7538d
                 } else if (!strcmp(cipher, "DES")) {
b7538d
@@ -210,7 +312,7 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
                     protocol |= SSLV3;
b7538d
                 } else if (!strcmp(cipher, "TLSv1")) {
b7538d
                     protocol |= TLSV1;
b7538d
-                } else if (!strcmp(cipher, "TLSv12")) {
b7538d
+                } else if (!strcmp(cipher, "TLSv1.2")) {
b7538d
                     protocol |= TLSV1_2;
b7538d
                 } else if (!strcmp(cipher, "HIGH")) {
b7538d
                     strength |= SSL_HIGH;
b7538d
@@ -229,32 +331,58 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
                 if (c)
b7538d
                     cipher = c;
b7538d
 
b7538d
-            } /* while */
b7538d
-
b7538d
-            /* If we have a mask, apply it. If not then perhaps they provided
b7538d
-             * a specific cipher to enable.
b7538d
-             */
b7538d
-            if (mask || strength || protocol)
b7538d
-                for (i=0; i
b7538d
-                    if (((ciphers_def[i].attr & mask) ||
b7538d
-                     (ciphers_def[i].strength & strength) ||
b7538d
-                     (ciphers_def[i].version & protocol)) &&
b7538d
-                     (cipher_list[i] != -1)) {
b7538d
-                        /* Enable the NULL ciphers only if explicity
b7538d
-                         * requested */
b7538d
-                        if (ciphers_def[i].attr & SSL_eNULL) {
b7538d
-                            if (mask & SSL_eNULL)
b7538d
-                                cipher_list[i] = action;
b7538d
-                        } else
b7538d
-                            cipher_list[i] = action;
b7538d
+                /* If we have a mask, apply it. If not then perhaps they
b7538d
+                 * provided a specific cipher to enable.
b7538d
+                 */
b7538d
+                if (mask || strength || protocol) {
b7538d
+                    merge = PR_TRUE;
b7538d
+                    found = PR_TRUE;
b7538d
+                    for (i=0; i
b7538d
+                        if (((ciphers_def[i].attr & mask) ||
b7538d
+                         (ciphers_def[i].strength & strength) ||
b7538d
+                         (ciphers_def[i].version & protocol)) &&
b7538d
+                         (cipher_list[i] != -1)) {
b7538d
+#if 0
b7538d
+                            /* Enable the NULL ciphers only if explicity
b7538d
+                             * requested */
b7538d
+                            if (ciphers_def[i].attr & SSL_eNULL) {
b7538d
+                                if (mask & SSL_eNULL)
b7538d
+                                    temp_list[i] = 1;
b7538d
+                            } else
b7538d
+#endif
b7538d
+                                temp_list[i] = 1;
b7538d
+                            }
b7538d
+                    }
b7538d
+                    /* Merge the temp list into the candidate list */
b7538d
+                    for (i=0; i
b7538d
+                        if (!(candidate_list[i] & temp_list[i])) {
b7538d
+                            candidate_list[i] = 0;
b7538d
+                        }
b7538d
+                    }
b7538d
+                } else if (!strcmp(cipher, "FIPS")) {
b7538d
+                        SSLCipherSuiteInfo suite;
b7538d
+                    for (i=0; i
b7538d
+                        if (SSL_GetCipherSuiteInfo(ciphers_def[i].num,
b7538d
+                            &suite, sizeof suite) == SECSuccess) {
b7538d
+                            if (suite.isFIPS)
b7538d
+                                set_cipher_value(cipher_list, i, action);
b7538d
+                        }
b7538d
+                    }
b7538d
+                } else {
b7538d
+                    for (i=0; i
b7538d
+                        if (!strcmp(ciphers_def[i].openssl_name, cipher))
b7538d
+                            set_cipher_value(cipher_list, i, action);
b7538d
                     }
b7538d
                 }
b7538d
-            else {
b7538d
+            } /* while */
b7538d
+            if (PR_TRUE == merge) {
b7538d
+                /* Merge the candidate list into the cipher list */
b7538d
                 for (i=0; i
b7538d
-                    if (!strcmp(ciphers_def[i].openssl_name, cipher) &&
b7538d
-                        cipher_list[i] != -1)
b7538d
-                        cipher_list[i] = action;
b7538d
+                    if (candidate_list[i])
b7538d
+                        set_cipher_value(cipher_list, i, action);
b7538d
                 }
b7538d
+                merge = PR_FALSE;
b7538d
+                found = PR_FALSE;
b7538d
             }
b7538d
         }
b7538d
 
b7538d
@@ -262,6 +390,8 @@ static int parse_openssl_ciphers(server_rec *s, char *ciphers, PRBool cipher_lis
b7538d
             cipher = ciphers;
b7538d
 
b7538d
     }
b7538d
+    if (found && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2))
b7538d
+        return 1; /* no matching ciphers */
b7538d
     return 0;
b7538d
 }
b7538d
 
b7538d
diff --git a/nss_engine_cipher.h b/nss_engine_cipher.h
b7538d
index f0c12f1..2cd103b 100644
b7538d
--- a/nss_engine_cipher.h
b7538d
+++ b/nss_engine_cipher.h
b7538d
@@ -29,27 +29,30 @@ typedef struct
b7538d
 } cipher_properties;
b7538d
 
b7538d
 /* OpenSSL-compatible cipher attributes */
b7538d
-#define SSL_kRSA  0x00000001L
b7538d
-#define SSL_aRSA  0x00000002L
b7538d
-#define SSL_aDSS  0x00000004L
b7538d
-#define SSL_DSS   SSL_aDSS
b7538d
-#define SSL_eNULL 0x00000008L
b7538d
-#define SSL_DES   0x00000010L
b7538d
-#define SSL_3DES  0x00000020L
b7538d
-#define SSL_RC4   0x00000040L
b7538d
-#define SSL_RC2   0x00000080L
b7538d
-#define SSL_MD5   0x00000200L
b7538d
-#define SSL_SHA1  0x00000400L
b7538d
-#define SSL_SHA   SSL_SHA1
b7538d
-#define SSL_RSA   (SSL_kRSA|SSL_aRSA)
b7538d
-#define SSL_kEDH  0x00000800L
b7538d
-#define SSL_EDH   (SSL_kEDH)
b7538d
-#define SSL_aNULL 0x00001000L
b7538d
-#define SSL_kECDHe 0x00002000L
b7538d
-#define SSL_aECDH 0x00004000L
b7538d
-#define SSL_aECDSA 0x00008000L
b7538d
-#define SSL_kECDHr 0x00010000L
b7538d
-#define SSL_kEECDH 0x00020000L
b7538d
+#define SSL_kRSA	0x00000001L
b7538d
+#define SSL_aRSA	0x00000002L
b7538d
+#define SSL_aDSS	0x00000004L
b7538d
+#define SSL_DSS		SSL_aDSS
b7538d
+#define SSL_eNULL	0x00000008L
b7538d
+#define SSL_DES		0x00000010L
b7538d
+#define SSL_3DES	0x00000020L
b7538d
+#define SSL_RC4		0x00000040L
b7538d
+#define SSL_RC2		0x00000080L
b7538d
+#define SSL_MD5		0x00000200L
b7538d
+#define SSL_SHA1	0x00000400L
b7538d
+#define SSL_SHA		SSL_SHA1
b7538d
+#define SSL_RSA		(SSL_kRSA)
b7538d
+#define SSL_kEDH	0x00000800L
b7538d
+#define SSL_EDH		(SSL_kEDH)
b7538d
+#define SSL_aNULL	0x00001000L
b7538d
+#define SSL_kECDHe	0x00002000L
b7538d
+#define SSL_aECDH	0x00004000L
b7538d
+#define SSL_aECDSA	0x00008000L
b7538d
+#define SSL_kECDHr	0x00010000L
b7538d
+#define SSL_kEECDH	0x00020000L
b7538d
+#define SSL_ECDH	(SSL_kECDHe|SSL_kECDHr|SSL_kEECDH)
b7538d
+#define SSL_EECDH	(SSL_kEECDH)
b7538d
+#define SSL_ADH		(SSL_kEDH)
b7538d
 
b7538d
 /* cipher strength */
b7538d
 #define SSL_STRONG_NONE   0x00000001L
b7538d
@@ -60,14 +63,14 @@ typedef struct
b7538d
 #define SSL_MEDIUM        0x00000020L
b7538d
 #define SSL_HIGH          0x00000040L
b7538d
 
b7538d
-#define SSL_AES128        0x00004000L
b7538d
-#define SSL_AES256        0x00008000L
b7538d
-#define SSL_CAMELLIA128   0x00010000L
b7538d
-#define SSL_CAMELLIA256   0x00020000L
b7538d
-#define SSL_AES128GCM     0x00040000L
b7538d
-#define SSL_AES256GCM     0x00080000L
b7538d
-#define SSL_SHA256        0x00100000L
b7538d
-#define SSL_AEAD          0x00200000L
b7538d
+#define SSL_AES128        0x00400000L
b7538d
+#define SSL_AES256        0x00800000L
b7538d
+#define SSL_CAMELLIA128   0x01000000L
b7538d
+#define SSL_CAMELLIA256   0x02000000L
b7538d
+#define SSL_AES128GCM     0x04000000L
b7538d
+#define SSL_AES256GCM     0x08000000L
b7538d
+#define SSL_SHA256        0x10000000L
b7538d
+#define SSL_AEAD          0x20000000L
b7538d
 
b7538d
 #define SSL_AES           (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
b7538d
 #define SSL_CAMELLIA      (SSL_CAMELLIA128|SSL_CAMELLIA256)
b7538d
diff --git a/test/createinstance.sh b/test/createinstance.sh
b7538d
index c3b7260..9cdba62 100755
b7538d
--- a/test/createinstance.sh
b7538d
+++ b/test/createinstance.sh
b7538d
@@ -25,6 +25,7 @@ mkdir lib
b7538d
 # Create the content
b7538d
 mkdir content/rc4_cipher
b7538d
 mkdir content/openssl_rc4_cipher
b7538d
+mkdir content/openssl_aes_cipher
b7538d
 mkdir content/acl
b7538d
 mkdir content/protocolssl2
b7538d
 mkdir content/protocolssl3
b7538d
diff --git a/test/suite1.tmpl b/test/suite1.tmpl
b7538d
index eb2a16c..0f739a2 100644
b7538d
--- a/test/suite1.tmpl
b7538d
+++ b/test/suite1.tmpl
b7538d
@@ -39,6 +39,12 @@ NSSUserName SSL_CLIENT_S_DN_UID
b7538d
     NSSCipherSuite RC4-SHA
b7538d
 </Location>
b7538d
 
b7538d
+<Location "/openssl_aes_cipher">
b7538d
+    # In openssl equivalent of AES:-ECDH:-ADH:-PSK:-DH
b7538d
+    # In NSS equivalent of AES:-ECDH
b7538d
+    NSSCipherSuite AES+RSA
b7538d
+</Location>
b7538d
+
b7538d
 <Location "/acl/aclS01.html">
b7538d
     NSSOptions +StdEnvVars +CompatEnvVars +ExportCertData
b7538d
     NSSVerifyClient require
b7538d
diff --git a/test/test.py b/test/test.py
b7538d
index ee8d95b..23e093c 100644
b7538d
--- a/test/test.py
b7538d
+++ b/test/test.py
b7538d
@@ -69,6 +69,12 @@ class test_suite1(Declarative):
b7538d
         ),
b7538d
 
b7538d
         dict(
b7538d
+            desc='server-side OpenSSL-style AES cipher check',
b7538d
+            request=('/openssl_aes_cipher/', {'ciphers': 'AES128-SHA'}),
b7538d
+            expected=200,
b7538d
+        ),
b7538d
+
b7538d
+        dict(
b7538d
             desc='Basic client auth, no certificate',
b7538d
             request=('/acl/aclS01.html', {}),
b7538d
             expected=requests.exceptions.SSLError(),
b7538d
diff --git a/test/test_cipher.py b/test/test_cipher.py
b7538d
index 55989bd..a91f411 100644
b7538d
--- a/test/test_cipher.py
b7538d
+++ b/test/test_cipher.py
b7538d
@@ -10,9 +10,50 @@ WITH_ECC=47
b7538d
 cwd = os.getcwd()
b7538d
 srcdir = os.path.dirname(cwd)
b7538d
 exe = "%s/test_cipher" % srcdir
b7538d
+openssl = "/usr/bin/openssl"
b7538d
 
b7538d
 ciphernum = 0
b7538d
 
b7538d
+CIPHERS_NOT_IN_NSS = ['ECDH-RSA-AES128-SHA256',
b7538d
+                      'ECDH-ECDSA-AES128-GCM-SHA256',
b7538d
+                      'ECDH-ECDSA-AES128-SHA256',
b7538d
+                      'ECDH-RSA-AES128-GCM-SHA256',
b7538d
+                      'EXP-DES-CBC-SHA',
b7538d
+]
b7538d
+
b7538d
+def assert_equal_openssl(nss_ciphers, ossl_ciphers):
b7538d
+    (nss, err, rc) = run([exe, "--o", nss_ciphers])
b7538d
+    assert rc == 0
b7538d
+    (ossl, err, rc) = run([openssl, "ciphers", ossl_ciphers])
b7538d
+    assert rc == 0
b7538d
+
b7538d
+    nss_list = nss.strip().split(':')
b7538d
+    nss_list.sort()
b7538d
+
b7538d
+    ossl_list = ossl.strip().split(':')
b7538d
+    ossl_list = list(set(ossl_list))
b7538d
+    ossl_list.sort()
b7538d
+
b7538d
+    # NSS doesn't support the SHA-384 ciphers, remove them from the OpenSSL
b7538d
+    # output.
b7538d
+    t = list()
b7538d
+    for o in ossl_list:
b7538d
+        if 'SHA384' in o:
b7538d
+            continue
b7538d
+        if o in CIPHERS_NOT_IN_NSS:
b7538d
+            continue
b7538d
+        t.append(o)
b7538d
+    ossl_list = t
b7538d
+
b7538d
+    if len(nss_list) > len(ossl_list):
b7538d
+        diff = set(nss_list) - set(ossl_list)
b7538d
+    elif len(ossl_list) > len(nss_list):
b7538d
+        diff = set(ossl_list) - set(nss_list)
b7538d
+    else:
b7538d
+        diff = ''
b7538d
+
b7538d
+    assert nss_list == ossl_list, '%r != %r. Difference %r' % (':'.join(nss_list), ':'.join(ossl_list), diff)
b7538d
+
b7538d
 class test_ciphers(object):
b7538d
     @classmethod
b7538d
     def setUpClass(cls):
b7538d
@@ -20,131 +61,172 @@ class test_ciphers(object):
b7538d
         assert rc == 0
b7538d
         cls.ciphernum = int(out)
b7538d
 
b7538d
+    def test_RSA(self):
b7538d
+        assert_equal_openssl("RSA", "RSA:-SSLv2:-SEED:-IDEA")
b7538d
+
b7538d
+    def test_kRSA(self):
b7538d
+        assert_equal_openssl("kRSA", "kRSA:-SSLv2:-SEED:-IDEA")
b7538d
+
b7538d
+    def test_aRSA(self):
b7538d
+        assert_equal_openssl("aRSA", "aRSA:-SSLv2:-SEED:-IDEA:-DH")
b7538d
+
b7538d
+    def test_EDH(self):
b7538d
+        # No DH ciphers supported yet
b7538d
+        (out, err, rc) = run([exe, "EDH"])
b7538d
+        assert rc == 1
b7538d
+
b7538d
     def test_RC4(self):
b7538d
-        (out, err, rc) = run([exe, "RC4"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc4_56_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc4_56_sha, ecdh_ecdsa_rc4_128_sha, ecdhe_ecdsa_rc4_128_sha, ecdh_rsa_128_sha, ecdhe_rsa_rc4_128_sha, ecdh_anon_rc4_128sha')
b7538d
+        assert_equal_openssl("RC4", "RC4:-KRB5:-PSK:-ADH")
b7538d
+
b7538d
+    def test_RC2(self):
b7538d
+        assert_equal_openssl("RC2", "RC2:-SSLv2:-KRB5")
b7538d
 
b7538d
     def test_AES(self):
b7538d
-        (out, err, rc) = run([exe, "AES"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
b7538d
+        assert_equal_openssl("AES", "AES:-PSK:-ADH:-DSS:-DH")
b7538d
 
b7538d
+    def test_AESGCM(self):
b7538d
+        assert_equal_openssl("AESGCM", "AESGCM:-PSK:-ADH:-DSS:-DH")
b7538d
+
b7538d
+    def test_AES128(self):
b7538d
+        assert_equal_openssl("AES128", "AES128:-PSK:-ADH:-DSS:-DH")
b7538d
+
b7538d
+    def test_AES256(self):
b7538d
+        assert_equal_openssl("AES256", "AES256:-PSK:-ADH:-DSS:-DH")
b7538d
+
b7538d
+    def test_CAMELLIA(self):
b7538d
+        assert_equal_openssl("CAMELLIA", "CAMELLIA:-DH")
b7538d
+
b7538d
+    def test_CAMELLIA128(self):
b7538d
+        assert_equal_openssl("CAMELLIA128", "CAMELLIA128:-DH")
b7538d
+
b7538d
+    def test_CAMELLIA256(self):
b7538d
+        assert_equal_openssl("CAMELLIA256", "CAMELLIA256:-DH")
b7538d
+
b7538d
+    def test_3DES(self):
b7538d
+        assert_equal_openssl("3DES", "3DES:-SSLv2:-PSK:-KRB5:-DH")
b7538d
+
b7538d
+    def test_DES(self):
b7538d
+        assert_equal_openssl("DES", "DES:-SSLv2:-KRB5:-DH")
b7538d
 
b7538d
     def test_ALL(self):
b7538d
-        (out, err, rc) = run([exe, "ALL"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, rsa_aes_128_gcm_sha_256'
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, aes_128_sha_256, aes_256_sha_256, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, rsa_aes_128_gcm_sha_256, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
b7538d
+        assert_equal_openssl("ALL", "ALL:-SSLv2:-KRB5:-ADH:-DH:-DSS:-PSK:-SEED:-IDEA")
b7538d
 
b7538d
     def test_ALL_no_AES(self):
b7538d
-        (out, err, rc) = run([exe, "ALL:-AES"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
b7538d
+        assert_equal_openssl("ALL:-AES", "ALL:-AES:-SSLv2:-KRB5:-ADH:-DH:-DSS:-PSK:-SEED:-IDEA")
b7538d
+
b7538d
+    def test_COMPLEMENTOFALL(self):
b7538d
+        assert_equal_openssl("COMPLEMENTOFALL", "COMPLEMENTOFALL")
b7538d
+
b7538d
+    # skipping DEFAULT as we use the NSS defaults
b7538d
+    # skipping COMPLEMENTOFDEFAULT as these are all ADH ciphers
b7538d
 
b7538d
     def test_SSLv3(self):
b7538d
-        (out, err, rc) = run([exe, "SSLv3"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha')
b7538d
+        assert_equal_openssl("SSLv3", "SSLv3:-KRB5:-PSK:-ADH:-EDH:-SEED:-IDEA")
b7538d
 
b7538d
     def test_SSLv3_equals_TLSv1(self):
b7538d
-        (out, err, rc) = run([exe, "SSLv3"])
b7538d
-        (out2, err2, rc2) = run([exe, "TLSv1"])
b7538d
+        (nss, err, rc) = run([exe, "--o", "SSLv3"])
b7538d
+        (nss2, err, rc2) = run([exe, "--o", "TLSv1"])
b7538d
         assert rc == 0
b7538d
         assert rc2 == 0
b7538d
-        assert_equal(out, out2)
b7538d
+        assert_equal(nss, nss2)
b7538d
 
b7538d
     def test_TLSv12(self):
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            raise nose.SkipTest('ECC disabled')
b7538d
-        (out, err, rc) = run([exe, "TLSv12"])
b7538d
-        assert rc == 0
b7538d
-        assert_equal(out, 'aes_128_sha_256, aes_256_sha_256, rsa_aes_128_gcm_sha_256, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256, ecdhe_ecdsa_aes_128_gcm_sha_256, ecdhe_rsa_aes_128_gcm_sha_256')
b7538d
+        assert_equal_openssl("TLSv1.2", "TLSv1.2:TLSv1.2:-ADH:-DH:-DSS")
b7538d
 
b7538d
     def test_NULL(self):
b7538d
-        (out, err, rc) = run([exe, "NULL"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_null_md5, rsa_null_sha, null_sha_256')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_null_md5, rsa_null_sha, null_sha_256, ecdh_ecdsa_null_sha, ecdhe_ecdsa_null_sha, ecdh_rsa_null_sha, ecdhe_rsa_null, ecdh_anon_null_sha')
b7538d
+        assert_equal_openssl("NULL", "NULL")
b7538d
 
b7538d
     def test_nss_rsa_rc4_128(self):
b7538d
+        # Test NSS cipher parsing
b7538d
         (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+rsa_rc4_128_sha"])
b7538d
         assert rc == 0
b7538d
         assert_equal(out, 'rsa_rc4_128_md5, rsa_rc4_128_sha')
b7538d
 
b7538d
-    def test_openssl_cipher(self):
b7538d
-        (out, err, rc) = run([exe, "DES-CBC3-SHA"])
b7538d
-        assert rc == 0
b7538d
-        assert_equal(out, 'rsa_3des_sha')
b7538d
+    def test_EXP(self):
b7538d
+        assert_equal_openssl("EXP", "EXP:-SSLv2:-DH:-KRB5")
b7538d
 
b7538d
-    def test_openssl_cipherlist(self):
b7538d
-        (out, err, rc) = run([exe, "DES-CBC3-SHA:RC4-SHA"])
b7538d
-        assert rc == 0
b7538d
-        assert_equal(out, 'rsa_rc4_128_sha, rsa_3des_sha')
b7538d
+    def test_EXPORT(self):
b7538d
+        assert_equal_openssl("EXPORT", "EXPORT:-SSLv2:-DH:-KRB5")
b7538d
 
b7538d
-    def test_EXP(self):
b7538d
-        (out, err, rc) = run([exe, "EXP"])
b7538d
-        assert rc == 0
b7538d
-        assert_equal(out, 'rsa_rc4_40_md5, rsa_rc2_40_md5, rsa_des_56_sha, rsa_rc4_56_sha')
b7538d
+    def test_EXPORT40(self):
b7538d
+        assert_equal_openssl("EXPORT40", "EXPORT40:-SSLv2:-ADH:-DH:-KRB5")
b7538d
 
b7538d
     def test_MD5(self):
b7538d
-        (out, err, rc) = run([exe, "MD5"])
b7538d
-        assert rc == 0
b7538d
-        assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc2_40_md5')
b7538d
+        assert_equal_openssl("MD5", "MD5:-SSLv2:-DH:-KRB5")
b7538d
 
b7538d
     def test_SHA(self):
b7538d
-        (out, err, rc) = run([exe, "SHA"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_128_sha, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_128_sha, rsa_des_sha, rsa_3des_sha, rsa_aes_128_sha, rsa_aes_256_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdh_ecdsa_rc4_128_sha, ecdh_ecdsa_3des_sha, ecdh_ecdsa_aes_128_sha, ecdh_ecdsa_aes_256_sha, ecdhe_ecdsa_rc4_128_sha, ecdhe_ecdsa_3des_sha, ecdhe_ecdsa_aes_128_sha, ecdhe_ecdsa_aes_256_sha, ecdh_rsa_128_sha, ecdh_rsa_3des_sha, ecdh_rsa_aes_128_sha, ecdh_rsa_aes_256_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdhe_rsa_aes_128_sha, ecdhe_rsa_aes_256_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha, ecdh_anon_aes_128_sha, ecdh_anon_aes_256_sha')
b7538d
+        assert_equal_openssl("SHA", "SHA:-SSLv2:-DH:-KRB5:-PSK:-IDEA:-SEED")
b7538d
+
b7538d
+    def test_HIGH(self):
b7538d
+        assert_equal_openssl("HIGH", "HIGH:-SSLv2:-DH:-ADH:-KRB5:-PSK")
b7538d
+
b7538d
+    def test_MEDIUM(self):
b7538d
+        assert_equal_openssl("MEDIUM", "MEDIUM:-SSLv2:-ADH:-KRB5:-PSK:-SEED:-IDEA")
b7538d
+
b7538d
+    def test_LOW(self):
b7538d
+        assert_equal_openssl("LOW", "LOW:-SSLv2:-DH:-ADH:-KRB5")
b7538d
 
b7538d
     def test_SHA256(self):
b7538d
-        (out, err, rc) = run([exe, "SHA256"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'aes_128_sha_256, aes_256_sha_256')
b7538d
-        else:
b7538d
-            assert_equal(out, 'aes_128_sha_256, aes_256_sha_256, ecdhe_ecdsa_aes_128_sha_256, ecdhe_rsa_aes_128_sha_256')
b7538d
+        assert_equal_openssl("SHA256", "SHA256:-ADH:-DSS:-DH")
b7538d
 
b7538d
     def test_SHA_MD5_minus_AES(self):
b7538d
-        (out, err, rc) = run([exe, "SHA:MD5:-AES"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
b7538d
+        assert_equal_openssl("SHA:MD5:-AES", "SHA:MD5:-AES:-SSLv2:-DH:-DSS:-KRB5:-SEED:-PSK:-IDEA")
b7538d
 
b7538d
-    def test_SHA_MD5_not_AES_HIGH(self):
b7538d
-        (out, err, rc) = run([exe, "!AES:SHA:MD5"])
b7538d
-        assert rc == 0
b7538d
-        if self.ciphernum < WITH_ECC:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha')
b7538d
-        else:
b7538d
-            assert_equal(out, 'rsa_rc4_40_md5, rsa_rc4_128_md5, rsa_rc4_128_sha, rsa_rc2_40_md5, rsa_des_sha, rsa_3des_sha, camelia_128_sha, rsa_des_56_sha, rsa_rc4_56_sha, camelia_256_sha, fips_3des_sha, fips_des_sha, ecdhe_rsa_rc4_128_sha, ecdhe_rsa_3des_sha, ecdh_anon_rc4_128sha, ecdh_anon_3des_sha')
b7538d
+    def test_SHA_MD5_not_AES(self):
b7538d
+        assert_equal_openssl("!AES:SHA:MD5", "!AES:SHA:MD5:-SSLv2:-DH:-KRB5:-DSS:-SEED:-PSK:-IDEA")
b7538d
+
b7538d
+    def test_aECDH(self):
b7538d
+        assert_equal_openssl("aECDH", "aECDH")
b7538d
+
b7538d
+    def test_kECDHe(self):
b7538d
+        assert_equal_openssl("kECDHe", "kECDHe")
b7538d
+
b7538d
+    def test_kECDHr(self):
b7538d
+        assert_equal_openssl("kECDHr", "kECDHr")
b7538d
+
b7538d
+    def test_kEECDH(self):
b7538d
+        assert_equal_openssl("kEECDH", "kEECDH")
b7538d
+
b7538d
+    def test_ECDH(self):
b7538d
+        assert_equal_openssl("ECDH", "ECDH")
b7538d
+
b7538d
+    def test_AES_no_ECDH(self):
b7538d
+        assert_equal_openssl("AES:-ECDH", "AES:-ECDH:-ADH:-PSK:-DH")
b7538d
+        assert_equal_openssl("AES+RSA", "AES+RSA")
b7538d
+
b7538d
+    def test_logical_and_3DES_RSA(self):
b7538d
+        assert_equal_openssl("3DES+RSA", "3DES+RSA:-SSLv2")
b7538d
+
b7538d
+    def test_logical_and_RSA_RC4(self):
b7538d
+        assert_equal_openssl("RSA+RC4", "RSA+RC4:-SSLv2")
b7538d
+
b7538d
+    def test_logical_and_ECDH_SHA(self):
b7538d
+        assert_equal_openssl("ECDH+SHA", "ECDH+SHA")
b7538d
+
b7538d
+    def test_logical_and_RSA_RC4_no_SHA(self):
b7538d
+        assert_equal_openssl("RSA+RC4:!SHA", "RSA+RC4:-SSLv2:!SHA")
b7538d
+
b7538d
+    def test_additive_RSA_RC4(self):
b7538d
+        assert_equal_openssl("RSA:+RC4", "RSA:+RC4:-SSLv2:-SEED:-IDEA")
b7538d
+
b7538d
+    def test_negative_plus_RSA_MD5(self):
b7538d
+        assert_equal_openssl("-RC2:RSA+MD5", "-RC2:RSA+MD5:-SSLv2")
b7538d
 
b7538d
     def test_nss_subtraction(self):
b7538d
         (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+rsa_rc4_128_sha,-rsa_rc4_128_md5"])
b7538d
         assert rc == 0
b7538d
         assert_equal(out, 'rsa_rc4_128_sha')
b7538d
 
b7538d
+    def test_openssl_cipher(self):
b7538d
+        (out, err, rc) = run([exe, "DES-CBC3-SHA"])
b7538d
+        assert rc == 0
b7538d
+        assert_equal(out, 'rsa_3des_sha')
b7538d
+
b7538d
+    def test_openssl_cipherlist(self):
b7538d
+        (out, err, rc) = run([exe, "DES-CBC3-SHA:RC4-SHA"])
b7538d
+        assert rc == 0
b7538d
+        assert_equal(out, 'rsa_rc4_128_sha, rsa_3des_sha')
b7538d
+
b7538d
     # As long as at least one is valid, things are ok
b7538d
     def test_nss_unknown(self):
b7538d
         (out, err, rc) = run([exe, "+rsa_rc4_128_md5,+unknown"])
b7538d
@@ -156,7 +238,9 @@ class test_ciphers(object):
b7538d
         assert rc == 0
b7538d
         assert_equal(out, 'aes_128_sha_256')
b7538d
 
b7538d
+    def test_openssl_single_cipher(self):
b7538d
+        assert_equal_openssl("RC4-SHA", "RC4-SHA")
b7538d
+
b7538d
     def test_invalid_format(self):
b7538d
         (out, err, rc) = run([exe, "none"])
b7538d
         assert rc == 1
b7538d
-        assert_equal(err, 'nss_engine_cipher.c:292, invalid cipher string none. Format is +cipher1,-cipher2...Unable to parse cipher list')
b7538d
diff --git a/test_cipher.c b/test_cipher.c
b7538d
index 91d112b..86a88d6 100644
b7538d
--- a/test_cipher.c
b7538d
+++ b/test_cipher.c
b7538d
@@ -40,7 +40,7 @@ int ap_log_error_(const char *fn, int line, int module_index,
b7538d
 
b7538d
     va_start(args, fmt);
b7538d
     vsprintf(out, fmt, args);
b7538d
-    fprintf(stderr,"%s:%d, %s", fn, line, out);
b7538d
+    fprintf(stderr,"%s:%d, %s\n", fn, line, out);
b7538d
     va_end(args);
b7538d
 
b7538d
     return 0;
b7538d
@@ -53,10 +53,11 @@ int main(int argc, char ** argv)
b7538d
     int rv=0;
b7538d
     int i;
b7538d
     char *ciphers;
b7538d
+    PRBool openssl_output = PR_FALSE;
b7538d
     PRBool ciphers_list[ciphernum];
b7538d
 
b7538d
-    if (argc != 2) {
b7538d
-        fprintf(stderr, "Usage: test_cipher [--count] <cipher_list>\n");
b7538d
+    if (argc != 2 && argc != 3) {
b7538d
+        fprintf(stderr, "Usage: test_cipher [--count] [--o] <cipher_list>\n");
b7538d
         exit(1);
b7538d
     }
b7538d
 
b7538d
@@ -70,9 +71,14 @@ int main(int argc, char ** argv)
b7538d
         ciphers_list[i] = PR_FALSE;
b7538d
     }
b7538d
 
b7538d
-    ciphers = strdup(argv[1]);
b7538d
+    i = 1; /* index of ciphers */
b7538d
+    if (!strcmp(argv[1], "--o")) {
b7538d
+        openssl_output = PR_TRUE;
b7538d
+        i = 2;
b7538d
+    }
b7538d
+
b7538d
+    ciphers = strdup(argv[i]);
b7538d
     if (nss_parse_ciphers(NULL, ciphers, ciphers_list) < 0) {
b7538d
-        fprintf(stderr, "Unable to parse cipher list\n");
b7538d
         rv = 1;
b7538d
     }
b7538d
     free(ciphers);
b7538d
@@ -85,12 +91,22 @@ int main(int argc, char ** argv)
b7538d
         for (i = 0; i < ciphernum; i++)
b7538d
         {
b7538d
             if (ciphers_list[i] == 1) {
b7538d
-                strncat(output,  ciphers_def[i].name, sizeof(output));
b7538d
-                strncat(output,  ", ", sizeof(output));
b7538d
+                if (openssl_output) {
b7538d
+                    strncat(output,  ciphers_def[i].openssl_name, sizeof(output));
b7538d
+                    strncat(output,  ":", sizeof(output));
b7538d
+                } else {
b7538d
+                    strncat(output,  ciphers_def[i].name, sizeof(output));
b7538d
+                    strncat(output,  ", ", sizeof(output));
b7538d
+                }
b7538d
             }
b7538d
         }
b7538d
-        output[strlen(output) - 2] = '\0';
b7538d
+        if (openssl_output)
b7538d
+            output[strlen(output) - 1] = '\0';
b7538d
+        else
b7538d
+            output[strlen(output) - 2] = '\0';
b7538d
         fprintf(stdout, "%s\n", output);
b7538d
+    } else {
b7538d
+        fprintf(stdout, "Unable to parse cipher list\n");
b7538d
     }
b7538d
 
b7538d
     return rv;
b7538d
-- 
b7538d
1.9.3
b7538d