Skip to content

Commit

Permalink
dtls.c: add RFC5746 minimal version implementation.
Browse files Browse the repository at this point in the history
Supports RFC5746 minimal version without renegotiation.
Add detailed documentation about the message length calculations.
Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV to DTLS_CH_LENGTH_MAX.
Remove eclipse_curves from ServerHello length.

Signed-off-by: Achim Kraus <[email protected]>
  • Loading branch information
boaks committed Jul 24, 2023
1 parent ba830a3 commit 4ea6312
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
2 changes: 2 additions & 0 deletions crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ typedef struct dtls_user_parameters_t {
*/
dtls_cipher_t cipher_suites[DTLS_MAX_CIPHER_SUITES + 1];
unsigned int force_extended_master_secret:1; /** force extended master secret extension (RFC7627) */
unsigned int force_renegotiation_info:1; /** force renegotiation info extension (RFC5746) */
} dtls_user_parameters_t;

typedef struct {
Expand All @@ -159,6 +160,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;
Expand Down
50 changes: 46 additions & 4 deletions dtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ memarray_t dtlscontext_storage;
* ec point format := 6 bytes => 26
* sign. and hash algos := 8 bytes
* extended master secret := 4 bytes => 12
*
* (The ClientHello uses TLS_EMPTY_RENEGOTIATION_INFO_SCSV
* instead of renegotiation info)
*/
#define DTLS_CH_LENGTH sizeof(dtls_client_hello_t) /* no variable length fields! */
#define DTLS_COOKIE_LENGTH_MAX 32
Expand Down Expand Up @@ -660,6 +663,7 @@ static const dtls_user_parameters_t default_user_parameters = {
},
#endif /* DTLS_DEFAULT_CIPHER_SUITES */
.force_extended_master_secret = 1,
.force_renegotiation_info = 1,
};

/** only one compression method is currently defined */
Expand Down Expand Up @@ -1260,6 +1264,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) {
config->renegotiation_info = 1;
} else {
dtls_warn("only empty renegotiation info is supported.\n");
goto error;
}
break;
default:
dtls_notice("unsupported tls extension: %i\n", i);
break;
Expand Down Expand Up @@ -1288,6 +1301,11 @@ dtls_check_tls_extension(dtls_peer_t *peer,
goto error;
}
}
if (config->user_parameters.force_renegotiation_info) {
if (!config->renegotiation_info) {
goto error;
}
}
return 0;

error:
Expand Down Expand Up @@ -1366,9 +1384,13 @@ dtls_update_parameters(dtls_context_t *ctx,
}

ok = 0;
while ((i >= (int)sizeof(uint16)) && !ok) {
config->cipher_index = get_cipher_index(config->user_parameters.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 if (!ok) {
config->cipher_index = get_cipher_index(config->user_parameters.cipher_suites, dtls_uint16_to_int(data));
ok = known_cipher(ctx, config->cipher_index, 0);
}
i -= sizeof(uint16);
data += sizeof(uint16);
}
Expand Down Expand Up @@ -2435,17 +2457,19 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer)
* server certificate type := 5 bytes
* ec_point_formats := 6 bytes
* extended master secret := 4 bytes
* renegotiation info := 5 bytes
*
* (no elliptic_curves in ServerHello.)
*/
uint8 buf[DTLS_SH_LENGTH + 2 + 5 + 5 + 6 + 4];
uint8 buf[DTLS_SH_LENGTH + 2 + 5 + 5 + 6 + 4 + 5];
uint8 *p;
uint8 extension_size;
dtls_handshake_parameters_t * const handshake = peer->handshake_params;
const dtls_cipher_t cipher_suite = get_cipher_suite(handshake->cipher_index);
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 */
Expand Down Expand Up @@ -2527,6 +2551,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, 5 bytes */
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,
Expand Down Expand Up @@ -3098,6 +3135,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);

Expand Down
4 changes: 3 additions & 1 deletion global.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ typedef unsigned char uint48[6];
/** Known cipher suites.*/
typedef enum {
TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF, /**< see RFC 5746 */
TLS_PSK_WITH_AES_128_CCM = 0xC0A4, /**< see RFC 6655 */
TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xC0AC, /**< see RFC 7251 */
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE, /**< see RFC 7251 */
} dtls_cipher_t;

/** Known compression suites.*/
Expand All @@ -92,6 +93,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 */

Expand Down

0 comments on commit 4ea6312

Please sign in to comment.