From c87339e5c324c78dd7f5d521b32a084c51cada93 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 29 Nov 2023 15:55:59 +0100 Subject: [PATCH 1/6] dtls13: Add support for 0.5-RTT data --- src/internal.c | 37 +++++++++++++++++++++++++++++++------ src/ssl.c | 10 ++++++++-- tests/api.c | 18 ++++++++++++++++-- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/internal.c b/src/internal.c index d69696f650..b7c8111a82 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19597,7 +19597,8 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) return BUFFER_ERROR; } #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData > early_data_ext) { + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData > early_data_ext) { if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) { if (sniff == NO_SNIFF) { SendAlert(ssl, alert_fatal, unexpected_message); @@ -19637,6 +19638,15 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) #endif *inOutIdx = idx; +#ifdef WOLFSSL_DTLS13 + if (ssl->options.connectState == WAIT_FINISHED_ACK) { + /* Reset the processReply state since + * we finished processing this message. */ + ssl->options.processReply = doProcessInit; + /* DTLS 1.3 is waiting for an ACK but we can still return app data. */ + return APP_DATA_READY; + } +#endif #ifdef HAVE_SECURE_RENEGOTIATION if (IsSCR(ssl)) { /* Reset the processReply state since @@ -20234,7 +20244,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE - #ifdef HAVE_SECURE_RENEGOTIATION + #if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13) && ssl->error != APP_DATA_READY #endif #ifdef WOLFSSL_ASYNC_CRYPT @@ -21258,9 +21268,18 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* input exhausted */ if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length #ifdef WOLFSSL_DTLS - /* If app data was processed then return now to avoid - * dropping any app data. */ - || (ssl->options.dtls && ssl->curRL.type == application_data) + || (ssl->options.dtls && + /* If app data was processed then return now to avoid + * dropping any app data. */ + (ssl->curRL.type == application_data || + /* client: if we processed a finished message, return to + * allow higher layers to establish the crypto + * parameters of the connection. The remaining data + * may be app data that we would drop without the + * crypto setup. */ + (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == SERVER_FINISHED_COMPLETE && + ssl->options.handShakeState != HANDSHAKE_DONE))) #endif ) { /* Shrink input buffer when we successfully finish record @@ -23586,6 +23605,12 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) groupMsgs = 1; #endif } + else if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) { + /* We can send data without waiting on peer finished msg */ + WOLFSSL_MSG("server sending data before receiving client finished"); + } else #endif if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) { @@ -23823,7 +23848,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) #ifdef WOLFSSL_ASYNC_CRYPT && ssl->error != WC_PENDING_E #endif -#ifdef HAVE_SECURE_RENEGOTIATION +#if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13) && ssl->error != APP_DATA_READY #endif ) { diff --git a/src/ssl.c b/src/ssl.c index 275fa5f715..e27e5b9048 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3233,8 +3233,14 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) } #endif #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) { - ssl->error = ret; + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) { + /* We can send data without waiting on peer finished msg */ + WOLFSSL_MSG("server sending data before receiving client finished"); + } + else if (ssl->earlyData != no_early_data && + (ret = wolfSSL_negotiate(ssl)) < 0) { return WOLFSSL_FATAL_ERROR; } ssl->earlyData = no_early_data; diff --git a/tests/api.c b/tests/api.c index fffd51249f..e71f7a48d0 100644 --- a/tests/api.c +++ b/tests/api.c @@ -68124,6 +68124,7 @@ static int test_dtls13_early_data(void) char msg[] = "This is early data"; char msg2[] = "This is client data"; char msg3[] = "This is server data"; + char msg4[] = "This is server immediate data"; char msgBuf[50]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); @@ -68151,6 +68152,7 @@ static int test_dtls13_early_data(void) ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS); #endif + /* Test 0-RTT data */ ExpectIntEQ(wolfSSL_write_early_data(ssl_c, msg, sizeof(msg), &written), sizeof(msg)); ExpectIntEQ(written, sizeof(msg)); @@ -68160,6 +68162,15 @@ static int test_dtls13_early_data(void) ExpectIntEQ(read, sizeof(msg)); ExpectStrEQ(msg, msgBuf); + /* Test 0.5-RTT data */ + ExpectIntEQ(wolfSSL_write(ssl_s, msg4, sizeof(msg4)), sizeof(msg4)); + + ExpectIntEQ(wolfSSL_connect(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), APP_DATA_READY); + + ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), sizeof(msg4)); + ExpectStrEQ(msg4, msgBuf); + /* Complete handshake */ ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); @@ -68171,11 +68182,14 @@ static int test_dtls13_early_data(void) * parsing logic. */ ExpectFalse(wolfSSL_is_init_finished(ssl_s)); ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf), - &read), WOLFSSL_FAILURE); - ExpectTrue(wolfSSL_is_init_finished(ssl_s)); + &read), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); + ExpectTrue(wolfSSL_is_init_finished(ssl_s)); + + /* Test bi-directional write */ ExpectIntEQ(wolfSSL_write(ssl_c, msg2, sizeof(msg2)), sizeof(msg2)); ExpectIntEQ(wolfSSL_read(ssl_s, msgBuf, sizeof(msgBuf)), sizeof(msg2)); From a7dce987971d5baee333519b02ee83fc5f2dcb32 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 29 Nov 2023 19:11:49 +0100 Subject: [PATCH 2/6] Don't touch processReply state in DoApplicationData --- src/internal.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/internal.c b/src/internal.c index b7c8111a82..6c57df04aa 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19640,18 +19640,12 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) *inOutIdx = idx; #ifdef WOLFSSL_DTLS13 if (ssl->options.connectState == WAIT_FINISHED_ACK) { - /* Reset the processReply state since - * we finished processing this message. */ - ssl->options.processReply = doProcessInit; /* DTLS 1.3 is waiting for an ACK but we can still return app data. */ return APP_DATA_READY; } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (IsSCR(ssl)) { - /* Reset the processReply state since - * we finished processing this message. */ - ssl->options.processReply = doProcessInit; /* If we are in a secure renegotiation then APP DATA is treated * differently */ return APP_DATA_READY; @@ -21211,7 +21205,13 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) &ssl->buffers.inputBuffer.idx, NO_SNIFF)) != 0) { WOLFSSL_ERROR(ret); - return ret; + #if defined(WOLFSSL_DTLS13) || \ + defined(HAVE_SECURE_RENEGOTIATION) + /* Not really an error. We will return after cleaning + * up the processReply state. */ + if (ret != APP_DATA_READY) + #endif + return ret; } break; @@ -21334,6 +21334,11 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) * by higher layers. */ if (ret != 0) return ret; +#endif +#if defined(WOLFSSL_DTLS13) || defined(HAVE_SECURE_RENEGOTIATION) + /* Signal to user that we have application data ready to read */ + if (ret == APP_DATA_READY) + return ret; #endif /* It is safe to shrink the input buffer here now. local vars will * be reset to the new starting value. */ From e891c721b8abace4039b81f86418da240a6b8335 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 29 Nov 2023 23:22:38 +0100 Subject: [PATCH 3/6] fixup! dtls13: Add support for 0.5-RTT data --- src/ssl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ssl.c b/src/ssl.c index e27e5b9048..959d240dd9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3241,6 +3241,7 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) } else if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) { + ssl->error = ret; return WOLFSSL_FATAL_ERROR; } ssl->earlyData = no_early_data; From cf8a6efaa5a70151a9842f698fb6d11fd49acb4f Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 6 Dec 2023 08:59:54 +1000 Subject: [PATCH 4/6] SP int neg sp_mont_red_ex: disallow negative numbers Don't support negative a or m with sp_mont_red_ex(). --- wolfcrypt/src/sp_int.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 73da134ea5..cb1364535c 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -17524,6 +17524,11 @@ int sp_mont_red_ex(sp_int* a, const sp_int* m, sp_int_digit mp, int ct) if ((a == NULL) || (m == NULL) || sp_iszero(m)) { err = MP_VAL; } +#ifdef WOLFSSL_SP_INT_NEGATIVE + else if ((a->sign == MP_NEG) || (m->sign == MP_NEG)) { + err = MP_VAL; + } +#endif /* Ensure a has enough space for calculation. */ else if (a->size < m->used * 2 + 1) { err = MP_VAL; From db14914951b4996c04e9c1f6ff2ab6e3f7c8840c Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 6 Dec 2023 12:43:26 -0800 Subject: [PATCH 5/6] Fixes for building wolfSSL in Visual Studio. Adds missing files. Fix for type cast warnings. --- IDE/WIN10/wolfssl-fips.vcxproj | 1 + src/internal.c | 6 +++--- src/ssl.c | 4 ++-- src/tls13.c | 2 +- wolfcrypt/src/pkcs7.c | 10 +++++----- wolfssl.vcxproj | 1 + 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/IDE/WIN10/wolfssl-fips.vcxproj b/IDE/WIN10/wolfssl-fips.vcxproj index 99ffb4352e..5d0122ea57 100644 --- a/IDE/WIN10/wolfssl-fips.vcxproj +++ b/IDE/WIN10/wolfssl-fips.vcxproj @@ -272,6 +272,7 @@ + diff --git a/src/internal.c b/src/internal.c index 81bc5376d7..a0a2cf6c41 100644 --- a/src/internal.c +++ b/src/internal.c @@ -27050,7 +27050,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) #endif ) { - *length = GetPrivateKeySigSize(ssl); + *length = (word16)GetPrivateKeySigSize(ssl); return 0; } else @@ -31582,7 +31582,7 @@ int SendCertificateVerify(WOLFSSL* ssl) if (ssl->buffers.key == NULL) { #ifdef HAVE_PK_CALLBACKS if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - args->length = GetPrivateKeySigSize(ssl); + args->length = (word16)GetPrivateKeySigSize(ssl); else #endif ERROR_OUT(NO_PRIVATE_KEY, exit_scv); @@ -33555,7 +33555,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.key == NULL) { #ifdef HAVE_PK_CALLBACKS if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - keySz = (word32)GetPrivateKeySigSize(ssl); + keySz = (word16)GetPrivateKeySigSize(ssl); else #endif ERROR_OUT(NO_PRIVATE_KEY, exit_sske); diff --git a/src/ssl.c b/src/ssl.c index 32d81e7aae..4aac9f8fc8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7779,11 +7779,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifdef WOLF_PRIVATE_KEY_ID if (ssl != NULL) { - ssl->buffers.keyType = keyType; + ssl->buffers.keyType = (byte)keyType; ssl->buffers.keySz = keySz; } else if (ctx != NULL) { - ctx->privateKeyType = keyType; + ctx->privateKeyType = (byte)keyType; ctx->privateKeySz = keySz; } #endif diff --git a/src/tls13.c b/src/tls13.c index 93ec08ff65..16a9e7b314 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8633,7 +8633,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) if (ssl->buffers.key == NULL) { #ifdef HAVE_PK_CALLBACKS if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - args->length = GetPrivateKeySigSize(ssl); + args->length = (word16)GetPrivateKeySigSize(ssl); else #endif ERROR_OUT(NO_PRIVATE_KEY, exit_scv); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 0792d59538..36983d5016 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -4627,7 +4627,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3"); ret = ASN_VERSION_E; } - pkcs7->version = version; + pkcs7->version = (byte)version; /* Get the set of DigestAlgorithmIdentifiers */ if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) @@ -4913,7 +4913,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (multiPart) { pkcs7->stream->expected = contentLen + ASN_TAG_SZ; } - pkcs7->stream->multi = multiPart; + pkcs7->stream->multi = (byte)multiPart; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3); @@ -5221,7 +5221,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->stream = stream; #endif } - pkcs7->version = version; + pkcs7->version = (byte)version; #ifdef ASN_BER_TO_DER pkcs7->der = der; #endif @@ -7692,7 +7692,7 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, if (*outSz < (word32)outLen) return BUFFER_E; - out[0] = cekSz; + out[0] = (byte)cekSz; out[1] = ~cek[0]; out[2] = ~cek[1]; out[3] = ~cek[2]; @@ -10845,7 +10845,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, byte* encryptedContent = NULL; int explicitOctet = 0; word32 localIdx; - byte tag; + byte tag = 0; if (pkcs7 == NULL) return BAD_FUNC_ARG; diff --git a/wolfssl.vcxproj b/wolfssl.vcxproj index 7b5d251669..b5e9b07659 100644 --- a/wolfssl.vcxproj +++ b/wolfssl.vcxproj @@ -299,6 +299,7 @@ + From 226c631feb7bde84c2cf45ca4fd0d139af8fd2d5 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 7 Dec 2023 07:51:43 +1000 Subject: [PATCH 6/6] Heapmath mp_add_d: fix for when a and c same pointer When parameters a and c to mp_add_d are the same pointer, c->sign was being set to zero/positive and then a->sign was being checked. Set the c->sign at end as it will always be zero/positive through the code and the sign of the result isn't otherwise used. --- wolfcrypt/src/integer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index d701cfcd86..21ae2353a4 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4425,9 +4425,6 @@ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) /* //NOLINT(misc-no-recursion) * /* old number of used digits in c */ oldused = c->used; - /* sign always positive */ - c->sign = MP_ZPOS; - /* source alias */ tmpa = a->dp; @@ -4478,6 +4475,9 @@ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) /* //NOLINT(misc-no-recursion) * ix = 1; } + /* sign always positive */ + c->sign = MP_ZPOS; + /* now zero to oldused */ while (ix++ < oldused) { *tmpc++ = 0;