check sequence Numbers of received messages
Signed-off-by: Jannis Konrad <jannis.Konrad@h-brs.de>
diff --git a/crypto.h b/crypto.h
index f319109..b0b7d56 100644
--- a/crypto.h
+++ b/crypto.h
@@ -87,6 +87,11 @@
} dtls_handshake_parameters_psk_t;
typedef struct {
+ uint64_t cseq;
+ uint64_t bitfield;
+} seqnum_t;
+
+typedef struct {
dtls_compression_t compression; /**< compression method */
dtls_cipher_t cipher; /**< cipher type */
@@ -100,6 +105,8 @@
* access the components of the key block.
*/
uint8 key_block[MAX_KEYBLOCK_LENGTH];
+
+ seqnum_t cseq; /**<sequence number of last record received*/
} dtls_security_parameters_t;
struct netq_t;
diff --git a/dtls.c b/dtls.c
index 3e9b285..2da67f8 100644
--- a/dtls.c
+++ b/dtls.c
@@ -3662,7 +3662,51 @@
dtls_debug("got packet %d (%d bytes)\n", msg[0], rlen);
if (peer) {
- data_length = decrypt_verify(peer, msg, rlen, &data);
+ dtls_record_header_t *header = DTLS_RECORD_HEADER(msg);
+
+ dtls_security_parameters_t *security = dtls_security_params_epoch(peer, dtls_get_epoch(header));
+ if (!security) {
+ dtls_alert("No security context for epoch: %i\n", dtls_get_epoch(header));
+ data_length = -1;
+ } else {
+ uint64_t pkt_seq_nr = dtls_uint48_to_int(header->sequence_number);
+ if(pkt_seq_nr == 0 && security->cseq.cseq == 0) {
+ data_length = decrypt_verify(peer, msg, rlen, &data);
+ if (data_length) {
+ security->cseq.cseq = 0;
+ security->cseq.bitfield = -1;
+ }
+ } else if (pkt_seq_nr == security->cseq.cseq) {
+ dtls_info("Duplicate packet arrived (cseq=%llu)\n", security->cseq.cseq);
+ return 0;
+ } else if ((int64_t)(security->cseq.cseq-pkt_seq_nr) > 0) { //pkt_seq_nr < security->cseq.cseq)
+ if (((security->cseq.cseq-1)-pkt_seq_nr) < 64) {
+ if(security->cseq.bitfield & (1<<((security->cseq.cseq-1)-pkt_seq_nr))) {
+ dtls_info("Duplicate packet arrived (bitfield)\n");
+ //seen it
+ return 0;
+ } else {
+ dtls_info("Packet arrived out of order\n");
+ data_length = decrypt_verify(peer, msg, rlen, &data);
+ if(data_length > 0) {
+ security->cseq.bitfield |= (1<<((security->cseq.cseq-1)-pkt_seq_nr));
+ }
+ }
+ } else {
+ dtls_info("Packet from before the bitfield arrived\n");
+ return 0;
+ }
+ } else { //pkt_seq_nr > security->cseq.cseq
+ data_length = decrypt_verify(peer, msg, rlen, &data);
+ if(data_length > 0) {
+ security->cseq.bitfield <<= (pkt_seq_nr-security->cseq.cseq);
+ security->cseq.bitfield |= 1<<((pkt_seq_nr-security->cseq.cseq)-1);
+ security->cseq.cseq = pkt_seq_nr;
+ dtls_debug("new packet arrived with seqNr: %llu\n", pkt_seq_nr);
+ dtls_debug("new bitfield is : %llx\n", security->cseq.bitfield);
+ }
+ }
+ }
if (data_length < 0) {
if (hs_attempt_with_existing_peer(msg, rlen, peer)) {
data = msg + DTLS_RH_LENGTH;