Test and fix anti-replay functions
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 31be3ca..d48ccf5 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2697,10 +2697,12 @@
 /*
  * 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 @@
     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 @@
         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 2e4d9d4..42d34f3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -86,6 +86,7 @@
 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 c37b790..b519d5c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -65,6 +65,7 @@
 		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 @@
 	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 0000000..a39f6f0
--- /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 0000000..f138c2f
--- /dev/null
+++ b/tests/suites/test_suite_ssl.function
@@ -0,0 +1,33 @@
+/* BEGIN_HEADER */
+#include <polarssl/ssl.h>
+/* 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 */