diff --git a/crypto.h b/crypto.h index 18616832..0b0253db 100644 --- a/crypto.h +++ b/crypto.h @@ -168,6 +168,7 @@ typedef struct { unsigned int do_client_auth:1; unsigned int extended_master_secret:1; unsigned int renegotiation_info:1; + unsigned int reported_reorder:1; union { #ifdef DTLS_ECC dtls_handshake_parameters_ecdsa_t ecdsa; diff --git a/dtls.c b/dtls.c index c58017ff..86836d3d 100644 --- a/dtls.c +++ b/dtls.c @@ -4404,16 +4404,27 @@ handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t dat return 0; } + size_t buffered_length = data_length; netq_t *node = netq_head(&peer->handshake_params->reorder_queue); while (node) { dtls_handshake_header_t *node_header = DTLS_HANDSHAKE_HEADER(node->data); - if (dtls_uint16_to_int(node_header->message_seq) == mseq) { + uint16_t hmseq = dtls_uint16_to_int(node_header->message_seq); + if (hmseq == mseq) { dtls_warn("a packet with this sequence number is already stored\n"); return 0; } + buffered_length += node->length; node = netq_next(node); } + if (buffered_length > DTLS_MAX_REORDER_BUF) { + if (!peer->handshake_params->reported_reorder) { + peer->handshake_params->reported_reorder = 1; + dtls_warn("the packet exceeds the maximum reorder buffer size\n"); + } + return 0; + } + n = netq_node_new(data_length); if (!n) { dtls_warn("no space in reorder buffer\n"); @@ -4422,6 +4433,7 @@ handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t dat n->peer = peer; n->length = data_length; + n->t = mseq; /* use handshake message sequence number for time to sort */ memcpy(n->data, data, data_length); if (!netq_insert_node(&peer->handshake_params->reorder_queue, n)) { @@ -4432,35 +4444,21 @@ handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t dat return 0; } else if (mseq == peer->handshake_params->hs_state.mseq_r) { /* Found the expected packet, use this and all the buffered packet */ - int next = 1; - + netq_t *node =NULL; res = handle_handshake_msg(ctx, peer, data, data_length); - if (res < 0) - return res; - - /* We do not know in which order the packet are in the list just search the list for every packet. */ - while (next && peer->handshake_params) { - next = 0; - netq_t *node = netq_head(&peer->handshake_params->reorder_queue); - while (node) { - dtls_handshake_header_t *node_header = DTLS_HANDSHAKE_HEADER(node->data); - - if (dtls_uint16_to_int(node_header->message_seq) == peer->handshake_params->hs_state.mseq_r) { - netq_remove(&peer->handshake_params->reorder_queue, node); - next = 1; - res = handle_handshake_msg(ctx, peer, node->data, node->length); - - /* free message data */ - netq_node_free(node); + while (res >= 0 && peer->handshake_params && + (node = netq_head(&peer->handshake_params->reorder_queue))) { + dtls_handshake_header_t *node_header = DTLS_HANDSHAKE_HEADER(node->data); - if (res < 0) { - return res; - } + /* Using netq_t.time for the handshake message sequence number */ + if (dtls_uint16_to_int(node_header->message_seq) == peer->handshake_params->hs_state.mseq_r) { + netq_remove(&peer->handshake_params->reorder_queue, node); + res = handle_handshake_msg(ctx, peer, node->data, node->length); - break; - } else { - node = netq_next(node); - } + /* free message data */ + netq_node_free(node); + } else { + break; } } return res; diff --git a/global.h b/global.h index d915aed1..51a8858e 100644 --- a/global.h +++ b/global.h @@ -57,6 +57,15 @@ typedef unsigned char uint48[6]; #endif /* WITH_CONTIKI || RIOT_VERSION */ #endif +#ifndef DTLS_MAX_REORDER_BUF +/** + * Limit size of reordered handshake messages. + * Using RPK the largest server flight has about 450 bytes + * and the largest server flight has about 400 bytes + */ +#define DTLS_MAX_REORDER_BUF 512 +#endif + /* * DTLS send buf is alloctaed on the stack by default */