From 0bbd4f1600ab6648b531740d3501a994442cc8c3 Mon Sep 17 00:00:00 2001 From: Achim Kraus Date: Tue, 29 Nov 2022 13:10:05 +0100 Subject: [PATCH] Add RFC5746 minimal version implementation. Supports RFC5746 minimal version without renegotiation. Signed-off-by: Achim Kraus --- crypto.h | 1 + dtls.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- global.h | 1 + 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/crypto.h b/crypto.h index 97f5a9ad..a759cf66 100644 --- a/crypto.h +++ b/crypto.h @@ -145,6 +145,7 @@ typedef struct { dtls_cipher_index_t cipher_index; /**< internal index for cipher_suite_params, DTLS_CIPHER_INDEX_NULL for TLS_NULL_WITH_NULL_NULL */ unsigned int do_client_auth:1; unsigned int extended_master_secret:1; + unsigned int renegotiation_info:1; union { #ifdef DTLS_ECC dtls_handshake_parameters_ecdsa_t ecdsa; diff --git a/dtls.c b/dtls.c index b3029d07..8e8dc13d 100644 --- a/dtls.c +++ b/dtls.c @@ -1058,7 +1058,7 @@ static int verify_ext_sig_hash_algo(uint8 *data, size_t data_length) { */ static int dtls_check_tls_extension(dtls_peer_t *peer, - uint8 *data, size_t data_length, int client_hello) + uint8 *data, size_t data_length, int is_client_hello) { uint16_t i, j; int ext_elliptic_curve = 0; @@ -1109,7 +1109,7 @@ dtls_check_tls_extension(dtls_peer_t *peer, break; case TLS_EXT_CLIENT_CERTIFICATE_TYPE: ext_client_cert_type = 1; - if (client_hello) { + if (is_client_hello) { if (verify_ext_cert_type(data, j)) goto error; } else { @@ -1119,7 +1119,7 @@ dtls_check_tls_extension(dtls_peer_t *peer, break; case TLS_EXT_SERVER_CERTIFICATE_TYPE: ext_server_cert_type = 1; - if (client_hello) { + if (is_client_hello) { if (verify_ext_cert_type(data, j)) goto error; } else { @@ -1145,6 +1145,15 @@ dtls_check_tls_extension(dtls_peer_t *peer, if (verify_ext_sig_hash_algo(data, j)) goto error; break; + case TLS_EXT_RENEGOTIATION_INFO: + /* RFC 5746, minimal version, only empty info is supported */ + if (j == 1 && *data == 0) { + peer->handshake_params->renegotiation_info = 1; + } else { + dtls_warn("only empty renegotiation info is supported.\n"); + goto error; + } + break; default: dtls_warn("unsupported tls extension: %i\n", i); break; @@ -1153,7 +1162,7 @@ dtls_check_tls_extension(dtls_peer_t *peer, data_length -= j; } if (ecdsa) { - if (client_hello) { + if (is_client_hello) { if (!ext_elliptic_curve || !ext_client_cert_type || !ext_server_cert_type || !ext_ec_point_formats) { dtls_warn("not all required tls extensions found in client hello\n"); goto error; @@ -1168,7 +1177,7 @@ dtls_check_tls_extension(dtls_peer_t *peer, return 0; error: - if (client_hello && peer->state == DTLS_STATE_CONNECTED) { + if (is_client_hello && peer->state == DTLS_STATE_CONNECTED) { return dtls_alert_create(DTLS_ALERT_LEVEL_WARNING, DTLS_ALERT_NO_RENEGOTIATION); } else { return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); @@ -1245,9 +1254,13 @@ dtls_update_parameters(dtls_context_t *ctx, } ok = 0; - while ((i >= (int)sizeof(uint16)) && !ok) { - config->cipher_index = get_cipher_index(config->cipher_suites, dtls_uint16_to_int(data)); - ok = known_cipher(ctx, config->cipher_index, 0); + while ((i >= (int)sizeof(uint16)) && (!ok || !config->renegotiation_info)) { + if (dtls_uint16_to_int(data) == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { + config->renegotiation_info = 1; + } else { + config->cipher_index = get_cipher_index(config->cipher_suites, dtls_uint16_to_int(data)); + ok = known_cipher(ctx, config->cipher_index, 0); + } i -= sizeof(uint16); data += sizeof(uint16); } @@ -2312,6 +2325,7 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) const int ecdsa = is_key_exchange_ecdhe_ecdsa(handshake->cipher_index); extension_size = (handshake->extended_master_secret ? 4 : 0) + + (handshake->renegotiation_info ? 5 : 0) + (ecdsa ? 5 + 5 + 6 : 0); /* Handshake header */ @@ -2393,6 +2407,19 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) p += sizeof(uint16); } + if (handshake->renegotiation_info) { + /* RFC5746 minimal version, empty renegotiation info */ + dtls_int_to_uint16(p, TLS_EXT_RENEGOTIATION_INFO); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 1); + p += sizeof(uint16); + + /* empty renegotiation info */ + *p++ = 0; + } + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); /* TODO use the same record sequence number as in the ClientHello, @@ -2966,6 +2993,11 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); } + /* RFC5746 add RENEGOTIATION_INFO_SCSV */ + dtls_int_to_uint16(p, TLS_EMPTY_RENEGOTIATION_INFO_SCSV); + p += sizeof(uint16); + cipher_suites_size += sizeof(uint16); + /* set size of known cipher suites */ dtls_int_to_uint16(p_cipher_suites_size, cipher_suites_size); diff --git a/global.h b/global.h index 47f153c4..add26fa9 100644 --- a/global.h +++ b/global.h @@ -84,6 +84,7 @@ typedef enum { #define TLS_EXT_SERVER_CERTIFICATE_TYPE 20 /* see RFC 7250 */ #define TLS_EXT_ENCRYPT_THEN_MAC 22 /* see RFC 7366 */ #define TLS_EXT_EXTENDED_MASTER_SECRET 23 /* see RFC 7627 */ +#define TLS_EXT_RENEGOTIATION_INFO 65281 /* see RFC 5746 */ #define TLS_CERT_TYPE_RAW_PUBLIC_KEY 2 /* see RFC 7250 */