diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 31be3ca3e..d48ccf5b1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2697,10 +2697,12 @@ static int ssl_prepare_handshake_record( ssl_context *ssl ) /* * DTLS anti-replay: RFC 6347 4.1.2.6 * - * - in_window_top is the highest record sequence number seen - * - the lsb of in_window is set iff in_window_top - 1 has been seen - * ... - * the msb of in_window is set iff in_window_top - 64 has been seen + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). */ #if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) static void ssl_dtls_replay_reset( ssl_context *ssl ) @@ -2730,10 +2732,7 @@ int ssl_dtls_replay_check( ssl_context *ssl ) if( rec_seqnum > ssl->in_window_top ) return( 0 ); - if( rec_seqnum == ssl->in_window_top ) - return( -1 ); - - bit = ssl->in_window_top - rec_seqnum - 1; + bit = ssl->in_window_top - rec_seqnum; if( bit >= 64 ) return( -1 ); @@ -2757,20 +2756,19 @@ void ssl_dtls_replay_update( ssl_context *ssl ) uint64_t shift = rec_seqnum - ssl->in_window_top; if( shift >= 64 ) - ssl->in_window = 0; + ssl->in_window = 1; else + { ssl->in_window <<= shift; + ssl->in_window |= 1; + } ssl->in_window_top = rec_seqnum; } - else if( rec_seqnum == ssl->in_window_top ) - { - ; /* Can't happen, but anyway, nothing to do if it happened */ - } else { /* Mark that number as seen in the current window */ - uint64_t bit = ssl->in_window_top - rec_seqnum - 1; + uint64_t bit = ssl->in_window_top - rec_seqnum; if( bit < 64 ) /* Always true, but be extra sure */ ssl->in_window |= (uint64_t) 1 << bit; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2e4d9d4a9..42d34f3cd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -86,6 +86,7 @@ add_test_suite(pk) add_test_suite(pkparse) add_test_suite(pkwrite) add_test_suite(shax) +add_test_suite(ssl) add_test_suite(rsa) add_test_suite(version) add_test_suite(xtea) diff --git a/tests/Makefile b/tests/Makefile index c37b790fa..b519d5c6e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -65,6 +65,7 @@ APPS = test_suite_aes.ecb test_suite_aes.cbc \ test_suite_pkparse test_suite_pkwrite \ test_suite_pk \ test_suite_rsa test_suite_shax \ + test_suite_ssl \ test_suite_x509parse test_suite_x509write \ test_suite_xtea test_suite_version @@ -376,6 +377,10 @@ test_suite_shax: test_suite_shax.c $(DEP) echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ +test_suite_ssl: test_suite_ssl.c $(DEP) + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + test_suite_x509parse: test_suite_x509parse.c $(DEP) echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data new file mode 100644 index 000000000..a39f6f09f --- /dev/null +++ b/tests/suites/test_suite_ssl.data @@ -0,0 +1,56 @@ +SSL DTLS replay: initial state, seqnum 0 +ssl_dtls_replay:"":"000000000000":0 + +SSL DTLS replay: 0 seen, 1 arriving +ssl_dtls_replay:"000000000000":"000000000001":0 + +SSL DTLS replay: 0 seen, 0 replayed +ssl_dtls_replay:"000000000000":"000000000000":-1 + +SSL DTLS replay: 0-1 seen, 2 arriving +ssl_dtls_replay:"000000000000,000000000001":"000000000002":0 + +SSL DTLS replay: 0-1 seen, 1 replayed +ssl_dtls_replay:"000000000000,000000000001":"000000000001":-1 + +SSL DTLS replay: 0-1 seen, 0 replayed +ssl_dtls_replay:"000000000000,000000000001":"000000000000":-1 + +SSL DTLS replay: new +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd12340003":"abcd12340004":0 + +SSL DTLS replay: way new +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd12340003":"abcd12350000":0 + +SSL DTLS replay: delayed +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd12340003":"abcd12340002":0 + +SSL DTLS replay: lastest replayed +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd12340003":"abcd12340003":-1 + +SSL DTLS replay: older replayed +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd12340003":"abcd12340001":-1 + +SSL DTLS replay: most recent in window, replayed +ssl_dtls_replay:"abcd12340000,abcd12340002,abcd12340003":"abcd12340002":-1 + +SSL DTLS replay: oldest in window, replayed +ssl_dtls_replay:"abcd12340000,abcd12340001,abcd1234003f":"abcd12340000":-1 + +SSL DTLS replay: oldest in window, not replayed +ssl_dtls_replay:"abcd12340001,abcd12340002,abcd1234003f":"abcd12340000":0 + +SSL DTLS replay: just out of the window +ssl_dtls_replay:"abcd12340001,abcd12340002,abcd1234003f":"abcd1233ffff":-1 + +SSL DTLS replay: way out of the window +ssl_dtls_replay:"abcd12340001,abcd12340002,abcd1234003f":"abcd12330000":-1 + +SSL DTLS replay: big jump then replay +ssl_dtls_replay:"abcd12340000,abcd12340100":"abcd12340100":-1 + +SSL DTLS replay: big jump then new +ssl_dtls_replay:"abcd12340000,abcd12340100":"abcd12340101":0 + +SSL DTLS replay: big jump then just delayed +ssl_dtls_replay:"abcd12340000,abcd12340100":"abcd123400ff":0 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function new file mode 100644 index 000000000..f138c2f78 --- /dev/null +++ b/tests/suites/test_suite_ssl.function @@ -0,0 +1,33 @@ +/* BEGIN_HEADER */ +#include +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:POLARSSL_SSL_TLS_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE depends_on:POLARSSL_SSL_DTLS_ANTI_REPLAY */ +void ssl_dtls_replay( char *prevs, char *new, int ret ) +{ + ssl_context ssl; + char *end_prevs = prevs + strlen( prevs ) + 1; + + TEST_ASSERT( ssl_init( &ssl ) == 0 ); + TEST_ASSERT( ssl_set_transport( &ssl, SSL_TRANSPORT_DATAGRAM ) == 0 ); + + /* Read previous record numbers */ + for( ; end_prevs - prevs >= 13; prevs += 13 ) + { + prevs[12] = '\0'; + unhexify( ssl.in_ctr + 2, prevs ); + ssl_dtls_replay_update( &ssl ); + } + + /* Check new number */ + unhexify( ssl.in_ctr + 2, new ); + TEST_ASSERT( ssl_dtls_replay_check( &ssl ) == ret ); + + ssl_free( &ssl ); +} +/* END_CASE */