Add SSL_CIPHER_get_rfc_name. OpenSSL's internal names for the ciphers are not the standard ones and are not easy to consistently map to the standard ones. Add an API to get the real names out. (WebRTC wants an API to get the standard names out.) Also change some incorrect flags on SHA-256 TLS 1.2 ciphers; SSL_HANDSHAKE_MAC_DEFAULT and SSL_HANDSHAKE_MAC_SHA256 are the same after TLS 1.2. A TLS 1.2 cipher should be tagged explicitly with SHA-256. (This avoids tripping a check in SSL_CIPHER_get_rfc_name which asserts that default-hash ciphers only ever use SHA-1 or MD5 for the bulk cipher MAC.) Change-Id: Iaec2fd4aa97df29883094d3c2ae60f0ba003bf07
diff --git a/ssl/ssl_test.c b/ssl/ssl_test.c index 70291a2..de0f8ed 100644 --- a/ssl/ssl_test.c +++ b/ssl/ssl_test.c
@@ -214,9 +214,13 @@ static int test_cipher_rule(CIPHER_TEST *t) { int ret = 0; - SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX *ctx = SSL_CTX_new(TLS_method()); size_t i; + if (ctx == NULL) { + goto done; + } + if (!SSL_CTX_set_cipher_list(ctx, t->rule)) { fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule); BIO_print_errors_fp(stderr); @@ -243,7 +247,9 @@ ret = 1; done: - SSL_CTX_free(ctx); + if (ctx != NULL) { + SSL_CTX_free(ctx); + } return ret; } @@ -257,8 +263,12 @@ for (i = 0; kBadRules[i] != NULL; i++) { SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); + if (ctx == NULL) { + return 0; + } if (SSL_CTX_set_cipher_list(ctx, kBadRules[i])) { fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]); + SSL_CTX_free(ctx); return 0; } ERR_clear_error(); @@ -420,7 +430,8 @@ return ret; } -int test_default_version(uint16_t version, const SSL_METHOD *(*method)(void)) { +static int test_default_version(uint16_t version, + const SSL_METHOD *(*method)(void)) { SSL_CTX *ctx; int ret; @@ -434,6 +445,78 @@ return ret; } +static char *cipher_get_rfc_name(const char *name) { + SSL_CTX *ctx = SSL_CTX_new(TLS_method()); + char *ret = NULL; + + if (ctx == NULL) { + goto done; + } + + if (!SSL_CTX_set_cipher_list(ctx, name) || + sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != 1) { + fprintf(stderr, "Error finding cipher '%s'\n", name); + BIO_print_errors_fp(stderr); + goto done; + } + + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, 0); + ret = SSL_CIPHER_get_rfc_name(cipher); + +done: + if (ctx != NULL) { + SSL_CTX_free(ctx); + } + return ret; +} + +typedef struct { + const char *name; + const char *rfc_name; +} CIPHER_RFC_NAME_TEST; + +static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = { + { "DES-CBC3-SHA", "TLS_RSA_WITH_3DES_EDE_CBC_SHA" }, + { "RC4-MD5", "TLS_RSA_WITH_RC4_MD5" }, + { "AES128-SHA", "TLS_RSA_WITH_AES_128_CBC_SHA" }, + { "ADH-AES128-SHA", "TLS_DH_anon_WITH_AES_128_CBC_SHA" }, + { "DHE-RSA-AES256-SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" }, + { "DHE-RSA-AES256-SHA256", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" }, + { "AECDH-AES128-SHA", "TLS_ECDH_anon_WITH_AES_128_CBC_SHA" }, + { "ECDHE-RSA-AES128-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" }, + { "ECDHE-RSA-AES256-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" }, + { "ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" }, + { "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, + { "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" }, + { "PSK-RC4-SHA", "TLS_PSK_WITH_RC4_SHA" }, + /* These names are non-standard: */ + { "ECDHE-RSA-CHACHA20-POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" }, + { "ECDHE-ECDSA-CHACHA20-POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" }, + { "ECDHE-PSK-WITH-AES-128-GCM-SHA256", "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256" }, +}; + +static int test_cipher_get_rfc_name() { + size_t i; + + for (i = 0; i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); + i++) { + const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i]; + char *rfc_name = cipher_get_rfc_name(test->name); + if (rfc_name == NULL) { + fprintf(stderr, "cipher_get_rfc_name failed on '%s'\n", test->name); + return 0; + } + if (strcmp(rfc_name, test->rfc_name) != 0) { + fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n", + rfc_name, test->rfc_name); + OPENSSL_free(rfc_name); + return 0; + } + OPENSSL_free(rfc_name); + } + return 1; +} + int main(void) { SSL_library_init(); @@ -447,7 +530,8 @@ !test_default_version(TLS1_2_VERSION, &TLSv1_2_method) || !test_default_version(0, &DTLS_method) || !test_default_version(DTLS1_VERSION, &DTLSv1_method) || - !test_default_version(DTLS1_2_VERSION, &DTLSv1_2_method)) { + !test_default_version(DTLS1_2_VERSION, &DTLSv1_2_method) || + !test_cipher_get_rfc_name()) { return 1; }