Merge remote-tracking branch 'restricted/development-restricted' into mbedtls-4.1.0.rc3

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
This commit is contained in:
Minos Galanakis
2026-03-26 22:18:31 +00:00
25 changed files with 653 additions and 109 deletions
+71 -22
View File
@@ -275,6 +275,7 @@ exit:
/* Forward declarations for functions related to message buffering. */
static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
uint8_t slot);
static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl, unsigned shift);
static void ssl_free_buffered_record(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message(mbedtls_ssl_context *ssl);
@@ -2985,8 +2986,12 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
* expected `message_seq` for the incoming and outgoing
* handshake messages.
*/
ssl->handshake->in_msg_seq = recv_msg_seq;
ssl->handshake->out_msg_seq = recv_msg_seq;
if ((ssl->handshake->in_msg_seq == 0) && (recv_msg_seq > 0)) {
MBEDTLS_SSL_DEBUG_MSG(3, ("shift slots by %u", recv_msg_seq));
ssl_buffering_shift_slots(ssl, recv_msg_seq);
ssl->handshake->in_msg_seq = recv_msg_seq;
ssl->handshake->out_msg_seq = recv_msg_seq;
}
/* Epoch should be 0 for initial handshakes */
if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) {
@@ -2996,6 +3001,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2,
sizeof(ssl->cur_out_ctr) - 2);
} else if (mbedtls_ssl_is_handshake_over(ssl) == 1) {
/* In case of a post-handshake ClientHello that initiates a
* renegotiation check that the handshake message sequence
@@ -3180,28 +3186,10 @@ int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake != NULL) {
unsigned offset;
mbedtls_ssl_hs_buffer *hs_buf;
/* Increment handshake sequence number */
hs->in_msg_seq++;
/*
* Clear up handshake buffering and reassembly structure.
*/
/* Free first entry */
ssl_buffering_free_slot(ssl, 0);
/* Shift all other entries */
for (offset = 0, hs_buf = &hs->buffering.hs[0];
offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
offset++, hs_buf++) {
*hs_buf = *(hs_buf + 1);
}
/* Create a fresh last entry */
memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));
ssl_buffering_shift_slots(ssl, 1);
}
#endif
return 0;
@@ -3618,7 +3606,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
(
"datagram of length %u too small to hold DTLS record header of length %u",
(unsigned) len,
(unsigned) (rec_hdr_len_len + rec_hdr_len_len)));
(unsigned) (rec_hdr_len_offset + rec_hdr_len_len)));
return MBEDTLS_ERR_SSL_INVALID_RECORD;
}
@@ -4750,6 +4738,31 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
}
#if defined(MBEDTLS_SSL_SRV_C)
/*
* In DTLS, invalid records are usually ignored because it is easy
* for an attacker to inject UDP datagrams, and we do not want such
* packets to disrupt the entire connection.
*
* However, when expecting the ClientHello, we reject invalid or
* unexpected records. This avoids waiting for further records
* before receiving at least one valid message. Such records could
* be leftover messages from a previous connection, accidental
* input, or part of a DoS attempt.
*
* Since no valid message has been received yet, immediately
* closing the connection does not result in any loss.
*/
if ((ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) &&
(ssl->state == MBEDTLS_SSL_CLIENT_HELLO)
#if defined(MBEDTLS_SSL_RENEGOTIATION)
&& (ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE)
#endif
) {
return ret;
}
#endif /* MBEDTLS_SSL_SRV_C */
if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) {
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
/* Reset in pointers to default state for TLS/DTLS records,
@@ -6134,6 +6147,42 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
}
}
/*
* Shift the buffering slots to the left by `shift` positions.
* After the operation, slot i contains the previous slot i + shift.
*/
static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl,
unsigned shift)
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
unsigned offset;
if (shift == 0) {
return;
}
if (shift >= MBEDTLS_SSL_MAX_BUFFERED_HS) {
shift = MBEDTLS_SSL_MAX_BUFFERED_HS;
}
/* Free discarded entries */
for (offset = 0; offset < shift; offset++) {
ssl_buffering_free_slot(ssl, offset);
}
/* Shift remaining entries left */
for (offset = 0; offset + shift < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {
hs->buffering.hs[offset] = hs->buffering.hs[offset + shift];
}
/* Reset the remaining entries at the end. Some may already have been
* cleared by the loop freeing the discarded entries, but resetting all
* of them is simpler and avoids tracking which ones were already handled.
*/
for (; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {
memset(&hs->buffering.hs[offset], 0, sizeof(hs->buffering.hs[offset]));
}
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
/*
+44 -6
View File
@@ -1732,6 +1732,48 @@ static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl,
uint16_t sig_alg,
mbedtls_md_type_t *md_alg,
mbedtls_pk_sigalg_t *pk_alg)
{
if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg(sig_alg, pk_alg, md_alg) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1,
("Server used unsupported value in SigAlg extension 0x%04x",
sig_alg));
return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
}
/*
* mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg() understands sig_alg code points across
* TLS versions. Make sure that the received sig_alg extension is valid in TLS 1.2.
*/
if (!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) {
MBEDTLS_SSL_DEBUG_MSG(1,
("Server used unsupported value in SigAlg extension 0x%04x",
sig_alg));
return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
}
/*
* Check if the signature algorithm is acceptable
*/
if (!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value 0x%04x that was not offered", sig_alg));
return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
}
MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", sig_alg & 0x00FF));
MBEDTLS_SSL_DEBUG_MSG(2, ("Server used HashAlgorithm %d", sig_alg >> 8));
return 0;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl)
{
@@ -1889,7 +1931,6 @@ start_processing:
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
size_t params_len = (size_t) (p - params);
void *rs_ctx = NULL;
uint16_t sig_alg;
mbedtls_pk_context *peer_pk;
@@ -1908,11 +1949,8 @@ start_processing:
* Handle the digitally-signed structure
*/
MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg(
sig_alg, &pk_alg, &md_alg) != 0 &&
!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) &&
!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) {
uint16_t sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
if (ssl_parse_signature_algorithm(ssl, sig_alg, &md_alg, &pk_alg) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1,
("bad server key exchange message"));
mbedtls_ssl_send_alert_message(
+33
View File
@@ -879,6 +879,39 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl)
*/
if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record ", ret);
#if defined(MBEDTLS_SSL_PROTO_DTLS)
/*
* In the case of an alert message corresponding to the termination of
* a previous connection, `ssl_parse_record_header()` and then
* `mbedtls_ssl_read_record()` may return
* MBEDTLS_ERR_SSL_UNEXPECTED_RECORD because of a non zero epoch.
*
* Historically, the library has returned
* MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE in this situation.
* The sample program dtls_server.c relies on this behavior
* (see
* https://github.com/Mbed-TLS/mbedtls/blob/d5e35a376bee23fad0b17f2e3e94a32ce4017c64/programs/ssl/dtls_server.c#L295),
* and user applications may rely on it as well.
*
* For compatibility, map MBEDTLS_ERR_SSL_UNEXPECTED_RECORD
* to MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE here.
*
* MBEDTLS_ERR_SSL_UNEXPECTED_RECORD does not appear to be
* used to detect a specific error condition, so this mapping
* should not remove any meaningful distinction.
*/
if ((ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM)
#if defined(MBEDTLS_SSL_RENEGOTIATION)
&& (ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE)
#endif
) {
if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) {
ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
}
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
return ret;
}
+15 -7
View File
@@ -1755,6 +1755,11 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
if (handshake->key_exchange_mode !=
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {
hrr_required = (no_usable_share_for_key_agreement != 0);
}
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
if (handshake->key_exchange_mode &
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) {
@@ -1765,17 +1770,12 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
((unsigned) psk.ciphersuite_info->id),
psk.ciphersuite_info->name));
if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION && (!hrr_required)) {
handshake->resume = 1;
}
}
#endif
if (handshake->key_exchange_mode !=
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {
hrr_required = (no_usable_share_for_key_agreement != 0);
}
mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info);
return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK;
@@ -1948,6 +1948,9 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)
/*
* Version 1.2 of the protocol has to be used for the handshake.
* If we have sent an HRR, then the second ClientHello is inconsistent
* with the first one and we abort the handshake with an `illegal_parameter`
* fatal alert.
* If TLS 1.2 is not supported, abort the handshake. Otherwise, set the
* ssl->keep_current_message flag for the ClientHello to be kept and parsed
* as a TLS 1.2 ClientHello. We also change ssl->tls_version to
@@ -1955,7 +1958,12 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)
* will dispatch to the TLS 1.2 state machine.
*/
if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) {
/* Check if server supports TLS 1.2 */
if (ssl->handshake->hello_retry_request_flag) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Non compliant 2nd ClientHello, TLS 1.2 version"));
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("TLS 1.2 not supported."));
+3
View File
@@ -487,6 +487,9 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam
} else {
oid.len = strlen(attr_descr->oid);
oid.p = mbedtls_calloc(1, oid.len);
if (oid.p == NULL) {
return MBEDTLS_ERR_X509_ALLOC_FAILED;
}
memcpy(oid.p, attr_descr->oid, oid.len);
numericoid = 0;
}
+12 -9
View File
@@ -2719,22 +2719,25 @@ static int x509_inet_pton_ipv6(const char *src, void *dst)
if (*p == '\0') {
break;
} else if (*p == '.') {
/* Don't accept IPv4 too early or late */
if ((nonzero_groups == 0 && zero_group_start == -1) ||
/* Don't accept IPv4 too early or late:
* - The first 6 nonzero groups must be 16 bit pieces of address delimited by ':'
* - This might be fully or partially represented with compressed syntax (a zero
* group "::")
*/
if ((nonzero_groups < 6 && zero_group_start == -1) ||
nonzero_groups >= 7) {
break;
}
/* Walk back to prior ':', then parse as IPv4-mapped */
int steps = 4;
/* Walk back to prior ':', then parse as IPv4-mapped.
* At this point nonzero_groups == 6 or zero_group_start >= 0. Either way we have a
* ':' before the current position and still inside the buffer. Thus it is safe to
* search back for that ':' without any further checks.
*/
do {
p--;
steps--;
} while (*p != ':' && steps > 0);
} while (*p != ':');
if (*p != ':') {
break;
}
p++;
nonzero_groups--;
if (x509_inet_pton_ipv4((const char *) p,