]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
This commit resolves issue #46. The GCM mode was using the wrong master SALT length...
authorjfigus <jfig_us@yahoo.com>
Tue, 8 Apr 2014 13:15:49 +0000 (09:15 -0400)
committerTravis Cross <tc@traviscross.com>
Tue, 8 Apr 2014 15:25:39 +0000 (15:25 +0000)
libs/srtp/crypto/cipher/aes_gcm_ossl.c
libs/srtp/crypto/include/aes_gcm_ossl.h
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_test_gcm.sh
libs/srtp/test/srtp_driver.c

index f36ce9d3b29cf186f7f3ae4c114a0389ecd06e20..f281025d8c33e3d6229020211dcc96c9770eb6f8 100644 (file)
@@ -73,7 +73,7 @@ extern cipher_type_t aes_gcm_256_openssl;
 
 /*
  * This function allocates a new instance of this crypto engine.
- * The key_len parameter should be one of 30 or 46 for
+ * The key_len parameter should be one of 28 or 44 for
  * AES-128-GCM or AES-256-GCM respectively.  Note that the 
  * key length includes the 14 byte salt value that is used when
  * initializing the KDF.
@@ -89,8 +89,8 @@ err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
     /*
      * Verify the key_len is valid for one of: AES-128/256
      */
-    if (key_len != AES_128_KEYSIZE_WSALT && 
-       key_len != AES_256_KEYSIZE_WSALT) {
+    if (key_len != AES_128_GCM_KEYSIZE_WSALT && 
+       key_len != AES_256_GCM_KEYSIZE_WSALT) {
         return (err_status_bad_param);
     }
 
@@ -108,14 +108,14 @@ err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
 
     /* increment ref_count */
     switch (key_len) {
-    case AES_128_KEYSIZE_WSALT:
+    case AES_128_GCM_KEYSIZE_WSALT:
         (*c)->type = &aes_gcm_128_openssl;
         (*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;  
         break;
-    case AES_256_KEYSIZE_WSALT:
+    case AES_256_GCM_KEYSIZE_WSALT:
         (*c)->type = &aes_gcm_256_openssl;
         (*c)->algorithm = AES_256_GCM;
         aes_gcm_256_openssl.ref_count++;
@@ -376,11 +376,11 @@ char aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl";
  * values we're derived from independent test code 
  * using OpenSSL.
  */
-uint8_t aes_gcm_test_case_0_key[AES_128_KEYSIZE_WSALT] = {
+uint8_t aes_gcm_test_case_0_key[AES_128_GCM_KEYSIZE_WSALT] = {
     0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
     0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 
+    0x09, 0x0a, 0x0b, 0x0c,  
 };
 
 uint8_t aes_gcm_test_case_0_iv[12] = {
@@ -419,7 +419,7 @@ uint8_t aes_gcm_test_case_0_ciphertext[68] = {
 };
 
 cipher_test_case_t aes_gcm_test_case_0 = {
-    AES_128_KEYSIZE_WSALT,                 /* octets in key            */
+    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      */
@@ -431,13 +431,13 @@ cipher_test_case_t aes_gcm_test_case_0 = {
     NULL                                   /* pointer to next testcase */
 };
 
-uint8_t aes_gcm_test_case_1_key[AES_256_KEYSIZE_WSALT] = {
+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,
     0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2, 
     0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 
+    0x09, 0x0a, 0x0b, 0x0c,  
 
 };
 
@@ -477,7 +477,7 @@ uint8_t aes_gcm_test_case_1_ciphertext[68] = {
 };
 
 cipher_test_case_t aes_gcm_test_case_1 = {
-    AES_256_KEYSIZE_WSALT,                 /* octets in key            */
+    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      */
index 87b3e9f7e1b71ea34ad6703be9e4b2bf3a2a82df..8e7711dc526c13fffa1b5b9382f1720c15d7436d 100644 (file)
@@ -47,6 +47,7 @@
 #define AES_GCM_OSSL_H
 
 #include "cipher.h"
+#include "srtp.h"
 #include <openssl/evp.h>
 #include <openssl/aes.h>
 
index c4b4d668de62cdf140db61e6a16a34c682ae8466..26992e1f23a868fc234e6356f473f53974491479 100644 (file)
@@ -200,11 +200,11 @@ main(int argc, char *argv[]) {
       cipher_driver_test_array_throughput(&aes_icm_256, 46, num_cipher); 
 
     for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) {
-       cipher_driver_test_array_throughput(&aes_gcm_128_openssl, 30, num_cipher);         
+       cipher_driver_test_array_throughput(&aes_gcm_128_openssl, AES_128_GCM_KEYSIZE_WSALT, num_cipher);         
     }
 
     for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) {
-       cipher_driver_test_array_throughput(&aes_gcm_256_openssl, 46, num_cipher);         
+       cipher_driver_test_array_throughput(&aes_gcm_256_openssl, AES_256_GCM_KEYSIZE_WSALT, num_cipher);         
     }
 #endif
   }
@@ -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, 30);
+    status = cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT);
     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, 46);
+    status = cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT);
     if (status) {
         fprintf(stderr, "error: can't allocate GCM 256 cipher\n");
         exit(status);
index b2738e8fb481ca318fcdccef90cb973a42c52638..8c11a16ac069655073355198a89e4c5807903007 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "err.h"
 #include "stat.h"
+#include "srtp.h"
 
 #include "cipher.h"
 
@@ -141,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, 30));
+    err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT));
     err_check(cipher_init(c, key));
     err_check(cipher_set_iv(c, &nonce, direction_encrypt));
     err_check(cipher_encrypt(c, buffer, &buf_len));
@@ -170,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, 46));
+    err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT));
     err_check(cipher_init(c, key));
     err_check(cipher_set_iv(c, &nonce, direction_encrypt));
     err_check(cipher_encrypt(c, buffer, &buf_len));
index a9c73d46e7bc54e08333ab2d210193f4e8f4e137..d64f946576ef688ca2d7aa12f0ddbcf6647b6b1a 100644 (file)
@@ -94,6 +94,10 @@ extern "C" {
  * as part of the IV formation logic applied to each RTP packet.
  */
 #define SRTP_AEAD_SALT_LEN     12
+#define AES_128_GCM_KEYSIZE_WSALT   SRTP_AEAD_SALT_LEN + 16
+#define AES_192_GCM_KEYSIZE_WSALT   SRTP_AEAD_SALT_LEN + 24
+#define AES_256_GCM_KEYSIZE_WSALT   SRTP_AEAD_SALT_LEN + 32
+
 
 /* 
  * nota bene: since libSRTP doesn't support the use of the MKI, the
index 4dbda3e2724fe37aa8ee9f98ccc1751e8a4730e9..04a99fd2126b720047c760382b147ddf447669a4 100644 (file)
@@ -46,6 +46,9 @@
 #include "srtp.h"
 #include "ekt.h"             /* for SRTP Encrypted Key Transport */
 #include "alloc.h"           /* for crypto_alloc()          */
+#ifdef OPENSSL
+#include "aes_gcm_ossl.h"    /* for AES GCM mode  */
+#endif
 
 #ifndef SRTP_KERNEL
 # include <limits.h>
@@ -451,24 +454,37 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
   /* 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;
+  rtp_base_key_len = base_key_length(srtp->rtp_cipher->type, rtp_keylen);
+  rtp_salt_len = rtp_keylen - rtp_base_key_len;
+
+  if (rtp_keylen > kdf_keylen) {
+    kdf_keylen = 46;  /* AES-CTR mode is always used for KDF */
+  }
+
+  if (rtcp_keylen > kdf_keylen) {
+    kdf_keylen = 46;  /* AES-CTR mode is always used for KDF */
+  }
+
   debug_print(mod_srtp, "srtp key len: %d", rtp_keylen);
   debug_print(mod_srtp, "srtcp key len: %d", rtcp_keylen);
+  debug_print(mod_srtp, "base key len: %d", rtp_base_key_len);
+  debug_print(mod_srtp, "kdf key len: %d", kdf_keylen);
+  debug_print(mod_srtp, "rtp salt len: %d", rtp_salt_len);
+
+  /* 
+   * Make sure the key given to us is 'zero' appended.  GCM
+   * mode uses a shorter master SALT (96 bits), but still relies on 
+   * the legacy CTR mode KDF, which uses a 112 bit master SALT.
+   */
+  memset(tmp_key, 0x0, MAX_SRTP_KEY_LEN);
+  memcpy(tmp_key, key, (rtp_base_key_len + rtp_salt_len));
 
   /* initialize KDF state     */
-  stat = srtp_kdf_init(&kdf, AES_ICM, (const uint8_t *)key, kdf_keylen);
+  stat = srtp_kdf_init(&kdf, AES_ICM, (const uint8_t *)tmp_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;
-  debug_print(mod_srtp, "rtp salt len: %d", rtp_salt_len);
   
   /* generate encryption key  */
   stat = srtp_kdf_generate(&kdf, label_rtp_encryption, 
@@ -478,6 +494,8 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
     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, rtp_base_key_len));
 
   /* 
    * if the cipher in the srtp context uses a salt, then we need
@@ -496,8 +514,6 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
     }
     memcpy(srtp->salt, tmp_key + rtp_base_key_len, SRTP_AEAD_SALT_LEN);
   }
-  debug_print(mod_srtp, "cipher key: %s", 
-             octet_string_hex_string(tmp_key, rtp_base_key_len));
   if (rtp_salt_len > 0) {
     debug_print(mod_srtp, "cipher salt: %s",
                octet_string_hex_string(tmp_key + rtp_base_key_len, rtp_salt_len));
@@ -2049,7 +2065,7 @@ crypto_policy_set_aes_cm_256_null_auth (crypto_policy_t *p)
 void
 crypto_policy_set_aes_gcm_128_8_auth(crypto_policy_t *p) {
   p->cipher_type     = AES_128_GCM;           
-  p->cipher_key_len  = AES_128_KEYSIZE_WSALT; 
+  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    = 8;   /* 8 octet tag length */
@@ -2062,7 +2078,7 @@ crypto_policy_set_aes_gcm_128_8_auth(crypto_policy_t *p) {
 void
 crypto_policy_set_aes_gcm_256_8_auth(crypto_policy_t *p) {
   p->cipher_type     = AES_256_GCM;           
-  p->cipher_key_len  = AES_256_KEYSIZE_WSALT; 
+  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    = 8;   /* 8 octet tag length */
@@ -2075,7 +2091,7 @@ crypto_policy_set_aes_gcm_256_8_auth(crypto_policy_t *p) {
 void
 crypto_policy_set_aes_gcm_128_8_only_auth(crypto_policy_t *p) {
   p->cipher_type     = AES_128_GCM;           
-  p->cipher_key_len  = AES_128_KEYSIZE_WSALT; 
+  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    = 8;   /* 8 octet tag length */
@@ -2088,7 +2104,7 @@ 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) {
   p->cipher_type     = AES_256_GCM;           
-  p->cipher_key_len  = AES_256_KEYSIZE_WSALT; 
+  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    = 8;   /* 8 octet tag length */
index dfac33514eb73e62089f9eda7954c66e5bcb191d..b34d60d11254d530f53b3b29325410fab82662ac 100644 (file)
@@ -18,7 +18,7 @@ killall rtpw 2>/dev/null
 
 if test -x $RTPW; then
 
-GCMARGS128="-k 012345678901234567890123456789012345678901234567890123456789 -g -e 128"
+GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -e 128"
 echo  $0 ": starting GCM mode 128-bit rtpw receiver process... "
 
 exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT &
@@ -62,7 +62,7 @@ kill $sender_pid
 
 
 
-GCMARGS256="-k 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 -g -e 256"
+GCMARGS256="-k 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -e 256"
 echo  $0 ": starting GCM mode 256-bit rtpw receiver process... "
 
 exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT &
index 783d5182e316adaed6923a069c40c748fdc28c7c..887297170c0601d95720257c9debac20fce31da3 100644 (file)
@@ -1670,7 +1670,7 @@ const srtp_policy_t aes128_gcm_8_policy = {
     { ssrc_any_outbound, 0 },  /* SSRC                           */
     {                      /* SRTP policy                    */                  
         AES_128_GCM,            /* cipher type                 */
-        30,                     /* cipher key length in octets */
+        AES_128_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1678,7 +1678,7 @@ const srtp_policy_t aes128_gcm_8_policy = {
     },
     {                      /* SRTCP policy                   */
         AES_128_GCM,            /* cipher type                 */
-        30,                     /* cipher key length in octets */
+        AES_128_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1695,7 +1695,7 @@ const srtp_policy_t aes128_gcm_8_cauth_policy = {
     { ssrc_any_outbound, 0 },  /* SSRC                           */
     {                      /* SRTP policy                    */                  
         AES_128_GCM,            /* cipher type                 */
-        30,                     /* cipher key length in octets */
+        AES_128_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1703,7 +1703,7 @@ const srtp_policy_t aes128_gcm_8_cauth_policy = {
     },
     {                      /* SRTCP policy                   */
         AES_128_GCM,            /* cipher type                 */
-        30,                     /* cipher key length in octets */
+        AES_128_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1720,7 +1720,7 @@ const srtp_policy_t aes256_gcm_8_policy = {
     { ssrc_any_outbound, 0 },  /* SSRC                           */
     {                      /* SRTP policy                    */                  
         AES_256_GCM,            /* cipher type                 */
-        46,                     /* cipher key length in octets */
+        AES_256_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1728,7 +1728,7 @@ const srtp_policy_t aes256_gcm_8_policy = {
     },
     {                      /* SRTCP policy                   */
         AES_256_GCM,            /* cipher type                 */
-        46,                     /* cipher key length in octets */
+        AES_256_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1745,7 +1745,7 @@ const srtp_policy_t aes256_gcm_8_cauth_policy = {
     { ssrc_any_outbound, 0 },  /* SSRC                           */
     {                      /* SRTP policy                    */                  
         AES_256_GCM,            /* cipher type                 */
-        46,                     /* cipher key length in octets */
+        AES_256_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */
@@ -1753,7 +1753,7 @@ const srtp_policy_t aes256_gcm_8_cauth_policy = {
     },
     {                      /* SRTCP policy                   */
         AES_256_GCM,            /* cipher type                 */
-        46,                     /* cipher key length in octets */
+        AES_256_GCM_KEYSIZE_WSALT,  /* cipher key length in octets */
         NULL_AUTH,              /* authentication func type    */
         0,                      /* auth key length in octets   */
         8,                      /* auth tag length in octets   */