Add support for user-selectable srtp window size, as a parameter in srtp_policy_t.
diff --git a/crypto/include/rdbx.h b/crypto/include/rdbx.h
index 00a9e2e..146fb42 100644
--- a/crypto/include/rdbx.h
+++ b/crypto/include/rdbx.h
@@ -46,19 +46,29 @@
 
 typedef struct {
   xtd_seq_num_t index;
-  v128_t bitmask;
+  bitvector_t bitmask;
 } rdbx_t;
 
 
 /*
- * rdbx_init(rdbx_ptr)
+ * rdbx_init(rdbx_ptr, ws)
  *
- * initializes the rdbx pointed to by its argument, setting the
- * rollover counter and sequence number to zero
+ * initializes the rdbx pointed to by its argument with the window size ws,
+ * setting the rollover counter and sequence number to zero
  */
 
 err_status_t
-rdbx_init(rdbx_t *rdbx);
+rdbx_init(rdbx_t *rdbx, unsigned long ws);
+
+
+/*
+ * rdbx_dealloc(rdbx_ptr)
+ *
+ * frees memory associated with the rdbx
+ */
+
+err_status_t
+rdbx_dealloc(rdbx_t *rdbx);
 
 
 /*
@@ -127,6 +137,15 @@
  * api instead!
  */
 
+/*
+ * rdbx_get_ws(rdbx_ptr)
+ *
+ * gets the window size which was used to initialize the rdbx
+ */
+
+unsigned long
+rdbx_get_window_size(const rdbx_t *rdbx);
+
 
 /* index_init(&pi) initializes a packet index pi (sets it to zero) */
 
diff --git a/crypto/replay/rdbx.c b/crypto/replay/rdbx.c
index ce713bb..15d52b5 100644
--- a/crypto/replay/rdbx.c
+++ b/crypto/replay/rdbx.c
@@ -45,7 +45,6 @@
 
 #include "rdbx.h"
 
-#define rdbx_high_bit_in_bitmask 127
 
 /*
  * from RFC 3711:
@@ -180,17 +179,32 @@
 
 
 /*
- *  rdbx_init(&r) initalizes the rdbx_t pointed to by r 
+ *  rdbx_init(&r, ws) initializes the rdbx_t pointed to by r with window size ws
  */
 
 err_status_t
-rdbx_init(rdbx_t *rdbx) {
-  v128_set_to_zero(&rdbx->bitmask);
+rdbx_init(rdbx_t *rdbx, unsigned long ws) {
+  if (ws == 0)
+    return err_status_bad_param;
+
+  if (bitvector_alloc(&rdbx->bitmask, ws) != 0)
+    return err_status_alloc_fail;
+
   index_init(&rdbx->index);
 
   return err_status_ok;
 }
 
+/*
+ *  rdbx_dealloc(&r) frees memory for the rdbx_t pointed to by r
+ */
+
+err_status_t
+rdbx_dealloc(rdbx_t *rdbx) {
+  bitvector_dealloc(&rdbx->bitmask);
+
+  return err_status_ok;
+}
 
 /*
  * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx
@@ -202,7 +216,7 @@
 
 err_status_t
 rdbx_set_roc(rdbx_t *rdbx, uint32_t roc) {
-  v128_set_to_zero(&rdbx->bitmask);
+  bitvector_set_to_zero(&rdbx->bitmask);
 
 #ifdef NO_64BIT_MATH
   #error not yet implemented
@@ -231,6 +245,17 @@
 }
 
 /*
+ * rdbx_get_window_size(rdbx) returns the value of the window size
+ * for the rdbx_t pointed to by rdbx
+ * 
+ */
+
+unsigned long
+rdbx_get_window_size(const rdbx_t *rdbx) {
+  return bitvector_get_length(&rdbx->bitmask);
+}
+
+/*
  * rdbx_check(&r, delta) checks to see if the xtd_seq_num_t
  * which is at rdbx->index + delta is in the rdb
  */
@@ -240,11 +265,11 @@
   
   if (delta > 0) {       /* if delta is positive, it's good */
     return err_status_ok;
-  } else if (rdbx_high_bit_in_bitmask + delta < 0) {   
+  } else if ((int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta < 0) {   
                          /* if delta is lower than the bitmask, it's bad */
     return err_status_replay_old; 
-  } else if (v128_get_bit(&rdbx->bitmask, 
-			  rdbx_high_bit_in_bitmask + delta) == 1) {
+  } else if (bitvector_get_bit(&rdbx->bitmask, 
+			       (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) {
                          /* delta is within the window, so check the bitmask */
     return err_status_replay_fail;    
   }
@@ -268,11 +293,11 @@
   if (delta > 0) {
     /* shift forward by delta */
     index_advance(&rdbx->index, delta);
-    v128_left_shift(&rdbx->bitmask, delta);
-    v128_set_bit(&rdbx->bitmask, 127);
+    bitvector_left_shift(&rdbx->bitmask, delta);
+    bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1);
   } else {
     /* delta is in window */
-    v128_set_bit(&rdbx->bitmask, rdbx_high_bit_in_bitmask + delta);
+    bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) -1 + delta);
   }
 
   /* note that we need not consider the case that delta == 0 */
diff --git a/include/srtp.h b/include/srtp.h
index 81cd617..68073e5 100644
--- a/include/srtp.h
+++ b/include/srtp.h
@@ -223,6 +223,8 @@
 				*    this stream.                        */
   ekt_policy_t ekt;            /**< Pointer to the EKT policy structure
                                 *   for this stream (if any)             */ 
+  unsigned long window_size;   /**< The window size to use for replay
+				*   protection. */
   struct srtp_policy_t *next;  /**< Pointer to next stream policy.       */
 } srtp_policy_t;
 
diff --git a/srtp/srtp.c b/srtp/srtp.c
index 2877e8e..04a917a 100644
--- a/srtp/srtp.c
+++ b/srtp/srtp.c
@@ -231,6 +231,10 @@
       return status;
   }
 
+  status = rdbx_dealloc(&stream->rtp_rdbx);
+  if (status)
+    return status;
+
   /* DAM - need to deallocate EKT here */
   
   /* deallocate srtp stream context */
@@ -275,7 +279,10 @@
     return status;
 
   /* initialize replay databases */
-  rdbx_init(&str->rtp_rdbx);
+  status = rdbx_init(&str->rtp_rdbx,
+		     rdbx_get_window_size(&stream_template->rtp_rdbx));
+  if (status)
+    return status;
   rdb_init(&str->rtcp_rdb);
   
   /* set ssrc to that provided */
@@ -491,7 +498,18 @@
 	       p->ssrc.value);
 
    /* initialize replay database */
-   rdbx_init(&srtp->rtp_rdbx);
+   /* window size MUST be at least 64.  MAY be larger.  Values more than
+    * 2^15 aren't meaningful due to how extended sequence numbers are
+    * calculated.   Let a window size of 0 imply the default value. */
+
+   if (p->window_size != 0 && (p->window_size < 64 || p->window_size >= 0x8000))
+     return err_status_bad_param;
+
+   if (p->window_size != 0)
+     err = rdbx_init(&srtp->rtp_rdbx, p->window_size);
+   else
+     err = rdbx_init(&srtp->rtp_rdbx, 128);
+   if (err) return err;
 
    /* initialize key limit to maximum value */
 #ifdef NO_64BIT_MATH
@@ -525,14 +543,20 @@
 
    /* initialize keys */
    err = srtp_stream_init_keys(srtp, p->key);
-   if (err) return err;
+   if (err) {
+     rdbx_dealloc(&srtp->rtp_rdbx);
+     return err;
+   }
 
    /* 
     * if EKT is in use, then initialize the EKT data associated with
     * the stream
     */
    err = ekt_stream_init_from_policy(srtp->ekt, p->ekt);
-   if (err) return err;
+   if (err) {
+     rdbx_dealloc(&srtp->rtp_rdbx);
+     return err;
+   }
 
    return err_status_ok;  
  }
@@ -1220,6 +1244,9 @@
     status = auth_dealloc(session->stream_template->rtp_auth);
     if (status)
       return status;
+    status = rdbx_dealloc(&session->stream_template->rtp_rdbx);
+    if (status)
+      return status;
     crypto_free(session->stream_template);
   }
 
diff --git a/test/dtls_srtp_driver.c b/test/dtls_srtp_driver.c
index 2f3cade..6980305 100644
--- a/test/dtls_srtp_driver.c
+++ b/test/dtls_srtp_driver.c
@@ -191,6 +191,7 @@
   if (err) return err;
   policy.ssrc.type  = ssrc_any_inbound;
   policy.ekt = NULL;
+  policy.window_size = 128;
   policy.next = NULL;
     
   err = srtp_add_stream(s, &policy);
diff --git a/test/rdbx_driver.c b/test/rdbx_driver.c
index cb4e4fe..838cc43 100644
--- a/test/rdbx_driver.c
+++ b/test/rdbx_driver.c
@@ -55,10 +55,10 @@
 #include "ut_sim.h"
 
 err_status_t 
-test_replay_dbx(int num_trials);
+test_replay_dbx(int num_trials, unsigned long ws);
 
 double
-rdbx_check_adds_per_second(int num_trials);
+rdbx_check_adds_per_second(int num_trials, unsigned long ws);
 
 void
 usage(char *prog_name) {
@@ -99,9 +99,18 @@
     usage(argv[0]);
 
   if (do_validation) {
-  printf("testing rdbx_t...\n");
+    printf("testing rdbx_t (ws=128)...\n");
 
-    status = test_replay_dbx(1 << 12);
+    status = test_replay_dbx(1 << 12, 128);
+    if (status) {
+      printf("failed\n");
+      exit(1);
+    }
+    printf("passed\n");
+
+    printf("testing rdbx_t (ws=1024)...\n");
+
+    status = test_replay_dbx(1 << 12, 1024);
     if (status) {
       printf("failed\n");
       exit(1);
@@ -110,8 +119,10 @@
   }
 
   if (do_timing_test) {
-    rate = rdbx_check_adds_per_second(1 << 18);
-    printf("rdbx_check/replay_adds per second: %e\n", rate);
+    rate = rdbx_check_adds_per_second(1 << 18, 128);
+    printf("rdbx_check/replay_adds per second (ws=128): %e\n", rate);
+    rate = rdbx_check_adds_per_second(1 << 18, 1024);
+    printf("rdbx_check/replay_adds per second (ws=1024): %e\n", rate);
   }
   
   return 0;
@@ -119,8 +130,11 @@
 
 void
 print_rdbx(rdbx_t *rdbx) {
+  char buf[2048];
   printf("rdbx: {%llu, %s}\n",
-	 (unsigned long long)(rdbx->index), v128_bit_string(&rdbx->bitmask));
+	 (unsigned long long)(rdbx->index),
+	 bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf))
+);
 }
 
 
@@ -206,17 +220,15 @@
   return err_status_ok;
 }
 
-#define MAX_IDX 160
-
 err_status_t
-test_replay_dbx(int num_trials) {
+test_replay_dbx(int num_trials, unsigned long ws) {
   rdbx_t rdbx;
   uint32_t idx, ircvd;
   ut_connection utc;
   err_status_t status;
   int num_fp_trials;
 
-  status = rdbx_init(&rdbx);
+  status = rdbx_init(&rdbx, ws);
   if (status) {
     printf("replay_init failed with error code %d\n", status);
     exit(1);
@@ -253,7 +265,9 @@
   printf("passed\n");
 
   /* re-initialize */
-  if (rdbx_init(&rdbx) != err_status_ok) {
+  rdbx_dealloc(&rdbx);
+
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
     printf("replay_init failed\n");
     return err_status_init_fail;
   }
@@ -279,7 +293,9 @@
   printf("passed\n");
 
   /* re-initialize */
-  if (rdbx_init(&rdbx) != err_status_ok) {
+  rdbx_dealloc(&rdbx);
+
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
     printf("replay_init failed\n");
     return err_status_init_fail;
   }
@@ -299,6 +315,8 @@
   }
   printf("passed\n");
 
+  rdbx_dealloc(&rdbx);
+
   return err_status_ok;
 }
 
@@ -308,7 +326,7 @@
 #include <stdlib.h>     /* for random() */
 
 double
-rdbx_check_adds_per_second(int num_trials) {
+rdbx_check_adds_per_second(int num_trials, unsigned long ws) {
   uint32_t i;
   int delta;
   rdbx_t rdbx;
@@ -316,7 +334,7 @@
   clock_t timer;
   int failures;                    /* count number of failures        */
   
-  if (rdbx_init(&rdbx) != err_status_ok) {
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
     printf("replay_init failed\n");
     exit(1);
   }  
@@ -337,6 +355,8 @@
 
   printf("number of failures: %d \n", failures);
 
+  rdbx_dealloc(&rdbx);
+
   return (double) CLOCKS_PER_SEC * num_trials / timer;
 }
 
diff --git a/test/rtpw.c b/test/rtpw.c
index ccfdc31..b95ecfd 100644
--- a/test/rtpw.c
+++ b/test/rtpw.c
@@ -350,6 +350,7 @@
     policy.ssrc.value = ssrc;
     policy.key  = (uint8_t *) key;
     policy.next = NULL;
+    policy.window_size = 128;
     policy.rtp.sec_serv = sec_servs;
     policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
 
@@ -402,6 +403,7 @@
     policy.rtcp.auth_key_len   = 0;
     policy.rtcp.auth_tag_len   = 0;
     policy.rtcp.sec_serv       = sec_serv_none;   
+    policy.window_size         = 0;
     policy.next                = NULL;
   }
 
diff --git a/test/srtp_driver.c b/test/srtp_driver.c
index 7b62147..db0bc4f 100644
--- a/test/srtp_driver.c
+++ b/test/srtp_driver.c
@@ -329,6 +329,8 @@
     policy.ssrc.type  = ssrc_specific;
     policy.ssrc.value = 0xdecafbad;
     policy.key  = test_key;
+    policy.ekt = NULL;
+    policy.window_size = 128;
     policy.next = NULL;
 
     printf("mips estimate: %e\n", mips);
@@ -1026,14 +1028,16 @@
 	   "# rtp services:  %s\r\n" 
            "# rtcp cipher:   %s\r\n"
 	   "# rtcp auth:     %s\r\n"
-	   "# rtcp services: %s\r\n",
+	   "# rtcp services: %s\r\n"
+	   "# window size:   %lu\r\n",
 	   direction[stream->direction],
 	   stream->rtp_cipher->type->description,
 	   stream->rtp_auth->type->description,
 	   serv_descr[stream->rtp_services],
 	   stream->rtcp_cipher->type->description,
 	   stream->rtcp_auth->type->description,
-	   serv_descr[stream->rtcp_services]);
+	   serv_descr[stream->rtcp_services],
+	   rdbx_get_window_size(&stream->rtp_rdbx));
   }
 
   /* loop over streams in session, printing the policy of each */
@@ -1048,14 +1052,16 @@
 	   "# rtp services:  %s\r\n" 
            "# rtcp cipher:   %s\r\n"
 	   "# rtcp auth:     %s\r\n"
-	   "# rtcp services: %s\r\n",
+	   "# rtcp services: %s\r\n"
+	   "# window size:   %lu\r\n",
 	   stream->ssrc,
 	   stream->rtp_cipher->type->description,
 	   stream->rtp_auth->type->description,
 	   serv_descr[stream->rtp_services],
 	   stream->rtcp_cipher->type->description,
 	   stream->rtcp_auth->type->description,
-	   serv_descr[stream->rtcp_services]);
+	   serv_descr[stream->rtcp_services],
+	   rdbx_get_window_size(&stream->rtp_rdbx));
 
     /* advance to next stream in the list */
     stream = stream->next;
@@ -1209,6 +1215,8 @@
   policy.ssrc.type  = ssrc_specific;
   policy.ssrc.value = 0xcafebabe;
   policy.key  = test_key;
+  policy.ekt = NULL;
+  policy.window_size = 128;
   policy.next = NULL;
 
   status = srtp_create(&srtp_snd, &policy);
@@ -1394,6 +1402,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1417,6 +1426,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1440,6 +1450,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1463,6 +1474,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1486,6 +1498,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1509,6 +1522,7 @@
   },
   test_key,
   NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
   NULL
 };
 
@@ -1546,6 +1560,7 @@
   },
   test_key,
   &ekt_test_policy,        /* indicates that EKT is not in use */
+  128,                     /* replay window size */
   NULL
 };
 
@@ -1598,5 +1613,6 @@
   },
   test_key,
   NULL,
+  128,                   /* replay window size */
   NULL
 };