mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-01 03:34:39 +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)
|
||||
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;
|
||||
|
@@ -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)) || \
|
||||
|
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 */
|
||||
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)
|
||||
|
113
src/tls13.c
113
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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user