From 94157634e1d48c66fddb5a65a4ceecbdb635a7ae Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 13 Apr 2018 11:53:42 +1000 Subject: [PATCH] TLS 1.3 fixes/improvements Support Draft 28: able to compile code to return BAD_BINDER if no PSKs match and certificates not to be used. Change key share implementation to use server preference - server now checks each client key share's group is in supported_groups extension. Client and server examples modified to support server preference. Application can set client's and server's supported groups by rank. Server's supported groups is sent back in encrypted_extensions if preferred group is not in client's list - able to be turned off at compile time. Application can query server's preferred group from client. Able to compile using 0x0304 as version instead of draft version. Fix state machine in TLS 1.3 to support unexpected hello_retry_request. Also fixes non-blocking. Fix resumption to use the named group from session. Fix named group in session structure to be a 2-byte field. Better detection of errors in message flow. Fix DoTls13ClientHello when downgrading - don't do TLS 1.3 things. Not downgrading on client fixed. Downgrade protocol version from TLS 1.3 when not TLS 1.3 ciphersuite. Get downgrading from TLS 1.3 and resumption working. Change earlyData value to an enum. Support no extensions data (as opposed to zero length extension data) in TLS 1.3 ClientHello. Check PSK cipher suite is available to both client and server before using. Check first PSK identity chosen when server says it is using early data at client. Check PSK extension is last in client_hello on server. Check the PSK cipher suite to use is supported on client. Check the returned cipher suite for pre-shared keys is the same as client expects. Send alert decrypt_error when verification fails in certificate_verify or finished message doesn't match calculated value. Fail when certificate messages recieved in handshake when using PSK. Validate on the server that EndOfEarlyData message has been recieved before finished message when server sent EarlyData extension. --- examples/client/client.c | 140 +++--- examples/server/server.c | 29 +- scripts/tls13.test | 65 +++ src/internal.c | 279 ++++++----- src/ssl.c | 21 +- src/tls.c | 856 ++++++++++++++++++++++----------- src/tls13.c | 960 +++++++++++++++++++++++++++----------- tests/api.c | 34 ++ tests/test-tls13-ecc.conf | 22 +- tests/test-tls13.conf | 8 +- wolfssl/internal.h | 46 +- wolfssl/ssl.h | 18 +- 12 files changed, 1713 insertions(+), 765 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index d5bc0d544..c637fcc07 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -189,6 +189,50 @@ static void ShowVersions(void) printf("\n"); } +#ifdef WOLFSSL_TLS13 +static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519) +{ + (void)useX25519; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + if (onlyKeyShare == 0 || onlyKeyShare == 2) { + #ifdef HAVE_CURVE25519 + if (useX25519) { + int groups[1] = { WOLFSSL_ECC_X25519 }; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) + err_sys("unable to use curve x25519"); + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) + err_sys("unable to set groups: x25519"); + } + else + #endif + { + #ifdef HAVE_ECC + #if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES) + int groups[1] = { WOLFSSL_ECC_SECP256R1 }; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) + err_sys("unable to set groups: secp256r1"); + #endif + #endif + } + } + if (onlyKeyShare == 0 || onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + int groups[1] = { WOLFSSL_FFDHE_2048 }; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) + err_sys("unable to use DH 2048-bit parameters"); + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) + err_sys("unable to set groups: DH 2048-bit"); + #endif + } + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); +} +#endif + /* Measures average time to create, connect and disconnect a connection (TPS). Benchmark = number of connections. */ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, @@ -230,55 +274,21 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (ssl == NULL) err_sys("unable to get SSL object"); + #ifndef NO_SESSION_CACHE + if (benchResume) + wolfSSL_set_session(ssl, benchSession); + #endif #ifdef WOLFSSL_TLS13 - if (version >= 4) { - if (!helloRetry) { - WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); - if (onlyKeyShare == 0 || onlyKeyShare == 2) { - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - else - #endif - #ifdef HAVE_ECC - #if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES) - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - else - #endif - #endif - { - } - } - if (onlyKeyShare == 0 || onlyKeyShare == 1) { - #ifdef HAVE_FFDHE_2048 - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) - != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - #endif - } - WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); - } - else { + else if (version >= 4) { + if (!helloRetry) + SetKeyShare(ssl, onlyKeyShare, useX25519); + else wolfSSL_NoKeyShares(ssl); - } } #endif tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); - #ifndef NO_SESSION_CACHE - if (benchResume) - wolfSSL_set_session(ssl, benchSession); - #endif - if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { err_sys("error in setting fd"); } @@ -1198,7 +1208,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_MAX_FRAGMENT maxFragment = atoi(myoptarg); if (maxFragment < WOLFSSL_MFL_2_9 || - maxFragment > WOLFSSL_MFL_2_13) { + maxFragment > WOLFSSL_MFL_2_13) { Usage(); exit(MY_EX_USAGE); } @@ -1801,6 +1811,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) != WOLFSSL_SUCCESS) { err_sys("unable to support secp256r1"); } + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP384R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to support secp384r1"); + } } #endif /* HAVE_CURVE25519 && HAVE_SUPPORTED_CURVES */ @@ -1893,7 +1907,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_CURVE25519 if (useX25519) { if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { + != WOLFSSL_SUCCESS) { err_sys("unable to use curve x25519"); } } @@ -1901,13 +1915,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_ECC #if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES) if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { + != WOLFSSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP384R1) - != WOLFSSL_SUCCESS) { + != WOLFSSL_SUCCESS) { err_sys("unable to use curve secp384r1"); } #endif @@ -2310,38 +2324,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void*)"resumed session"); #endif -#ifdef WOLFSSL_TLS13 - if (!helloRetry) { - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - #endif - #ifdef HAVE_ECC - if (wolfSSL_UseKeyShare(sslResume, - WOLFSSL_ECC_SECP256R1) != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) - if (wolfSSL_UseKeyShare(sslResume, - WOLFSSL_ECC_SECP384R1) != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp384r1"); - } - #endif - #endif - #ifdef HAVE_FFDHE_2048 - if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - #endif - } - else { - wolfSSL_NoKeyShares(ssl); - } -#endif - #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { wolfSSL_set_using_nonblock(sslResume, 1); @@ -2420,7 +2402,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #else timeout.tv_sec = DEFAULT_TIMEOUT_SEC; timeout.tv_usec = 0; - ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + ret = NonBlockingSSL_Connect(sslResume); /* will keep retrying on timeout */ #endif if (ret != WOLFSSL_SUCCESS) { printf("wolfSSL_connect resume error %d, %s\n", err, diff --git a/examples/server/server.c b/examples/server/server.c index 896d4760a..36673be01 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1206,10 +1206,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_TLS13 - if (noPskDheKe) - wolfSSL_CTX_no_dhe_psk(ctx); - if (noTicket) - wolfSSL_CTX_no_ticket_TLSv13(ctx); + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); + if (noTicket) + wolfSSL_CTX_no_ticket_TLSv13(ctx); #endif while (1) { @@ -1337,30 +1337,45 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (onlyKeyShare == 2) { if (useX25519 == 1) { #ifdef HAVE_CURVE25519 + int groups[1] = { WOLFSSL_ECC_X25519 }; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) { err_sys("unable to use curve x25519"); } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: x25519"); + } #endif } else { #ifdef HAVE_ECC #if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES) - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + int groups[1] = { WOLFSSL_ECC_SECP256R1 }; + + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } + err_sys("unable to use curve secp256r1"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: secp256r1"); + } #endif #endif } } else if (onlyKeyShare == 1) { #ifdef HAVE_FFDHE_2048 + int groups[1] = { WOLFSSL_FFDHE_2048 }; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) { err_sys("unable to use DH 2048-bit parameters"); } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: DH 2048-bit"); + } #endif } WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); diff --git a/scripts/tls13.test b/scripts/tls13.test index 4136c85e4..847b2626f 100755 --- a/scripts/tls13.test +++ b/scripts/tls13.test @@ -421,6 +421,71 @@ if [ $RESULT -ne 0 ]; then fi echo "" +# TLS Downgrade server / TLS Downgrade client. +echo -e "\n\nTLS server and client able to downgrade but don't" +port=0 +./examples/server/server -v d -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v d -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS not downgrading" + do_cleanup + exit 1 +fi +echo "" + +# TLS Downgrade server / TLS Downgrade client resumption. +echo -e "\n\nTLS server and client able to downgrade but don't and resume" +port=0 +./examples/server/server -v d -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v d -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS not downgrading and resumption" + do_cleanup + exit 1 +fi +echo "" + +# TLS Downgrade server / TLS 1.2 client and resume. +echo -e "\n\nTLS server downgrade and resume" +port=0 +./examples/server/server -v d -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 3 -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS server downgrading and resumption" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.2 server / TLS downgrade client and resume. +echo -e "\n\nTLS client downgrade and resume" +port=0 +./examples/server/server -v 3 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v d -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS client downgrading and resumption" + do_cleanup + exit 1 +fi +echo "" + +# TLS Downgrade server / TLS Downgrade client. # TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data. echo -e "\n\nTLS v1.3 KeyUpdate" port=0 diff --git a/src/internal.c b/src/internal.c index c96189994..3607bcd02 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4458,6 +4458,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) ssl->options.postHandshakeAuth = ctx->postHandshakeAuth; #endif + + if (ctx->numGroups > 0) { + XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups); + ssl->numGroups = ctx->numGroups; + } #endif #ifdef HAVE_TLS_EXTENSIONS @@ -9374,10 +9379,6 @@ exit_ppc: ssl->nonblockarg = NULL; #endif -#ifdef OPENSSL_EXTRA - ssl->options.serverState = SERVER_CERT_COMPLETE; -#endif - FreeKeyExchange(ssl); return ret; @@ -9394,6 +9395,10 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = ProcessPeerCerts(ssl, input, inOutIdx, size); +#ifdef OPENSSL_EXTRA + ssl->options.serverState = SERVER_CERT_COMPLETE; +#endif + WOLFSSL_LEAVE("DoCertificateVerify", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); @@ -11938,7 +11943,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) #endif #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { } else #endif @@ -11963,7 +11968,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) return BUFFER_ERROR; } #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) { SendAlert(ssl, alert_fatal, unexpected_message); return WOLFSSL_FATAL_ERROR; @@ -12592,7 +12597,7 @@ int ProcessReply(WOLFSSL* ssl) if (ssl->options.side == WOLFSSL_SERVER_END && ssl->earlyData && ssl->options.handShakeState == HANDSHAKE_DONE) { - ssl->earlyData = 0; + ssl->earlyData = no_early_data; ssl->options.processReply = doProcessInit; return ZERO_RETURN; } @@ -14435,7 +14440,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if (ssl->options.handShakeState == HANDSHAKE_DONE) { WOLFSSL_MSG("handshake complete, trying to send early data"); return BUILD_MSG_ERROR; @@ -14599,7 +14604,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) } #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { } else #endif @@ -16833,31 +16838,26 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, #endif if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo && ssl->suites->sigAlgo == rsa_sa_algo)) { - if (hashAlgo == sha_mac) { - ssl->suites->sigAlgo = sigAlgo; - break; - } + switch (hashAlgo) { + case sha_mac: #ifndef NO_SHA256 - else if (hashAlgo == sha256_mac) { - ssl->suites->hashAlgo = sha256_mac; - ssl->suites->sigAlgo = sigAlgo; - break; - } + case sha256_mac: #endif #ifdef WOLFSSL_SHA384 - else if (hashAlgo == sha384_mac) { - ssl->suites->hashAlgo = sha384_mac; - ssl->suites->sigAlgo = sigAlgo; - break; - } + case sha384_mac: #endif #ifdef WOLFSSL_SHA512 - else if (hashAlgo == sha512_mac) { - ssl->suites->hashAlgo = sha512_mac; - ssl->suites->sigAlgo = sigAlgo; - break; - } + case sha512_mac: #endif + if (hashAlgo < ssl->suites->hashAlgo) + continue; + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + break; + default: + continue; + } + break; } else if (ssl->specs.sig_algo == 0) { ssl->suites->hashAlgo = ssl->specs.mac_algorithm; @@ -17383,6 +17383,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) { #ifdef WOLFSSL_TLS13 + #ifndef WOLFSSL_TLS13_FINAL /* TODO: [TLS13] Remove this. * Translate the draft TLS v1.3 version to final version. */ @@ -17390,6 +17391,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, pv.major = SSLv3_MAJOR; pv.minor = TLSv1_3_MINOR; } + #endif #endif #ifdef OPENSSL_EXTRA @@ -17520,38 +17522,43 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, return ret; #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(pv)) - return DoTls13ServerHello(ssl, input, inOutIdx, helloSz); + if (IsAtLeastTLSv1_3(pv)) { + byte type = server_hello; + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type); + } #endif /* random */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; + if (!ssl->options.resuming) { #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { - /* TLS v1.3 capable client not allowed to downgrade when connecting - * to TLS v1.3 capable server. - */ - if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), - tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable client not allowed to downgrade when + * connecting to TLS v1.3 capable server unless cipher suite + * demands it. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && (*(input + i - 1) == 0 || *(input + i - 1) == 1)) { - SendAlert(ssl, alert_fatal, illegal_parameter); - return VERSION_ERROR; + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } } - } - else + else #endif - if (ssl->ctx->method->version.major == SSLv3_MAJOR && + if (ssl->ctx->method->version.major == SSLv3_MAJOR && ssl->ctx->method->version.minor == TLSv1_2_MINOR) { - /* TLS v1.2 capable client not allowed to downgrade when connecting - * to TLS v1.2 capable server. - */ - if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), - tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + /* TLS v1.2 capable client not allowed to downgrade when + * connecting to TLS v1.2 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && *(input + i - 1) == 0) { - SendAlert(ssl, alert_fatal, illegal_parameter); - return VERSION_ERROR; + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } } } @@ -22963,7 +22970,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC) if (!TLSX_ValidateSupportedCurves(ssl, first, second)) { WOLFSSL_MSG("Don't have matching curves"); - return 0; + return 0; } #endif @@ -22976,7 +22983,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.haveQSH = 1; /* matched TLS_QSH */ } else { - WOLFSSL_MSG("Version of SSL connection does not support TLS_QSH"); + WOLFSSL_MSG("Version of SSL connection does not support " + "TLS_QSH"); } return 0; } @@ -22988,10 +22996,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Try to establish a key share. */ int ret = TLSX_KeyShare_Establish(ssl); if (ret == KEY_SHARE_ERROR) - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; else if (ret != 0) return 0; } + else if (first == TLS13_BYTE) { + /* Can't negotiate TLS 1.3 ciphersuites with lower protocol + * version. */ + return 0; + } #endif return 1; @@ -23267,6 +23280,76 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* OLD_HELLO_ALLOWED */ + int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites) + { + int ret = 0; + WOLFSSL_SESSION* session = GetSession(ssl, + ssl->arrays->masterSecret, 1); + + (void)bogusID; + + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket == 1) { + session = &ssl->session; + } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { + WOLFSSL_MSG("Bogus session ID without session ticket"); + return BUFFER_ERROR; + } + #endif + + if (!session) { + WOLFSSL_MSG("Session lookup for resume failed"); + ssl->options.resuming = 0; + } + else if (session->haveEMS != ssl->options.haveEMS) { + /* RFC 7627, 5.3, server-side */ + /* if old sess didn't have EMS, but new does, full handshake */ + if (!session->haveEMS && ssl->options.haveEMS) { + WOLFSSL_MSG("Attempting to resume a session that didn't " + "use EMS with a new session with EMS. Do full " + "handshake."); + ssl->options.resuming = 0; + } + /* if old sess used EMS, but new doesn't, MUST abort */ + else if (session->haveEMS && !ssl->options.haveEMS) { + WOLFSSL_MSG("Trying to resume a session with EMS without " + "using EMS"); + return EXT_MASTER_SECRET_NEEDED_E; + } + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + } + else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + if (MatchSuite(ssl, clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return UNSUPPORTED_SUITE; + } + + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, + RAN_LEN); + if (ret != 0) + return ret; + + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + + return ret; + } + /* handle processing of client_hello (1) */ int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, @@ -23331,6 +23414,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* WOLFSSL_DTLS */ i += OPAQUE16_LEN; + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR) + pv.minor = TLSv1_2_MINOR; + if ((!ssl->options.dtls && ssl->version.minor > pv.minor) || (ssl->options.dtls && ssl->version.minor != DTLS_MINOR && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR @@ -23643,10 +23730,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_QSH QSH_Init(ssl); #endif - if (TLSX_SupportExtensions(ssl)) { + if (TLSX_SupportExtensions(ssl)) #else - if (IsAtLeastTLSv1_2(ssl)) { + if (IsAtLeastTLSv1_2(ssl)) #endif + { /* Process the hello extension. Skip unsupported. */ word16 totalExtSz; @@ -23742,66 +23830,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* ProcessOld uses same resume code */ if (ssl->options.resuming) { - WOLFSSL_SESSION* session = GetSession(ssl, - ssl->arrays->masterSecret, 1); - #ifdef HAVE_SESSION_TICKET - if (ssl->options.useTicket == 1) { - session = &ssl->session; - } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { - WOLFSSL_MSG("Bogus session ID without session ticket"); - return BUFFER_ERROR; - } - #endif - - if (!session) { - WOLFSSL_MSG("Session lookup for resume failed"); - ssl->options.resuming = 0; - } - else if (session->haveEMS != ssl->options.haveEMS) { - /* RFC 7627, 5.3, server-side */ - /* if old sess didn't have EMS, but new does, full handshake */ - if (!session->haveEMS && ssl->options.haveEMS) { - WOLFSSL_MSG("Attempting to resume a session that didn't " - "use EMS with a new session with EMS. Do full " - "handshake."); - ssl->options.resuming = 0; - } - /* if old sess used EMS, but new doesn't, MUST abort */ - else if (session->haveEMS && !ssl->options.haveEMS) { - WOLFSSL_MSG("Trying to resume a session with EMS without " - "using EMS"); - return EXT_MASTER_SECRET_NEEDED_E; - } -#ifdef HAVE_EXT_CACHE - wolfSSL_SESSION_free(session); -#endif - } - else { -#ifdef HAVE_EXT_CACHE - wolfSSL_SESSION_free(session); -#endif - if (MatchSuite(ssl, &clSuites) < 0) { - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); - return UNSUPPORTED_SUITE; - } - - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, - RAN_LEN); - if (ret != 0) - return ret; - - #ifdef NO_OLD_TLS - ret = DeriveTlsKeys(ssl); - #else - #ifndef NO_TLS - if (ssl->options.tls) - ret = DeriveTlsKeys(ssl); - #endif - if (!ssl->options.tls) - ret = DeriveKeys(ssl); - #endif - ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; - + ret = HandleTlsResumption(ssl, bogusID, &clSuites); + if (ret != 0) + return ret; + if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) { WOLFSSL_LEAVE("DoClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); @@ -24227,7 +24259,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 haveEMS; /* have extended master secret */ #ifdef WOLFSSL_TLS13 word32 ageAdd; /* Obfuscation of age */ - byte namedGroup; /* Named group used */ + word16 namedGroup; /* Named group used */ #ifndef WOLFSSL_TLS13_DRAFT_18 TicketNonce ticketNonce; /* Ticket nonce */ #endif @@ -24278,7 +24310,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TLS13 /* Client adds to ticket age to obfuscate. */ ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd, - sizeof(it.ageAdd)); + sizeof(it.ageAdd)); if (ret != 0) return BAD_TICKET_ENCRYPT; ssl->session.ticketAdd = it.ageAdd; @@ -24387,6 +24419,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { + if (ssl->version.minor < it->pv.minor) { + WOLFSSL_MSG("Ticket has greater version"); + return VERSION_ERROR; + } + else if (ssl->version.minor > it->pv.minor) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Ticket has lesser version"); + return VERSION_ERROR; + } + + WOLFSSL_MSG("Downgrading protocol due to ticket"); + + if (it->pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = it->pv.minor; + } + if (!IsAtLeastTLSv1_3(ssl->version)) { XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); /* Copy the haveExtendedMasterSecret property from the ticket to diff --git a/src/ssl.c b/src/ssl.c index d410f7cf8..9cb763a17 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1599,11 +1599,11 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) return BAD_FUNC_ARG; #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData && (ret = wolfSSL_negotiate(ssl)) < 0) { + if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) { ssl->error = ret; return WOLFSSL_FATAL_ERROR; } - ssl->earlyData = 0; + ssl->earlyData = no_early_data; #endif #ifdef HAVE_WRITE_DUP @@ -8581,6 +8581,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* get response */ while (ssl->options.serverState < neededState) { + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; @@ -8635,13 +8639,14 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, /* get response */ while (ssl->options.serverState < neededState) { if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; } /* if resumption failed, reset needed state */ - else if (neededState == SERVER_FINISHED_COMPLETE) + if (neededState == SERVER_FINISHED_COMPLETE) { if (!ssl->options.resuming) neededState = SERVER_HELLODONE_COMPLETE; + } } } #endif @@ -9759,9 +9764,13 @@ int AddSession(WOLFSSL* ssl) session->cipherSuite = ssl->options.cipherSuite; } #endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) +#if defined(WOLFSSL_TLS13) if (error == 0) { session->namedGroup = ssl->session.namedGroup; + } +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (error == 0) { session->ticketSeen = ssl->session.ticketSeen; session->ticketAdd = ssl->session.ticketAdd; #ifndef WOLFSSL_TLS13_DRAFT_18 diff --git a/src/tls.c b/src/tls.c index ed36fe93b..05deb6b11 100755 --- a/src/tls.c +++ b/src/tls.c @@ -56,6 +56,11 @@ #endif #endif /* HAVE_QSH */ +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +static int TLSX_KeyShare_IsSupported(int namedGroup); +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions); +#endif #ifndef NO_TLS @@ -3092,7 +3097,8 @@ static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output) return offset; } -#ifndef NO_WOLFSSL_SERVER +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) @@ -3113,7 +3119,34 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != OPAQUE16_LEN + offset) return BUFFER_ERROR; - for (offset = OPAQUE16_LEN; offset < length; offset += OPAQUE16_LEN) { + offset = OPAQUE16_LEN; + if (offset == length) + return 0; + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + if (!isRequest) { + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) { + /* Replace client list with server list of supported groups. */ + curve = (SupportedCurve*)extension->data; + extension->data = NULL; + TLSX_SupportedCurve_FreeAll(curve, ssl->heap); + + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap); + if (ret != 0) + return ret; /* throw error */ + extension->data = (void*)curve; + } + } +#endif + + for (; offset < length; offset += OPAQUE16_LEN) { ato16(input + offset, &name); ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); @@ -3124,6 +3157,89 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } +#endif + +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + +/* Checks the priority of the groups on the server and set the supported groups + * response if there is a group not advertised by the client that is preferred. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl) +{ + int ret; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + word16 name; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + curve = (SupportedCurve*)ext->data; + name = curve->name; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (curve->name == name) + break; + curve = curve->next; + } + + if (curve == NULL) { + /* Couldn't find the preferred group in client list. */ + extension->resp = 1; + + /* Send server list back and free client list. */ + curve = (SupportedCurve*)extension->data; + extension->data = ext->data; + ext->data = curve; + } + + TLSX_FreeAll(priority, ssl->heap); + + return 0; +} + +/* Return the preferred group. + * + * ssl SSL/TLS object. + * checkSupported Whether to check for the first supported group. + * returns BAD_FUNC_ARG if no group found, otherwise the group. + */ +int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported) +{ + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension == NULL) + return BAD_FUNC_ARG; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name)) + return curve->name; + curve = curve->next; + } + + return BAD_FUNC_ARG; +} + +#endif + +#ifndef NO_WOLFSSL_SERVER + static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { @@ -3444,7 +3560,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { TLSX* extension = NULL; SupportedCurve* curve = NULL; - int ret = 0; + int ret; if (extensions == NULL) return BAD_FUNC_ARG; @@ -3469,9 +3585,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) return ret; } - return (TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS) == NULL) - ? TLSX_UsePointFormat(extensions, WOLFSSL_EC_PF_UNCOMPRESSED, heap) - : WOLFSSL_SUCCESS; + return WOLFSSL_SUCCESS; } int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) @@ -3517,7 +3631,8 @@ int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) #define EC_WRITE(a, b) 0 #endif -#ifndef NO_WOLFSSL_SERVER +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) #define EC_PARSE TLSX_SupportedCurve_Parse #else #define EC_PARSE(a, b, c, d) 0 @@ -4525,8 +4640,12 @@ static word16 TLSX_SupportedVersions_GetSize(void* data, byte msgType) int cnt = 2; #ifndef NO_OLD_TLS - /* TLS v1 and TLS v1.1 */ - cnt += 2; + /* TLS v1.1 */ + cnt++; + #ifdef WOLFSSL_ALLOW_TLSV10 + /* TLS v1.0 */ + cnt++; + #endif #endif if (!ssl->options.downgrade) @@ -4563,8 +4682,12 @@ static word16 TLSX_SupportedVersions_Write(void* data, byte* output, cnt = 2; #ifndef NO_OLD_TLS - /* TLS v1 and TLS v1.1 */ - cnt += 2; + /* TLS v1.1 */ + cnt++; + #ifdef WOLFSSL_ALLOW_TLSV10 + /* TLS v1.0 */ + cnt++; + #endif #endif if (!ssl->options.downgrade) @@ -4572,6 +4695,7 @@ static word16 TLSX_SupportedVersions_Write(void* data, byte* output, *(output++) = (byte)(cnt * OPAQUE16_LEN); for (i = 0; i < cnt; i++) { +#ifndef WOLFSSL_TLS13_FINAL /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ if (pv.minor - i == TLSv1_3_MINOR) { /* The TLS draft major number. */ @@ -4580,6 +4704,7 @@ static word16 TLSX_SupportedVersions_Write(void* data, byte* output, *(output++) = TLS_DRAFT_MINOR; continue; } +#endif *(output++) = pv.major; *(output++) = pv.minor - i; @@ -4607,13 +4732,14 @@ static word16 TLSX_SupportedVersions_Write(void* data, byte* output, * msgType The type of the message this extension is being parsed from. * returns 0 on success, otherwise failure. */ -static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, +static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType) { ProtocolVersion pv = ssl->ctx->method->version; int i; int len; byte major, minor; + int newMinor = 0; if (msgType == client_hello) { /* Must contain a length and at least one version. */ @@ -4633,11 +4759,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, major = input[i]; minor = input[i + OPAQUE8_LEN]; +#ifndef WOLFSSL_TLS13_FINAL /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { major = SSLv3_MAJOR; minor = TLSv1_3_MINOR; } +#endif if (major != pv.major) continue; @@ -4664,8 +4792,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, #ifndef WOLFSSL_TLS13_DRAFT_18 TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); #endif + newMinor = minor; } - break; + else if (ssl->options.oldMinor < minor) + ssl->options.oldMinor = minor; + + if (newMinor != 0 && ssl->options.oldMinor != 0) + break; } } #ifndef WOLFSSL_TLS13_DRAFT_18 @@ -4677,11 +4810,13 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, major = input[0]; minor = input[OPAQUE8_LEN]; + #ifndef WOLFSSL_TLS13_FINAL /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { major = SSLv3_MAJOR; minor = TLSv1_3_MINOR; } + #endif if (major != pv.major) return VERSION_ERROR; @@ -5591,8 +5726,6 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) #ifndef NO_DH int ret; const DhParams* params; - word16 i; - byte b; DhKey dhKey; switch (keyShareEntry->group) { @@ -5630,42 +5763,24 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); #endif - if (params->p_len != keyShareEntry->keLen) - return BUFFER_ERROR; - ssl->options.dhKeySz = params->p_len; - - /* TODO: [TLS13] move this check down into wolfcrypt. */ - /* Check that public DH key is not 0 or 1. */ - b = 0; - for (i = 0; i < params->p_len - 1; i++) - b |= keyShareEntry->ke[i]; - if (b == 0 && (keyShareEntry->ke[i] == 0x00 || - keyShareEntry->ke[i] == 0x01)) { - return PEER_KEY_ERROR; - } - /* Check that public DH key is not mod, mod + 1 or mod - 1. */ - b = 0; - for (i = 0; i < params->p_len - 1; i++) - b |= params->p[i] ^ keyShareEntry->ke[i]; - if (b == 0 && (params->p[i] == keyShareEntry->ke[i] || - params->p[i] - 1 == keyShareEntry->ke[i] || - params->p[i] + 1 == keyShareEntry->ke[i])) { - return PEER_KEY_ERROR; - } - ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); if (ret != 0) return ret; /* Set key */ - ret = wc_DhSetKey(&dhKey, - (byte*)params->p, params->p_len, - (byte*)params->g, params->g_len); + ret = wc_DhSetKey(&dhKey, (byte*)params->p, params->p_len, (byte*)params->g, + params->g_len); if (ret != 0) { wc_FreeDhKey(&dhKey); return ret; } + ret = wc_DhCheckPubKey(&dhKey, keyShareEntry->ke, keyShareEntry->keLen); + if (ret != 0) { + wc_FreeDhKey(&dhKey); + return PEER_KEY_ERROR; + } + /* Derive secret from private key and peer's public key. */ ret = wc_DhAgree(&dhKey, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, @@ -5947,8 +6062,11 @@ static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) KeyShareEntry* list; extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); - if (extension == NULL) - return 0; + if (extension == NULL) { + extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return 0; + } list = (KeyShareEntry*)extension->data; while (list != NULL) { @@ -5973,8 +6091,13 @@ static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) TLSX* extension; SupportedCurve* curve = NULL; - if ((extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS)) == NULL) - return 0; + if ((extension = TLSX_Find(ssl->extensions, + TLSX_SUPPORTED_GROUPS)) == NULL) { + if ((extension = TLSX_Find(ssl->ctx->extensions, + TLSX_SUPPORTED_GROUPS)) == NULL) { + return 0; + } + } for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) { if (curve->name == name) @@ -6003,6 +6126,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, { int ret; KeyShareEntry *keyShareEntry; + word16 group; if (msgType == client_hello) { int offset = 0; @@ -6041,6 +6165,20 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, else if (msgType == server_hello) { int len; + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (!TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + /* ServerHello contains one key share entry. */ len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); if (len != length) @@ -6052,10 +6190,10 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, /* Process the entry to calculate the secret. */ ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + if (ret == 0) + ssl->session.namedGroup = ssl->namedGroup = group; } else if (msgType == hello_retry_request) { - word16 group; - if (length != OPAQUE16_LEN) return BUFFER_ERROR; @@ -6264,6 +6402,68 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) return 1; } +/* Examines the application specified group ranking and returns the rank of the + * group. + * If no group ranking set then all groups are rank 0 (highest). + * + * ssl The SSL/TLS object. + * group The group to check ranking for. + * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list. + */ +static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) +{ + byte i; + + if (ssl->numGroups == 0) { +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1; + #endif + #endif +#endif + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519; + #endif + #endif +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1; + #endif + #endif +#endif + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048; + #endif + #ifdef HAVE_FFDHE_3072 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072; + #endif + #ifdef HAVE_FFDHE_4096 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096; + #endif + #ifdef HAVE_FFDHE_6144 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144; + #endif + #ifdef HAVE_FFDHE_8192 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; + #endif + } + + for (i = 0; i < ssl->numGroups; i++) + if (ssl->group[i] == group) + return i; + + return -1; +} + /* Set a key share that is supported by the client into extensions. * * ssl The SSL/TLS object. @@ -6272,21 +6472,32 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) */ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) { - int ret; + int ret; #ifdef HAVE_SUPPORTED_CURVES - TLSX* extension; + TLSX* extension; SupportedCurve* curve = NULL; + SupportedCurve* preferredCurve = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; - /* Use SupportedGroup's order. */ extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); if (extension != NULL) curve = (SupportedCurve*)extension->data; + /* Use server's preference order. */ for (; curve != NULL; curve = curve->next) { - if (TLSX_KeyShare_IsSupported(curve->name) && - !TLSX_KeyShare_Find(ssl, curve->name)) { - break; + if (!TLSX_KeyShare_IsSupported(curve->name)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, curve->name); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredCurve = curve; + preferredRank = rank; } } + curve = preferredCurve; + if (curve == NULL) return BAD_KEY_SHARE_DATA; @@ -6326,6 +6537,9 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) KeyShareEntry* clientKSE = NULL; KeyShareEntry* serverKSE; KeyShareEntry* list = NULL; + KeyShareEntry* preferredKSE = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; /* Find the KeyShare extension if it exists. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); @@ -6335,8 +6549,7 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (extension && extension->resp == 1) return 0; - /* TODO: [TLS13] Server's preference and sending back SupportedGroups */ - /* Use client's preference. */ + /* Use server's preference order. */ for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { if (clientKSE->ke == NULL) continue; @@ -6346,13 +6559,25 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) return BAD_KEY_SHARE_DATA; #ifdef OPENSSL_EXTRA - /* Check if server supports group. */ - if (ssl->ctx->disabledCurves & (1 << clientKSE->group)) - continue; + if ((clientKSE->group & NAMED_DH_MASK) == 0) { + /* Check if server supports group. */ + if (ssl->ctx->disabledCurves & (1 << clientKSE->group)) + continue; + } #endif - if (TLSX_KeyShare_IsSupported(clientKSE->group)) - break; + if (!TLSX_KeyShare_IsSupported(clientKSE->group)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredKSE = clientKSE; + preferredRank = rank; + } } + clientKSE = preferredKSE; + /* No supported group found - send HelloRetryRequest. */ if (clientKSE == NULL) { ret = TLSX_KeyShare_SetSupported(ssl); @@ -6458,30 +6683,6 @@ static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap) (void)heap; } -/* Delete the extension. - * - * ssl The SSL object with the extension. - */ -static void TLSX_PreSharedKey_Delete(WOLFSSL* ssl) -{ - TLSX* extension = ssl->extensions; - TLSX* prev = NULL; - - while (extension && extension->type != TLSX_PRE_SHARED_KEY) { - prev = extension; - extension = extension->next; - } - - if (extension != NULL) { - if (prev) - prev->next = extension->next; - else - ssl->extensions = extension->next; - TLSX_PreSharedKey_FreeAll((PreSharedKey*)extension->data, ssl->heap); - XFREE(extension, ssl->heap, XFREE(extension, heap, DYNAMIC_TYPE_TLSX)); - } -} - /* Get the size of the encoded pre shared key extension. * * list The linked list of pre-shared key extensions. @@ -6659,7 +6860,7 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, word16 len; word16 idx = 0; - TLSX_PreSharedKey_Delete(ssl); + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); /* Length of identities and of binders. */ if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN) @@ -6747,6 +6948,10 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, return BUFFER_E; ato16(input, &idx); + #ifdef WOLFSSL_EARLY_DATA + ssl->options.pskIdIndex = idx + 1; + #endif + /* Find the list of identities sent to server. */ extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (extension == NULL) @@ -6763,18 +6968,14 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifdef HAVE_SESSION_TICKET if (list->resumption) { /* Check that the session's details are the same as the server's. */ - if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || - ssl->options.cipherSuite != ssl->session.cipherSuite || - ssl->session.version.major != ssl->version.major || - ssl->session.version.minor != ssl->version.minor ) { + if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || + ssl->options.cipherSuite != ssl->session.cipherSuite || + ssl->session.version.major != ssl->ctx->method->version.major || + ssl->session.version.minor != ssl->ctx->method->version.minor) { return PSK_KEY_ERROR; } } #endif - /* TODO: [TLS13] More checks of consistency. - * the "key_share", and "signature_algorithms" extensions are - * consistent with the indicated ke_modes and auth_modes values - */ return 0; } @@ -7236,6 +7437,12 @@ static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != 0) return BUFFER_E; + /* Ensure the index of PSK identity chosen by server is 0. + * Index is plus one to handle 'not set' value of 0. + */ + if (ssl->options.pskIdIndex != 1) + return PSK_KEY_ERROR; + return TLSX_EarlyData_Use(ssl, 1); } if (msgType == session_ticket) { @@ -7309,6 +7516,24 @@ TLSX* TLSX_Find(TLSX* list, TLSX_Type type) return extension; } +/** Remove an extension. */ +void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap) +{ + TLSX* extension = *list; + TLSX** next = list; + + while (extension && extension->type != type) { + next = &extension->next; + extension = extension->next; + } + + if (extension) { + *next = extension->next; + extension->next = NULL; + TLSX_FreeAll(extension, heap); + } +} + /** Releases all extensions in the provided list. */ void TLSX_FreeAll(TLSX* list, void* heap) { @@ -7593,7 +7818,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, break; case TLSX_SUPPORTED_GROUPS: - WOLFSSL_MSG("Elliptic Curves extension to write"); + WOLFSSL_MSG("Supported Groups extension to write"); offset += EC_WRITE((SupportedCurve*)extension->data, output + offset); break; @@ -7904,6 +8129,168 @@ static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) } #endif /* HAVE_QSH */ +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) +{ + int ret; +#ifdef WOLFSSL_TLS13 + int i; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) { + return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup, + ssl->heap); + } +#endif + + if (ssl->numGroups != 0) { + for (i = 0; i < ssl->numGroups; i++) { + ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + return WOLFSSL_SUCCESS; + } +#endif + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #ifndef HAVE_FIPS + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_SECPR2 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif + + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + } + #endif + + return WOLFSSL_SUCCESS; +} + int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) { int ret = 0; @@ -7996,100 +8383,33 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - if (!ssl->options.userCurves && !ssl->ctx->userCurves && - TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { - - #ifndef HAVE_FIPS - #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP160R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_SECPR2 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP160R2, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP160K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP192R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP192K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #endif - #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP224R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP224K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #if defined(HAVE_CURVE25519) - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_X25519, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP256K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) - #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_SECP521R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + if (TLSX_Find(ssl->ctx->extensions, + TLSX_SUPPORTED_GROUPS) == NULL) { + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + if (!IsAtLeastTLSv1_3(ssl->version) && + TLSX_Find(ssl->ctx->extensions, + TLSX_EC_POINT_FORMATS) == NULL && + TLSX_Find(ssl->extensions, + TLSX_EC_POINT_FORMATS) == NULL) { + ret = TLSX_UsePointFormat(&ssl->extensions, + WOLFSSL_EC_PF_UNCOMPRESSED, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + TLSX_Find(ssl->ctx->extensions, + TLSX_EC_POINT_FORMATS) == NULL) { + ret = TLSX_UsePointFormat(&ssl->ctx->extensions, + WOLFSSL_EC_PF_UNCOMPRESSED, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } } #endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ } /* is not server */ @@ -8105,48 +8425,20 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) /* Add mandatory TLS v1.3 extension: supported version */ WOLFSSL_MSG("Adding supported versions extension"); if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl, - ssl->heap)) != 0) + ssl->heap)) != 0) { return ret; - -#ifdef HAVE_SUPPORTED_CURVES - if (!ssl->options.userCurves && !ssl->ctx->userCurves && - TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) - == NULL) { - /* Add FFDHE supported groups. */ - #ifdef HAVE_FFDHE_2048 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_2048, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_3072 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_3072, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_4096 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_4096, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_6144 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_6144, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_8192 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_8192, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - ret = 0; } -#endif + #if !defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { + /* Put in DH groups for TLS 1.3 only. */ + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + ret = 0; + } + #endif /* !HAVE_ECC && HAVE_SUPPORTED_CURVES */ + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) if (ssl->certHashSigAlgoSz > 0) { WOLFSSL_MSG("Adding signature algorithms cert extension"); @@ -8158,39 +8450,46 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + word16 namedGroup; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) + namedGroup = ssl->session.namedGroup; + else + #endif + { #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP256R1, 0, NULL, - NULL); + namedGroup = WOLFSSL_ECC_SECP256R1; #elif defined(HAVE_ECC) && defined(HAVE_CURVE25519) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_X25519, 0, NULL, NULL); + namedGroup = WOLFSSL_ECC_X25519; #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \ defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP384R1, 0, NULL, - NULL); + namedGroup = WOLFSSL_ECC_SECP384R1; #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \ defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP521R1, 0, NULL, - NULL); + namedGroup = WOLFSSL_ECC_SECP521R1; #elif defined(HAVE_FFDHE_2048) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_2048, 0, NULL, NULL); + namedGroup = WOLFSSL_FFDHE_2048; #elif defined(HAVE_FFDHE_3072) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_3072, 0, NULL, NULL); + namedGroup = WOLFSSL_FFDHE_3072; #elif defined(HAVE_FFDHE_4096) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_4096, 0, NULL, NULL); + namedGroup = WOLFSSL_FFDHE_4096; #elif defined(HAVE_FFDHE_6144) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_6144, 0, NULL, NULL); + namedGroup = WOLFSSL_FFDHE_6144; #elif defined(HAVE_FFDHE_8192) - ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_8192, 0, NULL, NULL); + namedGroup = WOLFSSL_FFDHE_8192; #else - ret = KEY_SHARE_ERROR; + return KEY_SHARE_ERROR; #endif + } + ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); if (ret != 0) return ret; } #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - TLSX_PreSharedKey_Delete(ssl); + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); #endif #if defined(HAVE_SESSION_TICKET) if (ssl->options.resuming && ssl->session.ticketLen > 0) { @@ -8701,6 +9000,9 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, #ifdef HAVE_EXTENDED_MASTER byte pendingEMS = 0; #endif +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int pskDone = 0; +#endif if (!ssl || !input || (isRequest && !suites)) return BAD_FUNC_ARG; @@ -8709,6 +9011,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, word16 type; word16 size; +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + if (msgType == client_hello && pskDone) + return PSK_KEY_ERROR; +#endif + if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN) return BUFFER_ERROR; @@ -8752,14 +9059,14 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, WOLFSSL_MSG("Truncated HMAC extension received"); #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version)) - return EXT_NOT_ALLOWED; + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; #endif ret = THM_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_SUPPORTED_GROUPS: - WOLFSSL_MSG("Elliptic Curves extension received"); + WOLFSSL_MSG("Supported Groups extension received"); #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && @@ -8775,11 +9082,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, WOLFSSL_MSG("Point Formats extension received"); #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && - msgType != encrypted_extensions) { - return EXT_NOT_ALLOWED; - } + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; #endif ret = PF_PARSE(ssl, input + offset, size, isRequest); break; @@ -8788,11 +9092,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, WOLFSSL_MSG("Certificate Status Request extension received"); #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && - msgType != encrypted_extensions) { - return EXT_NOT_ALLOWED; - } + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; #endif ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; @@ -8803,7 +9104,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && msgType != client_hello && - msgType != encrypted_extensions) { + msgType != certificate_request && + msgType != certificate) { return EXT_NOT_ALLOWED; } #endif @@ -8815,13 +9117,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, WOLFSSL_MSG("Extended Master Secret extension received"); #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello) { - return EXT_NOT_ALLOWED; - } + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; #endif #ifndef NO_WOLFSSL_SERVER - if (isRequest && !IsAtLeastTLSv1_3(ssl->version)) + if (isRequest) ssl->options.haveEMS = 1; #endif pendingEMS = 1; @@ -8831,6 +9131,10 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; +#endif ret = SCR_PARSE(ssl, input + offset, size, isRequest); break; @@ -8850,8 +9154,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version)) - return EXT_NOT_ALLOWED; + if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + break; #endif ret = QSH_PARSE(ssl, input + offset, size, isRequest); break; @@ -8889,13 +9193,17 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, case TLSX_SUPPORTED_VERSIONS: WOLFSSL_MSG("Supported Versions extension received"); + if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) + break; + if (IsAtLeastTLSv1_3(ssl->version) && -#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifdef WOLFSSL_TLS13_DRAFT_18 msgType != client_hello -#else - msgType != client_hello && msgType != server_hello && + #else + msgType != client_hello && + msgType != server_hello && msgType != hello_retry_request -#endif + #endif ) { return EXT_NOT_ALLOWED; } @@ -8920,14 +9228,16 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension received"); - if (!IsAtLeastTLSv1_3(ssl->version)) + if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) break; if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && msgType != server_hello) { + msgType != client_hello && + msgType != server_hello) { return EXT_NOT_ALLOWED; } ret = PSK_PARSE(ssl, input + offset, size, msgType); + pskDone = 1; break; case TLSX_PSK_KEY_EXCHANGE_MODES: @@ -8952,7 +9262,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, break; if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && msgType != session_ticket && + msgType != client_hello && + msgType != session_ticket && msgType != encrypted_extensions) { return EXT_NOT_ALLOWED; } @@ -8995,11 +9306,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, case TLSX_KEY_SHARE: WOLFSSL_MSG("Key Share extension received"); - if (!IsAtLeastTLSv1_3(ssl->version)) + if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && msgType != server_hello && + if (IsAtLeastTLSv1_3(ssl->ctx->method->version) && + msgType != client_hello && + msgType != server_hello && msgType != hello_retry_request) { return EXT_NOT_ALLOWED; } diff --git a/src/tls13.c b/src/tls13.c index 66dc9c264..009b6341e 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -21,20 +21,55 @@ /* - * WOLFSSL_TLS13_DRAFT_18 - * Conform with Draft 18 of the TLS v1.3 specification. - * WOLFSSL_EARLY_DATA - * Allow 0-RTT Handshake using Early Data extensions and handshake message - * WOLFSSL_POST_HANDSHAKE_AUTH - * Allow TLS v1.3 code to perform post-handshake authentication of the - * client. - * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED - * Allow a NewSessionTicket message to be sent by server before Client's - * Finished message. - * See TLS v.13 specification, Section 4.6.1, Paragraph 4 (Note). + * BUILD_GCM + * Enables AES-GCM ciphersuites. + * HAVE_AESCCM + * Enables AES-CCM ciphersuites. + * HAVE_SESSION_TICKET + * Enables session tickets - required for TLS 1.3 resumption. + * NO_PSK + * Do not enable Pre-Shared Keys. * TLS13_SUPPORTS_EXPORTERS * Gaurd to compile out any code for exporter keys. * Feature not supported yet. + * WOLFSSL_ASYNC_CRYPT + * Enables the use of asynchornous cryptographic operations. + * This is available for ciphers and certificates. + * HAVE_CHACHA && HAVE_POLY1305 + * Enables use of CHACHA20-POLY1305 ciphersuites. + * WOLFSSL_DEBUG_TLS + * Writes out details of TLS 1.3 protocol including hanshake message buffers + * and key generation input and output. + * WOLFSSL_EARLY_DATA + * Allow 0-RTT Handshake using Early Data extensions and handshake message + * WOLFSSL_NO_SERVER_GROUPS_EXT + * Do not send the server's groups in an extension when the server's top + * preference is not in client's list. + * WOLFSSL_POST_HANDSHAKE_AUTH + * Allow TLS v1.3 code to perform post-handshake authentication of the + * client. + * WOLFSSL_SEND_HRR_COOKIE + * Send a cookie in hello_retry_request message to enable stateless tracking + * of ClientHello replies. + * WOLFSSL_TLS13 + * Enable TLS 1.3 protocol implementation. + * WOLFSSL_TLS13_DRAFT_18 + * Conform with Draft 18 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_22 + * Conform with Draft 22 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_23 + * Conform with Draft 23 of the TLS v1.3 specification. + * WOLFSSL_TLS13_MIDDLEBOX_COMPAT + * Enable middlebox compatability in the TLS 1.3 handshake. + * This includes sending ChangeCipherSpec before encrypted messages and + * including a session id. + * WOLFSSL_TLS13_SHA512 + * Allow generation of SHA-512 digests in handshake - no ciphersuite + * requires SHA-512 at this time. + * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + * Allow a NewSessionTicket message to be sent by server before Client's + * Finished message. + * See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note). */ #ifdef HAVE_CONFIG_H @@ -134,7 +169,7 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, break; #endif - #ifdef WOLFSSL_TLS13_TLS13_SHA512 + #ifdef WOLFSSL_TLS13_SHA512 case sha512_mac: hash = WC_SHA512; len = WC_SHA512_DIGEST_SIZE; @@ -842,13 +877,13 @@ static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, #ifdef WOLFSSL_SHA384 case sha384_mac: - digestAlg = WC_SHA256; + digestAlg = WC_SHA384; break; #endif - #ifdef WOLFSSL_TLS13_TLS13_SHA512 + #ifdef WOLFSSL_TLS13_SHA512 case sha512_mac: - digestAlg = WC_SHA256; + digestAlg = WC_SHA512; break; #endif @@ -2122,6 +2157,28 @@ exit_buildmsg: return ret; } +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Find the cipher suite in the suites set in the SSL. + * + * ssl SSL/TLS object. + * suite Cipher suite to look for. + * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise. + */ +static int FindSuite(WOLFSSL* ssl, byte* suite) +{ + int i; + + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + if (ssl->suites->suites[i+0] == suite[0] && + ssl->suites->suites[i+1] == suite[1]) { + return 1; + } + } + + return 0; +} +#endif + #ifndef NO_WOLFSSL_CLIENT #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Setup pre-shared key based on the details in the extension data. @@ -2134,6 +2191,15 @@ exit_buildmsg: static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) { int ret; + byte suite[2]; + + if (ssl->options.noPskDheKe && ssl->arrays->preMasterSz != 0) + return PSK_KEY_ERROR; + + suite[0] = psk->cipherSuite0; + suite[1] = psk->cipherSuite; + if (!FindSuite(ssl, suite)) + return PSK_KEY_ERROR; ssl->options.cipherSuite0 = psk->cipherSuite0; ssl->options.cipherSuite = psk->cipherSuite; @@ -2144,7 +2210,7 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) if (psk->resumption) { #ifdef WOLFSSL_EARLY_DATA if (ssl->session.maxEarlyDataSz == 0) - ssl->earlyData = 0; + ssl->earlyData = no_early_data; #endif /* Resumption PSK is master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; @@ -2169,6 +2235,12 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { return PSK_KEY_ERROR; } + /* TODO: Callback should be able to specify ciphersuite. */ + + if (psk->cipherSuite0 != TLS13_BYTE || + psk->cipherSuite != WOLFSSL_DEF_PSK_CIPHER) { + return PSK_KEY_ERROR; + } } #endif @@ -2250,7 +2322,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) return ret; #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0) return ret; @@ -2327,9 +2399,15 @@ int SendTls13ClientHello(WOLFSSL* ssl) #else if (!ssl->options.resuming) #endif - ssl->earlyData = 0; - if (ssl->earlyData && (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) + ssl->earlyData = no_early_data; + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) + ssl->earlyData = no_early_data; + if (ssl->earlyData == no_early_data) + TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap); + if (ssl->earlyData != no_early_data && + (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) { return ret; + } #endif #ifdef HAVE_QSH if (QSH_Init(ssl) != 0) @@ -2352,9 +2430,10 @@ int SendTls13ClientHello(WOLFSSL* ssl) /* Put the record and handshake headers on. */ AddTls13Headers(output, length, client_hello, ssl); - /* Protocol version. */ + /* Protocol version - negotiation now in extension: supported_versions. */ output[idx++] = SSLv3_MAJOR; output[idx++] = TLSv1_2_MINOR; + /* Keep for downgrade. */ ssl->chVersion = ssl->version; /* Client Random */ @@ -2375,6 +2454,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) output[idx++] = 0; #else if (ssl->session.sessionIDSz > 0) { + /* Session resumption for old versions of protocol. */ output[idx++] = ID_LEN; XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); idx += ID_LEN; @@ -2385,6 +2465,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN); idx += ID_LEN; #else + /* TLS v1.3 does not use session id - 0 length. */ output[idx++] = 0; #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ } @@ -2606,7 +2687,7 @@ static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, *inOutIdx = i + totalExtSz; ssl->options.tls1_3 = 1; - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret); @@ -2639,7 +2720,7 @@ static byte helloRetryRequestRandom[] = { * returns 0 on success and otherwise failure. */ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - word32 helloSz) + word32 helloSz, byte* extMsgType) { ProtocolVersion pv; word32 i = *inOutIdx; @@ -2655,7 +2736,6 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, TLSX* ext; PreSharedKey* psk = NULL; #endif - byte extMsgType = server_hello; WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); WOLFSSL_ENTER("DoTls13ServerHello"); @@ -2705,7 +2785,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BUFFER_ERROR; if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) - extMsgType = hello_retry_request; + *extMsgType = hello_retry_request; #endif /* Server random - keep for debugging. */ @@ -2766,7 +2846,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->version.minor = TLSv1_2_MINOR; #endif /* Parse and handle extensions. */ - ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, extMsgType, NULL); + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType, + NULL); if (ret != 0) return ret; @@ -2837,7 +2918,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifndef WOLFSSL_TLS13_DRAFT_18 - if (extMsgType == server_hello) + if (*extMsgType == server_hello) #endif { ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); @@ -2858,11 +2939,13 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TLS13_DRAFT_18 ssl->keys.encryptionOn = 1; #else - if (extMsgType == server_hello) + if (*extMsgType == server_hello) { ssl->keys.encryptionOn = 1; + ssl->options.serverState = SERVER_HELLO_COMPLETE; + } else { ssl->options.tls1_3 = 1; - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; ret = RestartHandshakeHash(ssl); } @@ -2923,13 +3006,23 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, *inOutIdx += ssl->keys.padSz; #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); if (ext == NULL || !ext->val) - ssl->earlyData = 0; + ssl->earlyData = no_early_data; } #endif +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == no_early_data) { + ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY); + if (ret != 0) + return ret; + } +#endif + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret); WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO); @@ -3090,6 +3183,31 @@ 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]; + int suiteSz = 0; + int i, j; + + 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]; + } + } + } + + ssl->suites->suiteSz = suiteSz; + XMEMCPY(ssl->suites->suites, &suites, sizeof(suites)); +} + /* Handle any Pre-Shared Key (PSK) extension. * Must do this in ClientHello as it requires a hash of the truncated message. * Don't know size of binders until Pre-Shared Key extension has been parsed. @@ -3111,6 +3229,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, byte binder[WC_MAX_DIGEST_SIZE]; word32 binderLen; word16 modes; + byte suite[2]; #ifdef WOLFSSL_EARLY_DATA int pskCnt = 0; TLSX* extEarlyData; @@ -3121,7 +3240,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (ext == NULL) { #ifdef WOLFSSL_EARLY_DATA - ssl->earlyData = 0; + ssl->earlyData = no_early_data; #endif return 0; } @@ -3179,6 +3298,16 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, break; } + /* Check whether resumption is possible based on suites in SSL and + * ciphersuite in ticket. + */ + suite[0] = ssl->session.cipherSuite0; + suite[1] = ssl->session.cipherSuite; + if (!FindSuite(ssl, suite)) { + current = current->next; + continue; + } + #ifdef WOLFSSL_EARLY_DATA ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; #endif @@ -3191,15 +3320,15 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, /* Resumption PSK is resumption master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; -#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifdef WOLFSSL_TLS13_DRAFT_18 XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, ssl->arrays->psk_keySz); -#else + #else if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } -#endif + #endif /* Derive the early secret using the PSK. */ ret = DeriveEarlySecret(ssl); @@ -3219,15 +3348,23 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, MAX_PSK_KEY_LEN)) != 0) { if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR; + /* TODO: Callback should be able to specify ciphersuite. */ + suite[0] = TLS13_BYTE; + suite[1] = WOLFSSL_DEF_PSK_CIPHER; + if (!FindSuite(ssl, suite)) { + current = current->next; + continue; + } + + /* Default to ciphersuite if cb doesn't specify. */ ssl->options.resuming = 0; /* PSK age is always zero. */ if (current->ticketAge != ssl->session.ticketAdd) return PSK_KEY_ERROR; - /* TODO: Callback should be able to change ciphersuite. */ - /* Default to ciphersuite if cb doesn't specify. */ + /* Check whether PSK ciphersuite is in SSL. */ ssl->options.cipherSuite0 = TLS13_BYTE; ssl->options.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; ret = SetCipherSpecs(ssl); @@ -3274,8 +3411,17 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, break; } - if (current == NULL) + if (current == NULL) { +#ifdef WOLFSSL_PSK_ID_PROTECTION + #ifndef NO_CERTS + if (ssl->buffers.certChainCnt != 0) + return 0; + #endif + return BAD_BINDER; +#else return 0; +#endif + } /* Hash the rest of the ClientHello. */ ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); @@ -3285,7 +3431,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, #ifdef WOLFSSL_EARLY_DATA extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); if (extEarlyData != NULL) { - if (ssl->earlyData && current == ext->data) { + if (ssl->earlyData != no_early_data && current == ext->data) { extEarlyData->resp = 1; /* Derive early data decryption key. */ @@ -3295,7 +3441,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; - ssl->earlyData = 2; + ssl->earlyData = process_early_data; } else extEarlyData->resp = 0; @@ -3318,7 +3464,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, /* Pick key share and Generate a new key if not present. */ ret = TLSX_KeyShare_Establish(ssl); if (ret == KEY_SHARE_ERROR) { - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; ret = 0; } else if (ret < 0) @@ -3552,7 +3698,6 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) } #endif -/* handle processing of TLS 1.3 client_hello (1) */ /* Handle a ClientHello handshake message. * If the protocol version in the message is not TLS v1.3 or higher, use * DoClientHello() @@ -3575,9 +3720,10 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, Suites clSuites; word32 i = *inOutIdx; word32 begin = i; - word16 totalExtSz; + word16 totalExtSz = 0; int usingPSK = 0; byte sessIdSz; + int bogusID = 0; WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); WOLFSSL_ENTER("DoTls13ClientHello"); @@ -3595,10 +3741,20 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(&pv, input + i, OPAQUE16_LEN); ssl->chVersion = pv; /* store */ i += OPAQUE16_LEN; + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR) + pv.minor = TLSv1_2_MINOR; if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor < TLSv1_3_MINOR) return DoClientHello(ssl, input, inOutIdx, helloSz); +#ifdef HAVE_SESSION_TICKET + if (ssl->options.downgrade) { + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + } +#endif + /* Client random */ XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); i += RAN_LEN; @@ -3611,7 +3767,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TLS13_DRAFT_18 /* Session id - empty in TLS v1.3 */ sessIdSz = input[i++]; - if (sessIdSz > 0) { + if (sessIdSz > 0 && !ssl->options.downgrade) { WOLFSSL_MSG("Client sent session id - not supported"); return BUFFER_ERROR; } @@ -3619,11 +3775,15 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sessIdSz = input[i++]; if (sessIdSz != ID_LEN && sessIdSz != 0) return INVALID_PARAMETER; +#endif ssl->session.sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { XMEMCPY(ssl->session.sessionID, input + i, sessIdSz); i += ID_LEN; } +#ifdef HAVE_SESSION_TICKET + if (sessIdSz > 0 && sessIdSz < ID_LEN) + bogusID = 1; #endif /* Cipher suites */ @@ -3654,37 +3814,38 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return INVALID_PARAMETER; } - /* TLS v1.3 ClientHello messages will have extensions. */ - if ((i - begin) >= helloSz) { - WOLFSSL_MSG("ClientHello must have extensions in TLS v1.3"); - return BUFFER_ERROR; - } - if ((i - begin) + OPAQUE16_LEN > helloSz) - return BUFFER_ERROR; - ato16(&input[i], &totalExtSz); - i += OPAQUE16_LEN; - if ((i - begin) + totalExtSz > helloSz) - return BUFFER_ERROR; + if ((i - begin) < helloSz) { + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; -#ifdef HAVE_QSH - QSH_Init(ssl); -#endif + #ifdef HAVE_QSH + QSH_Init(ssl); + #endif - /* Auto populate extensions supported unless user defined. */ - if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) - return ret; + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; - /* Parse extensions */ - if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + /* Parse extensions */ + if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, &clSuites))) { - return ret; + return ret; + } + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) + if ((ret = SNI_Callback(ssl)) != 0) + return ret; + ssl->options.side = WOLFSSL_SERVER_END; +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ } -#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - if ((ret = SNI_Callback(ssl)) != 0) - return ret; - ssl->options.side = WOLFSSL_SERVER_END; -#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + i += totalExtSz; + *inOutIdx = i; if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) { if (!ssl->options.downgrade) { @@ -3698,39 +3859,90 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->version.minor = pv.minor; } -#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) - if (ssl->options.sendCookie && - ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { - TLSX* ext; - - if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) - return HRR_COOKIE_ERROR; - /* Ensure the cookie came from client and isn't the one in the response - * - HelloRetryRequest. - */ - if (ext->resp == 1) - return HRR_COOKIE_ERROR; - ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); - if (ret != 0) - return ret; - } -#endif - ssl->options.sendVerify = SEND_CERT; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - /* Process the Pre-Shared Key extension if present. */ - ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); - if (ret != 0) - return ret; + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.haveSessionId = 1; + + if (IsAtLeastTLSv1_3(ssl->version)) { +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) + if (ssl->options.sendCookie && + ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + TLSX* ext; + + if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) + return HRR_COOKIE_ERROR; + /* Ensure the cookie came from client and isn't the one in the + * response - HelloRetryRequest. + */ + if (ext->resp == 1) + return HRR_COOKIE_ERROR; + ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); + if (ret != 0) + return ret; + } #endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.downgrade) { + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + } + + /* Refine list for PSK processing. */ + RefineSuites(ssl, &clSuites); + + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; +#endif + } + else if (ssl->options.resuming) { + ret = HandleTlsResumption(ssl, bogusID, &clSuites); + if (ret != 0) + return ret; + /* Check wheter resuming has been chosen */ + if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) { + WOLFSSL_LEAVE("DoTls13ClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); + + return ret; + } + } + if (!usingPSK) { if ((ret = MatchSuite(ssl, &clSuites)) < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return ret; } + /* Check that the negotiated ciphersuite matches protocol version. */ + if (IsAtLeastTLSv1_3(ssl->version)) { + if (ssl->options.cipherSuite0 != TLS13_BYTE) { + TLSX* ext; + + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Negotiated ciphersuite from lesser version " + "than TLS v1.3"); + return VERSION_ERROR; + } + + WOLFSSL_MSG("Downgrading protocol due to cipher suite"); + + if (pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = ssl->options.oldMinor; + + /* Downgrade from TLS v1.3 */ + ssl->options.tls1_3 = 0; + ext = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS); + if (ext != NULL) + ext->resp = 0; + } + } + /* VerifyServerSuite handles when version is less than 1.3 */ + #ifdef HAVE_SESSION_TICKET if (ssl->options.resuming) { ssl->options.resuming = 0; @@ -3741,20 +3953,21 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif - if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) - return ret; +#ifdef HAVE_SESSION_TICKET + if (IsAtLeastTLSv1_3(ssl->version) || !ssl->options.downgrade) +#endif + { + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + } - /* Derive early secret for handshake secret. */ - if ((ret = DeriveEarlySecret(ssl)) != 0) - return ret; + if (IsAtLeastTLSv1_3(ssl->version)) { + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + } } - i += totalExtSz; - *inOutIdx = i; - - ssl->options.clientState = CLIENT_HELLO_COMPLETE; - ssl->options.haveSessionId = 1; - WOLFSSL_LEAVE("DoTls13ClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); @@ -3998,6 +4211,11 @@ static int SendTls13EncryptedExtensions(WOLFSSL* ssl) ssl->keys.encryptionOn = 1; +#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT + if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0) + return ret; +#endif + /* Derive the handshake secret now that we are at first message to be * encrypted under the keys. */ @@ -4011,7 +4229,7 @@ static int SendTls13EncryptedExtensions(WOLFSSL* ssl) #ifdef WOLFSSL_EARLY_DATA if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) return ret; - if (ssl->earlyData != 2) { + if (ssl->earlyData != process_early_data) { if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; } @@ -5192,16 +5410,21 @@ static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ENTER("DoTls13Certificate"); ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz); - -#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (ret == 0 && ssl->options.side == WOLFSSL_SERVER_END && - ssl->options.handShakeState == HANDSHAKE_DONE) { - /* reset handshake states */ - ssl->options.serverState = SERVER_FINISHED_COMPLETE; - ssl->options.acceptState = TICKET_SENT; - ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; - } + if (ret == 0) { +#if !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; #endif +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.acceptState = TICKET_SENT; + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + } +#endif + } WOLFSSL_LEAVE("DoTls13Certificate", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); @@ -5511,7 +5734,10 @@ exit_dcv: return ret; } + else #endif /* WOLFSSL_ASYNC_CRYPT */ + if (ret != 0) + SendAlert(ssl, alert_fatal, decrypt_error); /* Final cleanup */ FreeDcv13Args(ssl, args); @@ -5581,6 +5807,7 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Actually check verify data. */ if (XMEMCMP(input + *inOutIdx, mac, size) != 0){ WOLFSSL_MSG("Verify finished error on hashes"); + SendAlert(ssl, alert_fatal, decrypt_error); return VERIFY_FINISHED_ERROR; } } @@ -5591,7 +5818,7 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.side == WOLFSSL_SERVER_END && !ssl->options.handShakeDone) { #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0) return ret; } @@ -5709,7 +5936,7 @@ static int SendTls13Finished(WOLFSSL* ssl) return ret; } if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY, - !ssl->earlyData)) != 0) { + ssl->earlyData == no_early_data)) != 0) { return ret; } #else @@ -5725,7 +5952,7 @@ static int SendTls13Finished(WOLFSSL* ssl) if (ssl->options.side == WOLFSSL_CLIENT_END && !ssl->options.handShakeDone) { #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { return ret; @@ -5741,18 +5968,16 @@ static int SendTls13Finished(WOLFSSL* ssl) #endif } - if (ssl->options.resuming) { - if (ssl->options.side == WOLFSSL_CLIENT_END) { - ssl->options.handShakeState = HANDSHAKE_DONE; - ssl->options.handShakeDone = 1; - } - } #ifndef NO_WOLFSSL_CLIENT if (ssl->options.side == WOLFSSL_CLIENT_END) { - if (!ssl->options.resuming) { - ssl->options.handShakeState = HANDSHAKE_DONE; - ssl->options.handShakeDone = 1; - } + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; } #endif @@ -5974,12 +6199,20 @@ static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input, if ((*inOutIdx - begin) != size) return BUFFER_ERROR; + if (ssl->earlyData == no_early_data) { + WOLFSSL_MSG("EndOfEarlyData recieved unexpectedly"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + ssl->earlyData = done_early_data; + /* Always encrypted. */ *inOutIdx += ssl->keys.padSz; ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY); - WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret); + WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret); WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO); return ret; @@ -6076,6 +6309,7 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, if (nonceLength > 0) XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); #endif + ssl->session.namedGroup = ssl->namedGroup; if ((*inOutIdx - begin) + EXTS_SZ > size) return BUFFER_ERROR; @@ -6168,7 +6402,7 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) return ret; header[FINISHED_MSG_SIZE_OFFSET] = finishedSz; #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 }; ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); if (ret != 0) @@ -6346,6 +6580,16 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #ifndef NO_WOLFSSL_SERVER case client_hello: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("ClientHello received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("ClientHello received out of order"); + return OUT_OF_ORDER_E; + } if (ssl->msgsReceived.got_client_hello == 2) { WOLFSSL_MSG("Too many ClientHello received"); return DUPLICATE_MSG_E; @@ -6357,27 +6601,43 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #ifndef NO_WOLFSSL_CLIENT case server_hello: -#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("ServerHello received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifdef WOLFSSL_TLS13_DRAFT_18 if (ssl->msgsReceived.got_server_hello) { WOLFSSL_MSG("Duplicate ServerHello received"); return DUPLICATE_MSG_E; } ssl->msgsReceived.got_server_hello = 1; -#else + #else if (ssl->msgsReceived.got_server_hello == 2) { WOLFSSL_MSG("Duplicate ServerHello received"); return DUPLICATE_MSG_E; } ssl->msgsReceived.got_server_hello++; -#endif + #endif break; #endif #ifndef NO_WOLFSSL_CLIENT case session_ticket: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("NewSessionTicket received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("NewSessionTicket received out of order"); + return OUT_OF_ORDER_E; + } if (ssl->msgsReceived.got_session_ticket) { - WOLFSSL_MSG("Duplicate SessionTicket received"); + WOLFSSL_MSG("Duplicate NewSessionTicket received"); return DUPLICATE_MSG_E; } ssl->msgsReceived.got_session_ticket = 1; @@ -6388,6 +6648,20 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #ifndef NO_WOLFSSL_SERVER #ifdef WOLFSSL_EARLY_DATA case end_of_early_data: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("EndOfEarlyData received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } if (ssl->msgsReceived.got_end_of_early_data == 1) { WOLFSSL_MSG("Too many EndOfEarlyData received"); return DUPLICATE_MSG_E; @@ -6398,8 +6672,19 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #endif #endif -#ifndef NO_WOLFSSL_CLIENT +#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifndef NO_WOLFSSL_CLIENT case hello_retry_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("HelloRetryRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("HelloRetryRequest received out of order"); + return OUT_OF_ORDER_E; + } if (ssl->msgsReceived.got_hello_retry_request) { WOLFSSL_MSG("Duplicate HelloRetryRequest received"); return DUPLICATE_MSG_E; @@ -6407,10 +6692,21 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) ssl->msgsReceived.got_hello_retry_request = 1; break; + #endif #endif #ifndef NO_WOLFSSL_CLIENT case encrypted_extensions: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("EncryptedExtensions received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState != SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("EncryptedExtensions received out of order"); + return OUT_OF_ORDER_E; + } if (ssl->msgsReceived.got_encrypted_extensions) { WOLFSSL_MSG("Duplicate EncryptedExtensions received"); return DUPLICATE_MSG_E; @@ -6421,37 +6717,71 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #endif case certificate: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Client"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("Certificate received while using PSK"); + return SANITY_MSG_E; + } + #endif + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Server"); + return OUT_OF_ORDER_E; + } + #endif if (ssl->msgsReceived.got_certificate) { WOLFSSL_MSG("Duplicate Certificate received"); return DUPLICATE_MSG_E; } ssl->msgsReceived.got_certificate = 1; -#ifndef NO_WOLFSSL_CLIENT - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if ( ssl->msgsReceived.got_server_hello == 0) { - WOLFSSL_MSG("No ServerHello before Cert"); - return OUT_OF_ORDER_E; - } - } -#endif -#ifndef NO_WOLFSSL_SERVER - if (ssl->options.side == WOLFSSL_SERVER_END) { - if ( ssl->msgsReceived.got_client_hello == 0) { - WOLFSSL_MSG("No ClientHello before Cert"); - return OUT_OF_ORDER_E; - } - } -#endif break; #ifndef NO_WOLFSSL_CLIENT case certificate_request: - #ifdef WOLFSSL_POST_HANDSHAKE_AUTH - if (ssl->msgsReceived.got_finished) - ; - else - #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("CertificateRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #else + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + (ssl->options.serverState != SERVER_FINISHED_COMPLETE || + ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateRequset received while using PSK"); + return SANITY_MSG_E; + return SANITY_MSG_E; + } + #endif if (ssl->msgsReceived.got_certificate_request) { WOLFSSL_MSG("Duplicate CertificateRequest received"); return DUPLICATE_MSG_E; @@ -6462,24 +6792,77 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #endif case certificate_verify: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState != SERVER_CERT_COMPLETE) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateVerify received while using PSK"); + return SANITY_MSG_E; + } + #endif + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("CertificateVerify received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("CertificateVerify before ClientHello done"); + return OUT_OF_ORDER_E; + } + if (!ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("No Cert before CertificateVerify"); + return OUT_OF_ORDER_E; + } + } + #endif if (ssl->msgsReceived.got_certificate_verify) { WOLFSSL_MSG("Duplicate CertificateVerify received"); return DUPLICATE_MSG_E; } ssl->msgsReceived.got_certificate_verify = 1; - if (ssl->msgsReceived.got_certificate == 0) { - WOLFSSL_MSG("No Cert before CertVerify"); - return OUT_OF_ORDER_E; - } break; case finished: - #ifdef WOLFSSL_POST_HANDSHAKE_AUTH - if (1) { + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.serverState < + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } } - else - #endif + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == process_early_data) { + return OUT_OF_ORDER_E; + } + #endif + } + #endif if (ssl->msgsReceived.got_finished) { WOLFSSL_MSG("Duplicate Finished received"); return DUPLICATE_MSG_E; @@ -6528,8 +6911,9 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, return INCOMPLETE_DATA; /* sanity check msg received */ - if ( (ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { + if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + SendAlert(ssl, alert_fatal, unexpected_message); return ret; } @@ -6568,38 +6952,54 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* above checks handshake state */ switch (type) { - #ifndef NO_WOLFSSL_CLIENT -#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Messages only recieved by client. */ + #ifdef WOLFSSL_TLS13_DRAFT_18 case hello_retry_request: WOLFSSL_MSG("processing hello rety request"); ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); break; -#endif + #endif case server_hello: WOLFSSL_MSG("processing server hello"); - ret = DoTls13ServerHello(ssl, input, inOutIdx, size); - break; - -#ifndef NO_CERTS - case certificate_request: - WOLFSSL_MSG("processing certificate request"); - ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); - break; -#endif - - case session_ticket: - WOLFSSL_MSG("processing new session ticket"); - ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type); break; case encrypted_extensions: WOLFSSL_MSG("processing encrypted extensions"); ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size); break; + + #ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); + break; + #endif + + case session_ticket: + WOLFSSL_MSG("processing new session ticket"); + ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + break; #endif /* !NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER + /* Messages only recieved by server. */ + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; + + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + WOLFSSL_MSG("processing end of early data"); + ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size); + break; + #endif +#endif /* !NO_WOLFSSL_SERVER */ + + /* Messages recieved by both client and server. */ #ifndef NO_CERTS case certificate: WOLFSSL_MSG("processing certificate"); @@ -6614,15 +7014,6 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; #endif /* !NO_RSA || HAVE_ECC */ -#ifdef WOLFSSL_EARLY_DATA - #ifndef NO_WOLFSSL_SERVER - case end_of_early_data: - WOLFSSL_MSG("processing end of early data"); - ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size); - break; - #endif -#endif - case finished: WOLFSSL_MSG("processing finished"); ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); @@ -6633,13 +7024,6 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); break; -#ifndef NO_WOLFSSL_SERVER - case client_hello: - WOLFSSL_MSG("processing client hello"); - ret = DoTls13ClientHello(ssl, input, inOutIdx, size); - break; -#endif /* !NO_WOLFSSL_SERVER */ - default: WOLFSSL_MSG("Unknown handshake message type"); ret = UNKNOWN_HANDSHAKE_TYPE; @@ -6650,22 +7034,22 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret == 0 && ssl->error == WC_PENDING_E) ssl->error = 0; - if (ret == 0 && type != client_hello && type != session_ticket && - type != key_update && ssl->error != WC_PENDING_E) { + type != key_update) { ret = HashInput(ssl, input + inIdx, size); } if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) SendAlert(ssl, alert_fatal, decode_error); - - if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || - ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || - ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { + else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || + ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || + ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { SendAlert(ssl, alert_fatal, illegal_parameter); } if (ssl->options.tls1_3) { + /* Need to hash input message before deriving secrets. */ +#ifndef NO_WOLFSSL_CLIENT if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { if ((ret = DeriveEarlySecret(ssl)) != 0) return ret; @@ -6676,48 +7060,42 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { return ret; } -#ifdef WOLFSSL_EARLY_DATA + #ifdef WOLFSSL_EARLY_DATA if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; -#else + #else if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) return ret; -#endif + #endif } -#ifdef WOLFSSL_EARLY_DATA - if (type == encrypted_extensions && - ssl->options.side == WOLFSSL_CLIENT_END) { - if (!ssl->earlyData) - { - if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) - return ret; - } - } -#endif if (type == finished && ssl->options.side == WOLFSSL_CLIENT_END) { if ((ret = DeriveMasterSecret(ssl)) != 0) return ret; -#ifdef WOLFSSL_EARLY_DATA + #ifdef WOLFSSL_EARLY_DATA if ((ret = DeriveTls13Keys(ssl, traffic_key, - ENCRYPT_AND_DECRYPT_SIDE, !ssl->earlyData)) != 0) { + ENCRYPT_AND_DECRYPT_SIDE, + ssl->earlyData == no_early_data)) != 0) { return ret; } -#else + #else if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { return ret; } -#endif + #endif } +#endif /* NO_WOLFSSL_CLIENT */ -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) { ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); if (ret != 0) return ret; } -#endif + #endif +#endif /* NO_WOLFSSL_SERVER */ } #ifdef WOLFSSL_ASYNC_CRYPT @@ -6852,8 +7230,6 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, */ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) { - int neededState; - WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); #ifdef HAVE_ERRNO_H @@ -6898,7 +7274,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) ssl->options.connectState = CLIENT_HELLO_SENT; WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) if ((ssl->error = SendChangeCipher(ssl)) != 0) { @@ -6914,19 +7290,13 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case CLIENT_HELLO_SENT: - neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : - SERVER_HELLODONE_COMPLETE; /* Get the response/s from the server. */ - while (ssl->options.serverState < neededState) { + while (ssl->options.serverState < + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { if ((ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } - /* if resumption failed, reset needed state. */ - if (neededState == SERVER_FINISHED_COMPLETE && - !ssl->options.resuming) { - neededState = SERVER_HELLODONE_COMPLETE; - } } ssl->options.connectState = HELLO_AGAIN; @@ -6945,8 +7315,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) return VERSION_ERROR; } - if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { - ssl->options.serverState = NULL_STATE; + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) if (!ssl->options.sentChangeCipher) { @@ -6969,22 +7339,11 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case HELLO_AGAIN_REPLY: - if (ssl->options.serverState == NULL_STATE || - ssl->error == WC_PENDING_E) { - neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : - SERVER_HELLODONE_COMPLETE; - - /* Get the response/s from the server. */ - while (ssl->options.serverState < neededState) { - if ((ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - /* if resumption failed, reset needed state */ - else if (neededState == SERVER_FINISHED_COMPLETE) { - if (!ssl->options.resuming) - neededState = SERVER_HELLODONE_COMPLETE; - } + /* Get the response/s from the server. */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; } } @@ -6994,7 +7353,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) case FIRST_REPLY_DONE: #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; @@ -7290,7 +7649,7 @@ int wolfSSL_update_keys(WOLFSSL* ssl) /* Allow post-handshake authentication in TLS v1.3 connections. * * ctx The SSL/TLS CTX object. - * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a client and * 0 on success. */ int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx) @@ -7309,7 +7668,7 @@ int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx) * * ssl The SSL/TLS object. * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, - * SIDE_ERROR when not a server and 0 on success. + * SIDE_ERROR when not a client and 0 on success. */ int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl) { @@ -7363,6 +7722,80 @@ int wolfSSL_request_certificate(WOLFSSL* ssl) } #endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */ +#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +/* Get the preferred key exchange group. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, + * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete + * and group number on success. + */ +int wolfSSL_preferred_group(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + + /* Return supported groups only. */ + ret = TLSX_SupportedCurve_Preferred(ssl, 1); + + return ret; +} +#endif + +/* Sets the key exchange groups in rank order on a context. + * + * ctx SSL/TLS context object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) +{ + int i; + + if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ctx->group[i] = groups[i]; + ctx->numGroups = count; + + return WOLFSSL_SUCCESS; +} + +/* Sets the key exchange groups in rank order. + * + * ssl SSL/TLS object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) +{ + int i; + + if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ssl->group[i] = groups[i]; + ssl->numGroups = count; + + return WOLFSSL_SUCCESS; +} + #ifndef NO_WOLFSSL_SERVER /* The server accepting a connection from a client. * The protocol version is expecting to be TLS v1.3. @@ -7378,7 +7811,6 @@ int wolfSSL_request_certificate(WOLFSSL* ssl) int wolfSSL_accept_TLSv13(WOLFSSL* ssl) { word16 havePSK = 0; - word16 haveAnon = 0; WOLFSSL_ENTER("SSL_accept_TLSv13()"); #ifdef HAVE_ERRNO_H @@ -7390,11 +7822,6 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) #endif (void)havePSK; -#ifdef HAVE_ANON - haveAnon = ssl->options.haveAnon; -#endif - (void)haveAnon; - if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); return WOLFSSL_FATAL_ERROR; @@ -7402,7 +7829,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) #ifndef NO_CERTS /* allow no private key if using PK callbacks and CB is set */ - if (!havePSK && !haveAnon) { + if (!havePSK) { if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) { @@ -7449,7 +7876,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) switch (ssl->options.acceptState) { case ACCEPT_BEGIN : - /* get response */ + /* get client_hello */ while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { if ((ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); @@ -7463,14 +7890,16 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) case ACCEPT_CLIENT_HELLO_DONE : #ifdef WOLFSSL_TLS13_DRAFT_18 - if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } #else - if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { if ((ssl->error = SendTls13ServerHello(ssl, hello_retry_request)) != 0) { WOLFSSL_ERROR(ssl->error); @@ -7490,7 +7919,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case ACCEPT_HELLO_RETRY_REQUEST_DONE : - if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { ssl->options.clientState = NULL_STATE; while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { if ((ssl->error = ProcessReply(ssl)) < 0) { @@ -7590,7 +8020,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) ssl->options.acceptState = ACCEPT_FINISHED_DONE; WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData) { + if (ssl->earlyData != no_early_data) { ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; return WOLFSSL_SUCCESS; } @@ -7735,7 +8165,7 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) return SIDE_ERROR; if (ssl->options.handShakeState == NULL_STATE) { - ssl->earlyData = 1; + ssl->earlyData = expecting_early_data; ret = wolfSSL_connect_TLSv13(ssl); if (ret <= 0) return WOLFSSL_FATAL_ERROR; @@ -7779,7 +8209,7 @@ int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) return SIDE_ERROR; if (ssl->options.handShakeState == NULL_STATE) { - ssl->earlyData = 1; + ssl->earlyData = expecting_early_data; ret = wolfSSL_accept_TLSv13(ssl); if (ret <= 0) return WOLFSSL_FATAL_ERROR; diff --git a/tests/api.c b/tests/api.c index 59e9393f2..a2a5bc278 100644 --- a/tests/api.c +++ b/tests/api.c @@ -18087,6 +18087,8 @@ static int test_tls13_apis(void) #ifdef WOLFSSL_EARLY_DATA int outSz; #endif + int groups[1] = { WOLFSSL_ECC_X25519 }; + int numGroups = 1; clientTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); clientTls12Ssl = wolfSSL_new(clientTls12Ctx); @@ -18190,6 +18192,38 @@ static int test_tls13_apis(void) AssertIntEQ(wolfSSL_request_certificate(serverSsl), NOT_READY_ERROR); #endif +#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT + AssertIntEQ(wolfSSL_preferred_group(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_preferred_group(serverSsl), SIDE_ERROR); + AssertIntEQ(wolfSSL_preferred_group(clientTls12Ssl), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_preferred_group(clientSsl), NOT_READY_ERROR); +#endif + + AssertIntEQ(wolfSSL_CTX_set_groups(NULL, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(clientTls12Ctx, groups, numGroups), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, + WOLFSSL_MAX_GROUP_COUNT + 1), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, numGroups), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_set_groups(serverCtx, groups, numGroups), + WOLFSSL_SUCCESS); + + AssertIntEQ(wolfSSL_set_groups(NULL, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(clientSsl, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(clientTls12Ssl, groups, numGroups), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(clientSsl, groups, + WOLFSSL_MAX_GROUP_COUNT + 1), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(clientSsl, groups, numGroups), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_set_groups(serverSsl, groups, numGroups), + WOLFSSL_SUCCESS); + #ifdef WOLFSSL_EARLY_DATA AssertIntEQ(wolfSSL_CTX_set_max_early_data(NULL, 0), BAD_FUNC_ARG); AssertIntEQ(wolfSSL_CTX_set_max_early_data(clientCtx, 0), SIDE_ERROR); diff --git a/tests/test-tls13-ecc.conf b/tests/test-tls13-ecc.conf index e15d0878c..04f5022ee 100644 --- a/tests/test-tls13-ecc.conf +++ b/tests/test-tls13-ecc.conf @@ -1,12 +1,12 @@ -# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 -v 4 --l TLS13-CHACH20-POLY1305-SHA256 +-l TLS13-CHACHA20-POLY1305-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 -v 4 --l TLS13-CHACH20-POLY1305-SHA256 +-l TLS13-CHACHA20-POLY1305-SHA256 -A ./certs/ca-ecc-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 @@ -58,6 +58,7 @@ -l TLS13-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem +-t # client TLSv1.3 TLS13-AES128-GCM-SHA256 -v 4 @@ -65,3 +66,16 @@ -A ./certs/ca-ecc-cert.pem -t +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem +-Y + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-y + diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf index 8147c20bf..532934b89 100644 --- a/tests/test-tls13.conf +++ b/tests/test-tls13.conf @@ -1,10 +1,10 @@ -# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 -v 4 --l TLS13-CHACH20-POLY1305-SHA256 +-l TLS13-CHACHA20-POLY1305-SHA256 -# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 -v 4 --l TLS13-CHACH20-POLY1305-SHA256 +-l TLS13-CHACHA20-POLY1305-SHA256 # server TLSv1.3 TLS13-AES128-GCM-SHA256 -v 4 diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 432365d17..eed6a3057 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1026,6 +1026,7 @@ enum Misc { TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */ TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */ +#ifndef WOLFSSL_TLS13_FINAL TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ #ifdef WOLFSSL_TLS13_DRAFT_18 TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ @@ -1034,7 +1035,8 @@ enum Misc { #elif defined(WOLFSSL_TLS13_DRAFT_23) TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */ #else - TLS_DRAFT_MINOR = 0x1b, /* Minor version number of TLS draft */ + TLS_DRAFT_MINOR = 0x1c, /* Minor version number of TLS draft */ +#endif #endif OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ @@ -1380,6 +1382,7 @@ enum states { NULL_STATE = 0, SERVER_HELLOVERIFYREQUEST_COMPLETE, + SERVER_HELLO_RETRY_REQUEST_COMPLETE, SERVER_HELLO_COMPLETE, SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, SERVER_CERT_COMPLETE, @@ -1387,7 +1390,6 @@ enum states { SERVER_HELLODONE_COMPLETE, SERVER_CHANGECIPHERSPEC_COMPLETE, SERVER_FINISHED_COMPLETE, - SERVER_HELLO_RETRY_REQUEST, CLIENT_HELLO_COMPLETE, CLIENT_KEYEXCHANGE_COMPLETE, @@ -1465,6 +1467,8 @@ struct WOLFSSL_METHOD { /* wolfSSL buffer type - internal uses "buffer" type */ typedef WOLFSSL_BUFFER_INFO buffer; +typedef struct Suites Suites; + /* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); @@ -1474,6 +1478,8 @@ WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz, int sniff); WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx); /* TLS v1.3 needs these */ +WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID, + Suites* clSuites); WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); #ifdef WOLFSSL_TLS13 @@ -1513,7 +1519,8 @@ WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz); WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, - word32* inOutIdx, word32 helloSz); + word32* inOutIdx, word32 helloSz, + byte* extMsgType); #endif @@ -1594,7 +1601,7 @@ typedef struct { } bufferStatic; /* Cipher Suites holder */ -typedef struct Suites { +struct Suites { word16 suiteSz; /* suite length in bytes */ word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ byte suites[WOLFSSL_MAX_SUITE_SZ]; @@ -1602,7 +1609,7 @@ typedef struct Suites { byte setSuites; /* user set suites from default */ byte hashAlgo; /* selected hash algorithm */ byte sigAlgo; /* selected sig algorithm */ -} Suites; +}; WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, @@ -1935,6 +1942,7 @@ typedef struct TLSX { } TLSX; WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type); +WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap); WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap); WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest); @@ -2100,6 +2108,9 @@ WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second); +WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, + int checkSupported); #endif #endif /* HAVE_SUPPORTED_CURVES */ @@ -2420,6 +2431,10 @@ struct WOLFSSL_CTX { wc_psk_server_callback server_psk_cb; /* server callback */ char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; #endif /* HAVE_SESSION_TICKET || !NO_PSK */ +#ifdef WOLFSSL_TLS13 + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; +#endif #ifdef WOLFSSL_EARLY_DATA word32 maxEarlyDataSz; #endif @@ -2773,9 +2788,11 @@ struct WOLFSSL_SESSION { byte sessionCtxSz; /* sessionCtx length */ byte sessionCtx[ID_LEN]; /* app specific context id */ #endif +#ifdef WOLFSSL_TLS13 + word16 namedGroup; +#endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 - byte namedGroup; word32 ticketSeen; /* Time ticket seen (ms) */ word32 ticketAdd; /* Added by client */ #ifndef WOLFSSL_TLS13_DRAFT_18 @@ -3060,8 +3077,12 @@ typedef struct Options { byte verifyDepth; /* maximum verification depth */ #endif #ifdef WOLFSSL_EARLY_DATA + word16 pskIdIndex; word32 maxEarlyDataSz; #endif +#ifdef WOLFSSL_TLS13 + byte oldMinor; /* client preferred version < TLS 1.3 */ +#endif } Options; typedef struct Arrays { @@ -3357,6 +3378,15 @@ struct CertReqCtx { }; #endif +#ifdef WOLFSSL_EARLY_DATA +typedef enum EarlyDataState { + no_early_data, + expecting_early_data, + process_early_data, + done_early_data +} EarlyDataState; +#endif + /* wolfSSL ssl type */ struct WOLFSSL { WOLFSSL_CTX* ctx; @@ -3448,6 +3478,8 @@ struct WOLFSSL { #endif #ifdef WOLFSSL_TLS13 word16 namedGroup; + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; #endif byte pssAlgo; #ifdef WOLFSSL_TLS13 @@ -3636,7 +3668,7 @@ struct WOLFSSL { void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ #endif /* WOLFSSL_JNI */ #ifdef WOLFSSL_EARLY_DATA - int earlyData; + EarlyDataState earlyData; word32 earlyDataSz; #endif }; diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index e1615af7e..7ed13a191 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -396,6 +396,8 @@ enum AlertLevel { /* Maximum master key length (SECRET_LEN) */ #define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 +/* Maximum number of groups that can be set */ +#define WOLFSSL_MAX_GROUP_COUNT 10 typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap); @@ -552,6 +554,11 @@ WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); + WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); @@ -575,12 +582,11 @@ WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *); -WOLFSSL_API int wolfSSL_set_session(WOLFSSL* ssl,WOLFSSL_SESSION* session); -WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* session, long t); -WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl); -WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX *ctx, long tm); -WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL* ssl, const unsigned char*, - int, int); +WOLFSSL_API int wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*); +WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long); +WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int); #ifdef SESSION_INDEX WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl);