diff --git a/libs/srtp/crypto/cipher/aes_cbc.c b/libs/srtp/crypto/cipher/aes_cbc.c index fad74a411e..d57d0219d8 100644 --- a/libs/srtp/crypto/cipher/aes_cbc.c +++ b/libs/srtp/crypto/cipher/aes_cbc.c @@ -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 */ }; diff --git a/libs/srtp/crypto/cipher/aes_gcm_ossl.c b/libs/srtp/crypto/cipher/aes_gcm_ossl.c index f281025d8c..7ce52d001d 100644 --- a/libs/srtp/crypto/cipher/aes_gcm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_gcm_ossl.c @@ -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. */ diff --git a/libs/srtp/crypto/cipher/aes_icm.c b/libs/srtp/crypto/cipher/aes_icm.c index cf316b1ffd..64eb51dee6 100644 --- a/libs/srtp/crypto/cipher/aes_icm.c +++ b/libs/srtp/crypto/cipher/aes_icm.c @@ -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 */ }; diff --git a/libs/srtp/crypto/cipher/aes_icm_ossl.c b/libs/srtp/crypto/cipher/aes_icm_ossl.c index 2d9d4e068b..12054a2cc9 100644 --- a/libs/srtp/crypto/cipher/aes_icm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_icm_ossl.c @@ -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 */ }; diff --git a/libs/srtp/crypto/cipher/cipher.c b/libs/srtp/crypto/cipher/cipher.c index 07b472ebff..3f8f01aea6 100644 --- a/libs/srtp/crypto/cipher/cipher.c +++ b/libs/srtp/crypto/cipher/cipher.c @@ -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; diff --git a/libs/srtp/crypto/cipher/null_cipher.c b/libs/srtp/crypto/cipher/null_cipher.c index 8c2f09f996..b12b1bfe8f 100644 --- a/libs/srtp/crypto/cipher/null_cipher.c +++ b/libs/srtp/crypto/cipher/null_cipher.c @@ -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 */ }; diff --git a/libs/srtp/crypto/include/cipher.h b/libs/srtp/crypto/include/cipher.h index f98d2398d1..d0d6b57f27 100644 --- a/libs/srtp/crypto/include/cipher.h +++ b/libs/srtp/crypto/include/cipher.h @@ -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)) diff --git a/libs/srtp/crypto/include/crypto_kernel.h b/libs/srtp/crypto/include/crypto_kernel.h index 1acf4978d0..caccfa03a9 100644 --- a/libs/srtp/crypto/include/crypto_kernel.h +++ b/libs/srtp/crypto/include/crypto_kernel.h @@ -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); diff --git a/libs/srtp/crypto/kernel/crypto_kernel.c b/libs/srtp/crypto/kernel/crypto_kernel.c index 656c010460..8542be0b84 100644 --- a/libs/srtp/crypto/kernel/crypto_kernel.c +++ b/libs/srtp/crypto/kernel/crypto_kernel.c @@ -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)); } diff --git a/libs/srtp/crypto/test/cipher_driver.c b/libs/srtp/crypto/test/cipher_driver.c index 26992e1f23..d015b45523 100644 --- a/libs/srtp/crypto/test/cipher_driver.c +++ b/libs/srtp/crypto/test/cipher_driver.c @@ -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; diff --git a/libs/srtp/crypto/test/stat_driver.c b/libs/srtp/crypto/test/stat_driver.c index 8c11a16ac0..c53423ff5d 100644 --- a/libs/srtp/crypto/test/stat_driver.c +++ b/libs/srtp/crypto/test/stat_driver.c @@ -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)); diff --git a/libs/srtp/include/srtp.h b/libs/srtp/include/srtp.h index d64f946576..11ea33d7f6 100644 --- a/libs/srtp/include/srtp.h +++ b/libs/srtp/include/srtp.h @@ -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 diff --git a/libs/srtp/srtp/srtp.c b/libs/srtp/srtp/srtp.c index 0d2eabffcc..1f7ac1246a 100644 --- a/libs/srtp/srtp/srtp.c +++ b/libs/srtp/srtp/srtp.c @@ -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 /* diff --git a/libs/srtp/test/rtpw.c b/libs/srtp/test/rtpw.c index ae902689d0..26f2ffc443 100644 --- a/libs/srtp/test/rtpw.c +++ b/libs/srtp/test/rtpw.c @@ -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 use encryption (use 128 or 256 for key size)\n" " -g Use AES-GCM mode (must be used with -e)\n" + " -t Tag size to use in GCM mode (use 8 or 16)\n" " -k sets the srtp master key\n" " -s act as rtp sender\n" " -r act as rtp receiver\n" diff --git a/libs/srtp/test/rtpw_test_gcm.sh b/libs/srtp/test/rtpw_test_gcm.sh index b34d60d112..4b217f2243 100644 --- a/libs/srtp/test/rtpw_test_gcm.sh +++ b/libs/srtp/test/rtpw_test_gcm.sh @@ -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