|
|
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 |
|