Add AES-256 support.
diff --git a/crypto/Makefile.in b/crypto/Makefile.in
index c14dba5..842d08e 100644
--- a/crypto/Makefile.in
+++ b/crypto/Makefile.in
@@ -46,16 +46,23 @@
 	  test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \
 	  test/env$(EXE)
 
-# data values used to test the aes_calc application
+# data values used to test the aes_calc application for AES-128
+k128=000102030405060708090a0b0c0d0e0f
+p128=00112233445566778899aabbccddeeff
+c128=69c4e0d86a7b0430d8cdb78070b4c55a
 
-k=000102030405060708090a0b0c0d0e0f
-p=00112233445566778899aabbccddeeff
-c=69c4e0d86a7b0430d8cdb78070b4c55a
+
+# data values used to test the aes_calc application for AES-256
+k256=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+p256=00112233445566778899aabbccddeeff
+c256=8ea2b7ca516745bfeafc49904b496089
+
 
 runtest: libcryptomodule.a $(testapp)
 	test/env$(EXE) # print out information on the build environment
 	@echo "running libcryptomodule test applications..."
-	test `test/aes_calc $k $p` = $c
+	test `test/aes_calc $(k128) $(p128)` = $(c128)
+	test `test/aes_calc $(k256) $(p256)` = $(c256)
 	test/cipher_driver$(EXE) -v >/dev/null
 	test/datatypes_driver$(EXE) -v >/dev/null
 	test/stat_driver$(EXE) >/dev/null
diff --git a/crypto/cipher/aes.c b/crypto/cipher/aes.c
index 520d3c0..a17b9e4 100644
--- a/crypto/cipher/aes.c
+++ b/crypto/cipher/aes.c
@@ -1410,6 +1410,69 @@
   }
 }
 
+static void
+aes_256_expand_encryption_key(const unsigned char *key, 
+			      aes_expanded_key_t *expanded_key) {
+  int i;
+  gf2_8 rc;
+
+  /* initialize round constant */
+  rc = 1;
+
+  expanded_key->num_rounds = 14;
+
+  v128_copy_octet_string(&expanded_key->round[0], key);
+  v128_copy_octet_string(&expanded_key->round[1], key+16);
+
+#if 0
+  debug_print(mod_aes_icm, 
+	      "expanded key[0]:  %s", v128_hex_string(&expanded_key->round[0])); 
+  debug_print(mod_aes_icm, 
+	      "expanded key[1]:  %s", v128_hex_string(&expanded_key->round[1])); 
+#endif
+
+  /* loop over rest of round keys */
+  for (i=2; i < 15; i++) {
+
+    /* munge first word of round key */
+    if ((i & 1) == 0) {
+      expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
+      expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
+      expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
+      expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]];
+
+      /* modify round constant */
+      rc = gf2_8_shift(rc);
+    }
+    else {
+      expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[12]];
+      expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[13]];
+      expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[14]];
+      expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[15]];
+    }
+
+    expanded_key->round[i].v32[0] ^=  expanded_key->round[i-2].v32[0];
+
+    /* set remaining 32 bit words to the exor of the one previous with
+     * the one eight words previous */
+
+    expanded_key->round[i].v32[1] =
+      expanded_key->round[i].v32[0] ^ expanded_key->round[i-2].v32[1];
+
+    expanded_key->round[i].v32[2] =
+      expanded_key->round[i].v32[1] ^ expanded_key->round[i-2].v32[2];
+
+    expanded_key->round[i].v32[3] =
+      expanded_key->round[i].v32[2] ^ expanded_key->round[i-2].v32[3];
+
+#if 0
+    debug_print2(mod_aes_icm, 
+		 "expanded key[%d]:  %s", i,v128_hex_string(&expanded_key->round[i])); 
+#endif
+
+  }
+}
+
 err_status_t
 aes_expand_encryption_key(const uint8_t *key, 
 			  int key_len,
@@ -1418,6 +1481,14 @@
     aes_128_expand_encryption_key(key, expanded_key);
     return err_status_ok;
   }
+  else if (key_len == 24) {
+    /* AES-192 not yet supported */
+    return err_status_bad_param;
+  }
+  else if (key_len == 32) {
+    aes_256_expand_encryption_key(key, expanded_key);
+    return err_status_ok;
+  }
   else
     return err_status_bad_param;
 }
@@ -1428,16 +1499,17 @@
 			  aes_expanded_key_t *expanded_key) {
   int i;
   err_status_t status;
+  int num_rounds = expanded_key->num_rounds;
 
   status = aes_expand_encryption_key(key, key_len, expanded_key);
   if (status)
     return status;
 
   /* invert the order of the round keys */
-  for (i=0; i < 5; i++) {
+  for (i=0; i < num_rounds/2; i++) {
     v128_t tmp;
-    v128_copy(&tmp, &expanded_key->round[10-i]);
-    v128_copy(&expanded_key->round[10-i], &expanded_key->round[i]);
+    v128_copy(&tmp, &expanded_key->round[num_rounds-i]);
+    v128_copy(&expanded_key->round[num_rounds-i], &expanded_key->round[i]);
     v128_copy(&expanded_key->round[i], &tmp);
   }
 
@@ -1449,7 +1521,7 @@
    * followed by the T4 table (which cancels out the use of the sbox
    * in the U-tables)
    */
-  for (i=1; i < 10; i++) {
+  for (i=1; i < num_rounds; i++) {
 #ifdef CPU_RISC
     uint32_t tmp;
 
@@ -1932,7 +2004,7 @@
   /* add in the subkey */
   v128_xor_eq(plaintext, &exp_key->round[0]);
 
-  /* now do nine rounds */
+  /* now do the rounds */
   aes_round(plaintext, &exp_key->round[1]);
   aes_round(plaintext, &exp_key->round[2]);
   aes_round(plaintext, &exp_key->round[3]);
@@ -1942,9 +2014,21 @@
   aes_round(plaintext, &exp_key->round[7]);
   aes_round(plaintext, &exp_key->round[8]);  
   aes_round(plaintext, &exp_key->round[9]);
-  /* the last round is different */
-
-  aes_final_round(plaintext, &exp_key->round[10]);  
+  if (exp_key->num_rounds == 10) {
+    aes_final_round(plaintext, &exp_key->round[10]);
+  }
+  else if (exp_key->num_rounds == 12) {
+    aes_round(plaintext, &exp_key->round[10]);  
+    aes_round(plaintext, &exp_key->round[11]);
+    aes_final_round(plaintext, &exp_key->round[12]);
+  }
+  else if (exp_key->num_rounds == 14) {
+    aes_round(plaintext, &exp_key->round[10]);  
+    aes_round(plaintext, &exp_key->round[11]);
+    aes_round(plaintext, &exp_key->round[12]);  
+    aes_round(plaintext, &exp_key->round[13]);
+    aes_final_round(plaintext, &exp_key->round[14]);  
+  }
 }
 
 void
@@ -1953,7 +2037,7 @@
   /* add in the subkey */
   v128_xor_eq(plaintext, &exp_key->round[0]);
 
-  /* now do nine rounds */
+  /* now do the rounds */
   aes_inv_round(plaintext, &exp_key->round[1]);
   aes_inv_round(plaintext, &exp_key->round[2]);
   aes_inv_round(plaintext, &exp_key->round[3]);
@@ -1963,6 +2047,19 @@
   aes_inv_round(plaintext, &exp_key->round[7]);
   aes_inv_round(plaintext, &exp_key->round[8]);  
   aes_inv_round(plaintext, &exp_key->round[9]);
-  /* the last round is different */
-  aes_inv_final_round(plaintext, &exp_key->round[10]);  
+  if (exp_key->num_rounds == 10) {
+    aes_inv_final_round(plaintext, &exp_key->round[10]);  
+  }
+  else if (exp_key->num_rounds == 12) {
+    aes_inv_round(plaintext, &exp_key->round[10]);  
+    aes_inv_round(plaintext, &exp_key->round[11]);
+    aes_inv_final_round(plaintext, &exp_key->round[12]);  
+  }
+  else if (exp_key->num_rounds == 14) {
+    aes_inv_round(plaintext, &exp_key->round[10]);  
+    aes_inv_round(plaintext, &exp_key->round[11]);
+    aes_inv_round(plaintext, &exp_key->round[12]);  
+    aes_inv_round(plaintext, &exp_key->round[13]);
+    aes_inv_final_round(plaintext, &exp_key->round[14]);  
+  }
 }
diff --git a/crypto/cipher/aes_cbc.c b/crypto/cipher/aes_cbc.c
index 1887292..0ffbb06 100644
--- a/crypto/cipher/aes_cbc.c
+++ b/crypto/cipher/aes_cbc.c
@@ -63,7 +63,7 @@
   debug_print(mod_aes_cbc, 
 	      "allocating cipher with key length %d", key_len);
 
-  if (key_len != 16)
+  if (key_len != 16 && key_len != 24 && key_len != 32)
     return err_status_bad_param;
   
   /* allocate memory a cipher of type aes_cbc */
@@ -429,6 +429,100 @@
   &aes_cbc_test_case_0                    /* pointer to next testcase */
 };
 
+/*
+ * Test case 2 is like test case 0, but for 256-bit keys. (FIPS 197 
+ * appendix C.3).
+ */
+
+
+uint8_t aes_cbc_test_case_2_key[32] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+uint8_t aes_cbc_test_case_2_plaintext[64] =  {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff 
+};
+
+uint8_t aes_cbc_test_case_2_ciphertext[80] = {
+  0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+  0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89,  
+  0x72, 0x72, 0x6e, 0xe7, 0x71, 0x39, 0xbf, 0x11,
+  0xe5, 0x40, 0xe2, 0x7c, 0x54, 0x65, 0x1d, 0xee
+};
+
+uint8_t aes_cbc_test_case_2_iv[16] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+cipher_test_case_t aes_cbc_test_case_2 = {
+  32,                                    /* octets in key            */
+  aes_cbc_test_case_2_key,               /* key                      */
+  aes_cbc_test_case_2_iv,                /* initialization vector    */
+  16,                                    /* octets in plaintext      */
+  aes_cbc_test_case_2_plaintext,         /* plaintext                */
+  32,                                    /* octets in ciphertext     */
+  aes_cbc_test_case_2_ciphertext,        /* ciphertext               */
+  &aes_cbc_test_case_1                   /* pointer to next testcase */
+};
+
+
+/*
+ * this test case is taken directly from Appendix F.2 of NIST Special
+ * Publication SP 800-38A
+ */
+
+uint8_t aes_cbc_test_case_3_key[32] = {
+  0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+  0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+  0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+  0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+
+uint8_t aes_cbc_test_case_3_plaintext[64] =  {
+  0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 
+  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+  0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 
+  0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+  0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+  0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 
+  0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+uint8_t aes_cbc_test_case_3_ciphertext[80] = {
+  0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+  0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+  0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+  0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+  0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+  0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+  0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+  0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b,
+  0xfb, 0x98, 0x20, 0x2c, 0x45, 0xb2, 0xe4, 0xa0,
+  0x63, 0xc4, 0x68, 0xba, 0x84, 0x39, 0x16, 0x5a
+};
+
+uint8_t aes_cbc_test_case_3_iv[16] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+
+cipher_test_case_t aes_cbc_test_case_3 = {
+  32,                                    /* octets in key            */
+  aes_cbc_test_case_3_key,               /* key                      */
+  aes_cbc_test_case_3_iv,                /* initialization vector    */
+  64,                                    /* octets in plaintext      */
+  aes_cbc_test_case_3_plaintext,         /* plaintext                */
+  80,                                    /* octets in ciphertext     */
+  aes_cbc_test_case_3_ciphertext,        /* ciphertext               */
+  &aes_cbc_test_case_2                    /* pointer to next testcase */
+};
+
 cipher_type_t aes_cbc = {
   (cipher_alloc_func_t)          aes_cbc_alloc,
   (cipher_dealloc_func_t)        aes_cbc_dealloc,  
@@ -438,7 +532,7 @@
   (cipher_set_iv_func_t)         aes_cbc_set_iv,
   (char *)                       aes_cbc_description,
   (int)                          0,   /* instance count */
-  (cipher_test_case_t *)        &aes_cbc_test_case_1,
+  (cipher_test_case_t *)        &aes_cbc_test_case_3,
   (debug_module_t *)            &mod_aes_cbc
 };
 
diff --git a/crypto/cipher/aes_icm.c b/crypto/cipher/aes_icm.c
index 5460ff4..1532c7e 100644
--- a/crypto/cipher/aes_icm.c
+++ b/crypto/cipher/aes_icm.c
@@ -101,12 +101,13 @@
   /*
    * Ismacryp, for example, uses 16 byte key + 8 byte 
    * salt  so this function is called with key_len = 24.
-   * The check for key_len = 30 does not apply. Our usage
+   * The check for key_len = 30/38/46 does not apply. Our usage
    * of aes functions with key_len = values other than 30
    * has not broken anything. Don't know what would be the
    * effect of skipping this check for srtp in general.
    */
-  if (!forIsmacryp && key_len != 30)
+  if (!(forIsmacryp && key_len > 16 && key_len < 30) &&
+      key_len != 30 && key_len != 38 && key_len != 46)
     return err_status_bad_param;
 
   /* allocate memory a cipher of type aes_icm */
@@ -164,24 +165,31 @@
 err_status_t
 aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
   err_status_t status;
+  int base_key_len;
+
+  if (key_len > 16 && key_len < 30) /* Ismacryp */
+    base_key_len = 16;
+  else if (key_len == 30 || key_len == 38 || key_len == 46)
+    base_key_len = key_len - 14;
+  else
+    return err_status_bad_param;
+
   /* set counter and initial values to 'offset' value */
-  /* FIX!!! this assumes the salt is at key + 16, and thus that the */
-  /* FIX!!! cipher key length is 16!  Also note this copies past the
-            end of the 'key' array by 2 bytes! */
-  v128_copy_octet_string(&c->counter, key + 16);
-  v128_copy_octet_string(&c->offset, key + 16);
+  /* Note this copies past the end of the 'key' array by 2 bytes! */
+  v128_copy_octet_string(&c->counter, key + base_key_len);
+  v128_copy_octet_string(&c->offset, key + base_key_len);
 
   /* force last two octets of the offset to zero (for srtp compatibility) */
   c->offset.v8[14] = c->offset.v8[15] = 0;
   c->counter.v8[14] = c->counter.v8[15] = 0;
   
   debug_print(mod_aes_icm, 
-	      "key:  %s", octet_string_hex_string(key, 16)); 
+	      "key:  %s", octet_string_hex_string(key, base_key_len)); 
   debug_print(mod_aes_icm, 
 	      "offset: %s", v128_hex_string(&c->offset)); 
 
   /* expand key */
-  status = aes_expand_encryption_key(key, 16, &c->expanded_key);
+  status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
   if (status) {
     v128_set_to_zero(&c->counter);
     v128_set_to_zero(&c->offset);
@@ -492,6 +500,46 @@
   NULL                                   /* pointer to next testcase */
 };
 
+uint8_t aes_icm_test_case_1_key[46] = {
+  0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
+  0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
+  0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
+  0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
+  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+
+uint8_t aes_icm_test_case_1_nonce[16] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_test_case_1_plaintext[32] =  {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
+
+uint8_t aes_icm_test_case_1_ciphertext[32] = {
+  0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
+  0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
+  0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
+  0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
+};
+
+cipher_test_case_t aes_icm_test_case_1 = {
+  46,                                    /* octets in key            */
+  aes_icm_test_case_1_key,               /* key                      */
+  aes_icm_test_case_1_nonce,             /* packet index             */
+  32,                                    /* octets in plaintext      */
+  aes_icm_test_case_1_plaintext,         /* plaintext                */
+  32,                                    /* octets in ciphertext     */
+  aes_icm_test_case_1_ciphertext,        /* ciphertext               */
+  &aes_icm_test_case_0                   /* pointer to next testcase */
+};
+
+
 
 /*
  * note: the encrypt function is identical to the decrypt function
@@ -506,7 +554,7 @@
   (cipher_set_iv_func_t)         aes_icm_set_iv,
   (char *)                       aes_icm_description,
   (int)                          0,   /* instance count */
-  (cipher_test_case_t *)        &aes_icm_test_case_0,
+  (cipher_test_case_t *)        &aes_icm_test_case_1,
   (debug_module_t *)            &mod_aes_icm
 };
 
diff --git a/crypto/kernel/crypto_kernel.c b/crypto/kernel/crypto_kernel.c
index 230dda6..6dfd766 100644
--- a/crypto/kernel/crypto_kernel.c
+++ b/crypto/kernel/crypto_kernel.c
@@ -151,10 +151,10 @@
   status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
   if (status) 
     return status;
-  status = crypto_kernel_load_cipher_type(&aes_icm, AES_128_ICM);
+  status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM);
   if (status) 
     return status;
-  status = crypto_kernel_load_cipher_type(&aes_cbc, AES_128_CBC);
+  status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC);
   if (status) 
     return status;
 
diff --git a/crypto/test/aes_calc.c b/crypto/test/aes_calc.c
index 0ff242a..fe3c6ad 100644
--- a/crypto/test/aes_calc.c
+++ b/crypto/test/aes_calc.c
@@ -28,14 +28,14 @@
   exit(255);
 }
 
-#define AES_KEY_LEN 16
+#define AES_MAX_KEY_LEN 32
 
 int
 main (int argc, char *argv[]) {
   v128_t data;
-  uint8_t key[AES_KEY_LEN];
+  uint8_t key[AES_MAX_KEY_LEN];
   aes_expanded_key_t exp_key;
-  int len;
+  int key_len, len;
   int verbose;
   err_status_t status;
 
@@ -56,22 +56,23 @@
   }
   
   /* read in key, checking length */
-  if (strlen(argv[1]) > AES_KEY_LEN*2) {
+  if (strlen(argv[1]) > AES_MAX_KEY_LEN*2) {
     fprintf(stderr, 
 	    "error: too many digits in key "
-	    "(should be %d hexadecimal digits, found %u)\n",
-	    AES_KEY_LEN*2, (unsigned)strlen(argv[1]));
+	    "(should be at most %d hexadecimal digits, found %u)\n",
+	    AES_MAX_KEY_LEN*2, (unsigned)strlen(argv[1]));
     exit(1);    
   }
-  len = hex_string_to_octet_string((char*)key, argv[1], AES_KEY_LEN*2);
+  len = hex_string_to_octet_string((char*)key, argv[1], AES_MAX_KEY_LEN*2);
   /* check that hex string is the right length */
-  if (len < AES_KEY_LEN*2) {
+  if (len != 32 && len != 48 && len != 64) {
     fprintf(stderr, 
-	    "error: too few digits in key "
-	    "(should be %d hexadecimal digits, found %d)\n",
-	    AES_KEY_LEN*2, len);
+	    "error: bad number of digits in key "
+	    "(should be 32/48/64 hexadecimal digits, found %d)\n",
+	    len);
     exit(1);    
   } 
+  key_len = len/2;
       
   /* read in plaintext, checking length */
   if (strlen(argv[2]) > 16*2) {
@@ -97,7 +98,7 @@
   }
 
   /* encrypt plaintext */
-  status = aes_expand_encryption_key(key, 16, &exp_key);
+  status = aes_expand_encryption_key(key, key_len, &exp_key);
   if (status) {
     fprintf(stderr,
 	    "error: AES key expansion failed.\n");
@@ -108,7 +109,7 @@
 
   /* write ciphertext to output */
   if (verbose) {
-    printf("key:\t\t%s\n", octet_string_hex_string(key, 16));
+    printf("key:\t\t%s\n", octet_string_hex_string(key, key_len));
     printf("ciphertext:\t");
   }
   printf("%s\n", v128_hex_string(&data));
diff --git a/crypto/test/cipher_driver.c b/crypto/test/cipher_driver.c
index 2fac6c1..ea41ff5 100644
--- a/crypto/test/cipher_driver.c
+++ b/crypto/test/cipher_driver.c
@@ -120,10 +120,13 @@
 main(int argc, char *argv[]) {
   cipher_t *c = NULL;
   err_status_t status;
-  unsigned char test_key[20] = {
+  unsigned char test_key[48] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   };
   int q;
   unsigned do_timing_test = 0;
@@ -169,8 +172,13 @@
       cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher); 
 
     for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
+      cipher_driver_test_array_throughput(&aes_icm, 46, num_cipher); 
+
+    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
       cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher); 
  
+    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
+      cipher_driver_test_array_throughput(&aes_cbc, 32, num_cipher); 
   }
 
   if (do_validation) {
@@ -196,7 +204,7 @@
   check_status(status);
   
 
-  /* run the throughput test on the aes_icm cipher */
+  /* run the throughput test on the aes_icm cipher (128-bit key) */
     status = cipher_type_alloc(&aes_icm, &c, 30);  
     if (status) {
       fprintf(stderr, "error: can't allocate cipher\n");
@@ -216,6 +224,27 @@
     
     status = cipher_dealloc(c);
     check_status(status);
+
+  /* repeat the tests with 256-bit keys */
+    status = cipher_type_alloc(&aes_icm, &c, 46);  
+    if (status) {
+      fprintf(stderr, "error: can't allocate cipher\n");
+      exit(status);
+    }
+
+    status = cipher_init(c, test_key, direction_encrypt);
+    check_status(status);
+
+    if (do_timing_test)
+      cipher_driver_test_throughput(c);
+    
+    if (do_validation) {
+      status = cipher_driver_test_buffering(c);
+      check_status(status);
+    }
+    
+    status = cipher_dealloc(c);
+    check_status(status);
   
   return 0;
 }
@@ -227,7 +256,7 @@
   int max_enc_len = 2048;   /* should be a power of two */
   int num_trials = 1000000;  
   
-  printf("timing %s throughput:\n", c->type->description);
+  printf("timing %s throughput, key length %d:\n", c->type->description, c->key_len);
   fflush(stdout);
   for (i=min_enc_len; i <= max_enc_len; i = i * 2)
     printf("msg len: %d\tgigabits per second: %f\n",
@@ -472,8 +501,8 @@
   int max_enc_len = 2048;   /* should be a power of two */
   int num_trials = 1000000;
 
-  printf("timing %s throughput with array size %d:\n", 
-	 (ca[0])->type->description, num_cipher);
+  printf("timing %s throughput with key length %d, array size %d:\n", 
+	 (ca[0])->type->description, (ca[0])->key_len, num_cipher);
   fflush(stdout);
   for (i=min_enc_len; i <= max_enc_len; i = i * 4)
     printf("msg len: %d\tgigabits per second: %f\n", i,
diff --git a/crypto/test/stat_driver.c b/crypto/test/stat_driver.c
index 306c495..f9d75b7 100644
--- a/crypto/test/stat_driver.c
+++ b/crypto/test/stat_driver.c
@@ -37,7 +37,9 @@
   int i, j;
   extern cipher_type_t aes_icm;
   cipher_t *c;
-  uint8_t key[30] = {
+  uint8_t key[46] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
@@ -99,5 +101,39 @@
 
   err_check(cipher_dealloc(c));
 
+  printf("running stat_tests on AES-256-ICM, expecting success\n");
+  /* set buffer to cipher output */
+  for (i=0; i < 2500; i++)
+    buffer[i] = 0;
+  err_check(cipher_type_alloc(&aes_icm, &c, 46));
+  err_check(cipher_init(c, key, direction_encrypt));
+  err_check(cipher_set_iv(c, &nonce));
+  err_check(cipher_encrypt(c, buffer, &buf_len));
+  /* run tests on cipher outout */
+  printf("monobit %d\n", stat_test_monobit(buffer));
+  printf("poker   %d\n", stat_test_poker(buffer));
+  printf("runs    %d\n", stat_test_runs(buffer));
+
+  printf("runs test (please be patient): ");
+  fflush(stdout);
+  num_fail = 0;
+  v128_set_to_zero(&nonce);
+  for(j=0; j < num_trials; j++) {
+    for (i=0; i < 2500; i++)
+      buffer[i] = 0;
+    nonce.v32[3] = i;
+    err_check(cipher_set_iv(c, &nonce));
+    err_check(cipher_encrypt(c, buffer, &buf_len));
+    if (stat_test_runs(buffer)) {
+      num_fail++;
+    }
+  }
+
+  printf("%d failures in %d tests\n", num_fail, num_trials);
+  printf("(nota bene: a small fraction of stat_test failures does not \n"
+	 "indicate that the random source is invalid)\n");
+
+  err_check(cipher_dealloc(c));
+
   return 0;
 }
diff --git a/include/srtp.h b/include/srtp.h
index cf7d6c9..3813956 100644
--- a/include/srtp.h
+++ b/include/srtp.h
@@ -599,6 +599,70 @@
 void
 crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p);
 
+
+/**
+ * @brief crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto
+ * policy structure to a encryption and authentication policy using AES-256 
+ * for RTP protection.
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_cm_256_hmac_sha1_80(&p)
+ * sets the crypto_policy_t at location p to use policy
+ * AES_CM_256_HMAC_SHA1_80 as defined in
+ * draft-ietf-avt-srtp-big-aes-03.txt.  This policy uses AES-256
+ * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit
+ * authentication tag.
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ *
+ * @return void.
+ * 
+ */
+
+void crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p);
+
+
+/**
+ * @brief crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto
+ * policy structure to a short-authentication tag policy using AES-256
+ * encryption.
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_cm_256_hmac_sha1_32(&p)
+ * sets the crypto_policy_t at location p to use policy
+ * AES_CM_256_HMAC_SHA1_32 as defined in
+ * draft-ietf-avt-srtp-big-aes-03.txt.  This policy uses AES-256
+ * Counter Mode encryption and HMAC-SHA1 authentication, with an
+ * authentication tag that is only 32 bits long.  This length is
+ * considered adequate only for protecting audio and video media that
+ * use a stateless playback function.  See Section 7.5 of RFC 3711
+ * (http://www.ietf.org/rfc/rfc3711.txt).
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ *
+ * @warning This crypto policy is intended for use in SRTP, but not in
+ * SRTCP.  It is recommended that a policy that uses longer
+ * authentication tags be used for SRTCP.  See Section 7.5 of RFC 3711
+ * (http://www.ietf.org/rfc/rfc3711.txt).
+ *
+ * @return void.
+ * 
+ */
+
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p);
+
+
 /**
  * @brief srtp_dealloc() deallocates storage for an SRTP session
  * context.
diff --git a/srtp/srtp.c b/srtp/srtp.c
index fee38a6..d81a1f5 100644
--- a/srtp/srtp.c
+++ b/srtp/srtp.c
@@ -398,36 +398,76 @@
 #define MAX_SRTP_KEY_LEN 256
 
 
+/* Get the base key length corresponding to a given combined key+salt
+ * length for the given cipher.
+ * Assumption is that for AES-ICM a key length < 30 is Ismacryp using
+ * AES-128 and short salts; everything else uses a salt length of 14.
+ * TODO: key and salt lengths should be separate fields in the policy.  */
+inline int base_key_length(const cipher_type_t *cipher, int key_length)
+{
+  if (cipher != &aes_icm)
+    return key_length;
+  else if (key_length > 16 && key_length < 30)
+    return 16;
+  return key_length - 14;
+}
+
 err_status_t
 srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
   err_status_t stat;
   srtp_kdf_t kdf;
   uint8_t tmp_key[MAX_SRTP_KEY_LEN];
-  
+  int kdf_keylen = 30, rtp_keylen, rtcp_keylen;
+  int rtp_base_key_len, rtp_salt_len;
+  int rtcp_base_key_len, rtcp_salt_len;
+
+  /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */
+  /* TODO: kdf algorithm, master key length, and master salt length should
+   * be part of srtp_policy_t. */
+  rtp_keylen = cipher_get_key_length(srtp->rtp_cipher);
+  if (rtp_keylen > kdf_keylen)
+    kdf_keylen = rtp_keylen;
+
+  rtcp_keylen = cipher_get_key_length(srtp->rtcp_cipher);
+  if (rtcp_keylen > kdf_keylen)
+    kdf_keylen = rtcp_keylen;
+
   /* initialize KDF state     */
-  srtp_kdf_init(&kdf, AES_128_ICM, (const uint8_t *)key, 30);
+  stat = srtp_kdf_init(&kdf, AES_ICM, (const uint8_t *)key, kdf_keylen);
+  if (stat) {
+    return err_status_init_fail;
+  }
+
+  rtp_base_key_len = base_key_length(srtp->rtp_cipher->type, rtp_keylen);
+  rtp_salt_len = rtp_keylen - rtp_base_key_len;
   
   /* generate encryption key  */
-  srtp_kdf_generate(&kdf, label_rtp_encryption, 
-		    tmp_key, cipher_get_key_length(srtp->rtp_cipher));
+  stat = srtp_kdf_generate(&kdf, label_rtp_encryption, 
+			   tmp_key, rtp_base_key_len);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
   /* 
-   * if the cipher in the srtp context is aes_icm, then we need
+   * if the cipher in the srtp context uses a salt, then we need
    * to generate the salt value
    */
-  if (srtp->rtp_cipher->type == &aes_icm) {
-    /* FIX!!! this is really the cipher key length; rest is salt */
-    int base_key_len = 16;
-    int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;
-    
-    debug_print(mod_srtp, "found aes_icm, generating salt", NULL);
+  if (rtp_salt_len > 0) {
+    debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL);
 
     /* generate encryption salt, put after encryption key */
-    srtp_kdf_generate(&kdf, label_rtp_salt, 
-		      tmp_key + base_key_len, salt_len);
+    stat = srtp_kdf_generate(&kdf, label_rtp_salt, 
+			     tmp_key + rtp_base_key_len, rtp_salt_len);
+    if (stat) {
+      /* zeroize temp buffer */
+      octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+      return err_status_init_fail;
+    }
   }
   debug_print(mod_srtp, "cipher key: %s", 
-	      octet_string_hex_string(tmp_key, 
-		      cipher_get_key_length(srtp->rtp_cipher)));  
+	      octet_string_hex_string(tmp_key, rtp_keylen));
 
   /* initialize cipher */
   stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
@@ -438,8 +478,13 @@
   }
 
   /* generate authentication key */
-  srtp_kdf_generate(&kdf, label_rtp_msg_auth,
-		    tmp_key, auth_get_key_length(srtp->rtp_auth));
+  stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth,
+			   tmp_key, auth_get_key_length(srtp->rtp_auth));
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
   debug_print(mod_srtp, "auth key:   %s",
 	      octet_string_hex_string(tmp_key, 
 				      auth_get_key_length(srtp->rtp_auth))); 
@@ -456,27 +501,37 @@
    * ...now initialize SRTCP keys
    */
 
+  rtcp_base_key_len = base_key_length(srtp->rtcp_cipher->type, rtcp_keylen);
+  rtcp_salt_len = rtcp_keylen - rtcp_base_key_len;
+  
   /* generate encryption key  */
-  srtp_kdf_generate(&kdf, label_rtcp_encryption, 
-		    tmp_key, cipher_get_key_length(srtp->rtcp_cipher));
+  stat = srtp_kdf_generate(&kdf, label_rtcp_encryption, 
+			   tmp_key, rtcp_base_key_len);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
   /* 
-   * if the cipher in the srtp context is aes_icm, then we need
+   * if the cipher in the srtp context uses a salt, then we need
    * to generate the salt value
    */
-  if (srtp->rtcp_cipher->type == &aes_icm) {
-    /* FIX!!! this is really the cipher key length; rest is salt */
-    int base_key_len = 16;
-    int salt_len = cipher_get_key_length(srtp->rtcp_cipher) - base_key_len;
-
-    debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);
+  if (rtcp_salt_len > 0) {
+    debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt",
+		NULL);
 
     /* generate encryption salt, put after encryption key */
-    srtp_kdf_generate(&kdf, label_rtcp_salt, 
-		      tmp_key + base_key_len, salt_len);
+    stat = srtp_kdf_generate(&kdf, label_rtcp_salt, 
+			     tmp_key + rtcp_base_key_len, rtcp_salt_len);
+    if (stat) {
+      /* zeroize temp buffer */
+      octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+      return err_status_init_fail;
+    }
   }
   debug_print(mod_srtp, "rtcp cipher key: %s", 
-	      octet_string_hex_string(tmp_key, 
-		   cipher_get_key_length(srtp->rtcp_cipher)));  
+	      octet_string_hex_string(tmp_key, rtcp_keylen));  
 
   /* initialize cipher */
   stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);
@@ -487,8 +542,14 @@
   }
 
   /* generate authentication key */
-  srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
-		    tmp_key, auth_get_key_length(srtp->rtcp_auth));
+  stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
+			   tmp_key, auth_get_key_length(srtp->rtcp_auth));
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
   debug_print(mod_srtp, "rtcp auth key:   %s",
 	      octet_string_hex_string(tmp_key, 
 		     auth_get_key_length(srtp->rtcp_auth))); 
@@ -502,8 +563,10 @@
   }
 
   /* clear memory then return */
-  srtp_kdf_clear(&kdf);
+  stat = srtp_kdf_clear(&kdf);
   octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);  
+  if (stat)
+    return err_status_init_fail;
 
   return err_status_ok;
 }
@@ -1433,7 +1496,7 @@
 void
 crypto_policy_set_rtp_default(crypto_policy_t *p) {
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* default 128 bits per RFC 3711 */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
@@ -1445,7 +1508,7 @@
 void
 crypto_policy_set_rtcp_default(crypto_policy_t *p) {
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                 /* default 128 bits per RFC 3711 */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                 /* default 160 bits per RFC 3711 */
@@ -1463,7 +1526,7 @@
    * note that this crypto policy is intended for SRTP, but not SRTCP
    */
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                /* 160 bit key               */
@@ -1482,7 +1545,7 @@
    * note that this crypto policy is intended for SRTP, but not SRTCP
    */
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
   p->auth_type       = NULL_AUTH;             
   p->auth_key_len    = 0; 
@@ -1509,6 +1572,40 @@
 }
 
 
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p) {
+
+  /*
+   * corresponds to draft-ietf-avt-big-aes-03.txt
+   */
+
+  p->cipher_type     = AES_ICM;           
+  p->cipher_key_len  = 46;
+  p->auth_type       = HMAC_SHA1;             
+  p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
+  p->auth_tag_len    = 10;                /* default 80 bits per RFC 3711 */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
+
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p) {
+
+  /*
+   * corresponds to draft-ietf-avt-big-aes-03.txt
+   *
+   * note that this crypto policy is intended for SRTP, but not SRTCP
+   */
+
+  p->cipher_type     = AES_ICM;           
+  p->cipher_key_len  = 46;
+  p->auth_type       = HMAC_SHA1;             
+  p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
+  p->auth_tag_len    = 4;                 /* default 80 bits per RFC 3711 */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
+
 /* 
  * secure rtcp functions
  */
@@ -1958,10 +2055,16 @@
     crypto_policy_set_null_cipher_hmac_sha1_80(policy);
     crypto_policy_set_null_cipher_hmac_sha1_80(policy);
     break;
+  case srtp_profile_aes256_cm_sha1_80:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    crypto_policy_set_aes_cm_256_hmac_sha1_32(policy);
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
     /* the following profiles are not (yet) supported */
   case srtp_profile_null_sha1_32:
-  case srtp_profile_aes256_cm_sha1_80:
-  case srtp_profile_aes256_cm_sha1_32:
   default:
     return err_status_bad_param;
   }
@@ -1984,10 +2087,14 @@
   case srtp_profile_null_sha1_80:
     crypto_policy_set_null_cipher_hmac_sha1_80(policy);
     break;
+  case srtp_profile_aes256_cm_sha1_80:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
     /* the following profiles are not (yet) supported */
   case srtp_profile_null_sha1_32:
-  case srtp_profile_aes256_cm_sha1_80:
-  case srtp_profile_aes256_cm_sha1_32:
   default:
     return err_status_bad_param;
   }
@@ -2016,10 +2123,14 @@
   case srtp_profile_null_sha1_80:
     return 16;
     break;
+  case srtp_profile_aes256_cm_sha1_80:
+    return 32;
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    return 32;
+    break;
     /* the following profiles are not (yet) supported */
   case srtp_profile_null_sha1_32:
-  case srtp_profile_aes256_cm_sha1_80:
-  case srtp_profile_aes256_cm_sha1_32:
   default:
     return 0;  /* indicate error by returning a zero */
   }
@@ -2038,10 +2149,14 @@
   case srtp_profile_null_sha1_80:
     return 14;
     break;
+  case srtp_profile_aes256_cm_sha1_80:
+    return 14;
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    return 14;
+    break;
     /* the following profiles are not (yet) supported */
   case srtp_profile_null_sha1_32:
-  case srtp_profile_aes256_cm_sha1_80:
-  case srtp_profile_aes256_cm_sha1_32:
   default:
     return 0;  /* indicate error by returning a zero */
   }
diff --git a/test/srtp_driver.c b/test/srtp_driver.c
index d4c2afd..51b33f5 100644
--- a/test/srtp_driver.c
+++ b/test/srtp_driver.c
@@ -63,6 +63,9 @@
 srtp_validate(void);
 
 err_status_t
+srtp_validate_aes_256(void);
+
+err_status_t
 srtp_create_big_policy(srtp_policy_t **list);
 
 err_status_t
@@ -286,6 +289,19 @@
     }
 
     /*
+     * run validation test against the reference packets for
+     * AES-256
+     */
+    printf("testing srtp_protect and srtp_unprotect against "
+	   "reference packets (AES-256)\n");
+    if (srtp_validate_aes_256() == err_status_ok) 
+      printf("passed\n\n");
+    else {
+      printf("failed\n");
+       exit(1); 
+    }
+
+    /*
      * test the function srtp_remove_stream()
      */
     printf("testing srtp_remove_stream()...");
@@ -1276,6 +1292,114 @@
 }
 
 
+/*
+ * srtp_validate_aes_256() verifies the correctness of libsrtp by comparing
+ * some computed packets against some pre-computed reference values.
+ * These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy.
+ */
+
+
+err_status_t
+srtp_validate_aes_256() {
+  unsigned char test_key[46] = {
+    0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
+    0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
+    0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
+    0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
+
+    0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
+    0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
+  };
+  uint8_t srtp_plaintext_ref[28] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
+    0xab, 0xab, 0xab, 0xab
+  };
+  uint8_t srtp_plaintext[38] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
+    0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  };
+  uint8_t srtp_ciphertext[38] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xf1, 0xd9, 0xde, 0x17, 
+    0xff, 0x25, 0x1f, 0xf1, 0xaa, 0x00, 0x77, 0x74, 
+    0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a, 
+    0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b
+  };
+  srtp_t srtp_snd, srtp_recv;
+  err_status_t status;
+  int len;
+  srtp_policy_t policy;
+  
+  /*
+   * create a session with a single stream using the default srtp
+   * policy and with the SSRC value 0xcafebabe
+   */
+  crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
+  crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp);
+  policy.ssrc.type  = ssrc_specific;
+  policy.ssrc.value = 0xcafebabe;
+  policy.key  = test_key;
+  policy.ekt = NULL;
+  policy.window_size = 128;
+  policy.allow_repeat_tx = 0;
+  policy.next = NULL;
+
+  status = srtp_create(&srtp_snd, &policy);
+  if (status)
+    return status;
+ 
+  /* 
+   * protect plaintext, then compare with ciphertext 
+   */
+  len = 28;
+  status = srtp_protect(srtp_snd, srtp_plaintext, &len);
+  if (status || (len != 38))
+    return err_status_fail;
+
+  debug_print(mod_driver, "ciphertext:\n  %s", 	      
+	      octet_string_hex_string(srtp_plaintext, len));
+  debug_print(mod_driver, "ciphertext reference:\n  %s", 	      
+	      octet_string_hex_string(srtp_ciphertext, len));
+
+  if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
+    return err_status_fail;
+  
+  /*
+   * create a receiver session context comparable to the one created
+   * above - we need to do this so that the replay checking doesn't
+   * complain
+   */
+  status = srtp_create(&srtp_recv, &policy);
+  if (status)
+    return status;
+
+  /*
+   * unprotect ciphertext, then compare with plaintext 
+   */
+  status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
+  if (status || (len != 28))
+    return status;
+  
+  if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
+    return err_status_fail;
+
+  status = srtp_dealloc(srtp_snd);
+  if (status)
+    return status;
+
+  status = srtp_dealloc(srtp_recv);
+  if (status)
+    return status;
+
+  return err_status_ok;
+}
+
+
 err_status_t
 srtp_create_big_policy(srtp_policy_t **list) {
   extern const srtp_policy_t *policy_array[];
@@ -1538,6 +1662,41 @@
   NULL
 };
 
+unsigned char test_256_key[46] = {
+	0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
+	0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
+	0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
+	0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
+
+	0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
+	0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
+};
+
+const srtp_policy_t aes_256_hmac_policy = {
+  { ssrc_any_outbound, 0 },  /* SSRC                           */
+  {                      /* SRTP policy                    */                  
+    AES_ICM,                /* cipher type                 */
+    46,                     /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    10,                     /* auth tag length in octets   */
+    sec_serv_conf_and_auth  /* security services flag      */
+  },
+  {                      /* SRTCP policy                   */
+    AES_ICM,                /* cipher type                 */
+    46,                     /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    10,                     /* auth tag length in octets   */
+    sec_serv_conf_and_auth  /* security services flag      */
+  },
+  test_256_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
+  NULL
+};
+
 uint8_t ekt_test_key[16] = {
   0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca, 
   0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
@@ -1602,6 +1761,7 @@
 #endif
   &default_policy,
   &null_policy,
+  &aes_256_hmac_policy,
   &hmac_only_with_ekt_policy,
   NULL
 };