From 52f65d61cebbf1c6bfadf709fc0f3cb6e3cae48b Mon Sep 17 00:00:00 2001 From: Achim Kraus Date: Wed, 8 Dec 2021 09:59:29 +0100 Subject: [PATCH 1/2] dtls.c: fix receiving CertificateRequest. Add check for is_tls_ecdhe_ecdsa_with_aes_128_ccm_8 cipher-suite in order to fail receiving CertificateRequest for PSK. Signed-off-by: Achim Kraus --- dtls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dtls.c b/dtls.c index 106c9635..7cf12cb3 100644 --- a/dtls.c +++ b/dtls.c @@ -3628,7 +3628,8 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t #ifdef DTLS_ECC case DTLS_HT_CERTIFICATE_REQUEST: - if (state != DTLS_STATE_WAIT_SERVERHELLODONE) { + if (state != DTLS_STATE_WAIT_SERVERHELLODONE || + !is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) { return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); } From 40d863c1159a14a6fcb79e56bb6e515c320e5716 Mon Sep 17 00:00:00 2001 From: Achim Kraus Date: Mon, 22 Nov 2021 10:47:26 +0100 Subject: [PATCH 2/2] dtls.c: Check for optional handshake messages In general the handshake state machine forces the handshakes to go through a defined order. But optional handshake message are not controlled by that. This fix introduces a optional handshake message field. This new field enables the state-machine to check if this message is (optionally) expected. When processed, the field is reset and receiving the optional message twice will therefore fail the handshake. Fixes: Issue #78 Signed-off-by: Achim Kraus --- dtls.c | 13 ++++++++++--- dtls.h | 5 +++++ peer.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/dtls.c b/dtls.c index 7cf12cb3..ced00243 100644 --- a/dtls.c +++ b/dtls.c @@ -3440,6 +3440,7 @@ dtls_renegotiate(dtls_context_t *ctx, const session_t *dst) peer->handshake_params->hs_state.mseq_r = 0; peer->handshake_params->hs_state.mseq_s = 0; + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; if (peer->role == DTLS_CLIENT) { /* send ClientHello with empty Cookie */ @@ -3553,8 +3554,10 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t } if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; - else + else { + peer->optional_handshake_message = DTLS_HT_SERVER_KEY_EXCHANGE; peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; + } /* update_hs_hash(peer, data, data_length); */ break; @@ -3588,14 +3591,16 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) { return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); } + peer->optional_handshake_message = DTLS_HT_CERTIFICATE_REQUEST; err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length); } #endif /* DTLS_ECC */ #ifdef DTLS_PSK if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) { - if (state != DTLS_STATE_WAIT_SERVERHELLODONE) { + if (state != DTLS_STATE_WAIT_SERVERHELLODONE || peer->optional_handshake_message != DTLS_HT_SERVER_KEY_EXCHANGE) { return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); } + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; err = check_server_key_exchange_psk(ctx, peer, data, data_length); } #endif /* DTLS_PSK */ @@ -3629,10 +3634,11 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t case DTLS_HT_CERTIFICATE_REQUEST: if (state != DTLS_STATE_WAIT_SERVERHELLODONE || + peer->optional_handshake_message != DTLS_HT_CERTIFICATE_REQUEST || !is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) { return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); } - + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; err = check_certificate_request(ctx, peer, data, data_length); if (err < 0) { dtls_warn("error in check_certificate_request err: %i\n", err); @@ -3785,6 +3791,7 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t return err; } peer->state = DTLS_STATE_CLIENTHELLO; + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; break; default: diff --git a/dtls.h b/dtls.h index 16bf2594..a7c6c641 100644 --- a/dtls.h +++ b/dtls.h @@ -348,6 +348,11 @@ typedef struct __attribute__((__packed__)) { #define DTLS_HT_CLIENT_KEY_EXCHANGE 16 #define DTLS_HT_FINISHED 20 +/** + * Pseudo handshake message type, if no optional handshake message is expected. + */ +#define DTLS_HT_NO_OPTIONAL_MESSAGE -1 + /** Header structure for the DTLS handshake protocol. */ typedef struct __attribute__((__packed__)) { uint8 msg_type; /**< Type of handshake message (one of DTLS_HT_) */ diff --git a/peer.h b/peer.h index b79e4fbf..bd327fa7 100644 --- a/peer.h +++ b/peer.h @@ -52,6 +52,7 @@ typedef struct dtls_peer_t { dtls_peer_type role; /**< denotes if this host is DTLS_CLIENT or DTLS_SERVER */ dtls_state_t state; /**< DTLS engine state */ + int16_t optional_handshake_message; /**< optional next handshake message, DTLS_HT_NO_OPTIONAL_MESSAGE, if no optional message is expected. */ dtls_security_parameters_t *security_params[2]; dtls_handshake_parameters_t *handshake_params;