X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Fsslapitest.c;h=ce24fad51af4117f16ab767d7c93ae0c93bf3d4b;hp=b5878570e20ea79f759b79f6d9d3c7649a9bd7e1;hb=c39e4048b538ec76313c264e860cfb5cd677a9ac;hpb=cf72c7579201086cee303eadcb60bd28eff78dd9 diff --git a/test/sslapitest.c b/test/sslapitest.c index b5878570e2..ce24fad51a 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -254,6 +254,7 @@ static int test_keylog_output(char *buffer, const SSL *ssl, return 1; } +#if !defined(OPENSSL_NO_TLS1_2) || defined(OPENSSL_NO_TLS1_3) static int test_keylog(void) { SSL_CTX *cctx = NULL, *sctx = NULL; @@ -330,6 +331,7 @@ end: return testresult; } +#endif #ifndef OPENSSL_NO_TLS1_3 static int test_keylog_no_master_key(void) @@ -1273,6 +1275,7 @@ static int test_ssl_bio_change_wbio(void) return execute_test_ssl_bio(0, CHANGE_WBIO); } +#if !defined(OPENSSL_NO_TLS1_2) || defined(OPENSSL_NO_TLS1_3) typedef struct { /* The list of sig algs */ const int *list; @@ -1287,25 +1290,25 @@ typedef struct { } sigalgs_list; static const int validlist1[] = {NID_sha256, EVP_PKEY_RSA}; -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC static const int validlist2[] = {NID_sha256, EVP_PKEY_RSA, NID_sha512, EVP_PKEY_EC}; static const int validlist3[] = {NID_sha512, EVP_PKEY_EC}; -#endif +# endif static const int invalidlist1[] = {NID_undef, EVP_PKEY_RSA}; static const int invalidlist2[] = {NID_sha256, NID_undef}; static const int invalidlist3[] = {NID_sha256, EVP_PKEY_RSA, NID_sha256}; static const int invalidlist4[] = {NID_sha256}; static const sigalgs_list testsigalgs[] = { {validlist1, OSSL_NELEM(validlist1), NULL, 1, 1}, -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC {validlist2, OSSL_NELEM(validlist2), NULL, 1, 1}, {validlist3, OSSL_NELEM(validlist3), NULL, 1, 0}, -#endif +# endif {NULL, 0, "RSA+SHA256", 1, 1}, -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC {NULL, 0, "RSA+SHA256:ECDSA+SHA512", 1, 1}, {NULL, 0, "ECDSA+SHA512", 1, 0}, -#endif +# endif {invalidlist1, OSSL_NELEM(invalidlist1), NULL, 0, 0}, {invalidlist2, OSSL_NELEM(invalidlist2), NULL, 0, 0}, {invalidlist3, OSSL_NELEM(invalidlist3), NULL, 0, 0}, @@ -1401,6 +1404,7 @@ static int test_set_sigalgs(int idx) return testresult; } +#endif #ifndef OPENSSL_NO_TLS1_3 @@ -1488,7 +1492,11 @@ static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, { if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), sctx, - cctx, cert, privkey))) + cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_max_early_data(*sctx, + SSL3_RT_MAX_PLAIN_LENGTH)) + || !TEST_true(SSL_CTX_set_max_early_data(*cctx, + SSL3_RT_MAX_PLAIN_LENGTH))) return 0; if (idx == 1) { @@ -1819,7 +1827,7 @@ static int early_data_skip_helper(int hrr, int idx) * time. It could be any value as long as it is not within tolerance. * This should mean the ticket is rejected. */ - if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL) - 20))) + if (!TEST_true(SSL_SESSION_set_time(sess, (long)(time(NULL) - 20)))) goto end; } @@ -1961,13 +1969,11 @@ static int test_early_data_not_sent(int idx) return testresult; } -static const char *servhostname; - static int hostname_cb(SSL *s, int *al, void *arg) { const char *hostname = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); - if (hostname != NULL && strcmp(hostname, servhostname) == 0) + if (hostname != NULL && strcmp(hostname, "goodhost") == 0) return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_NOACK; @@ -1984,7 +1990,7 @@ static int alpn_select_cb(SSL *ssl, const unsigned char **out, for (prot = in; prot < in + inlen; prot += protlen) { protlen = *prot++; - if (in + inlen - prot < protlen) + if (in + inlen < prot + protlen) return SSL_TLSEXT_ERR_NOACK; if (protlen == strlen(servalpn) @@ -2024,7 +2030,6 @@ static int test_early_data_psk(int idx) &serverssl, &sess, 2))) goto end; - servhostname = "goodhost"; servalpn = "goodalpn"; /* @@ -2069,7 +2074,11 @@ static int test_early_data_psk(int idx) * Set inconsistent SNI (server detected). In this case the connection * will succeed but reject early_data. */ - servhostname = "badhost"; + SSL_SESSION_free(serverpsk); + serverpsk = SSL_SESSION_dup(clientpsk); + if (!TEST_ptr(serverpsk) + || !TEST_true(SSL_SESSION_set1_hostname(serverpsk, "badhost"))) + goto end; edstatus = SSL_EARLY_DATA_REJECTED; readearlyres = SSL_READ_EARLY_DATA_FINISH; /* Fall through */ @@ -2331,6 +2340,7 @@ static int test_ciphersuite_change(void) SSL_free(clientssl); serverssl = clientssl = NULL; +# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) /* Check we can resume a session with a different SHA-256 ciphersuite */ if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "TLS13-CHACHA20-POLY1305-SHA256")) @@ -2349,6 +2359,7 @@ static int test_ciphersuite_change(void) SSL_free(serverssl); SSL_free(clientssl); serverssl = clientssl = NULL; +# endif /* * Check attempting to resume a SHA-256 session with no SHA-256 ciphersuites @@ -2551,6 +2562,95 @@ static int test_tls13_psk(void) return testresult; } +static unsigned char cookie_magic_value[] = "cookie magic"; + +static int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + /* + * Not suitable as a real cookie generation function but good enough for + * testing! + */ + memcpy(cookie, cookie_magic_value, sizeof(cookie_magic_value) - 1); + *cookie_len = sizeof(cookie_magic_value) - 1; + + return 1; +} + +static int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + if (cookie_len == sizeof(cookie_magic_value) - 1 + && memcmp(cookie, cookie_magic_value, cookie_len) == 0) + return 1; + + return 0; +} + +static int test_stateless(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), &sctx, + &cctx, cert, privkey))) + goto end; + + /* Set up the cookie generation and verification callbacks */ + SSL_CTX_set_cookie_generate_cb(sctx, generate_cookie_callback); + SSL_CTX_set_cookie_verify_cb(sctx, verify_cookie_callback); + + /* The arrival of CCS messages can confuse the test */ + SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + /* Send the first ClientHello */ + || !TEST_false(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_WANT_READ)) + /* This should fail because there is no cookie */ + || !TEST_false(SSL_stateless(serverssl))) + goto end; + + /* Abandon the connection from this client */ + SSL_free(clientssl); + clientssl = NULL; + + /* + * Now create a connection from a new client but with the same server SSL + * object + */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + /* Send the first ClientHello */ + || !TEST_false(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_WANT_READ)) + /* This should fail because there is no cookie */ + || !TEST_false(SSL_stateless(serverssl)) + /* Send the second ClientHello */ + || !TEST_false(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_WANT_READ)) + /* This should succeed because a cookie is now present */ + || !TEST_true(SSL_stateless(serverssl)) + /* Complete the connection */ + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + shutdown_ssl_connection(serverssl, clientssl); + serverssl = clientssl = NULL; + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; + +} #endif /* OPENSSL_NO_TLS1_3 */ static int clntaddoldcb = 0; @@ -2686,6 +2786,12 @@ static int test_custom_exts(int tst) SSL_SESSION *sess = NULL; unsigned int context; +#if defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_3) + /* Skip tests for TLSv1.2 and below in this case */ + if (tst < 3) + return 1; +#endif + /* Reset callback counters */ clntaddoldcb = clntparseoldcb = srvaddoldcb = srvparseoldcb = 0; clntaddnewcb = clntparsenewcb = srvaddnewcb = srvparsenewcb = 0; @@ -3055,6 +3161,86 @@ static int test_export_key_mat(int tst) return testresult; } +#ifndef OPENSSL_NO_TLS1_3 +/* + * Test that SSL_export_keying_material_early() produces expected + * results. There are no test vectors so all we do is test that both + * sides of the communication produce the same results for different + * protocol versions. + */ +static int test_export_key_mat_early(int idx) +{ + static const char label[] = "test label"; + static const unsigned char context[] = "context"; + int testresult = 0; + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + SSL_SESSION *sess = NULL; + const unsigned char *emptycontext = NULL; + unsigned char ckeymat1[80], ckeymat2[80]; + unsigned char skeymat1[80], skeymat2[80]; + unsigned char buf[1]; + size_t readbytes, written; + + if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, + &sess, idx))) + goto end; + + /* Here writing 0 length early data is enough. */ + if (!TEST_true(SSL_write_early_data(clientssl, NULL, 0, &written)) + || !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_ERROR) + || !TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_ACCEPTED)) + goto end; + + if (!TEST_int_eq(SSL_export_keying_material_early( + clientssl, ckeymat1, sizeof(ckeymat1), label, + sizeof(label) - 1, context, sizeof(context) - 1), 1) + || !TEST_int_eq(SSL_export_keying_material_early( + clientssl, ckeymat2, sizeof(ckeymat2), label, + sizeof(label) - 1, emptycontext, 0), 1) + || !TEST_int_eq(SSL_export_keying_material_early( + serverssl, skeymat1, sizeof(skeymat1), label, + sizeof(label) - 1, context, sizeof(context) - 1), 1) + || !TEST_int_eq(SSL_export_keying_material_early( + serverssl, skeymat2, sizeof(skeymat2), label, + sizeof(label) - 1, emptycontext, 0), 1) + /* + * Check that both sides created the same key material with the + * same context. + */ + || !TEST_mem_eq(ckeymat1, sizeof(ckeymat1), skeymat1, + sizeof(skeymat1)) + /* + * Check that both sides created the same key material with an + * empty context. + */ + || !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), skeymat2, + sizeof(skeymat2)) + /* Different contexts should produce different results */ + || !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2, + sizeof(ckeymat2))) + goto end; + + testresult = 1; + + end: + if (sess != clientpsk) + SSL_SESSION_free(sess); + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} +#endif /* OPENSSL_NO_TLS1_3 */ + static int test_ssl_clear(int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; @@ -3216,6 +3402,65 @@ end: return testresult; } +#ifndef OPENSSL_NO_TLS1_3 +static int test_pha_key_update(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + &sctx, &cctx, cert, privkey))) + return 0; + + if (!TEST_true(SSL_CTX_set_min_proto_version(sctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_max_proto_version(sctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_min_proto_version(cctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_3_VERSION))) + goto end; + + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + SSL_force_post_handshake_auth(clientssl); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_set_verify(serverssl, SSL_VERIFY_PEER, NULL); + if (!TEST_true(SSL_verify_client_post_handshake(serverssl))) + goto end; + + if (!TEST_true(SSL_key_update(clientssl, SSL_KEY_UPDATE_NOT_REQUESTED))) + goto end; + + /* Start handshake on the server */ + if (!TEST_int_eq(SSL_do_handshake(serverssl), 1)) + goto end; + + /* Starts with SSL_connect(), but it's really just SSL_do_handshake() */ + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; +} +#endif + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) @@ -3238,8 +3483,10 @@ int setup_tests(void) ADD_TEST(test_ssl_bio_pop_ssl_bio); ADD_TEST(test_ssl_bio_change_rbio); ADD_TEST(test_ssl_bio_change_wbio); +#if !defined(OPENSSL_NO_TLS1_2) || defined(OPENSSL_NO_TLS1_3) ADD_ALL_TESTS(test_set_sigalgs, OSSL_NELEM(testsigalgs) * 2); ADD_TEST(test_keylog); +#endif #ifndef OPENSSL_NO_TLS1_3 ADD_TEST(test_keylog_no_master_key); #endif @@ -3261,11 +3508,16 @@ int setup_tests(void) ADD_TEST(test_ciphersuite_change); ADD_TEST(test_tls13_psk); ADD_ALL_TESTS(test_custom_exts, 5); + ADD_TEST(test_stateless); + ADD_TEST(test_pha_key_update); #else ADD_ALL_TESTS(test_custom_exts, 3); #endif ADD_ALL_TESTS(test_serverinfo, 8); ADD_ALL_TESTS(test_export_key_mat, 4); +#ifndef OPENSSL_NO_TLS1_3 + ADD_ALL_TESTS(test_export_key_mat_early, 3); +#endif ADD_ALL_TESTS(test_ssl_clear, 2); ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test)); return 1;