mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
DTLS 1.3: allow the server to operate without maintaining state
This commit is contained in:
12
src/dtls13.c
12
src/dtls13.c
@@ -1388,6 +1388,18 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
|
|||||||
if (frag_off + frag_length > message_length)
|
if (frag_off + frag_length > message_length)
|
||||||
return BUFFER_ERROR;
|
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);
|
ret = Dtls13RtxMsgRecvd(ssl, (enum HandShakeType)handshake_type, frag_off);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -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 HashRaw(WOLFSSL* ssl, const byte* data, int sz)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
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)data;
|
||||||
(void)sz;
|
(void)sz;
|
||||||
@@ -8817,16 +8825,31 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
|
|||||||
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz);
|
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Sha256");
|
||||||
|
wc_Sha256GetHash(&ssl->hsHashes->hashSha256, digest);
|
||||||
|
WOLFSSL_BUFFER(digest, WC_SHA224_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_SHA384
|
#ifdef WOLFSSL_SHA384
|
||||||
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz);
|
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Sha384");
|
||||||
|
wc_Sha384GetHash(&ssl->hsHashes->hashSha384, digest);
|
||||||
|
WOLFSSL_BUFFER(digest, WC_SHA384_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_SHA512
|
#ifdef WOLFSSL_SHA512
|
||||||
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz);
|
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Sha512");
|
||||||
|
wc_Sha512GetHash(&ssl->hsHashes->hashSha512, digest);
|
||||||
|
WOLFSSL_BUFFER(digest, WC_SHA512_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
|
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
|
||||||
((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
|
((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
|
||||||
|
12
src/tls.c
12
src/tls.c
@@ -6167,8 +6167,16 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length,
|
|||||||
|
|
||||||
/* client_hello */
|
/* client_hello */
|
||||||
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
|
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
|
||||||
if (extension == NULL)
|
if (extension == NULL) {
|
||||||
return HRR_COOKIE_ERROR;
|
#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;
|
cookie = (Cookie*)extension->data;
|
||||||
if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
|
if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
|
||||||
|
113
src/tls13.c
113
src/tls13.c
@@ -2889,7 +2889,7 @@ int RestartHandshakeHash(WOLFSSL* ssl)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
|
#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];
|
byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
|
||||||
TLSX* ext;
|
TLSX* ext;
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
@@ -4833,6 +4833,10 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
|
|||||||
return ret;
|
return ret;
|
||||||
if ((ret = HashRaw(ssl, header, sizeof(header))) != 0)
|
if ((ret = HashRaw(ssl, header, sizeof(header))) != 0)
|
||||||
return ret;
|
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)
|
if ((ret = HashRaw(ssl, cookieData + idx, hashSz)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -5282,20 +5286,45 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
|
|
||||||
#if defined(WOLFSSL_SEND_HRR_COOKIE)
|
#if defined(WOLFSSL_SEND_HRR_COOKIE)
|
||||||
if (ssl->options.sendCookie &&
|
if (ssl->options.sendCookie &&
|
||||||
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
|
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
|
||||||
TLSX* ext;
|
#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)
|
if (ext != NULL) {
|
||||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
/* Ensure the cookie came from client and isn't the one in the
|
||||||
|
* response - HelloRetryRequest.
|
||||||
/* 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);
|
||||||
if (ext->resp == 1)
|
#ifdef WOLFSSL_DTLS13
|
||||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
/* Send a new cookie request */
|
||||||
ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
|
if (ret == HRR_COOKIE_ERROR && ssl->options.dtls)
|
||||||
if (ret != 0)
|
ssl->options.serverState = NULL_STATE;
|
||||||
goto exit_dch;
|
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
|
#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
|
/* We are using DTLSv13 and set the HRR cookie secret, use the cookie to
|
||||||
perform a return-routability check. */
|
perform a return-routability check. */
|
||||||
if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie &&
|
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
|
so the client already provided a good KeyShareEntry. In this case
|
||||||
we don't add the KEY_SHARE extension to the HelloRetryRequest or
|
we don't add the KEY_SHARE extension to the HelloRetryRequest or
|
||||||
in the Cookie. The RFC8446 forbids to select a supported group
|
in the Cookie. The RFC8446 forbids to select a supported group
|
||||||
@@ -5556,18 +5585,27 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SEND_HRR_COOKIE
|
||||||
#ifdef WOLFSSL_DTLS13
|
if (ssl->options.sendCookie && extMsgType == hello_retry_request) {
|
||||||
if (ssl->options.dtls) {
|
/* Reset the hashes from here. We will be able to restart the hashes
|
||||||
ret = Dtls13HashHandshake(ssl,
|
* from the cookie in RestartHandshakeHashWithCookie */
|
||||||
output + Dtls13GetRlHeaderLength(0) ,
|
ret = InitHandshakeHashes(ssl);
|
||||||
sendSz - Dtls13GetRlHeaderLength(0));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
if (ssl->options.dtls) {
|
||||||
|
ret = Dtls13HashHandshake(ssl,
|
||||||
|
output + Dtls13GetRlHeaderLength(0) ,
|
||||||
|
sendSz - Dtls13GetRlHeaderLength(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
{
|
{
|
||||||
ret = HashOutput(ssl, output, sendSz, 0);
|
ret = HashOutput(ssl, output, sendSz, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -5598,7 +5636,6 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
|||||||
ssl->buffers.outputBuffer.length += sendSz;
|
ssl->buffers.outputBuffer.length += sendSz;
|
||||||
|
|
||||||
if (!ssl->options.groupMessages || extMsgType != server_hello)
|
if (!ssl->options.groupMessages || extMsgType != server_hello)
|
||||||
|
|
||||||
ret = SendBuffered(ssl);
|
ret = SendBuffered(ssl);
|
||||||
|
|
||||||
WOLFSSL_LEAVE("SendTls13ServerHello", ret);
|
WOLFSSL_LEAVE("SendTls13ServerHello", ret);
|
||||||
@@ -10754,6 +10791,36 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
|
|||||||
WOLFSSL_ERROR(ssl->error);
|
WOLFSSL_ERROR(ssl->error);
|
||||||
return WOLFSSL_FATAL_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;
|
ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE;
|
||||||
|
@@ -463,6 +463,7 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
|||||||
WOLFSSL_BUFFER(prk, prkLen);
|
WOLFSSL_BUFFER(prk, prkLen);
|
||||||
WOLFSSL_MSG(" Info");
|
WOLFSSL_MSG(" Info");
|
||||||
WOLFSSL_BUFFER(data, idx);
|
WOLFSSL_BUFFER(data, idx);
|
||||||
|
WOLFSSL_MSG_EX(" Digest %d", digest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
|
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
|
||||||
|
Reference in New Issue
Block a user