Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rfc5746 #181

Merged
merged 2 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
19 changes: 14 additions & 5 deletions tests/dtls-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static dtls_context_t *orig_dtls_context = NULL;

static const dtls_cipher_t* ciphers = NULL;
static unsigned int force_extended_master_secret = 0;
static unsigned int force_renegotiation_info = 0;


#ifdef DTLS_ECC
Expand Down Expand Up @@ -238,6 +239,7 @@ get_user_parameters(struct dtls_context_t *ctx,
(void) ctx;
(void) session;
user_parameters->force_extended_master_secret = force_extended_master_secret;
user_parameters->force_renegotiation_info = force_renegotiation_info;
if (ciphers) {
int i = 0;
while (i < DTLS_MAX_CIPHER_SUITES) {
Expand Down Expand Up @@ -353,19 +355,23 @@ usage( const char *program, const char *version) {
fprintf(stderr, "%s v%s -- DTLS client implementation\n"
"(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
#ifdef DTLS_PSK
"usage: %s [-c cipher suites] [-e] [-i file] [-k file] [-o file] [-p port] [-v num] addr [port]\n",
"usage: %s [-c cipher suites] [-e] [-i file] [-k file] [-o file]\n"
" %*s [-p port] [-r] [-v num] addr [port]\n",
#else /* DTLS_PSK */
"usage: %s [-c cipher suites] [-e] [-o file] [-p port] [-v num] addr [port]\n",
"usage: %s [-c cipher suites] [-e] [-o file] [-p port] [-r]\n"
" %*s [-v num] addr [port]\n",
#endif /* DTLS_PSK */
program, version, program);
program, version, program, (int)strlen(program), "");
cipher_suites_usage(stderr, "\t");
fprintf(stderr, "\t-e\t\tforce extended master secret (RFC7627)\n"
#ifdef DTLS_PSK
"\t-i file\t\tread PSK identity from file\n"
"\t-k file\t\tread pre-shared key from file\n"
#endif /* DTLS_PSK */
"\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n"
"\t-o file\t\toutput received data to this file\n"
"\t \t\t(use '-' for STDOUT)\n"
"\t-p port\t\tlisten on specified port (default is %d)\n"
"\t-r\t\tforce renegotiation info (RFC5746)\n"
"\t-v num\t\tverbosity level (default: 3)\n",
DEFAULT_PORT);
}
Expand Down Expand Up @@ -422,7 +428,7 @@ main(int argc, char **argv) {
memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length);
#endif /* DTLS_PSK */

while ((opt = getopt(argc, argv, "c:eo:p:v:" PSK_OPTIONS)) != -1) {
while ((opt = getopt(argc, argv, "c:eo:p:rv:" PSK_OPTIONS)) != -1) {
switch (opt) {
#ifdef DTLS_PSK
case 'i' :
Expand Down Expand Up @@ -464,6 +470,9 @@ main(int argc, char **argv) {
strncpy(port_str, optarg, NI_MAXSERV-1);
port_str[NI_MAXSERV - 1] = '\0';
break;
case 'r' :
force_renegotiation_info = 1;
break;
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
Expand Down
10 changes: 8 additions & 2 deletions tests/dtls-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static dtls_context_t *the_context = NULL;
static volatile int cmd_exit = 0;
static const dtls_cipher_t* ciphers = NULL;
static unsigned int force_extended_master_secret = 0;
static unsigned int force_renegotiation_info = 0;

#ifdef DTLS_ECC
static const unsigned char ecdsa_priv_key[] = {
Expand Down Expand Up @@ -199,6 +200,7 @@ get_user_parameters(struct dtls_context_t *ctx,
(void) ctx;
(void) session;
user_parameters->force_extended_master_secret = force_extended_master_secret;
user_parameters->force_renegotiation_info = force_renegotiation_info;
if (ciphers) {
int i = 0;
while (i < DTLS_MAX_CIPHER_SUITES) {
Expand Down Expand Up @@ -307,12 +309,13 @@ usage(const char *program, const char *version) {

fprintf(stderr, "%s v%s -- DTLS server implementation\n"
"(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
"usage: %s [-A address] [-c cipher suites] [-e] [-p port] [-v num]\n"
"usage: %s [-A address] [-c cipher suites] [-e] [-p port] [-r] [-v num]\n"
"\t-A address\t\tlisten on specified address (default is ::)\n",
program, version, program);
cipher_suites_usage(stderr, "\t");
fprintf(stderr, "\t-e\t\tforce extended master secret (RFC7627)\n"
"\t-p port\t\tlisten on specified port (default is %d)\n"
"\t-r\t\tforce renegotiation info (RFC5746)\n"
"\t-v num\t\tverbosity level (default: 3)\n",
DEFAULT_PORT);
}
Expand Down Expand Up @@ -355,7 +358,7 @@ main(int argc, char **argv) {
listen_addr.sin6_family = AF_INET6;
listen_addr.sin6_addr = in6addr_any;

while ((opt = getopt(argc, argv, "A:c:ep:v:")) != -1) {
while ((opt = getopt(argc, argv, "A:c:ep:rv:")) != -1) {
switch (opt) {
case 'A' :
if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
Expand All @@ -372,6 +375,9 @@ main(int argc, char **argv) {
case 'p' :
port = htons(atoi(optarg));
break;
case 'r' :
force_renegotiation_info = 1;
break;
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
Expand Down