diff --git a/src/dtls13.c b/src/dtls13.c index ca2389944c..644af22617 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -1040,7 +1040,7 @@ static int Dtls13SendFragmentedInternal(WOLFSSL* ssl) fragLength + DTLS_HANDSHAKE_HEADER_SZ, isEncrypted); if (outputSz < 0) { Dtls13FreeFragmentsBuffer(ssl); - return recordLength; + return outputSz; } ret = CheckAvailableSize(ssl, outputSz); @@ -1102,7 +1102,7 @@ static int Dtls13SendFragmented(WOLFSSL* ssl, byte* message, word16 length, isEncrypted = Dtls13TypeIsEncrypted(handshake_type); rlHeaderLength = Dtls13GetRlHeaderLength(ssl, isEncrypted); - if (length < rlHeaderLength) + if (length < rlHeaderLength + DTLS_HANDSHAKE_HEADER_SZ) return INCOMPLETE_DATA; /* DTLSv1.3 do not consider fragmentation for hash transcript. Build the @@ -2212,7 +2212,7 @@ static void Dtls13EpochCopyKeys(WOLFSSL* ssl, Dtls13Epoch* e, Keys* k, int side) byte clientWrite, serverWrite; byte enc, dec; - WOLFSSL_ENTER("Dtls13SetEpochKeys"); + WOLFSSL_ENTER("Dtls13EpochCopyKeys"); clientWrite = serverWrite = 0; enc = dec = 0; diff --git a/src/tls13.c b/src/tls13.c index 32428b2114..397e7c3f18 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -948,6 +948,13 @@ static const byte emptySHA512Hash[] = { 0xF9, 0x27, 0xDA, 0x3E }; #endif +#ifdef WOLFSSL_SM3 +static const byte emptySM3Hash[] = { + 0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0xA1, 0x7F, 0x8E, 0x61, 0x19, 0x48, + 0x31, 0xE8, 0x1A, 0x8F, 0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0xFB, 0x74, + 0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0xAA, 0x2B +}; +#endif /** * Implement section 7.5 of RFC 8446 * @return 0 on success @@ -1003,6 +1010,17 @@ int Tls13_Exporter(WOLFSSL* ssl, unsigned char *out, size_t outLen, emptyHash = emptySHA512Hash; break; #endif + + #ifdef WOLFSSL_SM3 + case sm3_mac: + hashType = WC_HASH_TYPE_SM3; + hashLen = WC_SM3_DIGEST_SIZE; + emptyHash = emptySM3Hash; + break; + #endif + + default: + return BAD_FUNC_ARG; } /* Derive-Secret(Secret, label, "") */ @@ -2572,7 +2590,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, const byte* aad, word16 aadSz, int asyncOkay) { int ret = 0; - word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 dataSz; word16 macSz = ssl->specs.aead_mac_size; word32 nonceSz = 0; #ifdef WOLFSSL_ASYNC_CRYPT @@ -2581,6 +2599,9 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, #endif WOLFSSL_ENTER("EncryptTls13"); + if (sz < ssl->specs.aead_mac_size) + return BUFFER_E; + dataSz = sz - ssl->specs.aead_mac_size; (void)output; (void)input; @@ -4054,6 +4075,7 @@ static const WOLFSSL_EVP_MD* ssl_handshake_md(const byte mac_alg) { switch(mac_alg) { case no_mac: + return NULL; #ifndef NO_MD5 case md5_mac: return wolfSSL_EVP_md5(); @@ -4161,6 +4183,8 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) #endif /* Set the client identity to use. */ + if (psk->identityLen > MAX_PSK_ID_LEN) + return PSK_KEY_ERROR; XMEMSET(ssl->arrays->client_identity, 0, sizeof(ssl->arrays->client_identity)); XMEMCPY(ssl->arrays->client_identity, psk->identity, psk->identityLen); @@ -5982,7 +6006,7 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, } if (*found) { if (*psk_keySz > MAX_PSK_KEY_LEN && - *((int*)psk_keySz) != WC_NO_ERR_TRACE(USE_HW_PSK)) { + (int)*psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK)) { WOLFSSL_MSG("Key len too long in FindPsk()"); ret = PSK_KEY_ERROR; WOLFSSL_ERROR_VERBOSE(ret); @@ -6322,6 +6346,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, client_hello, &bindersLen); if (ret < 0) return ret; + if (bindersLen > helloSz) + return BUFFER_ERROR; /* Refine list for PSK processing. */ sslRefineSuites(ssl, clSuites); @@ -6564,7 +6590,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) int keyShareExt = 0; int ret; - ret = TlsCheckCookie(ssl, cookie->data, (byte)cookie->len); + ret = TlsCheckCookie(ssl, cookie->data, cookie->len); if (ret < 0) return ret; cookieDataSz = (word16)ret; @@ -9741,6 +9767,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) #ifndef NO_RSA if (ssl->hsAltType == DYNAMIC_TYPE_RSA) { /* build encoded signature buffer */ + XFREE(rsaSigBuf->buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE); rsaSigBuf->length = WC_MAX_DIGEST_SIZE; rsaSigBuf->buffer = (byte*)XMALLOC(rsaSigBuf->length, ssl->heap, @@ -11488,13 +11515,13 @@ static int SendTls13Finished(WOLFSSL* ssl) */ ret = DeriveFinishedSecret(ssl, ssl->clientSecret, ssl->keys.client_write_MAC_secret, - WOLFSSL_SERVER_END); + WOLFSSL_CLIENT_END); if (ret != 0) return ret; ret = DeriveFinishedSecret(ssl, ssl->serverSecret, ssl->keys.server_write_MAC_secret, - WOLFSSL_CLIENT_END); + WOLFSSL_SERVER_END); if (ret != 0) return ret; @@ -11520,7 +11547,7 @@ static int SendTls13Finished(WOLFSSL* ssl) (word16)(Dtls13GetRlHeaderLength(ssl, 1) + headerSz + finishedSz), finished, 1); if (dtlsRet != 0 && dtlsRet != WC_NO_ERR_TRACE(WANT_WRITE)) - return ret; + return dtlsRet; } else #endif /* WOLFSSL_DTLS13 */ @@ -12166,7 +12193,7 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) word32 finishedSz = 0; byte mac[WC_MAX_DIGEST_SIZE]; Digest digest; - static byte header[] = { 0x14, 0x00, 0x00, 0x00 }; + byte header[] = { 0x14, 0x00, 0x00, 0x00 }; XMEMSET(&digest, 0, sizeof(Digest)); @@ -12206,25 +12233,26 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac, &finishedSz); if (ret != 0) - return ret; + goto restore; header[FINISHED_MSG_SIZE_OFFSET] = finishedSz; #ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData != no_early_data) { static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 }; ret = HashRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); if (ret != 0) - return ret; + goto restore; } #endif if ((ret = HashRaw(ssl, header, sizeof(header))) != 0) - return ret; + goto restore; if ((ret = HashRaw(ssl, mac, finishedSz)) != 0) - return ret; + goto restore; if ((ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret)) != 0) - return ret; + goto restore; /* Restore the hash inline with currently seen messages. */ +restore: switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 case sha256_mac: @@ -13460,7 +13488,8 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } ret = EarlySanityCheckMsgReceived(ssl, type, - min(inputLength - HANDSHAKE_HEADER_SZ, size)); + (inputLength > HANDSHAKE_HEADER_SZ) ? + min(inputLength - HANDSHAKE_HEADER_SZ, size) : 0); if (ret != 0) { WOLFSSL_ERROR(ret); return ret; @@ -15308,6 +15337,8 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) if (!IsAtLeastTLSv1_3(ssl->version)) return BAD_FUNC_ARG; + *outSz = 0; + #ifndef NO_WOLFSSL_CLIENT if (ssl->options.side == WOLFSSL_SERVER_END) return SIDE_ERROR; diff --git a/tests/api.c b/tests/api.c index 5818a69bc4..ae4b0b5181 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33050,6 +33050,46 @@ static int test_dtls13_missing_finished_server(void) return EXPECT_RESULT(); } +static int test_dtls13_finished_send_error_propagation(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = NULL; + struct test_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); + + /* CH1 */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + /* HRR */ + ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); + /* CH2 */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + /* Server first flight with finished */ + ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); + /* Client second flight with finished - block sends to force error */ + test_ctx.s_len = TEST_MEMIO_BUF_SZ; + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + /* Verify the error is propagated, not silently swallowed as success */ + ExpectIntNE(wolfSSL_get_error(ssl_c, -1), 0); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} + #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) #ifdef HAVE_CERTIFICATE_STATUS_REQUEST @@ -35393,6 +35433,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_dtls12_missing_finished), TEST_DECL(test_dtls13_missing_finished_client), TEST_DECL(test_dtls13_missing_finished_server), + TEST_DECL(test_dtls13_finished_send_error_propagation), TEST_DTLS_DECLS, TEST_DECL(test_tls_multi_handshakes_one_record), TEST_DECL(test_write_dup), diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 8ff9ad6bf3..63ddffb7aa 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -808,6 +808,11 @@ int test_tls13_apis(void) /* invoking without session or psk cbs */ ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_STATE_E)); + /* verify *outSz is initialized to 0 even on non-success paths */ + outSz = 42; + ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, + sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_STATE_E)); + ExpectIntEQ(outSz, 0); #endif ExpectIntEQ(wolfSSL_read_early_data(NULL, earlyDataBuffer,