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