Async fixes

This commit is contained in:
Juliusz Sosinowicz
2023-02-22 09:46:02 +01:00
parent f5f67f43d7
commit 335722c586
7 changed files with 107 additions and 41 deletions

View File

@@ -744,7 +744,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
/* TLSX_KeyShare_Choose is done deep inside MatchSuite_ex */ /* TLSX_KeyShare_Choose is done deep inside MatchSuite_ex */
ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts);
if (ret < 0) { if (ret < 0) {
WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); WOLFSSL_MSG("Unsupported cipher suite, ClientHello DTLS 1.3");
ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup);
} }
} }

View File

@@ -363,8 +363,10 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
msg->sz, msg->sz); msg->sz, msg->sz);
/* processing certificate_request triggers a connect. The error came /* processing certificate_request triggers a connect. The error came
* from there, the message can be considered processed successfully */ * from there, the message can be considered processed successfully.
if (ret == 0 || (msg->type == certificate_request && * WANT_WRITE means that we are done with processing the msg and we are
* waiting to flush the output buffer. */
if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request &&
ssl->options.handShakeDone && ret == WC_PENDING_E)) { ssl->options.handShakeDone && ret == WC_PENDING_E)) {
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type); Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);

View File

@@ -20125,7 +20125,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
) { ) {
/* Shrink input buffer when we successfully finish record /* Shrink input buffer when we successfully finish record
* processing */ * processing */
if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) if ((ret == 0) && ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, NO_FORCED_FREE); ShrinkInputBuffer(ssl, NO_FORCED_FREE);
return ret; return ret;
} }

View File

@@ -7393,7 +7393,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
* kse The key share entry holding peer data. * kse The key share entry holding peer data.
*/ */
static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
{ {
int ret; int ret;
/* Named FFDHE groups have a bit set to identify them. */ /* Named FFDHE groups have a bit set to identify them. */
@@ -9027,6 +9027,7 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
TLSX* extension; TLSX* extension;
SupportedCurve* curve = NULL; SupportedCurve* curve = NULL;
SupportedCurve* preferredCurve = NULL; SupportedCurve* preferredCurve = NULL;
KeyShareEntry* kse = NULL;
int preferredRank = WOLFSSL_MAX_GROUP_COUNT; int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
int rank; int rank;
@@ -9055,27 +9056,32 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
return BAD_KEY_SHARE_DATA; return BAD_KEY_SHARE_DATA;
} }
/* Delete the old key share data list. */ #ifdef WOLFSSL_ASYNC_CRYPT
/* Check the old key share data list. */
extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
if (extension != NULL) { if (extension != NULL) {
KeyShareEntry* kse = (KeyShareEntry*)extension->data; kse = (KeyShareEntry*)extension->data;
#ifdef WOLFSSL_ASYNC_CRYPT /* We should not be computing keys if we are only going to advertise
/* for async don't free, call `TLSX_KeyShare_Use` again */ * our choice here. */
if (kse && kse->lastRet != WC_PENDING_E) if (kse != NULL && kse->lastRet == WC_PENDING_E) {
WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
return BAD_KEY_SHARE_DATA;
}
}
#endif #endif
{
TLSX_KeyShare_FreeAll(kse, ssl->heap);
extension->data = NULL;
}
}
/* Add in the chosen group. */ /* Push new KeyShare extension. This will also free the old one */
ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL, extensions); ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
if (ret != 0 && ret != WC_PENDING_E) if (ret != 0)
return ret;
/* Extension got pushed to head */
extension = *extensions;
/* Push the selected curve */
ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, curve->name,
ssl->heap, &kse);
if (ret != 0)
return ret; return ret;
/* Set extension to be in response. */ /* Set extension to be in response. */
extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
extension->resp = 1; extension->resp = 1;
#else #else
@@ -9114,7 +9120,7 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
int ret = INCOMPLETE_DATA; int ret = INCOMPLETE_DATA;
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
/* in async case make sure key generation is finalized */ /* in async case make sure key generation is finalized */
serverKSE = (KeyShareEntry*)extension->data; KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data;
if (serverKSE && serverKSE->lastRet == WC_PENDING_E) { if (serverKSE && serverKSE->lastRet == WC_PENDING_E) {
if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
*searched = 1; *searched = 1;
@@ -9168,14 +9174,30 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE)
KeyShareEntry* serverKSE; KeyShareEntry* serverKSE;
KeyShareEntry* list = NULL; KeyShareEntry* list = NULL;
if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END || if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
clientKSE == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
if (extension == NULL) if (extension == NULL)
return BAD_STATE_E; return BAD_STATE_E;
if (clientKSE == NULL) {
#ifdef WOLFSSL_ASYNC_CRYPT
/* Not necessarily an error. The key may have already been setup. */
if (extension != NULL && extension->resp == 1) {
serverKSE = (KeyShareEntry*)extension->data;
if (serverKSE != NULL) {
/* in async case make sure key generation is finalized */
if (serverKSE->lastRet == WC_PENDING_E)
return TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE);
else if (serverKSE->lastRet == 0)
return 0;
}
}
#endif
return BAD_FUNC_ARG;
}
/* Generate a new key pair except in the case of OQS KEM because we /* Generate a new key pair except in the case of OQS KEM because we
* are going to encapsulate and that does not require us to generate a * are going to encapsulate and that does not require us to generate a
* key pair. * key pair.
@@ -9230,7 +9252,7 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE)
extension->data = (void *)serverKSE; extension->data = (void *)serverKSE;
extension->resp = 1; extension->resp = 1;
return 0; return ret;
} }
/* Ensure there is a key pair that can be used for key exchange. /* Ensure there is a key pair that can be used for key exchange.

View File

@@ -6581,6 +6581,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.sendVerify = SEND_CERT; ssl->options.sendVerify = SEND_CERT;
#if defined(WOLFSSL_SEND_HRR_COOKIE) #if defined(WOLFSSL_SEND_HRR_COOKIE)
ssl->options.cookieGood = 0;
if (ssl->options.sendCookie && if (ssl->options.sendCookie &&
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
#ifdef WOLFSSL_DTLS13 #ifdef WOLFSSL_DTLS13
@@ -6599,23 +6600,18 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
if (ret != 0) if (ret != 0)
goto exit_dch; goto exit_dch;
ssl->options.serverState = SERVER_HELLO_COMPLETE; /* Don't change state here as we may want to enter
* DoTls13ClientHello again. */
ssl->options.cookieGood = 1;
} }
else { else {
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls)
ssl->options.serverState = NULL_STATE;
else
#endif
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
} }
} }
else else {
#ifdef WOLFSSL_DTLS13
if (!ssl->options.dtls)
#endif
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
} }
}
#endif #endif
#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
@@ -6659,12 +6655,14 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((ret = ALPN_Select(ssl)) != 0) if ((ret = ALPN_Select(ssl)) != 0)
goto exit_dch; goto exit_dch;
#endif #endif
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_BUILD;
} /* case TLS_ASYNC_BEGIN */ } /* case TLS_ASYNC_BEGIN */
FALL_THROUGH; FALL_THROUGH;
case TLS_ASYNC_BUILD: case TLS_ASYNC_BUILD:
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_DO;
FALL_THROUGH;
case TLS_ASYNC_DO: case TLS_ASYNC_DO:
{ {
#ifndef NO_CERTS #ifndef NO_CERTS
@@ -6673,7 +6671,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (ret != WC_PENDING_E) if (ret != WC_PENDING_E)
#endif #endif
WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); WOLFSSL_MSG("Unsupported cipher suite, ClientHello 1.3");
goto exit_dch; goto exit_dch;
} }
} }
@@ -6695,10 +6693,31 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif #endif
/* Advance state and proceed */ /* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_FINALIZE; ssl->options.asyncState = TLS_ASYNC_VERIFY;
} /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */
FALL_THROUGH; FALL_THROUGH;
case TLS_ASYNC_VERIFY:
{
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SUPPORTED_CURVES)
/* Check if the KeyShare calculations from the previous state are complete.
* wolfSSL_AsyncPop advances ssl->options.asyncState so we may end up here
* with a pending calculation. */
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
if (extension != NULL && extension->resp == 1) {
KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data;
if (serverKSE != NULL && serverKSE->lastRet == WC_PENDING_E) {
ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
if (ret != 0)
goto exit_dch;
}
}
#endif
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_FINALIZE;
}
FALL_THROUGH;
case TLS_ASYNC_FINALIZE: case TLS_ASYNC_FINALIZE:
{ {
*inOutIdx = args->idx; *inOutIdx = args->idx;
@@ -6742,6 +6761,19 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = INPUT_CASE_ERROR; ret = INPUT_CASE_ERROR;
} /* switch (ssl->options.asyncState) */ } /* switch (ssl->options.asyncState) */
#if defined(WOLFSSL_SEND_HRR_COOKIE)
if (ret == 0 && ssl->options.sendCookie && ssl->options.cookieGood &&
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
#ifdef WOLFSSL_DTLS13
/* DTLS cookie exchange should be done in stateless code in
* DoClientHelloStateless. If we verified the cookie then
* always advance the state. */
|| ssl->options.dtls
#endif
))
ssl->options.serverState = SERVER_HELLO_COMPLETE;
#endif
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
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) {

View File

@@ -59356,6 +59356,12 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl)
sslCopy.keys.dtls_peer_handshake_number = 0; sslCopy.keys.dtls_peer_handshake_number = 0;
XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history));
sslCopy.hsHashes = NULL; sslCopy.hsHashes = NULL;
#ifdef WOLFSSL_ASYNC_IO
#ifdef WOLFSSL_ASYNC_CRYPT
sslCopy.asyncDev = NULL;
#endif
sslCopy.async = NULL;
#endif
AssertIntEQ(wc_HashInit(&hash, hashType), 0); AssertIntEQ(wc_HashInit(&hash, hashType), 0);
AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)&sslCopy, sizeof(sslCopy)), 0); AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)&sslCopy, sizeof(sslCopy)), 0);

View File

@@ -3084,6 +3084,7 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group,
WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, WOLFSSL_LOCAL int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl,
TLSX** extensions); TLSX** extensions);
WOLFSSL_LOCAL int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse);
WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
KeyShareEntry** kse, byte* searched); KeyShareEntry** kse, byte* searched);
WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE); WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE);
@@ -4389,10 +4390,13 @@ typedef struct Options {
word16 tls13MiddleBoxCompat:1; /* TLSv1.3 middlebox compatibility */ word16 tls13MiddleBoxCompat:1; /* TLSv1.3 middlebox compatibility */
#endif #endif
#ifdef WOLFSSL_DTLS_CID #ifdef WOLFSSL_DTLS_CID
byte useDtlsCID:1; word16 useDtlsCID:1;
#endif /* WOLFSSL_DTLS_CID */ #endif /* WOLFSSL_DTLS_CID */
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
byte useEch:1; word16 useEch:1;
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
word16 cookieGood:1;
#endif #endif
/* need full byte values for this section */ /* need full byte values for this section */