mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-07-30 16:26:33 +08:00
Merge pull request #1657 from bjwtaylor/ssl-ignores-failure-restricted-4.1
Backport 4.1: Fix issues in ssl where it ignores the failure return
This commit is contained in:
commit
5aac408d2a
17
ChangeLog.d/1583-1584-ssl-transcript-errors.txt
Normal file
17
ChangeLog.d/1583-1584-ssl-transcript-errors.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Security
|
||||
* Fix a bug where transcript-hash computation errors during TLS 1.2
|
||||
extended master secret calculation could be ignored instead of causing the
|
||||
handshake to fail. This could allow a handshake to continue with a master
|
||||
secret that was not correctly bound to the handshake transcript,
|
||||
undermining the security guarantees of the extended master secret
|
||||
extension. Report by Mathew Gretton-Dann. CVE-2026-50581
|
||||
* Fix a TLS 1.3 server-side error-handling bug affecting session ticket
|
||||
generation. Under rare conditions, such as memory allocation failures
|
||||
while computing the resumption master secret, the server could issue
|
||||
invalid session tickets instead of failing the handshake. Clients
|
||||
presented with such tickets would fail session resumption and fall back to
|
||||
a full handshake. In deployments relying on session resumption, repeated
|
||||
occurrences could increase the frequency of full handshakes and amplify
|
||||
resource consumption during periods of resource exhaustion or other
|
||||
transient failures. Reported by jjfz123.
|
||||
CVE-2026-50640
|
||||
@ -29,7 +29,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "mbedtls/psa_util.h"
|
||||
#include "md_psa.h" // for mbedtls_md_error_from_psa()
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
@ -846,21 +845,21 @@ int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
|
||||
#if defined(PSA_WANT_ALG_SHA_256)
|
||||
status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
#endif
|
||||
#if defined(PSA_WANT_ALG_SHA_384)
|
||||
status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@ -880,13 +879,13 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
|
||||
#if defined(PSA_WANT_ALG_SHA_256)
|
||||
status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
#endif
|
||||
#if defined(PSA_WANT_ALG_SHA_384)
|
||||
status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@ -896,8 +895,8 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
|
||||
static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
|
||||
const unsigned char *buf, size_t len)
|
||||
{
|
||||
return mbedtls_md_error_from_psa(psa_hash_update(
|
||||
&ssl->handshake->fin_sha256_psa, buf, len));
|
||||
return PSA_TO_MBEDTLS_ERR(psa_hash_update(
|
||||
&ssl->handshake->fin_sha256_psa, buf, len));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -905,8 +904,8 @@ static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
|
||||
static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,
|
||||
const unsigned char *buf, size_t len)
|
||||
{
|
||||
return mbedtls_md_error_from_psa(psa_hash_update(
|
||||
&ssl->handshake->fin_sha384_psa, buf, len));
|
||||
return PSA_TO_MBEDTLS_ERR(psa_hash_update(
|
||||
&ssl->handshake->fin_sha384_psa, buf, len));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -6293,11 +6292,16 @@ static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake,
|
||||
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
|
||||
if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
|
||||
lbl = "extended master secret";
|
||||
seed = session_hash;
|
||||
ret = handshake->calc_verify(ssl, session_hash, &seed_len);
|
||||
if (ret != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);
|
||||
return ret;
|
||||
}
|
||||
if (seed_len > sizeof(session_hash)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("bad session hash length"));
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
seed = session_hash;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret",
|
||||
session_hash, seed_len);
|
||||
@ -6564,7 +6568,7 @@ static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl,
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&cloned_op);
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
#if defined(PSA_WANT_ALG_SHA_256)
|
||||
@ -7257,7 +7261,7 @@ static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx,
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&cloned_op);
|
||||
return mbedtls_md_error_from_psa(status);
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
#if defined(PSA_WANT_ALG_SHA_256)
|
||||
|
||||
@ -1746,9 +1746,9 @@ static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
|
||||
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf,
|
||||
size_t *olen)
|
||||
static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf,
|
||||
size_t *olen)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char *p = buf;
|
||||
@ -1760,14 +1760,14 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
|
||||
/* Skip costly computation if not needed */
|
||||
if (ssl->handshake->ciphersuite_info->key_exchange !=
|
||||
MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension"));
|
||||
|
||||
if (end - p < 4) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
|
||||
return;
|
||||
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);
|
||||
@ -1780,13 +1780,14 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
|
||||
psa_destroy_key(ssl->handshake->psa_pake_password);
|
||||
psa_pake_abort(&ssl->handshake->psa_pake_ctx);
|
||||
MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);
|
||||
p += 2;
|
||||
|
||||
*olen = kkpp_len + 4;
|
||||
return 0;
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
|
||||
|
||||
@ -2169,7 +2170,11 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen);
|
||||
ret = ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen);
|
||||
if (ret != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret);
|
||||
return ret;
|
||||
}
|
||||
ext_len += olen;
|
||||
#endif
|
||||
|
||||
|
||||
@ -2804,6 +2804,7 @@ static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl,
|
||||
MBEDTLS_SSL_DEBUG_RET(
|
||||
1, "ssl_tls13_parse_new_session_ticket_early_data_ext",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
#endif /* MBEDTLS_SSL_EARLY_DATA */
|
||||
|
||||
@ -3077,6 +3077,7 @@ static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl)
|
||||
if (ret != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(
|
||||
1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);
|
||||
|
||||
@ -3378,6 +3378,22 @@ elliptic_curve_get_properties
|
||||
TLS 1.3 resume session with ticket
|
||||
tls13_resume_session_with_ticket
|
||||
|
||||
TLS 1.3 server propagates RMS computation error
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
|
||||
tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS:MBEDTLS_ERR_SSL_INTERNAL_ERROR
|
||||
|
||||
TLS 1.3 client propagates RMS computation error
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
|
||||
tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1:MBEDTLS_ERR_SSL_INTERNAL_ERROR
|
||||
|
||||
TLS 1.2 server propagates EMS computation error
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY:MBEDTLS_ERR_SSL_INTERNAL_ERROR
|
||||
|
||||
TLS 1.2 client propagates EMS computation error
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1:MBEDTLS_ERR_SSL_INTERNAL_ERROR
|
||||
|
||||
TLS 1.3 read early data, early data accepted
|
||||
tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED
|
||||
|
||||
|
||||
@ -55,6 +55,53 @@ static int failing_ticket_write_unset_lifetime(
|
||||
PSA_WANT_ALG_SHA_256 && PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY &&
|
||||
MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_DEBUG_C) && \
|
||||
defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \
|
||||
defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \
|
||||
defined(MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP) && \
|
||||
defined(PSA_WANT_ALG_SHA_256)
|
||||
typedef struct {
|
||||
/* Context for tls_abort_transcript(). The debug callback watches for
|
||||
* trigger in the SSL debug trace, then aborts this connection's transcript
|
||||
* hash operation exactly once so the test can check error propagation. */
|
||||
mbedtls_ssl_context *ssl;
|
||||
const char *trigger;
|
||||
int triggered;
|
||||
} tls_abort_transcript_context;
|
||||
|
||||
static void tls_abort_transcript(void *ctx, int level,
|
||||
const char *file, int line,
|
||||
const char *str)
|
||||
{
|
||||
tls_abort_transcript_context *abort_ctx = ctx;
|
||||
|
||||
(void) level;
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
if (abort_ctx->triggered) {
|
||||
return;
|
||||
}
|
||||
if (abort_ctx->ssl == NULL) {
|
||||
return;
|
||||
}
|
||||
if (abort_ctx->ssl->handshake == NULL) {
|
||||
return;
|
||||
}
|
||||
if (strstr(str, abort_ctx->trigger) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
abort_ctx->triggered = 1;
|
||||
#if defined(PSA_WANT_ALG_SHA_256)
|
||||
psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha256_psa);
|
||||
#endif
|
||||
#if defined(PSA_WANT_ALG_SHA_384)
|
||||
psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha384_psa);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
|
||||
defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \
|
||||
defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \
|
||||
@ -4358,6 +4405,92 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:PSA_WANT_ALG_SHA_256 */
|
||||
void tls_transcript_error_propagation(int endpoint,
|
||||
int tls_version,
|
||||
const char *trigger,
|
||||
int target_state,
|
||||
int peer_target_state,
|
||||
int expected_ret)
|
||||
{
|
||||
int ret = -1;
|
||||
mbedtls_test_ssl_endpoint client_ep, server_ep;
|
||||
mbedtls_test_handshake_test_options client_options;
|
||||
mbedtls_test_init_handshake_options(&client_options);
|
||||
mbedtls_test_handshake_test_options server_options;
|
||||
mbedtls_test_init_handshake_options(&server_options);
|
||||
tls_abort_transcript_context abort_ctx;
|
||||
memset(&abort_ctx, 0, sizeof(abort_ctx));
|
||||
mbedtls_ssl_context *peer_ssl_context = NULL;
|
||||
|
||||
PSA_INIT();
|
||||
|
||||
client_options.client_min_version = tls_version;
|
||||
client_options.client_max_version = tls_version;
|
||||
server_options.server_min_version = tls_version;
|
||||
server_options.server_max_version = tls_version;
|
||||
|
||||
abort_ctx.trigger = trigger;
|
||||
TEST_ASSERT(abort_ctx.trigger != NULL);
|
||||
|
||||
if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
|
||||
client_options.cli_log_obj = &abort_ctx;
|
||||
client_options.cli_log_fun = tls_abort_transcript;
|
||||
abort_ctx.ssl = &client_ep.ssl;
|
||||
peer_ssl_context = &server_ep.ssl;
|
||||
} else {
|
||||
server_options.srv_log_obj = &abort_ctx;
|
||||
server_options.srv_log_fun = tls_abort_transcript;
|
||||
abort_ctx.ssl = &server_ep.ssl;
|
||||
peer_ssl_context = &client_ep.ssl;
|
||||
}
|
||||
|
||||
mbedtls_debug_set_threshold(4);
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
|
||||
&client_options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
|
||||
&server_options), 0);
|
||||
|
||||
/* Keep enough socket capacity for setup traffic so the final step below
|
||||
* exercises the target state instead of only flushing previous messages. */
|
||||
TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket),
|
||||
&(server_ep.socket), 4096), 0);
|
||||
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(
|
||||
abort_ctx.ssl, peer_ssl_context,
|
||||
target_state), 0);
|
||||
/*
|
||||
* Advance the peer further through the handshake so that it emits the
|
||||
* messages needed by the endpoint under test to proceed through its next
|
||||
* step.
|
||||
*/
|
||||
if (peer_target_state != -1) {
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(
|
||||
peer_ssl_context, abort_ctx.ssl,
|
||||
peer_target_state), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_flush_output(peer_ssl_context), 0);
|
||||
}
|
||||
|
||||
TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0);
|
||||
TEST_EQUAL(abort_ctx.ssl->state, target_state);
|
||||
TEST_EQUAL(abort_ctx.triggered, 0);
|
||||
|
||||
ret = mbedtls_ssl_handshake_step(abort_ctx.ssl);
|
||||
TEST_ASSERT(abort_ctx.triggered);
|
||||
TEST_ASSERT(ret != 0);
|
||||
TEST_EQUAL(ret, expected_ret);
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client_ep);
|
||||
mbedtls_test_ssl_endpoint_free(&server_ep);
|
||||
mbedtls_test_free_handshake_options(&client_options);
|
||||
mbedtls_test_free_handshake_options(&server_options);
|
||||
mbedtls_debug_set_threshold(0);
|
||||
PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
|
||||
void tls13_resume_session_with_ticket()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user