From cb51c3adb97cda6656f3ebed387a4ce278bdd1eb Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 13 Sep 2020 16:51:31 +0000 Subject: Add regress for SSL_{CTX_,}set_ciphersuites(). --- regress/lib/libssl/ciphers/Makefile | 4 +- regress/lib/libssl/ciphers/cipherstest.c | 321 ++++++++++++++++++++++++++++++- 2 files changed, 318 insertions(+), 7 deletions(-) (limited to 'regress') diff --git a/regress/lib/libssl/ciphers/Makefile b/regress/lib/libssl/ciphers/Makefile index c9a58a5e098..2575db4df4f 100644 --- a/regress/lib/libssl/ciphers/Makefile +++ b/regress/lib/libssl/ciphers/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.1 2015/02/06 08:48:39 jsing Exp $ +# $OpenBSD: Makefile,v 1.2 2020/09/13 16:51:30 jsing Exp $ PROG= cipherstest -LDADD= -lssl -lcrypto +LDADD= ${SSL_INT} -lcrypto DPADD= ${LIBSSL} ${LIBCRYPTO} WARNINGS= Yes CFLAGS+= -DLIBRESSL_INTERNAL -Werror diff --git a/regress/lib/libssl/ciphers/cipherstest.c b/regress/lib/libssl/ciphers/cipherstest.c index d76fbfc8c03..34ac96e48c9 100644 --- a/regress/lib/libssl/ciphers/cipherstest.c +++ b/regress/lib/libssl/ciphers/cipherstest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Joel Sing + * Copyright (c) 2015, 2020 Joel Sing * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,6 +20,8 @@ #include #include +int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str); + static int get_put_test(const char *name, const SSL_METHOD *method) { @@ -71,7 +73,7 @@ get_put_test(const char *name, const SSL_METHOD *method) ret = 0; -failure: + failure: SSL_CTX_free(ssl_ctx); SSL_free(ssl); @@ -154,22 +156,331 @@ cipher_get_by_value_tests(void) ret = 0; -failure: + failure: SSL_CTX_free(ssl_ctx); SSL_free(ssl); return (ret); } +struct parse_ciphersuites_test { + const char *str; + const int want; + const unsigned long cids[32]; +}; + +struct parse_ciphersuites_test parse_ciphersuites_tests[] = { + { + /* LibreSSL names. */ + .str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + }, + }, + { + /* OpenSSL names. */ + .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + }, + }, + { + /* Different priority order. */ + .str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + }, + }, + { + /* Known but unsupported names. */ + .str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + }, + }, + { + /* Empty string means no TLSv1.3 ciphersuites. */ + .str = "", + .want = 1, + .cids = { 0 }, + }, + { + .str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE", + .want = 0, + }, + { + .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256", + .want = 0, + }, +}; + +#define N_PARSE_CIPHERSUITES_TESTS \ + (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests)) + +static int +parse_ciphersuites_test() +{ + struct parse_ciphersuites_test *pct; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CIPHER *cipher; + int failed = 1; + int j, ret; + size_t i; + + for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) { + pct = &parse_ciphersuites_tests[i]; + + ret = ssl_parse_ciphersuites(&ciphers, pct->str); + if (ret != pct->want) { + fprintf(stderr, "FAIL: test %zu - " + "ssl_parse_ciphersuites returned %d, want %d\n", + i, ret, pct->want); + goto failed; + } + if (ret == 0) + continue; + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + cipher = sk_SSL_CIPHER_value(ciphers, j); + if (SSL_CIPHER_get_id(cipher) == pct->cids[j]) + continue; + fprintf(stderr, "FAIL: test %zu - got cipher %d with " + "id %lx, want %lx\n", i, j, + SSL_CIPHER_get_id(cipher), pct->cids[j]); + goto failed; + } + if (pct->cids[j] != 0) { + fprintf(stderr, "FAIL: test %zu - got %d ciphers, " + "expected more", i, sk_SSL_CIPHER_num(ciphers)); + goto failed; + } + } + + failed = 0; + + failed: + sk_SSL_CIPHER_free(ciphers); + + return failed; +} + +struct cipher_set_test { + int ctx_ciphersuites_first; + const char *ctx_ciphersuites; + const char *ctx_rulestr; + int ssl_ciphersuites_first; + const char *ssl_ciphersuites; + const char *ssl_rulestr; + const unsigned long cids[32]; +}; + +struct cipher_set_test cipher_set_tests[] = { + { + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites_first = 1, + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 1, + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites_first = 0, + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 0, + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, +}; + +#define N_CIPHER_SET_TESTS \ + (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests)) + +static int +cipher_set_test() +{ + struct cipher_set_test *cst; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CIPHER *cipher; + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + int failed = 1; + size_t i; + int j; + + for (i = 0; i < N_CIPHER_SET_TESTS; i++) { + cst = &cipher_set_tests[i]; + + if ((ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "SSL_CTX_new"); + + if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { + if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) + errx(1, "SSL_CTX_set_ciphersuites"); + } + if (cst->ctx_rulestr != NULL) { + if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr)) + errx(1, "SSL_CTX_set_cipher_list"); + } + if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { + if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) + errx(1, "SSL_CTX_set_ciphersuites"); + } + + /* XXX - check SSL_CTX_get_ciphers(ctx) */ + + if ((ssl = SSL_new(ctx)) == NULL) + errx(1, "SSL_new"); + + if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { + if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) + errx(1, "SSL_set_ciphersuites"); + } + if (cst->ssl_rulestr != NULL) { + if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr)) + errx(1, "SSL_set_cipher_list"); + } + if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { + if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) + errx(1, "SSL_set_ciphersuites"); + } + + ciphers = SSL_get_ciphers(ssl); + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + cipher = sk_SSL_CIPHER_value(ciphers, j); + if (SSL_CIPHER_get_id(cipher) == cst->cids[j]) + continue; + fprintf(stderr, "FAIL: test %zu - got cipher %d with " + "id %lx, want %lx\n", i, j, + SSL_CIPHER_get_id(cipher), cst->cids[j]); + goto failed; + } + if (cst->cids[j] != 0) { + fprintf(stderr, "FAIL: test %zu - got %d ciphers, " + "expected more", i, sk_SSL_CIPHER_num(ciphers)); + goto failed; + } + + SSL_CTX_free(ctx); + ctx = NULL; + SSL_free(ssl); + ssl = NULL; + } + + failed = 0; + + failed: + SSL_CTX_free(ctx); + SSL_free(ssl); + + return failed; +} + int main(int argc, char **argv) { int failed = 0; - SSL_library_init(); - failed |= cipher_get_put_tests(); failed |= cipher_get_by_value_tests(); + failed |= parse_ciphersuites_test(); + failed |= cipher_set_test(); + return (failed); } -- cgit v1.2.3