]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Add support for 16-byte auth tag for AES GCM mode.
authorjfigus <jfig_us@yahoo.com>
Thu, 8 May 2014 17:34:53 +0000 (13:34 -0400)
committerTravis Cross <tc@traviscross.com>
Mon, 30 Jun 2014 19:18:20 +0000 (19:18 +0000)
15 files changed:
libs/srtp/crypto/cipher/aes_cbc.c
libs/srtp/crypto/cipher/aes_gcm_ossl.c
libs/srtp/crypto/cipher/aes_icm.c
libs/srtp/crypto/cipher/aes_icm_ossl.c
libs/srtp/crypto/cipher/cipher.c
libs/srtp/crypto/cipher/null_cipher.c
libs/srtp/crypto/include/cipher.h
libs/srtp/crypto/include/crypto_kernel.h
libs/srtp/crypto/kernel/crypto_kernel.c
libs/srtp/crypto/test/cipher_driver.c
libs/srtp/crypto/test/stat_driver.c
libs/srtp/include/srtp.h
libs/srtp/srtp/srtp.c
libs/srtp/test/rtpw.c
libs/srtp/test/rtpw_test_gcm.sh

index fad74a411eb38ab7d808f2b48a4414db184b0ca7..d57d0219d82d2a2a52a96f0890fa497400bdaadc 100644 (file)
@@ -55,7 +55,7 @@ debug_module_t mod_aes_cbc = {
 
 
 err_status_t
-aes_cbc_alloc(cipher_t **c, int key_len) {
+aes_cbc_alloc(cipher_t **c, int key_len, int tlen) {
   extern cipher_type_t aes_cbc;
   uint8_t *pointer;
   int tmp;
@@ -384,6 +384,7 @@ cipher_test_case_t aes_cbc_test_case_0 = {
   aes_cbc_test_case_0_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   NULL                                   /* pointer to next testcase */
 };
 
@@ -437,6 +438,7 @@ cipher_test_case_t aes_cbc_test_case_1 = {
   aes_cbc_test_case_1_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   &aes_cbc_test_case_0                    /* pointer to next testcase */
 };
 
@@ -480,6 +482,7 @@ cipher_test_case_t aes_cbc_test_case_2 = {
   aes_cbc_test_case_2_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   &aes_cbc_test_case_1                   /* pointer to next testcase */
 };
 
@@ -535,6 +538,7 @@ cipher_test_case_t aes_cbc_test_case_3 = {
   aes_cbc_test_case_3_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   &aes_cbc_test_case_2                    /* pointer to next testcase */
 };
 
index f281025d8c33e3d6229020211dcc96c9770eb6f8..7ce52d001df5cf17dbc4d3ef6154f48571366539 100644 (file)
@@ -64,11 +64,11 @@ extern cipher_type_t aes_gcm_128_openssl;
 extern cipher_type_t aes_gcm_256_openssl;
 
 /*
- * For now we only support 8 octet tags.  The spec allows for
- * optional 12 and 16 byte tags.  These longer tag lengths may
- * be implemented in the future.
+ * For now we only support 8 and 16 octet tags.  The spec allows for
+ * optional 12 byte tag, which may be supported in the future.  
  */
-#define GCM_AUTH_TAG_LEN 8
+#define GCM_AUTH_TAG_LEN    16
+#define GCM_AUTH_TAG_LEN_8  8
 
 
 /*
@@ -78,13 +78,14 @@ extern cipher_type_t aes_gcm_256_openssl;
  * key length includes the 14 byte salt value that is used when
  * initializing the KDF.
  */
-err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
+err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len, int tlen)
 {
     aes_gcm_ctx_t *gcm;
     int tmp;
     uint8_t *allptr;
 
     debug_print(mod_aes_gcm, "allocating cipher with key length %d", key_len);
+    debug_print(mod_aes_gcm, "allocating cipher with tag length %d", tlen);
 
     /*
      * Verify the key_len is valid for one of: AES-128/256
@@ -94,6 +95,11 @@ err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
         return (err_status_bad_param);
     }
 
+    if (tlen != GCM_AUTH_TAG_LEN &&
+       tlen != GCM_AUTH_TAG_LEN_8) {
+        return (err_status_bad_param);
+    }
+
     /* allocate memory a cipher of type aes_gcm */
     tmp = sizeof(cipher_t) + sizeof(aes_gcm_ctx_t);
     allptr = crypto_alloc(tmp);
@@ -113,14 +119,14 @@ err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
         (*c)->algorithm = AES_128_GCM;
         aes_gcm_128_openssl.ref_count++;
         ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE;
-        ((aes_gcm_ctx_t*)(*c)->state)->tag_len = GCM_AUTH_TAG_LEN;  
+        ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen;  
         break;
     case AES_256_GCM_KEYSIZE_WSALT:
         (*c)->type = &aes_gcm_256_openssl;
         (*c)->algorithm = AES_256_GCM;
         aes_gcm_256_openssl.ref_count++;
         ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE;
-        ((aes_gcm_ctx_t*)(*c)->state)->tag_len = GCM_AUTH_TAG_LEN;  
+        ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen;  
         break;
     }
 
@@ -405,7 +411,7 @@ uint8_t aes_gcm_test_case_0_aad[20] = {
     0xab, 0xad, 0xda, 0xd2
 };
 
-uint8_t aes_gcm_test_case_0_ciphertext[68] = {
+uint8_t aes_gcm_test_case_0_ciphertext[76] = {
     0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
     0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
     0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
@@ -414,11 +420,12 @@ uint8_t aes_gcm_test_case_0_ciphertext[68] = {
     0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
     0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
     0x3d, 0x58, 0xe0, 0x91,
-    /* the last 8 bytes are the tag */
+    /* the last 16 bytes are the tag */
     0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47,
 };
 
-cipher_test_case_t aes_gcm_test_case_0 = {
+cipher_test_case_t aes_gcm_test_case_0a = {
     AES_128_GCM_KEYSIZE_WSALT,             /* octets in key            */
     aes_gcm_test_case_0_key,               /* key                      */
     aes_gcm_test_case_0_iv,                /* packet index             */
@@ -428,9 +435,24 @@ cipher_test_case_t aes_gcm_test_case_0 = {
     aes_gcm_test_case_0_ciphertext,        /* ciphertext  + tag        */
     20,                                    /* octets in AAD            */
     aes_gcm_test_case_0_aad,               /* AAD                      */
+    GCM_AUTH_TAG_LEN_8,
     NULL                                   /* pointer to next testcase */
 };
 
+cipher_test_case_t aes_gcm_test_case_0 = {
+    AES_128_GCM_KEYSIZE_WSALT,             /* octets in key            */
+    aes_gcm_test_case_0_key,               /* key                      */
+    aes_gcm_test_case_0_iv,                /* packet index             */
+    60,                                    /* octets in plaintext      */
+    aes_gcm_test_case_0_plaintext,         /* plaintext                */
+    76,                                    /* octets in ciphertext     */
+    aes_gcm_test_case_0_ciphertext,        /* ciphertext  + tag        */
+    20,                                    /* octets in AAD            */
+    aes_gcm_test_case_0_aad,               /* AAD                      */
+    GCM_AUTH_TAG_LEN,
+    &aes_gcm_test_case_0a                  /* pointer to next testcase */
+};
+
 uint8_t aes_gcm_test_case_1_key[AES_256_GCM_KEYSIZE_WSALT] = {
     0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
     0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
@@ -463,7 +485,7 @@ uint8_t aes_gcm_test_case_1_aad[20] = {
     0xab, 0xad, 0xda, 0xd2
 };
 
-uint8_t aes_gcm_test_case_1_ciphertext[68] = {
+uint8_t aes_gcm_test_case_1_ciphertext[76] = {
     0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46, 
     0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a, 
     0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86, 
@@ -472,11 +494,12 @@ uint8_t aes_gcm_test_case_1_ciphertext[68] = {
     0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80, 
     0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10, 
     0x09, 0xc9, 0x86, 0xc1, 
-    /* the last 8 bytes are the tag */
+    /* the last 16 bytes are the tag */
     0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f, 
+    0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d,
 };
 
-cipher_test_case_t aes_gcm_test_case_1 = {
+cipher_test_case_t aes_gcm_test_case_1a = {
     AES_256_GCM_KEYSIZE_WSALT,                 /* octets in key            */
     aes_gcm_test_case_1_key,               /* key                      */
     aes_gcm_test_case_1_iv,                /* packet index             */
@@ -486,9 +509,24 @@ cipher_test_case_t aes_gcm_test_case_1 = {
     aes_gcm_test_case_1_ciphertext,        /* ciphertext  + tag        */
     20,                                    /* octets in AAD            */
     aes_gcm_test_case_1_aad,               /* AAD                      */
+    GCM_AUTH_TAG_LEN_8,
     NULL                                   /* pointer to next testcase */
 };
 
+cipher_test_case_t aes_gcm_test_case_1 = {
+    AES_256_GCM_KEYSIZE_WSALT,                 /* octets in key            */
+    aes_gcm_test_case_1_key,               /* key                      */
+    aes_gcm_test_case_1_iv,                /* packet index             */
+    60,                                    /* octets in plaintext      */
+    aes_gcm_test_case_1_plaintext,         /* plaintext                */
+    76,                                    /* octets in ciphertext     */
+    aes_gcm_test_case_1_ciphertext,        /* ciphertext  + tag        */
+    20,                                    /* octets in AAD            */
+    aes_gcm_test_case_1_aad,               /* AAD                      */
+    GCM_AUTH_TAG_LEN,
+    &aes_gcm_test_case_1a                  /* pointer to next testcase */
+};
+
 /*
  * This is the vector function table for this crypto engine.
  */
index cf316b1ffdf0d5c373f82255526b48b26d18559a..64eb51dee67e1f5a91c23ffbd8f7c892f07255b8 100644 (file)
@@ -516,6 +516,7 @@ cipher_test_case_t aes_icm_test_case_0 = {
   aes_icm_test_case_0_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   NULL                                   /* pointer to next testcase */
 };
 
@@ -557,6 +558,7 @@ cipher_test_case_t aes_icm_test_case_1 = {
   aes_icm_test_case_1_ciphertext,        /* ciphertext               */
   0,
   NULL,
+  0,
   &aes_icm_test_case_0                   /* pointer to next testcase */
 };
 
index 2d9d4e068b0bfb488cab1d0ef50393395f917abe..12054a2cc95e0e0d3db513ab10e1d08da55a3300 100644 (file)
@@ -103,9 +103,10 @@ extern cipher_type_t aes_icm_256;
  * The key_len parameter should be one of 30, 38, or 46 for
  * AES-128, AES-192, and AES-256 respectively.  Note, this key_len
  * value is inflated, as it also accounts for the 112 bit salt
- * value.
+ * value.  The tlen argument is for the AEAD tag length, which
+ * isn't used in counter mode.
  */
-err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int x)
+err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int tlen)
 {
     aes_icm_ctx_t *icm;
     int tmp;
@@ -382,6 +383,7 @@ cipher_test_case_t aes_icm_test_case_0 = {
     aes_icm_test_case_0_ciphertext,        /* ciphertext               */
     0,
     NULL,
+    0,
     NULL                                   /* pointer to next testcase */
 };
 
@@ -426,6 +428,7 @@ cipher_test_case_t aes_icm_192_test_case_1 = {
     aes_icm_192_test_case_1_ciphertext,    /* ciphertext               */
     0,
     NULL,
+    0,
     NULL                                   /* pointer to next testcase */
 };
 
@@ -472,6 +475,7 @@ cipher_test_case_t aes_icm_256_test_case_2 = {
     aes_icm_256_test_case_2_ciphertext,    /* ciphertext               */
     0,
     NULL,
+    0,
     NULL                                   /* pointer to next testcase */
 };
 
index 07b472ebff6d56f62b243182fa0a5725331346b8..3f8f01aea676374361ee79621e3f87c72dfdf464 100644 (file)
@@ -108,7 +108,7 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
    */  
   while (test_case != NULL) {
     /* allocate cipher */
-    status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
+    status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
     if (status)
       return status;
     
@@ -307,7 +307,7 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
 
   /* allocate cipher, using paramaters from the first test case */
   test_case = test_data;
-  status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
+  status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
   if (status)
       return status;
   
index 8c2f09f9967de00ae028b272f48d42743b8c32fd..b12b1bfe8f2586600cec5a80933d29fcb90191a9 100644 (file)
@@ -54,7 +54,7 @@
 extern debug_module_t mod_cipher;
 
 err_status_t
-null_cipher_alloc(cipher_t **c, int key_len) {
+null_cipher_alloc(cipher_t **c, int key_len, int tlen) {
   extern cipher_type_t null_cipher;
   uint8_t *pointer;
   
@@ -133,6 +133,7 @@ null_cipher_test_0 = {
   NULL,              /* ciphertext               */
   0,
   NULL,
+  0,
   NULL               /* pointer to next testcase */
 };
 
index f98d2398d1db3855348429ade416cc5b6070a7c3..d0d6b57f27b6aba9ed809ff5abf276ce162fea8d 100644 (file)
@@ -80,7 +80,7 @@ typedef struct cipher_t      *cipher_pointer_t;
  */
 
 typedef err_status_t (*cipher_alloc_func_t)
-     (cipher_pointer_t *cp, int key_len);
+     (cipher_pointer_t *cp, int key_len, int tag_len);
 
 /* 
  * a cipher_init_func_t [re-]initializes a cipher_t with a given key
@@ -148,6 +148,7 @@ typedef struct cipher_test_case_t {
   uint8_t *ciphertext;                        /* ciphertext               */
   int aad_length_octets;                      /* octets in AAD            */ 
   uint8_t *aad;                               /* AAD                      */
+  int tag_length_octets;                      /* Length of AEAD tag       */
   struct cipher_test_case_t *next_test_case;  /* pointer to next testcase */
 } cipher_test_case_t;
 
@@ -183,7 +184,7 @@ typedef struct cipher_t {
 
 /* some syntactic sugar on these function types */
 
-#define cipher_type_alloc(ct, c, klen) ((ct)->alloc((c), (klen)))
+#define cipher_type_alloc(ct, c, klen, tlen) ((ct)->alloc((c), (klen), (tlen)))
 
 #define cipher_dealloc(c) (((c)->type)->dealloc(c))
 
index 1acf4978d0ea4b0f5e73c90319fdd99a9ea7e77f..caccfa03a9623223a2a4fd7196e570b2b536669b 100644 (file)
@@ -221,7 +221,8 @@ crypto_kernel_load_debug_module(debug_module_t *new_dm);
 err_status_t
 crypto_kernel_alloc_cipher(cipher_type_id_t id, 
                           cipher_pointer_t *cp, 
-                          int key_len);
+                          int key_len,
+                          int tag_len);
 
 /*
  * crypto_kernel_alloc_auth(id, ap, key_len, tag_len); 
index 656c010460df9c70b5dbb31f6b7a8832f2ad686b..8542be0b84f88ebbddf5fc7b95a7a749e7cc69a1 100644 (file)
@@ -477,7 +477,8 @@ crypto_kernel_get_cipher_type(cipher_type_id_t id) {
 err_status_t
 crypto_kernel_alloc_cipher(cipher_type_id_t id, 
                              cipher_pointer_t *cp, 
-                             int key_len) {
+                             int key_len,
+                             int tag_len) {
   cipher_type_t *ct;
 
   /* 
@@ -491,7 +492,7 @@ crypto_kernel_alloc_cipher(cipher_type_id_t id,
   if (!ct)
     return err_status_fail;
   
-  return ((ct)->alloc(cp, key_len));
+  return ((ct)->alloc(cp, key_len, tag_len));
 }
 
 
index 26992e1f23a868fc234e6356f473f53974491479..d015b4552368d57143364adc940fd1ca3fc05a91 100644 (file)
@@ -223,7 +223,7 @@ main(int argc, char *argv[]) {
   }
 
   /* do timing and/or buffer_test on null_cipher */
-  status = cipher_type_alloc(&null_cipher, &c, 0); 
+  status = cipher_type_alloc(&null_cipher, &c, 0, 0); 
   check_status(status);
 
   status = cipher_init(c, NULL);
@@ -240,7 +240,7 @@ main(int argc, char *argv[]) {
   
 
   /* run the throughput test on the aes_icm cipher (128-bit key) */
-    status = cipher_type_alloc(&aes_icm, &c, 30);  
+    status = cipher_type_alloc(&aes_icm, &c, 30, 0);  
     if (status) {
       fprintf(stderr, "error: can't allocate cipher\n");
       exit(status);
@@ -262,9 +262,9 @@ main(int argc, char *argv[]) {
 
   /* repeat the tests with 256-bit keys */
 #ifndef OPENSSL
-    status = cipher_type_alloc(&aes_icm, &c, 46);  
+    status = cipher_type_alloc(&aes_icm, &c, 46, 0);  
 #else
-    status = cipher_type_alloc(&aes_icm_256, &c, 46);  
+    status = cipher_type_alloc(&aes_icm_256, &c, 46, 0);  
 #endif
     if (status) {
       fprintf(stderr, "error: can't allocate cipher\n");
@@ -287,7 +287,7 @@ main(int argc, char *argv[]) {
 
 #ifdef OPENSSL
     /* run the throughput test on the aes_gcm_128_openssl cipher */
-    status = cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT);
+    status = cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8);
     if (status) {
         fprintf(stderr, "error: can't allocate GCM 128 cipher\n");
         exit(status);
@@ -306,7 +306,7 @@ main(int argc, char *argv[]) {
     check_status(status);
 
     /* run the throughput test on the aes_gcm_256_openssl cipher */
-    status = cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT);
+    status = cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16);
     if (status) {
         fprintf(stderr, "error: can't allocate GCM 256 cipher\n");
         exit(status);
@@ -479,7 +479,7 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
   for (i=0; i < num_ciphers; i++) {
 
     /* allocate cipher */
-    status = cipher_type_alloc(ctype, cipher_array, klen);
+    status = cipher_type_alloc(ctype, cipher_array, klen, 16);
     if (status)
       return status;
     
index 8c11a16ac069655073355198a89e4c5807903007..c53423ff5d93361c197b19de62609c8e1be739b6 100644 (file)
@@ -77,7 +77,7 @@ main (int argc, char *argv[]) {
   /* set buffer to cipher output */
   for (i=0; i < 2500; i++)
     buffer[i] = 0;
-  err_check(cipher_type_alloc(&aes_icm, &c, 30));
+  err_check(cipher_type_alloc(&aes_icm, &c, 30, 0));
   err_check(cipher_init(c, key));
   err_check(cipher_set_iv(c, &nonce, direction_encrypt));
   err_check(cipher_encrypt(c, buffer, &buf_len));
@@ -111,7 +111,7 @@ main (int argc, char *argv[]) {
   /* 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_type_alloc(&aes_icm, &c, 46, 0));
   err_check(cipher_init(c, key));
   err_check(cipher_set_iv(c, &nonce, direction_encrypt));
   err_check(cipher_encrypt(c, buffer, &buf_len));
@@ -142,7 +142,7 @@ main (int argc, char *argv[]) {
     for (i=0; i < 2500; i++) {
        buffer[i] = 0;
     }
-    err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT));
+    err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8));
     err_check(cipher_init(c, key));
     err_check(cipher_set_iv(c, &nonce, direction_encrypt));
     err_check(cipher_encrypt(c, buffer, &buf_len));
@@ -171,7 +171,7 @@ main (int argc, char *argv[]) {
     for (i=0; i < 2500; i++) {
        buffer[i] = 0;
     }
-    err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT));
+    err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16));
     err_check(cipher_init(c, key));
     err_check(cipher_set_iv(c, &nonce, direction_encrypt));
     err_check(cipher_encrypt(c, buffer, &buf_len));
index d64f946576ef688ca2d7aa12f0ddbcf6647b6b1a..11ea33d7f65c4000461ab4a42cb965681a2d3fdb 100644 (file)
@@ -798,6 +798,54 @@ crypto_policy_set_aes_gcm_128_8_only_auth(crypto_policy_t *p);
 void
 crypto_policy_set_aes_gcm_256_8_only_auth(crypto_policy_t *p);
 
+/**
+ * @brief crypto_policy_set_aes_gcm_128_16_auth() sets a crypto
+ * policy structure to an AEAD encryption policy.
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_gcm_128_16_auth(&p) sets
+ * the crypto_policy_t at location p to use the SRTP default cipher
+ * (AES-128 Galois Counter Mode) with 16 octet auth tag.  This
+ * policy applies confidentiality and authentication to both the
+ * RTP and RTCP packets.
+ * 
+ * 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_gcm_128_16_auth(crypto_policy_t *p);
+
+/**
+ * @brief crypto_policy_set_aes_gcm_256_16_auth() sets a crypto
+ * policy structure to an AEAD encryption policy
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_gcm_256_16_auth(&p) sets
+ * the crypto_policy_t at location p to use the SRTP default cipher
+ * (AES-256 Galois Counter Mode) with 16 octet auth tag.  This 
+ * policy applies confidentiality and authentication to both the
+ * RTP and RTCP packets.
+ * 
+ * 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_gcm_256_16_auth(crypto_policy_t *p);
+
 
 /**
  * @brief srtp_dealloc() deallocates storage for an SRTP session
index 0d2eabffcc55f37b985da90e7cb041f670ebda2c..1f7ac1246a0a459a8bb43718e75a597808826d22 100644 (file)
@@ -96,7 +96,8 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
   /* allocate cipher */
   stat = crypto_kernel_alloc_cipher(p->rtp.cipher_type, 
                                    &str->rtp_cipher, 
-                                   p->rtp.cipher_key_len); 
+                                   p->rtp.cipher_key_len,
+                                   p->rtp.auth_tag_len); 
   if (stat) {
     crypto_free(str);
     return stat;
@@ -128,7 +129,8 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
    */
   stat = crypto_kernel_alloc_cipher(p->rtcp.cipher_type, 
                                    &str->rtcp_cipher, 
-                                   p->rtcp.cipher_key_len); 
+                                   p->rtcp.cipher_key_len, 
+                                   p->rtcp.auth_tag_len); 
   if (stat) {
     auth_dealloc(str->rtp_auth);
     cipher_dealloc(str->rtp_cipher);
@@ -359,7 +361,7 @@ err_status_t
 srtp_kdf_init(srtp_kdf_t *kdf, cipher_type_id_t cipher_id, const uint8_t *key, int length) {
 
   err_status_t stat;
-  stat = crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, length);
+  stat = crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, length, 0);
   if (stat)
     return stat;
 
@@ -1019,6 +1021,15 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta,
     enc_octet_len = (unsigned int) *pkt_octet_len - 
                     ((enc_start - (uint32_t *)hdr) << 2);
 
+    /*
+     * Sanity check the encrypted payload length against
+     * the tag size.  It must always be at least as large
+     * as the tag length.
+     */
+    if (enc_octet_len < tag_len) {
+        return err_status_cipher_fail;
+    }
+
     /*
      * update the key usage limit, and check it to make sure that we
      * didn't just hit either the soft limit or the hard limit, and call
@@ -2107,6 +2118,33 @@ crypto_policy_set_aes_gcm_256_8_only_auth(crypto_policy_t *p) {
   p->auth_tag_len    = 8;   /* 8 octet tag length */
   p->sec_serv        = sec_serv_auth;  /* This only applies to RTCP */
 }
+
+/*
+ * AES-128 GCM mode with 16 octet auth tag. 
+ */
+void
+crypto_policy_set_aes_gcm_128_16_auth(crypto_policy_t *p) {
+  p->cipher_type     = AES_128_GCM;           
+  p->cipher_key_len  = AES_128_GCM_KEYSIZE_WSALT; 
+  p->auth_type       = NULL_AUTH; /* GCM handles the auth for us */            
+  p->auth_key_len    = 0; 
+  p->auth_tag_len    = 16;   /* 16 octet tag length */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
+/*
+ * AES-256 GCM mode with 16 octet auth tag. 
+ */
+void
+crypto_policy_set_aes_gcm_256_16_auth(crypto_policy_t *p) {
+  p->cipher_type     = AES_256_GCM;           
+  p->cipher_key_len  = AES_256_GCM_KEYSIZE_WSALT; 
+  p->auth_type       = NULL_AUTH; /* GCM handles the auth for us */ 
+  p->auth_key_len    = 0; 
+  p->auth_tag_len    = 16;   /* 16 octet tag length */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
 #endif
 
 /* 
index ae902689d07e161c76461a303213b0e24964bc6b..26f2ffc443b18f929f1f8d8cefd4ac6db5820be6 100644 (file)
@@ -153,6 +153,7 @@ main (int argc, char *argv[]) {
   unsigned char ttl = 5;
   int c;
   int key_size = 128;
+  int tag_size = 8;
   int gcm_on = 0;
   char *input_key = NULL;
   char *address = NULL;
@@ -188,7 +189,7 @@ main (int argc, char *argv[]) {
 
   /* check args */
   while (1) {
-    c = getopt_s(argc, argv, "k:rsgae:ld:");
+    c = getopt_s(argc, argv, "k:rsgt:ae:ld:");
     if (c == -1) {
       break;
     }
@@ -204,6 +205,13 @@ main (int argc, char *argv[]) {
       }
       sec_servs |= sec_serv_conf;
       break;
+    case 't':
+      tag_size = atoi(optarg_s);
+      if (tag_size != 8 && tag_size != 16) {
+        printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size);
+        exit(1);
+      }
+      break;
     case 'a':
       sec_servs |= sec_serv_auth;
       break;
@@ -423,6 +431,10 @@ main (int argc, char *argv[]) {
     policy.rtp.sec_serv = sec_servs;
     policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
 
+    if (gcm_on && tag_size != 8) {
+       policy.rtp.auth_tag_len = tag_size;
+    }
+
     /*
      * read key from hexadecimal on command line into an octet string
      */
@@ -610,6 +622,7 @@ usage(char *string) {
         "where  -a use message authentication\n"
         "       -e <key size> use encryption (use 128 or 256 for key size)\n"
         "       -g Use AES-GCM mode (must be used with -e)\n"
+        "       -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
         "       -k <key>  sets the srtp master key\n"
         "       -s act as rtp sender\n"
         "       -r act as rtp receiver\n"
index b34d60d11254d530f53b3b29325410fab82662ac..4b217f224390c51967a9fef2a047d14ede62462b 100644 (file)
@@ -60,6 +60,48 @@ sleep $DURATION
 kill $receiver_pid
 kill $sender_pid
 
+GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -t 16 -e 128"
+echo  $0 ": starting GCM mode 128-bit (16 byte tag) rtpw receiver process... "
+
+exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT &
+
+receiver_pid=$!
+
+echo $0 ": receiver PID = $receiver_pid"
+
+sleep 1 
+
+# verify that the background job is running
+ps | grep -q $receiver_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 254
+fi
+
+echo  $0 ": starting GCM 128-bit (16 byte tag) rtpw sender process..."
+
+exec $RTPW $* $GCMARGS128 -s 127.0.0.1 $DEST_PORT  &
+
+sender_pid=$!
+
+echo $0 ": sender PID = $sender_pid"
+
+# verify that the background job is running
+ps | grep -q $sender_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 255
+fi
+
+sleep $DURATION
+
+kill $receiver_pid
+kill $sender_pid
+
 
 
 GCMARGS256="-k 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -e 256"
@@ -105,6 +147,49 @@ kill $receiver_pid
 kill $sender_pid
 
 
+GCMARGS256="-k a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -t 16 -e 256"
+echo  $0 ": starting GCM mode 256-bit (16 byte tag) rtpw receiver process... "
+
+exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT &
+
+receiver_pid=$!
+
+echo $0 ": receiver PID = $receiver_pid"
+
+sleep 1 
+
+# verify that the background job is running
+ps | grep -q $receiver_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 254
+fi
+
+echo  $0 ": starting GCM 256-bit (16 byte tag) rtpw sender process..."
+
+exec $RTPW $* $GCMARGS256 -s 127.0.0.1 $DEST_PORT  &
+
+sender_pid=$!
+
+echo $0 ": sender PID = $sender_pid"
+
+# verify that the background job is running
+ps | grep -q $sender_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 255
+fi
+
+sleep $DURATION
+
+kill $receiver_pid
+kill $sender_pid
+
+
 echo $0 ": done (test passed)"
 
 else