diff --git a/src/dtls13.c b/src/dtls13.c index 2f30c98db..0954f6f8a 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -1388,6 +1388,18 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, if (frag_off + frag_length > message_length) return BUFFER_ERROR; + if (handshake_type == client_hello && + /* Only when receiving an unverified ClientHello */ + ssl->options.serverState < SERVER_HELLO_COMPLETE) { + /* To be able to operate in stateless mode, we assume the ClientHello + * is in order and we use its Handshake Message number and Sequence + * Number for our Tx. */ + ssl->keys.dtls_expected_peer_handshake_number = + ssl->keys.dtls_handshake_number = + ssl->keys.dtls_peer_handshake_number; + ssl->dtls13Epochs[0].nextSeqNumber = ssl->keys.curSeq; + } + ret = Dtls13RtxMsgRecvd(ssl, (enum HandShakeType)handshake_type, frag_off); if (ret != 0) return ret; diff --git a/src/internal.c b/src/internal.c index 98286ba8c..f0b3f696d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8788,6 +8788,14 @@ static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz) int HashRaw(WOLFSSL* ssl, const byte* data, int sz) { int ret = 0; +#ifdef WOLFSSL_DEBUG_TLS + byte digest[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_MSG("HashRaw:"); + WOLFSSL_MSG("Data:"); + WOLFSSL_BUFFER(data, sz); + WOLFSSL_MSG("Hashes:"); +#endif (void)data; (void)sz; @@ -8817,16 +8825,31 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz) ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz); if (ret != 0) return ret; + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Sha256"); + wc_Sha256GetHash(&ssl->hsHashes->hashSha256, digest); + WOLFSSL_BUFFER(digest, WC_SHA224_DIGEST_SIZE); + #endif #endif #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz); if (ret != 0) return ret; + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Sha384"); + wc_Sha384GetHash(&ssl->hsHashes->hashSha384, digest); + WOLFSSL_BUFFER(digest, WC_SHA384_DIGEST_SIZE); + #endif #endif #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz); if (ret != 0) return ret; + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Sha512"); + wc_Sha512GetHash(&ssl->hsHashes->hashSha512, digest); + WOLFSSL_BUFFER(digest, WC_SHA512_DIGEST_SIZE); + #endif #endif #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ diff --git a/src/tls.c b/src/tls.c index 8a6617bd6..af3f197db 100644 --- a/src/tls.c +++ b/src/tls.c @@ -6167,8 +6167,16 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* client_hello */ extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); - if (extension == NULL) - return HRR_COOKIE_ERROR; + if (extension == NULL) { +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + /* TODO: Should we allow a ClientHello with a valid cookie even if + * the cookie wasn't sent by this WOLFSSL object? */ + return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0); + else +#endif + return HRR_COOKIE_ERROR; + } cookie = (Cookie*)extension->data; if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0) diff --git a/src/tls13.c b/src/tls13.c index ae3e32c5b..b8ec8a130 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2889,7 +2889,7 @@ int RestartHandshakeHash(WOLFSSL* ssl) #endif #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) - if (ssl->options.sendCookie) { + if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) { byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; TLSX* ext; word32 idx = 0; @@ -4833,6 +4833,10 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) return ret; if ((ret = HashRaw(ssl, header, sizeof(header))) != 0) return ret; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Restart Hash from Cookie"); + WOLFSSL_BUFFER(cookieData + idx, hashSz); +#endif if ((ret = HashRaw(ssl, cookieData + idx, hashSz)) != 0) return ret; @@ -5282,20 +5286,45 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(WOLFSSL_SEND_HRR_COOKIE) if (ssl->options.sendCookie && - ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) { - TLSX* ext; + (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE +#ifdef WOLFSSL_DTLS13 + /* Always check for a valid cookie since we may have already + * sent a HRR but we reset the state. */ + || ssl->options.dtls +#endif + )) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_COOKIE); - if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) - ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); - - /* Ensure the cookie came from client and isn't the one in the - * response - HelloRetryRequest. - */ - if (ext->resp == 1) - ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); - ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); - if (ret != 0) - goto exit_dch; + if (ext != NULL) { + /* Ensure the cookie came from client and isn't the one in the + * response - HelloRetryRequest. + */ + if (ext->resp == 0) { + ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); +#ifdef WOLFSSL_DTLS13 + /* Send a new cookie request */ + if (ret == HRR_COOKIE_ERROR && ssl->options.dtls) + ssl->options.serverState = NULL_STATE; + else +#endif + if (ret != 0) + goto exit_dch; + ssl->options.serverState = SERVER_HELLO_COMPLETE; + } + else { +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + ssl->options.serverState = NULL_STATE; + else +#endif + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + } + } + else +#ifdef WOLFSSL_DTLS13 + if (!ssl->options.dtls) +#endif + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); } #endif @@ -5424,9 +5453,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* We are using DTLSv13 and set the HRR cookie secret, use the cookie to perform a return-routability check. */ if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie && - ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE) { - /* ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE + /* ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE so the client already provided a good KeyShareEntry. In this case we don't add the KEY_SHARE extension to the HelloRetryRequest or in the Cookie. The RFC8446 forbids to select a supported group @@ -5556,18 +5585,27 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) if (ret != 0) return ret; - -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls) { - ret = Dtls13HashHandshake(ssl, - output + Dtls13GetRlHeaderLength(0) , - sendSz - Dtls13GetRlHeaderLength(0)); +#ifdef WOLFSSL_SEND_HRR_COOKIE + if (ssl->options.sendCookie && extMsgType == hello_retry_request) { + /* Reset the hashes from here. We will be able to restart the hashes + * from the cookie in RestartHandshakeHashWithCookie */ + ret = InitHandshakeHashes(ssl); } else +#endif + { +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + ret = Dtls13HashHandshake(ssl, + output + Dtls13GetRlHeaderLength(0) , + sendSz - Dtls13GetRlHeaderLength(0)); + } + else #endif /* WOLFSSL_DTLS13 */ { ret = HashOutput(ssl, output, sendSz, 0); } + } if (ret != 0) return ret; @@ -5598,7 +5636,6 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) ssl->buffers.outputBuffer.length += sendSz; if (!ssl->options.groupMessages || extMsgType != server_hello) - ret = SendBuffered(ssl); WOLFSSL_LEAVE("SendTls13ServerHello", ret); @@ -10754,6 +10791,36 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && wolfSSL_dtls_get_using_nonblock(ssl)) { + /* Reset the state so that we can statelessly await the + * ClientHello that contains the cookie. Return a WANT_READ + * to the user so that we don't drop UDP messages in the + * network callbacks. */ + + /* Reset DTLS window */ + w64Zero(&ssl->dtls13Epochs[0].nextSeqNumber); + w64Zero(&ssl->dtls13Epochs[0].nextPeerSeqNumber); + XMEMSET(ssl->dtls13Epochs[0].window, 0, + sizeof(ssl->dtls13Epochs[0].window)); + + ssl->keys.dtls_expected_peer_handshake_number = 0; + ssl->keys.dtls_handshake_number = 0; + + ssl->msgsReceived.got_client_hello = 0; + + /* Reset states */ + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + + ssl->error = WANT_READ; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } +#endif /* WOLFSSL_DTLS13 */ } ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE; diff --git a/wolfcrypt/src/kdf.c b/wolfcrypt/src/kdf.c index 77adf8e30..2960b3acc 100644 --- a/wolfcrypt/src/kdf.c +++ b/wolfcrypt/src/kdf.c @@ -463,6 +463,7 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, WOLFSSL_BUFFER(prk, prkLen); WOLFSSL_MSG(" Info"); WOLFSSL_BUFFER(data, idx); + WOLFSSL_MSG_EX(" Digest %d", digest); #endif ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);