mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-06-05 21:15:16 +00:00
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:
+71
-22
@@ -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 */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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."));
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user