diff options
-rw-r--r-- | lib/gnutls_dtls.c | 98 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 |
2 files changed, 56 insertions, 43 deletions
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c index 78e21fbf74..f17739f3ee 100644 --- a/lib/gnutls_dtls.c +++ b/lib/gnutls_dtls.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2012 Free Software Foundation, Inc. + * Copyright (C) 2013 Nikos Mavrogiannopoulos * * Authors: Jonathan Bastien-Filiatrault * Nikos Mavrogiannopoulos @@ -435,21 +436,28 @@ int ret; return 0; } - #define window_table rp->record_sw #define window_size rp->record_sw_size +#define window_head_idx rp->record_sw_head_idx -/* FIXME: could we modify that code to avoid using - * uint64_t? - */ - -static void rot_window(struct record_parameters_st * rp, int places) +static void slide_window(struct record_parameters_st * rp, unsigned int places) { - window_size -= places; - memmove(window_table, &window_table[places], window_size*sizeof(window_table[0])); +unsigned int old_head = window_head_idx; + + if (places < window_size) + { + window_head_idx += places; + window_head_idx %= DTLS_RECORD_WINDOW_SIZE; + + window_table[window_head_idx] = window_table[old_head] + places; + } + else + { + unsigned int last_idx = (window_head_idx + window_size - 1) % window_size; + window_table[window_head_idx] = window_table[last_idx]; + } } -#define MOVE_SIZE 20 /* Checks if a sequence number is not replayed. If replayed * returns a negative error code, otherwise zero. */ @@ -457,6 +465,7 @@ int _dtls_record_check(struct record_parameters_st *rp, uint64 * _seq) { uint64_t seq = 0, diff; unsigned int i, offset = 0; +unsigned int last_idx; for (i=2;i<8;i++) { @@ -464,68 +473,71 @@ unsigned int i, offset = 0; seq |= _seq->i[i] & 0xff; } + /* only two values allowed in window_size */ if (window_size == 0) { window_size = 1; - window_table[0] = seq; + window_head_idx = 0; + last_idx = window_size - 1; + window_table[last_idx] = window_table[window_head_idx] = seq; return 0; } - if (seq <= window_table[0]) - { - return -1; - } + last_idx = (window_head_idx + window_size - 1) % window_size; - if (window_size == DTLS_RECORD_WINDOW_SIZE) + if (seq <= window_table[window_head_idx]) { - rot_window(rp, MOVE_SIZE); + return -1; } - if (seq < window_table[window_size-1]) + if (seq <= window_table[last_idx]) { /* is between first and last */ - diff = window_table[window_size-1] - seq; + diff = window_table[last_idx] - seq; if (diff >= window_size) - return -1; + { + return -1; + } - offset = window_size-1-diff; + if (diff > last_idx) + { + diff = diff - last_idx; + offset = window_size - 1 - diff; + } + else + offset = last_idx - diff; if (window_table[offset] == seq) - return -1; + { + return -1; + } else window_table[offset] = seq; } - else /* seq >= last */ + else /* seq > last */ { - if (seq == window_table[window_size-1]) - { - return -1; - } + diff = seq - window_table[last_idx]; - diff = seq - window_table[window_size-1]; - if (diff <= DTLS_RECORD_WINDOW_SIZE - window_size) - { /* fits in our empty space */ - offset = diff + window_size-1; - - window_table[offset] = seq; - window_size = offset + 1; + if (window_size + diff <= DTLS_RECORD_WINDOW_SIZE) + { + window_size += diff; } else { - if (diff > DTLS_RECORD_WINDOW_SIZE/2) - { /* difference is too big */ - window_table[DTLS_RECORD_WINDOW_SIZE-1] = seq; - window_size = DTLS_RECORD_WINDOW_SIZE; - } - else + if (window_size < DTLS_RECORD_WINDOW_SIZE) { - rot_window(rp, diff); - offset = diff + window_size-1; - window_table[offset] = seq; - window_size = offset + 1; + offset = DTLS_RECORD_WINDOW_SIZE-window_size; + window_size = DTLS_RECORD_WINDOW_SIZE; + diff -= offset; } + + /* diff > 0 */ + slide_window(rp, diff); } + + offset = (window_head_idx + window_size - 1) % window_size; + window_table[offset] = seq; } return 0; } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 239c9b3b44..bc487442ea 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -560,6 +560,7 @@ struct record_parameters_st /* for DTLS */ uint64_t record_sw[DTLS_RECORD_WINDOW_SIZE]; + unsigned int record_sw_head_idx; unsigned int record_sw_size; record_state_st read; |