diff --git a/src/dtls.c b/src/dtls.c index d25f66bd01..dff1ffab3a 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -732,8 +732,13 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Ask the user for the ciphersuite matching this identity */ if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, - tlsx.elements, (word16)tlsx.size, ssl->heap) == 0) + tlsx.elements, (word16)tlsx.size, ssl->heap) == 0) { + /* suites only needs to be refined when searching for a PSK. + * MatchSuite_ex handles refining internally. */ + refineSuites(WOLFSSL_SUITES(ssl), &suites, &suites, + ssl->options.useClientOrder); FindPskSuiteFromExt(ssl, parsedExts, &pskInfo, &suites); + } /* Revert to full handshake if PSK parsing failed */ if (pskInfo.isValid) { @@ -753,8 +758,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); doKE = 1; } - else if ((modes & (1 << PSK_KE)) == 0) { - ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + else if ((modes & (1 << PSK_KE)) == 0 || + ssl->options.onlyPskDheKe) { + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); } usePSK = 1; } diff --git a/src/internal.c b/src/internal.c index e587982039..a8d602a479 100644 --- a/src/internal.c +++ b/src/internal.c @@ -37424,6 +37424,74 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return 1; } + void refineSuites(const Suites* sslSuites, const Suites* peerSuites, + Suites* outSuites, byte useClientOrder) + { + byte suites[WOLFSSL_MAX_SUITE_SZ]; + word16 suiteSz = 0; + word16 i; + word16 j; + + XMEMSET(suites, 0, sizeof(suites)); + + if (!useClientOrder) { + /* Server order refining. */ + for (i = 0; i < sslSuites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + if ((sslSuites->suites[i+0] == peerSuites->suites[j+0]) && + (sslSuites->suites[i+1] == peerSuites->suites[j+1])) { + suites[suiteSz++] = peerSuites->suites[j+0]; + suites[suiteSz++] = peerSuites->suites[j+1]; + break; + } + } + if (suiteSz == WOLFSSL_MAX_SUITE_SZ) + break; + } + } + else { + /* Client order refining. */ + for (j = 0; j < peerSuites->suiteSz; j += 2) { + for (i = 0; i < sslSuites->suiteSz; i += 2) { + if ((sslSuites->suites[i+0] == peerSuites->suites[j+0]) && + (sslSuites->suites[i+1] == peerSuites->suites[j+1])) { + suites[suiteSz++] = peerSuites->suites[j+0]; + suites[suiteSz++] = peerSuites->suites[j+1]; + break; + } + } + if (suiteSz == WOLFSSL_MAX_SUITE_SZ) + break; + } + } + + outSuites->suiteSz = suiteSz; + XMEMCPY(outSuites->suites, &suites, sizeof(suites)); + #ifdef WOLFSSL_DEBUG_TLS + { + int ii; + WOLFSSL_MSG("Refined Ciphers:"); + for (ii = 0 ; ii < suites->suiteSz; ii += 2) { + WOLFSSL_MSG(GetCipherNameInternal(suites->suites[ii+0], + suites->suites[ii+1])); + } + } + #endif + } + + /* Refine list of supported cipher suites to those common to server and client. + * + * ssl SSL/TLS object. + * peerSuites The peer's advertised list of supported cipher suites. + */ + void sslRefineSuites(WOLFSSL* ssl, Suites* peerSuites) + { + if (AllocateSuites(ssl) != 0) + return; + refineSuites(ssl->suites, peerSuites, ssl->suites, + (byte)ssl->options.useClientOrder); + } + static int CompareSuites(const WOLFSSL* ssl, const Suites* suites, Suites* peerSuites, word16 i, word16 j, CipherSuite* cs, TLSX* extensions) diff --git a/src/tls13.c b/src/tls13.c index 5f4c8697a5..c528363a4c 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5253,6 +5253,18 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Set the cipher suite from the message. */ ssl->options.cipherSuite0 = input[args->idx++]; ssl->options.cipherSuite = input[args->idx++]; + if (*extMsgType == hello_retry_request) { + ssl->options.hrrCipherSuite0 = ssl->options.cipherSuite0; + ssl->options.hrrCipherSuite = ssl->options.cipherSuite; + } + else if (ssl->msgsReceived.got_hello_retry_request && + (ssl->options.hrrCipherSuite0 != ssl->options.cipherSuite0 || + ssl->options.hrrCipherSuite != ssl->options.cipherSuite)) { + WOLFSSL_MSG("Received ServerHello with different cipher suite than " + "HelloRetryRequest"); + WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER); + return INVALID_PARAMETER; + } #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Chosen cipher suite:"); WOLFSSL_MSG(GetCipherNameInternal(ssl->options.cipherSuite0, @@ -5875,69 +5887,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, #ifndef NO_WOLFSSL_SERVER #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) -/* Refine list of supported cipher suites to those common to server and client. - * - * ssl SSL/TLS object. - * peerSuites The peer's advertised list of supported cipher suites. - */ -static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) -{ - byte suites[WOLFSSL_MAX_SUITE_SZ]; - word16 suiteSz = 0; - word16 i; - word16 j; - - if (AllocateSuites(ssl) != 0) - return; - - XMEMSET(suites, 0, sizeof(suites)); - - if (!ssl->options.useClientOrder) { - /* Server order refining. */ - for (i = 0; i < ssl->suites->suiteSz; i += 2) { - for (j = 0; j < peerSuites->suiteSz; j += 2) { - if ((ssl->suites->suites[i+0] == peerSuites->suites[j+0]) && - (ssl->suites->suites[i+1] == peerSuites->suites[j+1])) { - suites[suiteSz++] = peerSuites->suites[j+0]; - suites[suiteSz++] = peerSuites->suites[j+1]; - break; - } - } - if (suiteSz == WOLFSSL_MAX_SUITE_SZ) - break; - } - } - else { - /* Client order refining. */ - for (j = 0; j < peerSuites->suiteSz; j += 2) { - for (i = 0; i < ssl->suites->suiteSz; i += 2) { - if ((ssl->suites->suites[i+0] == peerSuites->suites[j+0]) && - (ssl->suites->suites[i+1] == peerSuites->suites[j+1])) { - suites[suiteSz++] = peerSuites->suites[j+0]; - suites[suiteSz++] = peerSuites->suites[j+1]; - break; - } - } - if (suiteSz == WOLFSSL_MAX_SUITE_SZ) - break; - } - } - - ssl->suites->suiteSz = suiteSz; - XMEMCPY(ssl->suites->suites, &suites, sizeof(suites)); -#ifdef WOLFSSL_DEBUG_TLS - { - int ii; - WOLFSSL_MSG("Refined Ciphers:"); - for (ii = 0 ; ii < ssl->suites->suiteSz; ii += 2) { - WOLFSSL_MSG(GetCipherNameInternal(ssl->suites->suites[ii+0], - ssl->suites->suites[ii+1])); - } - } -#endif -} - - #ifndef NO_PSK int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, word32* psk_keySz, const byte* suite, int* found, byte* foundSuite) @@ -6310,7 +6259,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, return ret; /* Refine list for PSK processing. */ - RefineSuites(ssl, clSuites); + sslRefineSuites(ssl, clSuites); #ifndef WOLFSSL_PSK_ONE_ID if (usingPSK == NULL) return BAD_FUNC_ARG; diff --git a/tests/api.c b/tests/api.c index 02a8a3d8d5..f0090c183e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -48134,9 +48134,8 @@ static int test_TLSX_CA_NAMES_bad_extension(void) EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \ !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) && \ - defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA384) && \ - defined(HAVE_NULL_CIPHER) && defined(HAVE_CHACHA) && \ - defined(HAVE_POLY1305) + defined(OPENSSL_EXTRA) && defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) && \ + defined(HAVE_ECC) && !defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) /* This test should only fail (with BUFFER_ERROR) when we actually try to * parse the CA Names extension. Otherwise it will return other non-related * errors. If CA Names will be parsed in more configurations, that should @@ -48144,7 +48143,7 @@ static int test_TLSX_CA_NAMES_bad_extension(void) WOLFSSL *ssl_c = NULL; WOLFSSL_CTX *ctx_c = NULL; struct test_memio_ctx test_ctx; - /* HRR + SH using TLS_DHE_PSK_WITH_NULL_SHA384 */ + /* HRR + SH using TLS_CHACHA20_POLY1305_SHA256 */ const byte shBadCaNamesExt[] = { 0x16, 0x03, 0x04, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, @@ -48155,7 +48154,7 @@ static int test_TLSX_CA_NAMES_bad_extension(void) 0x5c, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0x03, 0xcf, 0x21, 0xad, 0x74, 0x00, 0x00, 0x83, 0x3f, 0x3b, 0x80, 0x01, 0xac, 0x65, 0x8c, 0x19, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x02, 0x00, 0x9e, 0x09, 0x1c, 0xe8, - 0xa8, 0x09, 0x9c, 0x00, 0xc0, 0xb5, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, + 0xa8, 0x09, 0x9c, 0x00, 0x13, 0x03, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x13, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0d, 0x00, 0x2f, 0x00, 0x01, 0xff, @@ -48171,7 +48170,7 @@ static int test_TLSX_CA_NAMES_bad_extension(void) 0x5e, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0x7f, 0xd0, 0x2d, 0xea, 0x6e, 0x53, 0xa1, 0x6a, 0xc9, 0xc8, 0x54, 0xef, 0x75, 0xe4, 0xd9, 0xc6, 0x3e, 0x74, 0xcb, 0x30, 0x80, 0xcc, 0x83, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x5a, 0x00, 0xc0, 0xb5, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, + 0x00, 0xc0, 0x5a, 0x00, 0x13, 0x03, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x53, 0x25, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x04, 0x02, 0x05, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0d, 0x00, 0x2f, 0x00, 0x06, 0x00, diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index e0aa9d7345..ab4398ddad 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -2224,3 +2224,96 @@ int test_tls13_same_ch(void) #endif return EXPECT_RESULT(); } + +int test_tls13_hrr_different_cs(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(WOLFSSL_TLS13) && \ + defined(BUILD_TLS_AES_256_GCM_SHA384) && \ + defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) && \ + defined(HAVE_ECC) && defined(HAVE_ECC384) + /* + * TLSv1.3 Record Layer: Handshake Protocol: Hello Retry Request + * Content Type: Handshake (22) + * Version: TLS 1.2 (0x0303) + * Length: 56 + * Handshake Protocol: Hello Retry Request + * Handshake Type: Server Hello (2) + * Length: 52 + * Version: TLS 1.2 (0x0303) + * Random: cf21ad74e59a6111be1d8c021e65b891c2a211167abb8c5e079e09e2c8a8339c (HelloRetryRequest magic) + * Session ID Length: 0 + * Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302) + * Compression Method: null (0) + * Extensions Length: 12 + * Extension: supported_versions (len=2) TLS 1.3 + * Extension: key_share (len=2) secp384r1 + * + */ + unsigned char hrr[] = { + 0x16, 0x03, 0x03, 0x00, 0x38, 0x02, 0x00, 0x00, 0x34, 0x03, 0x03, 0xcf, + 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, + 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, + 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, 0x00, 0x13, 0x02, 0x00, 0x00, + 0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x18 + }; + /* + * TLSv1.3 Record Layer: Handshake Protocol: Server Hello + * Content Type: Handshake (22) + * Version: TLS 1.2 (0x0303) + * Length: 155 + * Handshake Protocol: Server Hello + * Handshake Type: Server Hello (2) + * Length: 151 + * Version: TLS 1.2 (0x0303) + * Random: 0101010101010101010101010101010101010101010101010101010101010101 + * Session ID Length: 0 + * Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303) + * Compression Method: null (0) + * Extensions Length: 111 + * Extension: key_share (len=101) secp384r1 + * Extension: supported_versions (len=2) TLS 1.3 + * + */ + unsigned char sh[] = { + 0x16, 0x03, 0x03, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x97, 0x03, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x13, 0x03, 0x00, 0x00, + 0x6f, 0x00, 0x33, 0x00, 0x65, 0x00, 0x18, 0x00, 0x61, 0x04, 0x53, 0x3e, + 0xe5, 0xbf, 0x40, 0xec, 0x2d, 0x67, 0x98, 0x8b, 0x77, 0xf3, 0x17, 0x48, + 0x9b, 0xb6, 0xdf, 0x95, 0x29, 0x25, 0xc7, 0x09, 0xfc, 0x03, 0x81, 0x11, + 0x1a, 0x59, 0x56, 0xf2, 0xd7, 0x58, 0x11, 0x0e, 0x59, 0xd3, 0xd7, 0xc1, + 0x72, 0x9e, 0x2c, 0x0d, 0x70, 0xea, 0xf7, 0x73, 0xe6, 0x12, 0x01, 0x16, + 0x42, 0x6d, 0xe2, 0x43, 0x6a, 0x2f, 0x5f, 0xdd, 0x7f, 0xe5, 0x4f, 0xaf, + 0x95, 0x2b, 0x04, 0xfd, 0x13, 0xf5, 0x16, 0xce, 0x62, 0x7f, 0x89, 0xd2, + 0x01, 0x9d, 0x4c, 0x87, 0x96, 0x95, 0x9e, 0x43, 0x33, 0xc7, 0x06, 0x5b, + 0x49, 0x6c, 0xa6, 0x34, 0xd5, 0xdc, 0x63, 0xbd, 0xe9, 0x1f, 0x00, 0x2b, + 0x00, 0x02, 0x03, 0x04 + }; + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL *ssl_c = NULL; + struct test_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, + wolfTLSv1_3_client_method, NULL), 0); + + ExpectIntEQ(wolfSSL_connect(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (char*)hrr, + sizeof(hrr)), 0); + ExpectIntEQ(wolfSSL_connect(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (char*)sh, + sizeof(sh)), 0); + ExpectIntEQ(wolfSSL_connect(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), INVALID_PARAMETER); + + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_c); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_tls13.h b/tests/api/test_tls13.h index fb46c404dd..42a19073b8 100644 --- a/tests/api/test_tls13.h +++ b/tests/api/test_tls13.h @@ -31,6 +31,7 @@ int test_tls13_rpk_handshake(void); int test_tls13_pq_groups(void); int test_tls13_early_data(void); int test_tls13_same_ch(void); +int test_tls13_hrr_different_cs(void); #define TEST_TLS13_DECLS \ TEST_DECL_GROUP("tls13", test_tls13_apis), \ @@ -39,6 +40,7 @@ int test_tls13_same_ch(void); TEST_DECL_GROUP("tls13", test_tls13_rpk_handshake), \ TEST_DECL_GROUP("tls13", test_tls13_pq_groups), \ TEST_DECL_GROUP("tls13", test_tls13_early_data), \ - TEST_DECL_GROUP("tls13", test_tls13_same_ch) + TEST_DECL_GROUP("tls13", test_tls13_same_ch), \ + TEST_DECL_GROUP("tls13", test_tls13_hrr_different_cs) #endif /* WOLFCRYPT_TEST_TLS13_H */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e88cc6e744..eb41159928 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2383,6 +2383,10 @@ WOLFSSL_LOCAL void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveAES128, word16 haveSHA1, word16 haveRC4, int side); +void refineSuites(const Suites* sslSuites, const Suites* peerSuites, + Suites* outSuites, byte useClientOrder); +void sslRefineSuites(WOLFSSL* ssl, Suites* peerSuites); + typedef struct TLSX TLSX; WOLFSSL_LOCAL int MatchSuite_ex(const WOLFSSL* ssl, Suites* peerSuites, CipherSuite* cs, TLSX* extensions); @@ -5100,6 +5104,10 @@ struct Options { byte processReply; /* nonblocking resume */ byte cipherSuite0; /* first byte, normally 0 */ byte cipherSuite; /* second byte, actual suite */ +#ifdef WOLFSSL_TLS13 + byte hrrCipherSuite0; /* first byte, normally 0 */ + byte hrrCipherSuite; /* second byte, actual suite */ +#endif byte hashAlgo; /* selected hash algorithm */ byte sigAlgo; /* selected sig algorithm */ byte peerHashAlgo; /* peer's chosen hash algo */