diff --git a/third_party/libsrtp/moz.yaml b/third_party/libsrtp/moz.yaml --- a/third_party/libsrtp/moz.yaml +++ b/third_party/libsrtp/moz.yaml @@ -10,12 +10,12 @@ url: "https://github.com/cisco/libsrtp/" license: BSD-3-Clause license-file: LICENSE - release: v2.4.2 (2021-09-20T16:10:47+02:00). - revision: v2.4.2 + release: v2.5.0 (2023-02-01T08:25:02+01:00). + revision: v2.5.0 updatebot: maintainer-phab: jesup maintainer-bz: rjesup@jesup.org diff --git a/third_party/libsrtp/src/CHANGES b/third_party/libsrtp/src/CHANGES --- a/third_party/libsrtp/src/CHANGES +++ b/third_party/libsrtp/src/CHANGES @@ -1,24 +1,56 @@ Changelog -2.4.2 +2.5.0 + +#636 - Make mbedtls hmac less restrictive in line with RFC and library capabilities + +#612 - Allow overriding stream list implementation + +#629 - update min openssl version to 1.1.0 + +#602 - Openssl 3 support for EVP MAC -#563 - Fix typo introduced by PR 559 +#628 - Add android build to CI + +#616 - add CIFuzz Github action to workflows + +#621 - Add policy_set_aes_cm_192_xxx symbols to def file + +#617 - Use current directions in stream update test + +#614 - Call `set_aad` and `get_tag` in AEAD performance tests -2.4.1 +#611 - Create alias for srtp2 as libSRTP::srtp2 + +#593 - Remove compatibility code for legacy OpenSSL to fix LibreSSL build + +#573 - Export CMake Targets + +#586 - Avoid initializing local char table when converting nibble to hex + +#591 - EVP_CIPHER_CTX_cleanup() is deprecated in OpenSSL 1.1.0 -Major changes +#589 - Correct null cipher key sizes and be more defensive + +#570 - Include directory should point to 'include' not to 'include/srtp2' + +#551 - Count blocks instead of bytes in AES-ICM limit computation -#560 - Merge PR 559, Use a full-length key even with null ciphers +#561 - Rtp decoder support ssrc and roc + +#559 - Use a full-length key even with null ciphers + +#558 - Fix set ROC functionality with gcm 2.4.0 Major changes #529 - Remove EKT files, this was never completed and the draft has since changed. -#512 - Adds suport for Mbedtls as a crypto backend. +#512 - Adds support for Mbedtls as a crypto backend. #503 - Support apple silicon build. #495 - Adds support for the Meson build system. This is an alternative to Cmake and auto tools. @@ -62,11 +94,11 @@ Major changes A fuzzer was added to the project based on libFuzzer. This is run as part of Google oss-fuzz, the current status can be found at https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp . Details available in PR #442 and issue #393. -CMake support was added as an alternative build system. This was primarily added to replace the Visual Studio project files currently checked in but has been extend to support building on all platforms. Initial PR #449 and #455 but has been support has been continuously improved. +CMake support was added as an alternative build system. This was primarily added to replace the Visual Studio project files currently checked in but has been extend to support building on all platforms. Initial PR #449 and #455 but has been support has been continuously improved. NSS support for crypto backend was added. This is can be used as an alternative to openssl. Initial PR #413 but there has been numerous improvements. Other changes diff --git a/third_party/libsrtp/src/README.md b/third_party/libsrtp/src/README.md --- a/third_party/libsrtp/src/README.md +++ b/third_party/libsrtp/src/README.md @@ -1,6 +1,7 @@ [![CMake Build](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml) +[![Autotools Build](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml) [![Build Status](https://travis-ci.org/cisco/libsrtp.svg?branch=master)](https://travis-ci.org/cisco/libsrtp) [![Coverity Scan Build Status](https://scan.coverity.com/projects/14274/badge.svg)](https://scan.coverity.com/projects/cisco-libsrtp) [![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp) @@ -217,15 +218,25 @@ inadequate. If you are implementing a feature using this library, you will want to read the Security Considerations section of [RFC 3711](https://tools.ietf.org/html/rfc3711#section-9). In addition, it is important that you read and understand the terms outlined in the [License and Disclaimer](#license-and-disclaimer) section. +This library also supports the AES-GCM Authenticated Encryption methods +described in [RFC 7714](https://tools.ietf.org/html/rfc7714) + -------------------------------------------------------------------------------- ## Implementation Notes + * It is possible to configure which 3rd party (ie openssl/nss/etc) crypto backend + libSRTP will be built with. If no 3rd party backend is set then libSRTP provides + an internal implementation of AES and Sha1. The internal implementation only + supports AES-128 & AES-256, so to use AES-192 or the AES-GCM group of ciphers a + 3rd party crypto backend must be configured. For this and performance reasons it + is highly recommended to use a 3rd party crypto backend. + * The `srtp_protect()` function assumes that the buffer holding the rtp packet has enough storage allocated that the authentication tag can be written to the end of that packet. If this assumption is not valid, memory corruption will ensue. @@ -280,15 +291,17 @@ Option | Description -------------------------------|-------------------- \-\-help \-h | Display help \-\-enable-debug-logging | Enable debug logging in all modules -\-\-enable-log-stdout | Enable logging to stdout \-\-enable-openssl | Enable OpenSSL crypto engine +\-\-enable-nss | Enable NSS crypto engine \-\-enable-openssl-kdf | Enable OpenSSL KDF algorithm +\-\-enable-log-stdout | Enable logging to stdout +\-\-with-openssl-dir | Location of OpenSSL installation +\-\-with-nss-dir | Location of NSS installation \-\-with-log-file | Use file for logging -\-\-with-openssl-dir | Location of OpenSSL installation By default there is no log output, logging can be enabled to be output to stdout or a given file using the configure options. This package has been tested on the following platforms: Mac OS X diff --git a/third_party/libsrtp/src/crypto/.cvsignore b/third_party/libsrtp/src/crypto/.cvsignore deleted file mode 100644 --- a/third_party/libsrtp/src/crypto/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/third_party/libsrtp/src/crypto/cipher/aes.c b/third_party/libsrtp/src/crypto/cipher/aes.c --- a/third_party/libsrtp/src/crypto/cipher/aes.c +++ b/third_party/libsrtp/src/crypto/cipher/aes.c @@ -1816,12 +1816,12 @@ static inline void aes_inv_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; -/* compute the columns of the output square in terms of the octets - of state, using the tables U0, U1, U2, U3 */ + /* compute the columns of the output square in terms of the octets + of state, using the tables U0, U1, U2, U3 */ #ifdef WORDS_BIGENDIAN column0 = U0[state->v32[0] >> 24] ^ U1[(state->v32[3] >> 16) & 0xff] ^ U2[(state->v32[2] >> 8) & 0xff] ^ U3[state->v32[1] & 0xff]; diff --git a/third_party/libsrtp/src/crypto/cipher/aes_gcm_mbedtls.c b/third_party/libsrtp/src/crypto/cipher/aes_gcm_mbedtls.c --- a/third_party/libsrtp/src/crypto/cipher/aes_gcm_mbedtls.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_gcm_mbedtls.c @@ -254,11 +254,10 @@ static srtp_err_status_t srtp_aes_gcm_mbedtls_set_aad(void *cv, const uint8_t *aad, uint32_t aad_len) { FUNC_ENTRY(); - int errCode = 0; srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; debug_print(srtp_mod_aes_gcm, "setting AAD: %s", srtp_octet_string_hex_string(aad, aad_len)); @@ -341,11 +340,10 @@ unsigned int *enc_len) { FUNC_ENTRY(); srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; int errCode = 0; - int len = *enc_len; if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) { return (srtp_err_status_bad_param); } diff --git a/third_party/libsrtp/src/crypto/cipher/aes_gcm_ossl.c b/third_party/libsrtp/src/crypto/cipher/aes_gcm_ossl.c --- a/third_party/libsrtp/src/crypto/cipher/aes_gcm_ossl.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_gcm_ossl.c @@ -191,11 +191,12 @@ default: return (srtp_err_status_bad_param); break; } - EVP_CIPHER_CTX_cleanup(c->ctx); + EVP_CIPHER_CTX_reset(c->ctx); + if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) { return (srtp_err_status_init_fail); } return (srtp_err_status_ok); @@ -273,11 +274,11 @@ return (srtp_err_status_algo_fail); } } rv = EVP_Cipher(c->ctx, NULL, aad, aad_len); - if (rv != aad_len) { + if (rv < 0 || (uint32_t)rv != aad_len) { return (srtp_err_status_algo_fail); } else { return (srtp_err_status_ok); } } diff --git a/third_party/libsrtp/src/crypto/cipher/aes_icm.c b/third_party/libsrtp/src/crypto/cipher/aes_icm.c --- a/third_party/libsrtp/src/crypto/cipher/aes_icm.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_icm.c @@ -96,10 +96,11 @@ static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c, int key_len, int tlen) { srtp_aes_icm_ctx_t *icm; + (void)tlen; debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len); /* @@ -236,10 +237,11 @@ uint8_t *iv, srtp_cipher_direction_t direction) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; + (void)direction; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); @@ -300,11 +302,13 @@ unsigned int bytes_to_encr = *enc_len; unsigned int i; uint32_t *b; /* check that there's enough segment left*/ - if ((bytes_to_encr + htons(c->counter.v16[7])) > 0xffff) { + unsigned int bytes_of_new_keystream = bytes_to_encr - c->bytes_in_buffer; + unsigned int blocks_of_new_keystream = (bytes_of_new_keystream + 15) >> 4; + if ((blocks_of_new_keystream + htons(c->counter.v16[7])) > 0xffff) { return srtp_err_status_terminus; } debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7])); if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) { @@ -333,14 +337,14 @@ /* now loop over entire 16-byte blocks of keystream */ for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) { /* fill buffer with new keystream */ srtp_aes_icm_advance(c); -/* - * add keystream into the data buffer (this would be a lot faster - * if we could assume 32-bit alignment!) - */ + /* + * add keystream into the data buffer (this would be a lot faster + * if we could assume 32-bit alignment!) + */ #if ALIGN_32 b = (uint32_t *)buf; *b++ ^= c->keystream_buffer.v32[0]; *b++ ^= c->keystream_buffer.v32[1]; diff --git a/third_party/libsrtp/src/crypto/cipher/aes_icm_mbedtls.c b/third_party/libsrtp/src/crypto/cipher/aes_icm_mbedtls.c --- a/third_party/libsrtp/src/crypto/cipher/aes_icm_mbedtls.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_icm_mbedtls.c @@ -116,10 +116,11 @@ static srtp_err_status_t srtp_aes_icm_mbedtls_alloc(srtp_cipher_t **c, int key_len, int tlen) { srtp_aes_icm_ctx_t *icm; + (void)tlen; debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len); /* @@ -262,10 +263,12 @@ uint8_t *iv, srtp_cipher_direction_t dir) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; + (void)dir; + c->nc_off = 0; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); diff --git a/third_party/libsrtp/src/crypto/cipher/aes_icm_nss.c b/third_party/libsrtp/src/crypto/cipher/aes_icm_nss.c --- a/third_party/libsrtp/src/crypto/cipher/aes_icm_nss.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_icm_nss.c @@ -105,10 +105,11 @@ int key_len, int tlen) { srtp_aes_icm_ctx_t *icm; NSSInitContext *nss; + (void)tlen; debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len); /* @@ -273,10 +274,11 @@ uint8_t *iv, srtp_cipher_direction_t dir) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; + (void)dir; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); diff --git a/third_party/libsrtp/src/crypto/cipher/aes_icm_ossl.c b/third_party/libsrtp/src/crypto/cipher/aes_icm_ossl.c --- a/third_party/libsrtp/src/crypto/cipher/aes_icm_ossl.c +++ b/third_party/libsrtp/src/crypto/cipher/aes_icm_ossl.c @@ -110,10 +110,11 @@ static srtp_err_status_t srtp_aes_icm_openssl_alloc(srtp_cipher_t **c, int key_len, int tlen) { srtp_aes_icm_ctx_t *icm; + (void)tlen; debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len); /* @@ -166,11 +167,11 @@ (*c)->type = &srtp_aes_icm_256; icm->key_size = SRTP_AES_256_KEY_LEN; break; } - /* set key size */ + /* set key size */ (*c)->key_len = key_len; return srtp_err_status_ok; } @@ -247,15 +248,14 @@ default: return srtp_err_status_bad_param; break; } - EVP_CIPHER_CTX_cleanup(c->ctx); + EVP_CIPHER_CTX_reset(c->ctx); + if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) { return srtp_err_status_fail; - } else { - return srtp_err_status_ok; } return srtp_err_status_ok; } @@ -268,10 +268,11 @@ uint8_t *iv, srtp_cipher_direction_t dir) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; + (void)dir; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); @@ -281,13 +282,13 @@ debug_print(srtp_mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); if (!EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, c->counter.v8)) { return srtp_err_status_fail; - } else { - return srtp_err_status_ok; } + + return srtp_err_status_ok; } /* * This function encrypts a buffer using AES CTR mode * diff --git a/third_party/libsrtp/src/crypto/cipher/cipher.c b/third_party/libsrtp/src/crypto/cipher/cipher.c --- a/third_party/libsrtp/src/crypto/cipher/cipher.c +++ b/third_party/libsrtp/src/crypto/cipher/cipher.c @@ -630,28 +630,51 @@ int i; v128_t nonce; clock_t timer; unsigned char *enc_buf; unsigned int len = octets_in_buffer; + uint32_t tag_len = SRTP_MAX_TAG_LEN; + unsigned char aad[4] = { 0, 0, 0, 0 }; + uint32_t aad_len = 4; - enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer); + enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer + tag_len); if (enc_buf == NULL) { return 0; /* indicate bad parameters by returning null */ } /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for (i = 0; i < num_trials; i++, nonce.v32[3] = i) { + // Set IV if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) != srtp_err_status_ok) { srtp_crypto_free(enc_buf); return 0; } + + // Set (empty) AAD if supported by the cipher + if (c->type->set_aad) { + if (srtp_cipher_set_aad(c, aad, aad_len) != srtp_err_status_ok) { + srtp_crypto_free(enc_buf); + return 0; + } + } + + // Encrypt the buffer if (srtp_cipher_encrypt(c, enc_buf, &len) != srtp_err_status_ok) { srtp_crypto_free(enc_buf); return 0; } + + // Get tag if supported by the cipher + if (c->type->get_tag) { + if (srtp_cipher_get_tag(c, (uint8_t *)(enc_buf + len), &tag_len) != + srtp_err_status_ok) { + srtp_crypto_free(enc_buf); + return 0; + } + } } timer = clock() - timer; srtp_crypto_free(enc_buf); diff --git a/third_party/libsrtp/src/crypto/cipher/null_cipher.c b/third_party/libsrtp/src/crypto/cipher/null_cipher.c --- a/third_party/libsrtp/src/crypto/cipher/null_cipher.c +++ b/third_party/libsrtp/src/crypto/cipher/null_cipher.c @@ -57,10 +57,11 @@ static srtp_err_status_t srtp_null_cipher_alloc(srtp_cipher_t **c, int key_len, int tlen) { extern const srtp_cipher_type_t srtp_null_cipher; + (void)tlen; debug_print(srtp_mod_cipher, "allocating cipher with key length %d", key_len); /* allocate memory a cipher of type null_cipher */ @@ -94,29 +95,36 @@ } static srtp_err_status_t srtp_null_cipher_init(void *cv, const uint8_t *key) { /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ - + (void)cv; + (void)key; debug_print0(srtp_mod_cipher, "initializing null cipher"); return srtp_err_status_ok; } static srtp_err_status_t srtp_null_cipher_set_iv(void *cv, uint8_t *iv, srtp_cipher_direction_t dir) { /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ + (void)cv; + (void)iv; + (void)dir; return srtp_err_status_ok; } static srtp_err_status_t srtp_null_cipher_encrypt(void *cv, unsigned char *buf, unsigned int *bytes_to_encr) { /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ + (void)cv; + (void)buf; + (void)bytes_to_encr; return srtp_err_status_ok; } static const char srtp_null_cipher_description[] = "null cipher"; diff --git a/third_party/libsrtp/src/crypto/hash/hmac_mbedtls.c b/third_party/libsrtp/src/crypto/hash/hmac_mbedtls.c --- a/third_party/libsrtp/src/crypto/hash/hmac_mbedtls.c +++ b/third_party/libsrtp/src/crypto/hash/hmac_mbedtls.c @@ -70,14 +70,10 @@ key_len); debug_print(srtp_mod_hmac, " tag length %d", out_len); /* check output length - should be less than 20 bytes */ - if (key_len > SHA1_DIGEST_SIZE) { - return srtp_err_status_bad_param; - } - /* check output length - should be less than 20 bytes */ if (out_len > SHA1_DIGEST_SIZE) { return srtp_err_status_bad_param; } *a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t)); diff --git a/third_party/libsrtp/src/crypto/hash/hmac_nss.c b/third_party/libsrtp/src/crypto/hash/hmac_nss.c --- a/third_party/libsrtp/src/crypto/hash/hmac_nss.c +++ b/third_party/libsrtp/src/crypto/hash/hmac_nss.c @@ -254,11 +254,11 @@ if (PK11_DigestFinal(hmac->ctx, hash_value, &len, SHA1_DIGEST_SIZE) != SECSuccess) { return srtp_err_status_auth_fail; } - if (len < tag_len) + if (tag_len < 0 || len < (unsigned int)tag_len) return srtp_err_status_auth_fail; /* copy hash_value to *result */ for (i = 0; i < tag_len; i++) { result[i] = hash_value[i]; diff --git a/third_party/libsrtp/src/crypto/hash/hmac_ossl.c b/third_party/libsrtp/src/crypto/hash/hmac_ossl.c --- a/third_party/libsrtp/src/crypto/hash/hmac_ossl.c +++ b/third_party/libsrtp/src/crypto/hash/hmac_ossl.c @@ -49,26 +49,61 @@ #include "auth.h" #include "alloc.h" #include "err.h" /* for srtp_debug */ #include "auth_test_cases.h" #include + +#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) +#define SRTP_OSSL_USE_EVP_MAC +/* before this version reinit of EVP_MAC_CTX was not supported so need to + * duplicate the CTX each time */ +#define SRTP_OSSL_MIN_REINIT_VERSION 0x30000030L +#endif + +#ifndef SRTP_OSSL_USE_EVP_MAC #include +#endif #define SHA1_DIGEST_SIZE 20 -/* the debug module for authentiation */ +/* the debug module for authentication */ srtp_debug_module_t srtp_mod_hmac = { 0, /* debugging is off by default */ "hmac sha-1 openssl" /* printable name for module */ }; +/* + * There are three different behaviors of OpenSSL HMAC for different versions. + * + * 1. Pre-3.0 - Use HMAC API + * 2. 3.0.0 - 3.0.2 - EVP API is required, but doesn't support reinitialization, + * so we have to use EVP_MAC_CTX_dup + * 3. 3.0.3 and later - EVP API is required and supports reinitialization + * + * The distingtion between cases 2 & 3 needs to be made at runtime, because in a + * shared library context you might end up building against 3.0.3 and running + * against 3.0.2. + */ + +typedef struct { +#ifdef SRTP_OSSL_USE_EVP_MAC + EVP_MAC *mac; + EVP_MAC_CTX *ctx; + int use_dup; + EVP_MAC_CTX *ctx_dup; +#else + HMAC_CTX *ctx; +#endif +} srtp_hmac_ossl_ctx_t; + static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a, int key_len, int out_len) { extern const srtp_auth_type_t srtp_hmac; + srtp_hmac_ossl_ctx_t *hmac; debug_print(srtp_mod_hmac, "allocating auth func with key length %d", key_len); debug_print(srtp_mod_hmac, " tag length %d", out_len); @@ -76,141 +111,202 @@ /* check output length - should be less than 20 bytes */ if (out_len > SHA1_DIGEST_SIZE) { return srtp_err_status_bad_param; } -/* OpenSSL 1.1.0 made HMAC_CTX an opaque structure, which must be allocated - using HMAC_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER - { - /* allocate memory for auth and HMAC_CTX structures */ - uint8_t *pointer; - HMAC_CTX *new_hmac_ctx; - pointer = (uint8_t *)srtp_crypto_alloc(sizeof(HMAC_CTX) + - sizeof(srtp_auth_t)); - if (pointer == NULL) { - return srtp_err_status_alloc_fail; - } - *a = (srtp_auth_t *)pointer; - (*a)->state = pointer + sizeof(srtp_auth_t); - new_hmac_ctx = (HMAC_CTX *)((*a)->state); - - HMAC_CTX_init(new_hmac_ctx); - } - -#else *a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t)); if (*a == NULL) { return srtp_err_status_alloc_fail; } - (*a)->state = HMAC_CTX_new(); - if ((*a)->state == NULL) { + hmac = + (srtp_hmac_ossl_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ossl_ctx_t)); + if (hmac == NULL) { + srtp_crypto_free(*a); + *a = NULL; + return srtp_err_status_alloc_fail; + } + +#ifdef SRTP_OSSL_USE_EVP_MAC + hmac->mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + if (hmac->mac == NULL) { + srtp_crypto_free(hmac); + srtp_crypto_free(*a); + *a = NULL; + return srtp_err_status_alloc_fail; + } + + hmac->ctx = EVP_MAC_CTX_new(hmac->mac); + if (hmac->ctx == NULL) { + EVP_MAC_free(hmac->mac); + srtp_crypto_free(hmac); + srtp_crypto_free(*a); + *a = NULL; + return srtp_err_status_alloc_fail; + } + + hmac->use_dup = + OpenSSL_version_num() < SRTP_OSSL_MIN_REINIT_VERSION ? 1 : 0; + + if (hmac->use_dup) { + debug_print0(srtp_mod_hmac, "using EVP_MAC_CTX_dup"); + hmac->ctx_dup = hmac->ctx; + hmac->ctx = NULL; + } +#else + hmac->ctx = HMAC_CTX_new(); + if (hmac->ctx == NULL) { + srtp_crypto_free(hmac); srtp_crypto_free(*a); *a = NULL; return srtp_err_status_alloc_fail; } #endif /* set pointers */ + (*a)->state = hmac; (*a)->type = &srtp_hmac; (*a)->out_len = out_len; (*a)->key_len = key_len; (*a)->prefix_len = 0; return srtp_err_status_ok; } static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a) { - HMAC_CTX *hmac_ctx; - - hmac_ctx = (HMAC_CTX *)a->state; + srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)a->state; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER - HMAC_CTX_cleanup(hmac_ctx); + if (hmac) { +#ifdef SRTP_OSSL_USE_EVP_MAC + EVP_MAC_CTX_free(hmac->ctx); + EVP_MAC_CTX_free(hmac->ctx_dup); + EVP_MAC_free(hmac->mac); +#else + HMAC_CTX_free(hmac->ctx); +#endif + /* zeroize entire state*/ + octet_string_set_to_zero(hmac, sizeof(srtp_hmac_ossl_ctx_t)); - /* zeroize entire state*/ - octet_string_set_to_zero(a, sizeof(HMAC_CTX) + sizeof(srtp_auth_t)); - -#else - HMAC_CTX_free(hmac_ctx); + srtp_crypto_free(hmac); + } /* zeroize entire state*/ octet_string_set_to_zero(a, sizeof(srtp_auth_t)); -#endif /* free memory */ srtp_crypto_free(a); return srtp_err_status_ok; } static srtp_err_status_t srtp_hmac_start(void *statev) { - HMAC_CTX *state = (HMAC_CTX *)statev; + srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev; - if (HMAC_Init_ex(state, NULL, 0, NULL, NULL) == 0) +#ifdef SRTP_OSSL_USE_EVP_MAC + if (hmac->use_dup) { + EVP_MAC_CTX_free(hmac->ctx); + hmac->ctx = EVP_MAC_CTX_dup(hmac->ctx_dup); + if (hmac->ctx == NULL) { + return srtp_err_status_alloc_fail; + } + } else { + if (EVP_MAC_init(hmac->ctx, NULL, 0, NULL) == 0) { + return srtp_err_status_auth_fail; + } + } +#else + if (HMAC_Init_ex(hmac->ctx, NULL, 0, NULL, NULL) == 0) return srtp_err_status_auth_fail; - +#endif return srtp_err_status_ok; } static srtp_err_status_t srtp_hmac_init(void *statev, const uint8_t *key, int key_len) { - HMAC_CTX *state = (HMAC_CTX *)statev; + srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev; + +#ifdef SRTP_OSSL_USE_EVP_MAC + OSSL_PARAM params[2]; + + params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0); + params[1] = OSSL_PARAM_construct_end(); - if (HMAC_Init_ex(state, key, key_len, EVP_sha1(), NULL) == 0) + if (EVP_MAC_init(hmac->use_dup ? hmac->ctx_dup : hmac->ctx, key, key_len, + params) == 0) { return srtp_err_status_auth_fail; - + } +#else + if (HMAC_Init_ex(hmac->ctx, key, key_len, EVP_sha1(), NULL) == 0) + return srtp_err_status_auth_fail; +#endif return srtp_err_status_ok; } static srtp_err_status_t srtp_hmac_update(void *statev, const uint8_t *message, int msg_octets) { - HMAC_CTX *state = (HMAC_CTX *)statev; + srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev; debug_print(srtp_mod_hmac, "input: %s", srtp_octet_string_hex_string(message, msg_octets)); - if (HMAC_Update(state, message, msg_octets) == 0) +#ifdef SRTP_OSSL_USE_EVP_MAC + if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) { return srtp_err_status_auth_fail; - + } +#else + if (HMAC_Update(hmac->ctx, message, msg_octets) == 0) + return srtp_err_status_auth_fail; +#endif return srtp_err_status_ok; } static srtp_err_status_t srtp_hmac_compute(void *statev, const uint8_t *message, int msg_octets, int tag_len, uint8_t *result) { - HMAC_CTX *state = (HMAC_CTX *)statev; + srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev; uint8_t hash_value[SHA1_DIGEST_SIZE]; int i; +#ifdef SRTP_OSSL_USE_EVP_MAC + size_t len; +#else unsigned int len; +#endif debug_print(srtp_mod_hmac, "input: %s", srtp_octet_string_hex_string(message, msg_octets)); /* check tag length, return error if we can't provide the value expected */ if (tag_len > SHA1_DIGEST_SIZE) { return srtp_err_status_bad_param; } /* hash message, copy output into H */ - if (HMAC_Update(state, message, msg_octets) == 0) +#ifdef SRTP_OSSL_USE_EVP_MAC + if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) { + return srtp_err_status_auth_fail; + } + + if (EVP_MAC_final(hmac->ctx, hash_value, &len, sizeof hash_value) == 0) { + return srtp_err_status_auth_fail; + } +#else + if (HMAC_Update(hmac->ctx, message, msg_octets) == 0) return srtp_err_status_auth_fail; - if (HMAC_Final(state, hash_value, &len) == 0) + if (HMAC_Final(hmac->ctx, hash_value, &len) == 0) return srtp_err_status_auth_fail; - - if (len < tag_len) +#endif + if (tag_len < 0 || len < (unsigned int)tag_len) return srtp_err_status_auth_fail; /* copy hash_value to *result */ for (i = 0; i < tag_len; i++) { result[i] = hash_value[i]; diff --git a/third_party/libsrtp/src/crypto/hash/null_auth.c b/third_party/libsrtp/src/crypto/hash/null_auth.c --- a/third_party/libsrtp/src/crypto/hash/null_auth.c +++ b/third_party/libsrtp/src/crypto/hash/null_auth.c @@ -100,10 +100,14 @@ static srtp_err_status_t srtp_null_auth_init(void *statev, const uint8_t *key, int key_len) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ + (void)statev; + (void)key; + (void)key_len; + /* accept any length of key, and do nothing */ return srtp_err_status_ok; } @@ -112,26 +116,35 @@ int msg_octets, int tag_len, uint8_t *result) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ + (void)statev; + (void)message; + (void)msg_octets; + (void)tag_len; + (void)result; return srtp_err_status_ok; } static srtp_err_status_t srtp_null_auth_update(void *statev, const uint8_t *message, int msg_octets) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ + (void)statev; + (void)message; + (void)msg_octets; return srtp_err_status_ok; } static srtp_err_status_t srtp_null_auth_start(void *statev) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ + (void)statev; return srtp_err_status_ok; } /* diff --git a/third_party/libsrtp/src/crypto/include/.cvsignore b/third_party/libsrtp/src/crypto/include/.cvsignore deleted file mode 100644 --- a/third_party/libsrtp/src/crypto/include/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -config.h diff --git a/third_party/libsrtp/src/crypto/include/datatypes.h b/third_party/libsrtp/src/crypto/include/datatypes.h --- a/third_party/libsrtp/src/crypto/include/datatypes.h +++ b/third_party/libsrtp/src/crypto/include/datatypes.h @@ -164,10 +164,15 @@ #elif defined(HAVE_BYTESWAP_H) /* We have (hopefully) optimized versions in byteswap.h */ #include #define be32_to_cpu(x) bswap_32((x)) #define be64_to_cpu(x) bswap_64((x)) +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include +#define be32_to_cpu(x) OSSwapInt32(x) +#define be64_to_cpu(x) OSSwapInt64(x) #else /* WORDS_BIGENDIAN */ #if defined(__GNUC__) && (defined(HAVE_X86) || defined(__x86_64__)) /* Fall back. */ static inline uint32_t be32_to_cpu(uint32_t v) diff --git a/third_party/libsrtp/src/crypto/include/err.h b/third_party/libsrtp/src/crypto/include/err.h --- a/third_party/libsrtp/src/crypto/include/err.h +++ b/third_party/libsrtp/src/crypto/include/err.h @@ -47,10 +47,21 @@ #include #include #include "srtp.h" +#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute)) +#if __has_attribute(format) +#define LIBSRTP_FORMAT_PRINTF(fmt, args) \ + __attribute__((format(__printf__, fmt, args))) +#else +#define LIBSRTP_FORMAT_PRINTF(fmt, args) +#endif +#else +#define LIBSRTP_FORMAT_PRINTF(fmt, args) +#endif + #ifdef __cplusplus extern "C" { #endif /** @@ -94,11 +105,12 @@ * Errors will be reported to stdout, if ERR_REPORTING_STDOUT * is defined. * */ -void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...); +void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...) + LIBSRTP_FORMAT_PRINTF(2, 3); /* * debug_module_t defines a debug module */ diff --git a/third_party/libsrtp/src/crypto/kernel/crypto_kernel.c b/third_party/libsrtp/src/crypto/kernel/crypto_kernel.c --- a/third_party/libsrtp/src/crypto/kernel/crypto_kernel.c +++ b/third_party/libsrtp/src/crypto/kernel/crypto_kernel.c @@ -58,20 +58,20 @@ "crypto kernel" /* printable name for module */ }; /* crypto_kernel is a global variable, the only one of its datatype */ -srtp_crypto_kernel_t crypto_kernel = { +static srtp_crypto_kernel_t crypto_kernel = { srtp_crypto_kernel_state_insecure, /* start off in insecure state */ NULL, /* no cipher types yet */ NULL, /* no auth types yet */ NULL /* no debug modules yet */ }; #define MAX_RNG_TRIALS 25 -srtp_err_status_t srtp_crypto_kernel_init() +srtp_err_status_t srtp_crypto_kernel_init(void) { srtp_err_status_t status; /* check the security state */ if (crypto_kernel.state == srtp_crypto_kernel_state_secure) { @@ -166,11 +166,11 @@ crypto_kernel.state = srtp_crypto_kernel_state_secure; return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_status() +srtp_err_status_t srtp_crypto_kernel_status(void) { srtp_err_status_t status; srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list; @@ -207,11 +207,11 @@ srtp_crypto_kernel_list_debug_modules(); return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_list_debug_modules() +srtp_err_status_t srtp_crypto_kernel_list_debug_modules(void) { srtp_kernel_debug_module_t *dm = crypto_kernel.debug_module_list; /* describe each debug module */ srtp_err_report(srtp_err_level_info, "debug modules loaded:\n"); @@ -226,11 +226,11 @@ } return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_shutdown() +srtp_err_status_t srtp_crypto_kernel_shutdown(void) { /* * free dynamic memory used in crypto_kernel at present */ diff --git a/third_party/libsrtp/src/crypto/kernel/err.c b/third_party/libsrtp/src/crypto/kernel/err.c --- a/third_party/libsrtp/src/crypto/kernel/err.c +++ b/third_party/libsrtp/src/crypto/kernel/err.c @@ -52,11 +52,11 @@ /* srtp_err_file is the FILE to which errors are reported */ static FILE *srtp_err_file = NULL; -srtp_err_status_t srtp_err_reporting_init() +srtp_err_status_t srtp_err_reporting_init(void) { #ifdef ERR_REPORTING_STDOUT srtp_err_file = stdout; #elif defined(ERR_REPORTING_FILE) /* open file for error reporting */ diff --git a/third_party/libsrtp/src/crypto/math/datatypes.c b/third_party/libsrtp/src/crypto/math/datatypes.c --- a/third_party/libsrtp/src/crypto/math/datatypes.c +++ b/third_party/libsrtp/src/crypto/math/datatypes.c @@ -60,14 +60,14 @@ /* the value MAX_PRINT_STRING_LEN is defined in datatypes.h */ /* include space for null terminator */ static char bit_string[MAX_PRINT_STRING_LEN + 1]; -uint8_t srtp_nibble_to_hex_char(uint8_t nibble) +static uint8_t srtp_nibble_to_hex_char(uint8_t nibble) { - char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + static const char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; return buf[nibble & 0xF]; } char *srtp_octet_string_hex_string(const void *s, int length) { @@ -277,11 +277,11 @@ *p++ = 0; } void octet_string_set_to_zero(void *s, size_t len) { -#if defined(OPENSSL) && !defined(OPENSSL_CLEANSE_BROKEN) +#if defined(OPENSSL) OPENSSL_cleanse(s, len); #else srtp_cleanse(s, len); #endif } diff --git a/third_party/libsrtp/src/crypto/replay/rdbx.c b/third_party/libsrtp/src/crypto/replay/rdbx.c --- a/third_party/libsrtp/src/crypto/replay/rdbx.c +++ b/third_party/libsrtp/src/crypto/replay/rdbx.c @@ -277,11 +277,11 @@ */ srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta) { if (delta > 0) { /* shift forward by delta */ - srtp_index_advance(&rdbx->index, delta); + srtp_index_advance(&rdbx->index, (srtp_sequence_number_t)delta); bitvector_left_shift(&rdbx->bitmask, delta); bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1); } else { /* delta is in window */ @@ -304,17 +304,17 @@ */ int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s) { -/* - * if the sequence number and rollover counter in the rdbx are - * non-zero, then use the srtp_index_guess(...) function, otherwise, just - * set the rollover counter to zero (since the srtp_index_guess(...) - * function might incorrectly guess that the rollover counter is - * 0xffffffff) - */ + /* + * if the sequence number and rollover counter in the rdbx are + * non-zero, then use the srtp_index_guess(...) function, otherwise, just + * set the rollover counter to zero (since the srtp_index_guess(...) + * function might incorrectly guess that the rollover counter is + * 0xffffffff) + */ #ifdef NO_64BIT_MATH /* seq_num_median = 0x8000 */ if (high32(rdbx->index) > 0 || low32(rdbx->index) > seq_num_median) #else diff --git a/third_party/libsrtp/src/crypto/test/.cvsignore b/third_party/libsrtp/src/crypto/test/.cvsignore deleted file mode 100644 --- a/third_party/libsrtp/src/crypto/test/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -aes_calc -cipher_driver -datatypes_driver -env -kernel_driver -rand_gen -sha1_driver -stat_driver diff --git a/third_party/libsrtp/src/crypto/test/aes_calc.c b/third_party/libsrtp/src/crypto/test/aes_calc.c --- a/third_party/libsrtp/src/crypto/test/aes_calc.c +++ b/third_party/libsrtp/src/crypto/test/aes_calc.c @@ -104,37 +104,41 @@ } } /* read in key, checking length */ if (strlen(argv[1]) > AES_MAX_KEY_LEN * 2) { - fprintf(stderr, "error: too many digits in key " - "(should be at most %d hexadecimal digits, found %u)\n", + fprintf(stderr, + "error: too many digits in key " + "(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_MAX_KEY_LEN * 2); /* check that hex string is the right length */ if (len != 32 && len != 48 && len != 64) { - fprintf(stderr, "error: bad number of digits in key " - "(should be 32/48/64 hexadecimal digits, found %d)\n", + fprintf(stderr, + "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) { - fprintf(stderr, "error: too many digits in plaintext " - "(should be %d hexadecimal digits, found %u)\n", + fprintf(stderr, + "error: too many digits in plaintext " + "(should be %d hexadecimal digits, found %u)\n", 16 * 2, (unsigned)strlen(argv[2])); exit(1); } len = hex_string_to_octet_string((char *)(&data), argv[2], 16 * 2); /* check that hex string is the right length */ if (len < 16 * 2) { - fprintf(stderr, "error: too few digits in plaintext " - "(should be %d hexadecimal digits, found %d)\n", + fprintf(stderr, + "error: too few digits in plaintext " + "(should be %d hexadecimal digits, found %d)\n", 16 * 2, len); exit(1); } if (verbose) { @@ -160,12 +164,13 @@ ciphertext = v128_hex_string(&data); printf("%s\n", ciphertext); if (expected_ciphertext && strcmp(ciphertext, expected_ciphertext) != 0) { - fprintf(stderr, "error: calculated ciphertext %s does not match " - "expected ciphertext %s\n", + fprintf(stderr, + "error: calculated ciphertext %s does not match " + "expected ciphertext %s\n", ciphertext, expected_ciphertext); exit(1); } return 0; diff --git a/third_party/libsrtp/src/crypto/test/cipher_driver.c b/third_party/libsrtp/src/crypto/test/cipher_driver.c --- a/third_party/libsrtp/src/crypto/test/cipher_driver.c +++ b/third_party/libsrtp/src/crypto/test/cipher_driver.c @@ -387,11 +387,11 @@ /* choose a short length */ len = srtp_cipher_rand_u32_for_tests() & 0x01f; /* make sure that len doesn't cause us to overreach the buffer */ if (current + len > end) - len = end - current; + len = (unsigned)(end - current); status = srtp_cipher_encrypt(c, current, &len); if (status) return status; diff --git a/third_party/libsrtp/src/crypto/test/datatypes_driver.c b/third_party/libsrtp/src/crypto/test/datatypes_driver.c --- a/third_party/libsrtp/src/crypto/test/datatypes_driver.c +++ b/third_party/libsrtp/src/crypto/test/datatypes_driver.c @@ -137,32 +137,32 @@ /* byte_order() prints out byte ordering of datatypes */ void byte_order(void) { - int i; + size_t i; v128_t e; printf("byte ordering of crypto/math datatypes:\n"); for (i = 0; i < sizeof(e); i++) - e.v8[i] = i; + e.v8[i] = (uint8_t)i; printf("v128_t: %s\n", v128_hex_string(&e)); } void test_hex_string_funcs(void) { char hex1[] = "abadcafe"; char hex2[] = "0123456789abcdefqqqqq"; char raw[10]; int len; - len = hex_string_to_octet_string(raw, hex1, strlen(hex1)); + len = hex_string_to_octet_string(raw, hex1, (int)strlen(hex1)); printf("computed length: %d\tstring: %s\n", len, octet_string_hex_string(raw, len / 2)); printf("expected length: %u\tstring: %s\n", (unsigned)strlen(hex1), hex1); - len = hex_string_to_octet_string(raw, hex2, strlen(hex2)); + len = hex_string_to_octet_string(raw, hex2, (int)strlen(hex2)); printf("computed length: %d\tstring: %s\n", len, octet_string_hex_string(raw, len / 2)); printf("expected length: %d\tstring: %s\n", 16, "0123456789abcdef"); } diff --git a/third_party/libsrtp/src/crypto/test/sha1_driver.c b/third_party/libsrtp/src/crypto/test/sha1_driver.c --- a/third_party/libsrtp/src/crypto/test/sha1_driver.c +++ b/third_party/libsrtp/src/crypto/test/sha1_driver.c @@ -141,11 +141,11 @@ } struct hex_sha1_test_case_t { unsigned bit_len; char hex_data[MAX_HASH_DATA_LEN * 2]; - char hex_hash[40]; + char hex_hash[40 + 1]; }; srtp_err_status_t sha1_add_test_cases(void) { int i; @@ -216,104 +216,135 @@ "041c512b5eed791f80d3282f3a28df263bb1df95e1239a7650e5670fc2187919", "e88cdcd233d99184a6fd260b8fca1b7f7687aee0" }, { 264, "17e81f6ae8c2e5579d69dafa6e070e7111461552d314b691e7a3e7a4feb3fae418", "010def22850deb1168d525e8c84c28116cb8a269" }, - { 272, "d15976b23a1d712ad28fad04d805f572026b54dd64961fda94d5355a0cc9862" - "0cf77", + { 272, + "d15976b23a1d712ad28fad04d805f572026b54dd64961fda94d5355a0cc9862" + "0cf77", "aeaa40ba1717ed5439b1e6ea901b294ba500f9ad" }, - { 280, "09fce4d434f6bd32a44e04b848ff50ec9f642a8a85b37a264dc73f130f22838" - "443328f", + { 280, + "09fce4d434f6bd32a44e04b848ff50ec9f642a8a85b37a264dc73f130f22838" + "443328f", "c6433791238795e34f080a5f1f1723f065463ca0" }, - { 288, "f17af27d776ec82a257d8d46d2b46b639462c56984cc1be9c1222eadb8b2659" - "4a25c709d", + { 288, + "f17af27d776ec82a257d8d46d2b46b639462c56984cc1be9c1222eadb8b2659" + "4a25c709d", "e21e22b89c1bb944a32932e6b2a2f20d491982c3" }, - { 296, "b13ce635d6f8758143ffb114f2f601cb20b6276951416a2f94fbf4ad081779d" - "79f4f195b22", + { 296, + "b13ce635d6f8758143ffb114f2f601cb20b6276951416a2f94fbf4ad081779d" + "79f4f195b22", "575323a9661f5d28387964d2ba6ab92c17d05a8a" }, - { 304, "5498793f60916ff1c918dde572cdea76da8629ba4ead6d065de3dfb48de94d2" - "34cc1c5002910", + { 304, + "5498793f60916ff1c918dde572cdea76da8629ba4ead6d065de3dfb48de94d2" + "34cc1c5002910", "feb44494af72f245bfe68e86c4d7986d57c11db7" }, - { 312, "498a1e0b39fa49582ae688cd715c86fbaf8a81b8b11b4d1594c49c902d197c8" - "ba8a621fd6e3be5", + { 312, + "498a1e0b39fa49582ae688cd715c86fbaf8a81b8b11b4d1594c49c902d197c8" + "ba8a621fd6e3be5", "cff2290b3648ba2831b98dde436a72f9ebf51eee" }, - { 320, "3a36ae71521f9af628b3e34dcb0d4513f84c78ee49f10416a98857150b8b15c" - "b5c83afb4b570376e", + { 320, + "3a36ae71521f9af628b3e34dcb0d4513f84c78ee49f10416a98857150b8b15c" + "b5c83afb4b570376e", "9b4efe9d27b965905b0c3dab67b8d7c9ebacd56c" }, - { 328, "dcc76b40ae0ea3ba253e92ac50fcde791662c5b6c948538cffc2d95e9de99ca" - "c34dfca38910db2678f", + { 328, + "dcc76b40ae0ea3ba253e92ac50fcde791662c5b6c948538cffc2d95e9de99ca" + "c34dfca38910db2678f", "afedb0ff156205bcd831cbdbda43db8b0588c113" }, - { 336, "5b5ec6ec4fd3ad9c4906f65c747fd4233c11a1736b6b228b92e90cddabb0c7c" - "2fcf9716d3fad261dff33", + { 336, + "5b5ec6ec4fd3ad9c4906f65c747fd4233c11a1736b6b228b92e90cddabb0c7c" + "2fcf9716d3fad261dff33", "8deb1e858f88293a5e5e4d521a34b2a4efa70fc4" }, - { 344, "df48a37b29b1d6de4e94717d60cdb4293fcf170bba388bddf7a9035a15d433f" - "20fd697c3e4c8b8c5f590ab", + { 344, + "df48a37b29b1d6de4e94717d60cdb4293fcf170bba388bddf7a9035a15d433f" + "20fd697c3e4c8b8c5f590ab", "95cbdac0f74afa69cebd0e5c7defbc6faf0cbeaf" }, - { 352, "1f179b3b82250a65e1b0aee949e218e2f45c7a8dbfd6ba08de05c55acfc226b" - "48c68d7f7057e5675cd96fcfc", + { 352, + "1f179b3b82250a65e1b0aee949e218e2f45c7a8dbfd6ba08de05c55acfc226b" + "48c68d7f7057e5675cd96fcfc", "f0307bcb92842e5ae0cd4f4f14f3df7f877fbef2" }, - { 360, "ee3d72da3a44d971578972a8e6780ce64941267e0f7d0179b214fa97855e179" - "0e888e09fbe3a70412176cb3b54", + { 360, + "ee3d72da3a44d971578972a8e6780ce64941267e0f7d0179b214fa97855e179" + "0e888e09fbe3a70412176cb3b54", "7b13bb0dbf14964bd63b133ac85e22100542ef55" }, - { 368, "d4d4c7843d312b30f610b3682254c8be96d5f6684503f8fbfbcd15774fc1b08" - "4d3741afb8d24aaa8ab9c104f7258", + { 368, + "d4d4c7843d312b30f610b3682254c8be96d5f6684503f8fbfbcd15774fc1b08" + "4d3741afb8d24aaa8ab9c104f7258", "c314d2b6cf439be678d2a74e890d96cfac1c02ed" }, - { 376, "32c094944f5936a190a0877fb9178a7bf60ceae36fd530671c5b38c5dbd5e6a" - "6c0d615c2ac8ad04b213cc589541cf6", + { 376, + "32c094944f5936a190a0877fb9178a7bf60ceae36fd530671c5b38c5dbd5e6a" + "6c0d615c2ac8ad04b213cc589541cf6", "4d0be361e410b47a9d67d8ce0bb6a8e01c53c078" }, - { 384, "e5d3180c14bf27a5409fa12b104a8fd7e9639609bfde6ee82bbf9648be2546d" - "29688a65e2e3f3da47a45ac14343c9c02", + { 384, + "e5d3180c14bf27a5409fa12b104a8fd7e9639609bfde6ee82bbf9648be2546d" + "29688a65e2e3f3da47a45ac14343c9c02", "e5353431ffae097f675cbf498869f6fbb6e1c9f2" }, - { 392, "e7b6e4b69f724327e41e1188a37f4fe38b1dba19cbf5a7311d6e32f1038e97a" - "b506ee05aebebc1eed09fc0e357109818b9", + { 392, + "e7b6e4b69f724327e41e1188a37f4fe38b1dba19cbf5a7311d6e32f1038e97a" + "b506ee05aebebc1eed09fc0e357109818b9", "b8720a7068a085c018ab18961de2765aa6cd9ac4" }, - { 400, "bc880cb83b8ac68ef2fedc2da95e7677ce2aa18b0e2d8b322701f67af7d5e7a" - "0d96e9e33326ccb7747cfff0852b961bfd475", + { 400, + "bc880cb83b8ac68ef2fedc2da95e7677ce2aa18b0e2d8b322701f67af7d5e7a" + "0d96e9e33326ccb7747cfff0852b961bfd475", "b0732181568543ba85f2b6da602b4b065d9931aa" }, - { 408, "235ea9c2ba7af25400f2e98a47a291b0bccdaad63faa2475721fda5510cc7da" - "d814bce8dabb611790a6abe56030b798b75c944", + { 408, + "235ea9c2ba7af25400f2e98a47a291b0bccdaad63faa2475721fda5510cc7da" + "d814bce8dabb611790a6abe56030b798b75c944", "9c22674cf3222c3ba921672694aafee4ce67b96b" }, - { 416, "07e3e29fed63104b8410f323b975fd9fba53f636af8c4e68a53fb202ca35dd9" - "ee07cb169ec5186292e44c27e5696a967f5e67709", + { 416, + "07e3e29fed63104b8410f323b975fd9fba53f636af8c4e68a53fb202ca35dd9" + "ee07cb169ec5186292e44c27e5696a967f5e67709", "d128335f4cecca9066cdae08958ce656ff0b4cfc" }, - { 424, "65d2a1dd60a517eb27bfbf530cf6a5458f9d5f4730058bd9814379547f34241" - "822bf67e6335a6d8b5ed06abf8841884c636a25733f", + { 424, + "65d2a1dd60a517eb27bfbf530cf6a5458f9d5f4730058bd9814379547f34241" + "822bf67e6335a6d8b5ed06abf8841884c636a25733f", "0b67c57ac578de88a2ae055caeaec8bb9b0085a0" }, - { 432, "dcc86b3bd461615bab739d8daafac231c0f462e819ad29f9f14058f3ab5b759" - "41d4241ea2f17ebb8a458831b37a9b16dead4a76a9b0e", + { 432, + "dcc86b3bd461615bab739d8daafac231c0f462e819ad29f9f14058f3ab5b759" + "41d4241ea2f17ebb8a458831b37a9b16dead4a76a9b0e", "c766f912a89d4ccda88e0cce6a713ef5f178b596" }, - { 440, "4627d54f0568dc126b62a8c35fb46a9ac5024400f2995e51635636e1afc4373" - "dbb848eb32df23914230560b82477e9c3572647a7f2bb92", + { 440, + "4627d54f0568dc126b62a8c35fb46a9ac5024400f2995e51635636e1afc4373" + "dbb848eb32df23914230560b82477e9c3572647a7f2bb92", "9aa3925a9dcb177b15ccff9b78e70cf344858779" }, - { 448, "ba531affd4381168ef24d8b275a84d9254c7f5cc55fded53aa8024b2c5c5c8a" - "a7146fe1d1b83d62b70467e9a2e2cb67b3361830adbab28d7", + { 448, + "ba531affd4381168ef24d8b275a84d9254c7f5cc55fded53aa8024b2c5c5c8a" + "a7146fe1d1b83d62b70467e9a2e2cb67b3361830adbab28d7", "4811fa30042fc076acf37c8e2274d025307e5943" }, - { 456, "8764dcbcf89dcf4282eb644e3d568bdccb4b13508bfa7bfe0ffc05efd1390be" - "22109969262992d377691eb4f77f3d59ea8466a74abf57b2ef4", + { 456, + "8764dcbcf89dcf4282eb644e3d568bdccb4b13508bfa7bfe0ffc05efd1390be" + "22109969262992d377691eb4f77f3d59ea8466a74abf57b2ef4", "6743018450c9730761ee2b130df9b91c1e118150" }, - { 464, "497d9df9ddb554f3d17870b1a31986c1be277bc44feff713544217a9f579623" - "d18b5ffae306c25a45521d2759a72c0459b58957255ab592f3be4", + { 464, + "497d9df9ddb554f3d17870b1a31986c1be277bc44feff713544217a9f579623" + "d18b5ffae306c25a45521d2759a72c0459b58957255ab592f3be4", "71ad4a19d37d92a5e6ef3694ddbeb5aa61ada645" }, - { 472, "72c3c2e065aefa8d9f7a65229e818176eef05da83f835107ba90ec2e95472e7" - "3e538f783b416c04654ba8909f26a12db6e5c4e376b7615e4a25819", + { 472, + "72c3c2e065aefa8d9f7a65229e818176eef05da83f835107ba90ec2e95472e7" + "3e538f783b416c04654ba8909f26a12db6e5c4e376b7615e4a25819", "a7d9dc68dacefb7d6116186048cb355cc548e11d" }, - { 480, "7cc9894454d0055ab5069a33984e2f712bef7e3124960d33559f5f3b81906bb" - "66fe64da13c153ca7f5cabc89667314c32c01036d12ecaf5f9a78de98", + { 480, + "7cc9894454d0055ab5069a33984e2f712bef7e3124960d33559f5f3b81906bb" + "66fe64da13c153ca7f5cabc89667314c32c01036d12ecaf5f9a78de98", "142e429f0522ba5abf5131fa81df82d355b96909" }, - { 488, "74e8404d5a453c5f4d306f2cfa338ca65501c840ddab3fb82117933483afd69" - "13c56aaf8a0a0a6b2a342fc3d9dc7599f4a850dfa15d06c61966d74ea59", + { 488, + "74e8404d5a453c5f4d306f2cfa338ca65501c840ddab3fb82117933483afd69" + "13c56aaf8a0a0a6b2a342fc3d9dc7599f4a850dfa15d06c61966d74ea59", "ef72db70dcbcab991e9637976c6faf00d22caae9" }, - { 496, "46fe5ed326c8fe376fcc92dc9e2714e2240d3253b105adfbb256ff7a19bc409" - "75c604ad7c0071c4fd78a7cb64786e1bece548fa4833c04065fe593f6fb10", + { 496, + "46fe5ed326c8fe376fcc92dc9e2714e2240d3253b105adfbb256ff7a19bc409" + "75c604ad7c0071c4fd78a7cb64786e1bece548fa4833c04065fe593f6fb10", "f220a7457f4588d639dc21407c942e9843f8e26b" }, - { 504, "836dfa2524d621cf07c3d2908835de859e549d35030433c796b81272fd8bc03" - "48e8ddbc7705a5ad1fdf2155b6bc48884ac0cd376925f069a37849c089c864" - "5", + { 504, + "836dfa2524d621cf07c3d2908835de859e549d35030433c796b81272fd8bc03" + "48e8ddbc7705a5ad1fdf2155b6bc48884ac0cd376925f069a37849c089c864" + "5", "ddd2117b6e309c233ede85f962a0c2fc215e5c69" }, - { 512, "7e3a4c325cb9c52b88387f93d01ae86d42098f5efa7f9457388b5e74b6d28b2" - "438d42d8b64703324d4aa25ab6aad153ae30cd2b2af4d5e5c00a8a2d0220c61" - "16", + { 512, + "7e3a4c325cb9c52b88387f93d01ae86d42098f5efa7f9457388b5e74b6d28b2" + "438d42d8b64703324d4aa25ab6aad153ae30cd2b2af4d5e5c00a8a2d0220c61" + "16", "a3054427cdb13f164a610b348702724c808a0dcc" } }; for (i = 0; i < 65; i++) { err = hash_test_case_add(&sha1_test_case_list, tc[i].hex_data, diff --git a/third_party/libsrtp/src/include/config.h b/third_party/libsrtp/src/include/config.h deleted file mode 100644 --- a/third_party/libsrtp/src/include/config.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -/* empty file; config done via Makefile.in & configure.in */ diff --git a/third_party/libsrtp/src/include/srtp2/meson.build b/third_party/libsrtp/src/include/srtp2/meson.build --- a/third_party/libsrtp/src/include/srtp2/meson.build +++ b/third_party/libsrtp/src/include/srtp2/meson.build @@ -3,6 +3,5 @@ foreach h : public_headers configure_file(input: h, output: '@BASENAME@.h', copy: true) endforeach -public_incs = include_directories('.') diff --git a/third_party/libsrtp/src/include/srtp_priv.h b/third_party/libsrtp/src/include/srtp_priv.h --- a/third_party/libsrtp/src/include/srtp_priv.h +++ b/third_party/libsrtp/src/include/srtp_priv.h @@ -64,10 +64,11 @@ #define SRTP_VER_STRING PACKAGE_STRING #define SRTP_VERSION PACKAGE_VERSION typedef struct srtp_stream_ctx_t_ srtp_stream_ctx_t; typedef srtp_stream_ctx_t *srtp_stream_t; +typedef struct srtp_stream_list_ctx_t_ *srtp_stream_list_t; /* * the following declarations are libSRTP internal functions */ @@ -95,16 +96,10 @@ unsigned char *key, srtp_master_key_t **keys, const unsigned int max_master_keys); /* - * srtp_stream_init(s, p) initializes the srtp_stream_t s to - * use the policy at the location p - */ -srtp_err_status_t srtp_stream_init(srtp_stream_t srtp, const srtp_policy_t *p); - -/* * libsrtp internal datatypes */ typedef enum direction_t { dir_unknown = 0, dir_srtp_sender = 1, @@ -147,18 +142,25 @@ direction_t direction; int allow_repeat_tx; int *enc_xtn_hdr; int enc_xtn_hdr_count; uint32_t pending_roc; - struct srtp_stream_ctx_t_ *next; /* linked list of streams */ + /* + The next and prev pointers are here to allow for a stream list to be + implemented as an intrusive doubly-linked list (the former being the + default). Other stream list implementations can ignore these fields or use + them for some other purpose specific to the stream list implementation. + */ + struct srtp_stream_ctx_t_ *next; + struct srtp_stream_ctx_t_ *prev; } strp_stream_ctx_t_; /* * an srtp_ctx_t holds a stream list and a service description */ typedef struct srtp_ctx_t_ { - struct srtp_stream_ctx_t_ *stream_list; /* linked list of streams */ + srtp_stream_list_t stream_list; /* linked list of streams */ struct srtp_stream_ctx_t_ *stream_template; /* act as template for other */ /* streams */ void *user_data; /* user custom data */ } srtp_ctx_t_; diff --git a/third_party/libsrtp/src/include/stream_list_priv.h b/third_party/libsrtp/src/include/stream_list_priv.h new file mode 100644 --- /dev/null +++ b/third_party/libsrtp/src/include/stream_list_priv.h @@ -0,0 +1,122 @@ +/* + * stream_list_priv.h + * + * list of SRTP streams, keyed by SSRC + * + * Alba Mendez + */ +/* + * + * Copyright (c) 2001-2017, Cisco Systems, Inc. + * Copyright (c) 2022, Dolby Laboratories, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_STREAM_LIST_PRIV_H +#define SRTP_STREAM_LIST_PRIV_H + +#include "srtp_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * srtp_stream_list_t holds a list of srtp_stream_t, each identified + * by their SSRC. + * + * the API was extracted to allow downstreams to override its + * implementation by defining the `SRTP_NO_STREAM_LIST` preprocessor + * directive, which removes the default implementation of these + * functions. if this is done, the `next` & `prev` fields are free for + * the implementation to use. + * + * this is still an internal interface; there is no stability + * guarantee--downstreams should watch this file for changes in + * signatures or semantics. + */ + +/** + * allocate and initialize a stream list instance + */ +srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr); + +/** + * deallocate a stream list instance + * + * the list must be empty or else an error is returned. + */ +srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list); + +/** + * insert a stream into the list + * + * returns srtp_err_status_alloc_fail if insertion failed due to unavailable + * capacity in the list. if operation succeeds, srtp_err_status_ok is returned + * + * if another stream with the same SSRC already exists in the list, + * behavior is undefined. if the SSRC field is mutated while the + * stream is inserted, further operations have undefined behavior + */ +srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list, + srtp_stream_t stream); + +/* + * look up the stream corresponding to the specified SSRC and return it. + * if no such SSRC is found, NULL is returned. + */ +srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc); + +/** + * remove the stream from the list. + * + * The stream to be removed is referenced "by value", i.e., by the pointer to be + * removed from the list. This pointer is obtained using `srtp_stream_list_get` + * or as callback parameter in `srtp_stream_list_for_each`. + */ +void srtp_stream_list_remove(srtp_stream_list_t list, srtp_stream_t stream); + +/** + * iterate through all stored streams. while iterating, it is allowed to delete + * the current element; any other mutation to the list is undefined behavior. + * returning non-zero from callback aborts the iteration. + */ +void srtp_stream_list_for_each(srtp_stream_list_t list, + int (*callback)(srtp_stream_t, void *), + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* SRTP_STREAM_LIST_PRIV_H */ diff --git a/third_party/libsrtp/src/srtp/srtp.c b/third_party/libsrtp/src/srtp/srtp.c --- a/third_party/libsrtp/src/srtp/srtp.c +++ b/third_party/libsrtp/src/srtp/srtp.c @@ -44,10 +44,11 @@ // Leave this as the top level import. Ensures the existence of defines #include "config.h" #include "srtp_priv.h" +#include "stream_list_priv.h" #include "crypto_types.h" #include "err.h" #include "alloc.h" /* for srtp_crypto_alloc() */ #ifdef GCM @@ -107,19 +108,19 @@ return srtp_err_status_bad_param; } return srtp_err_status_ok; } -const char *srtp_get_version_string() +const char *srtp_get_version_string(void) { /* * Simply return the autotools generated string */ return SRTP_VER_STRING; } -unsigned int srtp_get_version() +unsigned int srtp_get_version(void) { unsigned int major = 0, minor = 0, micro = 0; unsigned int rv = 0; int parse_rv; @@ -146,12 +147,13 @@ rv |= (minor & 0xFF) << 16; rv |= micro & 0xFF; return rv; } -srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream, - const srtp_stream_ctx_t *stream_template) +static srtp_err_status_t srtp_stream_dealloc( + srtp_stream_ctx_t *stream, + const srtp_stream_ctx_t *stream_template) { srtp_err_status_t status; unsigned int i = 0; srtp_session_keys_t *session_keys = NULL; srtp_session_keys_t *template_session_keys = NULL; @@ -171,12 +173,12 @@ } else { template_session_keys = NULL; } /* - * deallocate cipher, if it is not the same as that in template - */ + * deallocate cipher, if it is not the same as that in template + */ if (template_session_keys && session_keys->rtp_cipher == template_session_keys->rtp_cipher) { /* do nothing */ } else if (session_keys->rtp_cipher) { status = srtp_cipher_dealloc(session_keys->rtp_cipher); @@ -276,21 +278,62 @@ srtp_crypto_free(stream); return srtp_err_status_ok; } +/* try to insert stream in list or deallocate it */ +static srtp_err_status_t srtp_insert_or_dealloc_stream(srtp_stream_list_t list, + srtp_stream_t stream, + srtp_stream_t template) +{ + srtp_err_status_t status = srtp_stream_list_insert(list, stream); + /* on failure, ownership wasn't transferred and we need to deallocate */ + if (status) { + srtp_stream_dealloc(stream, template); + } + return status; +} + +struct remove_and_dealloc_streams_data { + srtp_err_status_t status; + srtp_stream_list_t list; + srtp_stream_t template; +}; + +static int remove_and_dealloc_streams_cb(srtp_stream_t stream, void *data) +{ + struct remove_and_dealloc_streams_data *d = + (struct remove_and_dealloc_streams_data *)data; + srtp_stream_list_remove(d->list, stream); + d->status = srtp_stream_dealloc(stream, d->template); + if (d->status) { + return 1; + } + return 0; +} + +static srtp_err_status_t srtp_remove_and_dealloc_streams( + srtp_stream_list_t list, + srtp_stream_t template) +{ + struct remove_and_dealloc_streams_data data = { srtp_err_status_ok, list, + template }; + srtp_stream_list_for_each(list, remove_and_dealloc_streams_cb, &data); + return data.status; +} + static srtp_err_status_t srtp_valid_policy(const srtp_policy_t *p) { if (p != NULL && p->deprecated_ekt != NULL) { return srtp_err_status_bad_param; } return srtp_err_status_ok; } -srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, - const srtp_policy_t *p) +static srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, + const srtp_policy_t *p) { srtp_stream_ctx_t *str; srtp_err_status_t stat; unsigned int i = 0; srtp_session_keys_t *session_keys = NULL; @@ -450,13 +493,14 @@ * * the only unique data in a cloned stream is the replay database and * the SSRC */ -srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, - uint32_t ssrc, - srtp_stream_ctx_t **str_ptr) +static srtp_err_status_t srtp_stream_clone( + const srtp_stream_ctx_t *stream_template, + uint32_t ssrc, + srtp_stream_ctx_t **str_ptr) { srtp_err_status_t status; srtp_stream_ctx_t *str; unsigned int i = 0; srtp_session_keys_t *session_keys = NULL; @@ -549,10 +593,11 @@ str->enc_xtn_hdr = stream_template->enc_xtn_hdr; str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count; /* defensive coding */ str->next = NULL; + str->prev = NULL; return srtp_err_status_ok; } /* * key derivation functions, internal to libSRTP @@ -792,11 +837,12 @@ default: return 0; } } -unsigned int srtp_validate_policy_master_keys(const srtp_policy_t *policy) +static unsigned int srtp_validate_policy_master_keys( + const srtp_policy_t *policy) { unsigned long i = 0; if (policy->key == NULL) { if (policy->num_master_keys <= 0) @@ -896,11 +942,11 @@ unsigned char *key = master_key->key; /* 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. - */ + */ session_keys = &srtp->session_keys[current_mki_index]; /* initialize key limit to maximum value */ #ifdef NO_64BIT_MATH { @@ -935,10 +981,20 @@ rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher); rtp_base_key_len = base_key_length(session_keys->rtp_cipher->type, rtp_keylen); rtp_salt_len = rtp_keylen - rtp_base_key_len; + /* + * We assume that the `key` buffer provided by the caller has a length + * equal to the greater of `rtp_keylen` and `rtcp_keylen`. Since we are + * about to read `input_keylen` bytes from it, we need to check that we will + * not overrun. + */ + if ((rtp_keylen < input_keylen) && (rtcp_keylen < input_keylen)) { + return srtp_err_status_bad_param; + } + if (rtp_keylen > kdf_keylen) { kdf_keylen = 46; /* AES-CTR mode is always used for KDF */ } if (rtcp_keylen > kdf_keylen) { @@ -1242,12 +1298,12 @@ return srtp_err_status_init_fail; return srtp_err_status_ok; } -srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp, - const srtp_policy_t *p) +static srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp, + const srtp_policy_t *p) { srtp_err_status_t err; err = srtp_valid_policy(p); if (err != srtp_err_status_ok) { @@ -1321,12 +1377,12 @@ * reports the events that are reported by the callbacks */ void srtp_event_reporter(srtp_event_data_t *data) { - srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ", - data->ssrc); + srtp_err_report(srtp_err_level_warning, + "srtp: in stream 0x%x: ", data->ssrc); switch (data->event) { case event_ssrc_collision: srtp_err_report(srtp_err_level_warning, "\tSSRC collision\n"); break; @@ -1768,17 +1824,27 @@ /* * estimate the packet index using the start of the replay window * and the sequence number from the header */ - delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq)); - status = srtp_rdbx_check(&stream->rtp_rdbx, delta); - if (status) { - if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) { - return status; /* we've been asked to reuse an index */ + status = srtp_get_est_pkt_index(hdr, stream, &est, &delta); + + if (status && (status != srtp_err_status_pkt_idx_adv)) + return status; + + if (status == srtp_err_status_pkt_idx_adv) { + srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16), + (uint16_t)(est & 0xFFFF)); + stream->pending_roc = 0; + srtp_rdbx_add_index(&stream->rtp_rdbx, 0); + } else { + status = srtp_rdbx_check(&stream->rtp_rdbx, delta); + if (status) { + if (status != srtp_err_status_replay_fail || + !stream->allow_repeat_tx) + return status; /* we've been asked to reuse an index */ } - } else { srtp_rdbx_add_index(&stream->rtp_rdbx, delta); } #ifdef NO_64BIT_MATH debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), @@ -1823,11 +1889,11 @@ } /* * Set the AAD over the RTP header */ - aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; + aad_len = (uint32_t)((uint8_t *)enc_start - (uint8_t *)hdr); status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len); if (status) { return (srtp_err_status_cipher_fail); } @@ -1873,11 +1939,12 @@ int delta, srtp_xtd_seq_num_t est, void *srtp_hdr, unsigned int *pkt_octet_len, srtp_session_keys_t *session_keys, - unsigned int mki_size) + unsigned int mki_size, + int advance_packet_index) { srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ v128_t iv; @@ -1968,11 +2035,11 @@ } /* * Set the AAD for AES-GCM, which is the RTP header */ - aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; + aad_len = (uint32_t)((uint8_t *)enc_start - (uint8_t *)hdr); status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len); if (status) { return (srtp_err_status_cipher_fail); } @@ -2032,23 +2099,34 @@ srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status; } - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set stream (the pointer used in this function) */ stream = new_stream; } /* * the message authentication function passed, so add the packet * index into the replay database */ - srtp_rdbx_add_index(&stream->rtp_rdbx, delta); + if (advance_packet_index) { + uint32_t roc_to_set = (uint32_t)(est >> 16); + uint16_t seq_to_set = (uint16_t)(est & 0xFFFF); + srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, roc_to_set, seq_to_set); + stream->pending_roc = 0; + srtp_rdbx_add_index(&stream->rtp_rdbx, 0); + } else { + srtp_rdbx_add_index(&stream->rtp_rdbx, delta); + } /* decrease the packet length by the length of the auth tag */ *pkt_octet_len -= tag_len; /* decrease the packet length by the length of the mki_size */ @@ -2083,11 +2161,10 @@ uint32_t prefix_len; srtp_hdr_xtnd_t *xtn_hdr = NULL; unsigned int mki_size = 0; srtp_session_keys_t *session_keys = NULL; uint8_t *mki_location = NULL; - int advance_packet_index = 0; debug_print0(mod_srtp, "function srtp_protect"); /* we assume the hdr is 32-bit aligned to start */ @@ -2116,13 +2193,16 @@ status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status; - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set direction to outbound */ new_stream->direction = dir_srtp_sender; /* set stream (the pointer used in this function) */ @@ -2234,14 +2314,11 @@ status = srtp_get_est_pkt_index(hdr, stream, &est, &delta); if (status && (status != srtp_err_status_pkt_idx_adv)) return status; - if (status == srtp_err_status_pkt_idx_adv) - advance_packet_index = 1; - - if (advance_packet_index) { + if (status == srtp_err_status_pkt_idx_adv) { srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16), (uint16_t)(est & 0xFFFF)); stream->pending_roc = 0; srtp_rdbx_add_index(&stream->rtp_rdbx, 0); } else { @@ -2507,11 +2584,11 @@ */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, (unsigned int *)pkt_octet_len, session_keys, - mki_size); + mki_size, advance_packet_index); } /* get tag length from stream */ tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); @@ -2715,16 +2792,20 @@ * stream, and some implementations will want to not return * failure here */ status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); - if (status) + if (status) { return status; - - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + } + + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set stream (the pointer used in this function) */ stream = new_stream; } @@ -2747,11 +2828,11 @@ *pkt_octet_len -= mki_size; return srtp_err_status_ok; } -srtp_err_status_t srtp_init() +srtp_err_status_t srtp_init(void) { srtp_err_status_t status; /* initialize crypto kernel */ status = srtp_crypto_kernel_init(); @@ -2764,11 +2845,11 @@ return status; return srtp_err_status_ok; } -srtp_err_status_t srtp_shutdown() +srtp_err_status_t srtp_shutdown(void) { srtp_err_status_t status; /* shut down crypto kernel */ status = srtp_crypto_kernel_shutdown(); @@ -2778,59 +2859,44 @@ /* shutting down crypto kernel frees the srtp debug module as well */ return srtp_err_status_ok; } -/* - * srtp_get_stream(ssrc) returns a pointer to the stream corresponding - * to ssrc, or NULL if no stream exists for that ssrc - * - * this is an internal function - */ - srtp_stream_ctx_t *srtp_get_stream(srtp_t srtp, uint32_t ssrc) { - srtp_stream_ctx_t *stream; - - /* walk down list until ssrc is found */ - stream = srtp->stream_list; - while (stream != NULL) { - if (stream->ssrc == ssrc) - return stream; - stream = stream->next; - } - - /* we haven't found our ssrc, so return a null */ - return NULL; + return srtp_stream_list_get(srtp->stream_list, ssrc); } srtp_err_status_t srtp_dealloc(srtp_t session) { - srtp_stream_ctx_t *stream; srtp_err_status_t status; /* * we take a conservative deallocation strategy - if we encounter an * error deallocating a stream, then we stop trying to deallocate * memory and just return an error */ - /* walk list of streams, deallocating as we go */ - stream = session->stream_list; - while (stream != NULL) { - srtp_stream_t next = stream->next; - status = srtp_stream_dealloc(stream, session->stream_template); - if (status) - return status; - stream = next; + /* deallocate streams */ + status = srtp_remove_and_dealloc_streams(session->stream_list, + session->stream_template); + if (status) { + return status; } /* deallocate stream template, if there is one */ if (session->stream_template != NULL) { status = srtp_stream_dealloc(session->stream_template, NULL); - if (status) + if (status) { return status; + } + } + + /* deallocate stream list */ + status = srtp_stream_list_dealloc(session->stream_list); + if (status) { + return status; } /* deallocate session context */ srtp_crypto_free(session); @@ -2889,12 +2955,15 @@ } session->stream_template = tmp; session->stream_template->direction = dir_srtp_receiver; break; case (ssrc_specific): - tmp->next = session->stream_list; - session->stream_list = tmp; + status = srtp_insert_or_dealloc_stream(session->stream_list, tmp, + session->stream_template); + if (status) { + return status; + } break; case (ssrc_undefined): default: srtp_stream_dealloc(tmp, NULL); return srtp_err_status_bad_param; @@ -2922,17 +2991,27 @@ ctx = (srtp_ctx_t *)srtp_crypto_alloc(sizeof(srtp_ctx_t)); if (ctx == NULL) return srtp_err_status_alloc_fail; *session = ctx; + ctx->stream_template = NULL; + ctx->stream_list = NULL; + ctx->user_data = NULL; + + /* allocate stream list */ + stat = srtp_stream_list_alloc(&ctx->stream_list); + if (stat) { + /* clean up everything */ + srtp_dealloc(*session); + *session = NULL; + return stat; + } + /* * loop over elements in the policy list, allocating and * initializing a stream for each element */ - ctx->stream_template = NULL; - ctx->stream_list = NULL; - ctx->user_data = NULL; while (policy != NULL) { stat = srtp_add_stream(ctx, policy); if (stat) { /* clean up everything */ srtp_dealloc(*session); @@ -2947,32 +3026,24 @@ return srtp_err_status_ok; } srtp_err_status_t srtp_remove_stream(srtp_t session, uint32_t ssrc) { - srtp_stream_ctx_t *stream, *last_stream; + srtp_stream_ctx_t *stream; srtp_err_status_t status; /* sanity check arguments */ if (session == NULL) return srtp_err_status_bad_param; - /* find stream in list; complain if not found */ - last_stream = stream = session->stream_list; - while ((stream != NULL) && (ssrc != stream->ssrc)) { - last_stream = stream; - stream = stream->next; - } - if (stream == NULL) + /* find and remove stream from the list */ + stream = srtp_stream_list_get(session->stream_list, ssrc); + if (stream == NULL) { return srtp_err_status_no_ctx; - - /* remove stream from the list */ - if (last_stream == stream) - /* stream was first in list */ - session->stream_list = stream->next; - else - last_stream->next = stream->next; + } + + srtp_stream_list_remove(session->stream_list, stream); /* deallocate the stream */ status = srtp_stream_dealloc(stream, session->stream_template); if (status) return status; @@ -3005,16 +3076,74 @@ policy = policy->next; } return srtp_err_status_ok; } +struct update_template_stream_data { + srtp_err_status_t status; + srtp_t session; + srtp_stream_t new_stream_template; + srtp_stream_list_t new_stream_list; +}; + +static int update_template_stream_cb(srtp_stream_t stream, void *raw_data) +{ + struct update_template_stream_data *data = + (struct update_template_stream_data *)raw_data; + srtp_t session = data->session; + uint32_t ssrc = stream->ssrc; + srtp_xtd_seq_num_t old_index; + srtp_rdb_t old_rtcp_rdb; + + /* old / non-template streams are copied unchanged */ + if (stream->session_keys[0].rtp_auth != + session->stream_template->session_keys[0].rtp_auth) { + srtp_stream_list_remove(session->stream_list, stream); + data->status = srtp_insert_or_dealloc_stream( + data->new_stream_list, stream, session->stream_template); + if (data->status) { + return 1; + } + return 0; + } + + /* save old extendard seq */ + old_index = stream->rtp_rdbx.index; + old_rtcp_rdb = stream->rtcp_rdb; + + /* remove stream */ + data->status = srtp_remove_stream(session, ssrc); + if (data->status) { + return 1; + } + + /* allocate and initialize a new stream */ + data->status = srtp_stream_clone(data->new_stream_template, ssrc, &stream); + if (data->status) { + return 1; + } + + /* add new stream to the head of the new_stream_list */ + data->status = srtp_insert_or_dealloc_stream(data->new_stream_list, stream, + data->new_stream_template); + if (data->status) { + return 1; + } + + /* restore old extended seq */ + stream->rtp_rdbx.index = old_index; + stream->rtcp_rdb = old_rtcp_rdb; + + return 0; +} + static srtp_err_status_t update_template_streams(srtp_t session, const srtp_policy_t *policy) { srtp_err_status_t status; srtp_stream_t new_stream_template; - srtp_stream_t new_stream_list = NULL; + srtp_stream_list_t new_stream_list; status = srtp_valid_policy(policy); if (status != srtp_err_status_ok) { return status; } @@ -3034,81 +3163,41 @@ if (status) { srtp_crypto_free(new_stream_template); return status; } - /* for all old templated streams */ - for (;;) { - srtp_stream_t stream; - uint32_t ssrc; - srtp_xtd_seq_num_t old_index; - srtp_rdb_t old_rtcp_rdb; - - stream = session->stream_list; - while ((stream != NULL) && - (stream->session_keys[0].rtp_auth != - session->stream_template->session_keys[0].rtp_auth)) { - stream = stream->next; - } - if (stream == NULL) { - /* no more templated streams */ - break; - } - - /* save old extendard seq */ - ssrc = stream->ssrc; - old_index = stream->rtp_rdbx.index; - old_rtcp_rdb = stream->rtcp_rdb; - - /* remove stream */ - status = srtp_remove_stream(session, ssrc); - if (status) { - /* free new allocations */ - while (new_stream_list != NULL) { - srtp_stream_t next = new_stream_list->next; - srtp_stream_dealloc(new_stream_list, new_stream_template); - new_stream_list = next; - } - srtp_stream_dealloc(new_stream_template, NULL); - return status; - } - - /* allocate and initialize a new stream */ - status = srtp_stream_clone(new_stream_template, ssrc, &stream); - if (status) { - /* free new allocations */ - while (new_stream_list != NULL) { - srtp_stream_t next = new_stream_list->next; - srtp_stream_dealloc(new_stream_list, new_stream_template); - new_stream_list = next; - } - srtp_stream_dealloc(new_stream_template, NULL); - return status; - } - - /* add new stream to the head of the new_stream_list */ - stream->next = new_stream_list; - new_stream_list = stream; - - /* restore old extended seq */ - stream->rtp_rdbx.index = old_index; - stream->rtcp_rdb = old_rtcp_rdb; + /* allocate new stream list */ + status = srtp_stream_list_alloc(&new_stream_list); + if (status) { + srtp_crypto_free(new_stream_template); + return status; } - /* dealloc old template */ + + /* process streams */ + struct update_template_stream_data data = { srtp_err_status_ok, session, + new_stream_template, + new_stream_list }; + srtp_stream_list_for_each(session->stream_list, update_template_stream_cb, + &data); + if (data.status) { + /* free new allocations */ + srtp_remove_and_dealloc_streams(new_stream_list, new_stream_template); + srtp_stream_list_dealloc(new_stream_list); + srtp_stream_dealloc(new_stream_template, NULL); + return data.status; + } + + /* dealloc old list / template */ + srtp_remove_and_dealloc_streams(session->stream_list, + session->stream_template); + srtp_stream_list_dealloc(session->stream_list); srtp_stream_dealloc(session->stream_template, NULL); - /* set new template */ + + /* set new list / template */ session->stream_template = new_stream_template; - /* add new list */ - if (new_stream_list) { - srtp_stream_t tail = new_stream_list; - while (tail->next) { - tail = tail->next; - } - tail->next = session->stream_list; - session->stream_list = new_stream_list; - } - return status; + session->stream_list = new_stream_list; + return srtp_err_status_ok; } static srtp_err_status_t update_stream(srtp_t session, const srtp_policy_t *policy) { @@ -3260,11 +3349,12 @@ /* * corresponds to RFC 4568 */ p->cipher_type = SRTP_NULL_CIPHER; - p->cipher_key_len = 16; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ p->auth_type = SRTP_HMAC_SHA1; p->auth_key_len = 20; p->auth_tag_len = 10; p->sec_serv = sec_serv_auth; } @@ -3274,11 +3364,12 @@ /* * Should only be used for testing */ p->cipher_type = SRTP_NULL_CIPHER; - p->cipher_key_len = 16; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ p->auth_type = SRTP_NULL_AUTH; p->auth_key_len = 0; p->auth_tag_len = 0; p->sec_serv = sec_serv_none; } @@ -3523,11 +3614,10 @@ /* * This code handles AEAD ciphers for outgoing RTCP. We currently support * AES-GCM mode with 128 or 256 bit keys. */ static srtp_err_status_t srtp_protect_rtcp_aead( - srtp_t ctx, srtp_stream_ctx_t *stream, void *rtcp_hdr, unsigned int *pkt_octet_len, srtp_session_keys_t *session_keys, unsigned int use_mki) @@ -3871,13 +3961,16 @@ srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status; } - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set stream (the pointer used in this function) */ stream = new_stream; } @@ -3937,13 +4030,16 @@ status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status; - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set stream (the pointer used in this function) */ stream = new_stream; } else { /* no template stream, so we return an error */ @@ -3975,11 +4071,11 @@ * Check if this is an AEAD stream (GCM mode). If so, then dispatch * the request to our AEAD handler. */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { - return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, + return srtp_protect_rtcp_aead(stream, rtcp_hdr, (unsigned int *)pkt_octet_len, session_keys, use_mki); } /* get tag length from stream context */ @@ -4384,13 +4480,16 @@ status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status; - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; + /* add new stream to the list */ + status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream, + ctx->stream_template); + if (status) { + return status; + } /* set stream (the pointer used in this function) */ stream = new_stream; } @@ -4567,49 +4666,66 @@ } return srtp_err_status_ok; } +struct get_protect_trailer_length_data { + uint32_t found_stream; /* whether at least one matching stream was found */ + uint32_t length; /* maximum trailer length found so far */ + uint32_t is_rtp; + uint32_t use_mki; + uint32_t mki_index; +}; + +static int get_protect_trailer_length_cb(srtp_stream_t stream, void *raw_data) +{ + struct get_protect_trailer_length_data *data = + (struct get_protect_trailer_length_data *)raw_data; + uint32_t temp_length; + + if (stream_get_protect_trailer_length(stream, data->is_rtp, data->use_mki, + data->mki_index, + &temp_length) == srtp_err_status_ok) { + data->found_stream = 1; + if (temp_length > data->length) { + data->length = temp_length; + } + } + + return 0; +} + srtp_err_status_t get_protect_trailer_length(srtp_t session, uint32_t is_rtp, uint32_t use_mki, uint32_t mki_index, uint32_t *length) { srtp_stream_ctx_t *stream; + struct get_protect_trailer_length_data data = { 0, 0, is_rtp, use_mki, + mki_index }; if (session == NULL) { return srtp_err_status_bad_param; } - if (session->stream_template == NULL && session->stream_list == NULL) { - return srtp_err_status_bad_param; - } - - *length = 0; - stream = session->stream_template; if (stream != NULL) { + data.found_stream = 1; stream_get_protect_trailer_length(stream, is_rtp, use_mki, mki_index, - length); + &data.length); } - stream = session->stream_list; - - while (stream != NULL) { - uint32_t temp_length; - if (stream_get_protect_trailer_length(stream, is_rtp, use_mki, - mki_index, &temp_length) == - srtp_err_status_ok) { - if (temp_length > *length) { - *length = temp_length; - } - } - stream = stream->next; + srtp_stream_list_for_each(session->stream_list, + get_protect_trailer_length_cb, &data); + + if (!data.found_stream) { + return srtp_err_status_bad_param; } + *length = data.length; return srtp_err_status_ok; } srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, uint32_t use_mki, @@ -4647,11 +4763,11 @@ */ static srtp_log_handler_func_t *srtp_log_handler = NULL; static void *srtp_log_handler_data = NULL; -void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg) +static void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg) { if (srtp_log_handler) { srtp_log_level_t log_level = srtp_log_level_error; switch (level) { case srtp_err_level_error: @@ -4719,5 +4835,94 @@ *roc = srtp_rdbx_get_roc(&stream->rtp_rdbx); return srtp_err_status_ok; } + +#ifndef SRTP_NO_STREAM_LIST + +/* in the default implementation, we have an intrusive doubly-linked list */ +struct srtp_stream_list_ctx_t_ { + /* a stub stream that just holds pointers to the beginning and end of the + * list */ + srtp_stream_ctx_t data; +} srtp_stream_list_ctx_t_; + +srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr) +{ + srtp_stream_list_t list = + srtp_crypto_alloc(sizeof(srtp_stream_list_ctx_t_)); + if (list == NULL) { + return srtp_err_status_alloc_fail; + } + + list->data.next = NULL; + list->data.prev = NULL; + + *list_ptr = list; + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list) +{ + /* list must be empty */ + if (list->data.next) { + return srtp_err_status_fail; + } + srtp_crypto_free(list); + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list, + srtp_stream_t stream) +{ + /* insert at the head of the list */ + stream->next = list->data.next; + if (stream->next != NULL) { + stream->next->prev = stream; + } + list->data.next = stream; + stream->prev = &(list->data); + + return srtp_err_status_ok; +} + +srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc) +{ + /* walk down list until ssrc is found */ + srtp_stream_t stream = list->data.next; + while (stream != NULL) { + if (stream->ssrc == ssrc) { + return stream; + } + stream = stream->next; + } + + /* we haven't found our ssrc, so return a null */ + return NULL; +} + +void srtp_stream_list_remove(srtp_stream_list_t list, + srtp_stream_t stream_to_remove) +{ + (void)list; + + stream_to_remove->prev->next = stream_to_remove->next; + if (stream_to_remove->next != NULL) { + stream_to_remove->next->prev = stream_to_remove->prev; + } +} + +void srtp_stream_list_for_each(srtp_stream_list_t list, + int (*callback)(srtp_stream_t, void *), + void *data) +{ + srtp_stream_t stream = list->data.next; + while (stream != NULL) { + srtp_stream_t tmp = stream; + stream = stream->next; + if (callback(tmp, data)) + break; + } +} + +#endif diff --git a/third_party/libsrtp/src/test/.cvsignore b/third_party/libsrtp/src/test/.cvsignore deleted file mode 100644 --- a/third_party/libsrtp/src/test/.cvsignore +++ /dev/null @@ -1,13 +0,0 @@ -aes_calc -cipher_driver -datatypes_driver -dtls_srtp_driver -kernel_driver -rand_gen -rdbx_driver -replay_driver -roc_driver -rtpw -sha1_driver -srtp_driver -stat_driver diff --git a/third_party/libsrtp/src/test/cutest.h b/third_party/libsrtp/src/test/cutest.h --- a/third_party/libsrtp/src/test/cutest.h +++ b/third_party/libsrtp/src/test/cutest.h @@ -257,20 +257,19 @@ test_current_failures__++; test_current_already_logged__++; } if (test_verbose_level__ >= verbose_level) { - size_t n = 0; va_list args; printf(" "); if (file != NULL) - n += printf("%s:%d: Check ", file, line); + printf("%s:%d: Check ", file, line); va_start(args, fmt); - n += vprintf(fmt, args); + vprintf(fmt, args); va_end(args); printf("... "); test_print_in_color__(result_color, result_str); printf("\n"); @@ -466,11 +465,12 @@ break; case SIGTERM: signame = "SIGTERM"; break; default: - sprintf(tmp, "signal %d", WTERMSIG(exit_code)); + snprintf(tmp, sizeof(tmp), "signal %d", + WTERMSIG(exit_code)); signame = tmp; break; } test_error__("Test interrupted by %s", signame); } else { diff --git a/third_party/libsrtp/src/test/rdbx_driver.c b/third_party/libsrtp/src/test/rdbx_driver.c --- a/third_party/libsrtp/src/test/rdbx_driver.c +++ b/third_party/libsrtp/src/test/rdbx_driver.c @@ -141,11 +141,11 @@ srtp_err_status_t rdbx_check_add(srtp_rdbx_t *rdbx, uint32_t idx) { int delta; srtp_xtd_seq_num_t est; - delta = srtp_index_guess(&rdbx->index, &est, idx); + delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx); if (srtp_rdbx_check(rdbx, delta) != srtp_err_status_ok) { printf("replay_check failed at index %u\n", idx); return srtp_err_status_algo_fail; } @@ -174,11 +174,11 @@ { int delta; srtp_xtd_seq_num_t est; srtp_err_status_t status; - delta = srtp_index_guess(&rdbx->index, &est, idx); + delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx); status = srtp_rdbx_check(rdbx, delta); if (status == srtp_err_status_ok) { printf("delta: %d ", delta); printf("replay_check failed at index %u (false positive)\n", idx); @@ -192,11 +192,11 @@ { int delta; srtp_xtd_seq_num_t est; srtp_err_status_t rstat; - delta = srtp_index_guess(&rdbx->index, &est, idx); + delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx); rstat = srtp_rdbx_check(rdbx, delta); if ((rstat != srtp_err_status_ok) && (rstat != srtp_err_status_replay_old)) { printf("replay_check_add_unordered failed at index %u\n", idx); @@ -331,11 +331,11 @@ } failures = 0; timer = clock(); for (i = 0; (int)i < num_trials; i++) { - delta = srtp_index_guess(&rdbx.index, &est, i); + delta = srtp_index_guess(&rdbx.index, &est, (srtp_sequence_number_t)i); if (srtp_rdbx_check(&rdbx, delta) != srtp_err_status_ok) ++failures; else if (srtp_rdbx_add_index(&rdbx, delta) != srtp_err_status_ok) ++failures; diff --git a/third_party/libsrtp/src/test/replay_driver.c b/third_party/libsrtp/src/test/replay_driver.c --- a/third_party/libsrtp/src/test/replay_driver.c +++ b/third_party/libsrtp/src/test/replay_driver.c @@ -130,11 +130,11 @@ } return srtp_err_status_ok; } -srtp_err_status_t test_rdb_db() +srtp_err_status_t test_rdb_db(void) { srtp_rdb_t rdb; uint32_t idx, ircvd; ut_connection utc; srtp_err_status_t err; @@ -249,31 +249,24 @@ double rdb_check_adds_per_second(void) { uint32_t i; srtp_rdb_t rdb; clock_t timer; - int failures = 0; /* count number of failures */ if (srtp_rdb_init(&rdb) != srtp_err_status_ok) { printf("rdb_init failed\n"); exit(1); } timer = clock(); for (i = 0; i < REPLAY_NUM_TRIALS; i += 3) { - if (srtp_rdb_check(&rdb, i + 2) != srtp_err_status_ok) - ++failures; - if (srtp_rdb_add_index(&rdb, i + 2) != srtp_err_status_ok) - ++failures; - if (srtp_rdb_check(&rdb, i + 1) != srtp_err_status_ok) - ++failures; - if (srtp_rdb_add_index(&rdb, i + 1) != srtp_err_status_ok) - ++failures; - if (srtp_rdb_check(&rdb, i) != srtp_err_status_ok) - ++failures; - if (srtp_rdb_add_index(&rdb, i) != srtp_err_status_ok) - ++failures; + srtp_rdb_check(&rdb, i + 2); + srtp_rdb_add_index(&rdb, i + 2); + srtp_rdb_check(&rdb, i + 1); + srtp_rdb_add_index(&rdb, i + 1); + srtp_rdb_check(&rdb, i); + srtp_rdb_add_index(&rdb, i); } timer = clock() - timer; return (double)CLOCKS_PER_SEC * REPLAY_NUM_TRIALS / timer; } diff --git a/third_party/libsrtp/src/test/roc_driver.c b/third_party/libsrtp/src/test/roc_driver.c --- a/third_party/libsrtp/src/test/roc_driver.c +++ b/third_party/libsrtp/src/test/roc_driver.c @@ -143,11 +143,11 @@ return srtp_err_status_algo_fail; } /* now update local srtp_xtd_seq_num_t as necessary */ if (delta > 0) - srtp_index_advance(&local, delta); + srtp_index_advance(&local, (srtp_sequence_number_t)delta); if (ref != est) { #if ROC_VERBOSE printf(" *bad estimate*\n"); #endif diff --git a/third_party/libsrtp/src/test/rtp.h b/third_party/libsrtp/src/test/rtp.h --- a/third_party/libsrtp/src/test/rtp.h +++ b/third_party/libsrtp/src/test/rtp.h @@ -121,18 +121,18 @@ int srtp_sender_init( rtp_sender_t rtp_ctx, /* structure to be init'ed */ struct sockaddr_in name, /* socket name */ srtp_sec_serv_t security_services, /* sec. servs. to be used */ unsigned char *input_key /* master key/salt in hex */ - ); +); int srtp_receiver_init( rtp_receiver_t rtp_ctx, /* structure to be init'ed */ struct sockaddr_in name, /* socket name */ srtp_sec_serv_t security_services, /* sec. servs. to be used */ unsigned char *input_key /* master key/salt in hex */ - ); +); int rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy); int rtp_sender_deinit_srtp(rtp_sender_t sender); diff --git a/third_party/libsrtp/src/test/rtp.c b/third_party/libsrtp/src/test/rtp.c --- a/third_party/libsrtp/src/test/rtp.c +++ b/third_party/libsrtp/src/test/rtp.c @@ -129,14 +129,13 @@ stat = srtp_unprotect(receiver->srtp_ctx, &receiver->message.header, &octets_recvd); if (stat) { fprintf(stderr, "error: srtp unprotection failed with code %d%s\n", stat, - stat == srtp_err_status_replay_fail - ? " (replay check failed)" - : stat == srtp_err_status_auth_fail ? " (auth check failed)" - : ""); + stat == srtp_err_status_replay_fail ? " (replay check failed)" + : stat == srtp_err_status_auth_fail ? " (auth check failed)" + : ""); return -1; } strncpy(msg, receiver->message.body, octets_recvd); return octets_recvd; diff --git a/third_party/libsrtp/src/test/rtp_decoder.h b/third_party/libsrtp/src/test/rtp_decoder.h --- a/third_party/libsrtp/src/test/rtp_decoder.h +++ b/third_party/libsrtp/src/test/rtp_decoder.h @@ -60,11 +60,11 @@ typedef struct rtp_decoder_ctx_t { srtp_policy_t policy; srtp_ctx_t *srtp_ctx; rtp_decoder_mode_t mode; - int rtp_offset; + size_t rtp_offset; struct timeval start_tv; int frame_nr; int error_cnt; int rtp_cnt; int rtcp_cnt; @@ -100,11 +100,12 @@ void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx); int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy, rtp_decoder_mode_t mode, - int rtp_packet_offset); + size_t rtp_packet_offset, + uint32_t roc); int rtp_decoder_deinit(rtp_decoder_t decoder); void rtp_decoder_srtp_log_handler(srtp_log_level_t level, const char *msg, diff --git a/third_party/libsrtp/src/test/rtp_decoder.c b/third_party/libsrtp/src/test/rtp_decoder.c --- a/third_party/libsrtp/src/test/rtp_decoder.c +++ b/third_party/libsrtp/src/test/rtp_decoder.c @@ -94,49 +94,50 @@ static struct srtp_crypto_suite srtp_crypto_suites[] = { #if 0 {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4}, #endif - {.can_name = "AES_CM_128_HMAC_SHA1_32", - .gcm_on = 0, - .key_size = 128, - .tag_size = 4 }, - {.can_name = "AES_CM_128_HMAC_SHA1_80", - .gcm_on = 0, - .key_size = 128, - .tag_size = 10 }, - {.can_name = "AES_192_CM_HMAC_SHA1_32", - .gcm_on = 0, - .key_size = 192, - .tag_size = 4 }, - {.can_name = "AES_192_CM_HMAC_SHA1_80", - .gcm_on = 0, - .key_size = 192, - .tag_size = 10 }, - {.can_name = "AES_256_CM_HMAC_SHA1_32", - .gcm_on = 0, - .key_size = 256, - .tag_size = 4 }, - {.can_name = "AES_256_CM_HMAC_SHA1_80", - .gcm_on = 0, - .key_size = 256, - .tag_size = 10 }, - {.can_name = "AEAD_AES_128_GCM", - .gcm_on = 1, - .key_size = 128, - .tag_size = 16 }, - {.can_name = "AEAD_AES_256_GCM", - .gcm_on = 1, - .key_size = 256, - .tag_size = 16 }, - {.can_name = NULL } + { .can_name = "AES_CM_128_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 128, + .tag_size = 4 }, + { .can_name = "AES_CM_128_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 128, + .tag_size = 10 }, + { .can_name = "AES_192_CM_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 192, + .tag_size = 4 }, + { .can_name = "AES_192_CM_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 192, + .tag_size = 10 }, + { .can_name = "AES_256_CM_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 256, + .tag_size = 4 }, + { .can_name = "AES_256_CM_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 256, + .tag_size = 10 }, + { .can_name = "AEAD_AES_128_GCM", + .gcm_on = 1, + .key_size = 128, + .tag_size = 16 }, + { .can_name = "AEAD_AES_256_GCM", + .gcm_on = 1, + .key_size = 256, + .tag_size = 16 }, + { .can_name = NULL } }; void rtp_decoder_srtp_log_handler(srtp_log_level_t level, const char *msg, void *data) { + (void)data; char level_char = '?'; switch (level) { case srtp_log_level_error: level_char = 'e'; break; @@ -171,14 +172,16 @@ int b64_input = 0; char key[MAX_KEY_LEN]; struct bpf_program fp; char filter_exp[MAX_FILTER] = ""; char pcap_file[MAX_FILE] = "-"; - int rtp_packet_offset = DEFAULT_RTP_OFFSET; + size_t rtp_packet_offset = DEFAULT_RTP_OFFSET; rtp_decoder_t dec; - srtp_policy_t policy = { { 0 } }; + srtp_policy_t policy = { 0 }; rtp_decoder_mode_t mode = mode_rtp; + srtp_ssrc_t ssrc = { ssrc_any_inbound, 0 }; + uint32_t roc = 0; srtp_err_status_t status; int len; int expected_len; int do_list_mods = 0; @@ -200,11 +203,11 @@ exit(1); } /* check args */ while (1) { - c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:m:p:o:"); + c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:c:m:p:o:s:r:"); if (c == -1) { break; } switch (c) { case 'b': @@ -254,11 +257,11 @@ strcpy(filter_exp, optarg_s); break; case 'l': do_list_mods = 1; break; - case 's': + case 'c': for (i_scsp = &srtp_crypto_suites[0]; i_scsp->can_name != NULL; i_scsp++) { if (strcasecmp(i_scsp->can_name, optarg_s) == 0) { break; } @@ -295,10 +298,17 @@ strcpy(pcap_file, optarg_s); break; case 'o': rtp_packet_offset = atoi(optarg_s); break; + case 's': + ssrc.type = ssrc_specific; + ssrc.value = strtol(optarg_s, NULL, 0); + break; + case 'r': + roc = atoi(optarg_s); + break; default: usage(argv[0]); } } @@ -538,18 +548,20 @@ expected_len = policy.rtp.cipher_key_len * 2; len = hex_string_to_octet_string(key, input_key, expected_len); } /* check that hex string is the right length */ if (len < expected_len) { - fprintf(stderr, "error: too few digits in key/salt " - "(should be %d digits, found %d)\n", + fprintf(stderr, + "error: too few digits in key/salt " + "(should be %d digits, found %d)\n", expected_len, len); exit(1); } - if (strlen(input_key) > policy.rtp.cipher_key_len * 2) { - fprintf(stderr, "error: too many digits in key/salt " - "(should be %d hexadecimal digits, found %u)\n", + if (strlen(input_key) > (size_t)policy.rtp.cipher_key_len * 2) { + fprintf(stderr, + "error: too many digits in key/salt " + "(should be %d hexadecimal digits, found %u)\n", policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key)); exit(1); } int key_octets = (scs.key_size / 8); @@ -563,10 +575,17 @@ fprintf(stderr, "error: neither encryption or authentication were selected\n"); exit(1); } + policy.ssrc = ssrc; + + if (roc != 0 && policy.ssrc.type != ssrc_specific) { + fprintf(stderr, "error: setting ROC (-r) requires -s \n"); + exit(1); + } + pcap_handle = pcap_open_offline(pcap_file, errbuf); if (!pcap_handle) { fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); exit(1); @@ -586,11 +605,11 @@ if (dec == NULL) { fprintf(stderr, "error: malloc() failed\n"); exit(1); } fprintf(stderr, "Starting decoder\n"); - if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset)) { + if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset, roc)) { fprintf(stderr, "error: init failed\n"); exit(1); } pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); @@ -618,27 +637,31 @@ void usage(char *string) { fprintf( stderr, - "usage: %s [-d ]* [[-k][-b] ] [-a][-t][-e] [-s " - "] [-m ]\n" + "usage: %s [-d ]* [[-k][-b] ] [-a][-t][-e] [-c " + "] [-m ] [-s [-r ]]\n" "or %s -l\n" "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 given in hexadecimal\n" " -b sets the srtp master key given in base64\n" " -l list debug modules\n" " -f \"\" to filter only the desired SRTP packets\n" " -d turn on debugging for module \n" - " -s \"\" to set both key and tag size based\n" + " -c \"\" to set both key and tag size based\n" " on RFC4568-style crypto suite specification\n" " -m set the mode to be one of [rtp]|rtcp|rtcp-mux\n" " -p path to pcap file (defaults to stdin)\n" - " -o byte offset of RTP packet in capture (defaults to 42)\n", + " -o byte offset of RTP packet in capture (defaults to 42)\n" + " -s restrict decrypting to the given SSRC (in host byte " + "order)\n" + " -r initial rollover counter, requires -s " + "(defaults to 0)\n", string, string); exit(1); } rtp_decoder_t rtp_decoder_alloc(void) @@ -660,11 +683,12 @@ } int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy, rtp_decoder_mode_t mode, - int rtp_packet_offset) + size_t rtp_packet_offset, + uint32_t roc) { dcdr->rtp_offset = rtp_packet_offset; dcdr->srtp_ctx = NULL; dcdr->start_tv.tv_usec = 0; dcdr->start_tv.tv_sec = 0; @@ -672,29 +696,34 @@ dcdr->error_cnt = 0; dcdr->rtp_cnt = 0; dcdr->rtcp_cnt = 0; dcdr->mode = mode; dcdr->policy = policy; - dcdr->policy.ssrc.type = ssrc_any_inbound; if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) { return 1; } + + if (policy.ssrc.type == ssrc_specific && roc != 0) { + if (srtp_set_stream_roc(dcdr->srtp_ctx, policy.ssrc.value, roc)) { + return 1; + } + } return 0; } /* * decodes key as base64 */ void hexdump(const void *ptr, size_t size) { - int i, j; + size_t i, j; const unsigned char *cptr = ptr; for (i = 0; i < size; i += 16) { - fprintf(stdout, "%04x ", i); + fprintf(stdout, "%04x ", (unsigned int)i); for (j = 0; j < 16 && i + j < size; j++) { fprintf(stdout, "%02x ", cptr[i + j]); } fprintf(stdout, "\n"); } @@ -762,9 +791,9 @@ return; } dcdr->rtcp_cnt++; } timersub(&hdr->ts, &dcdr->start_tv, &delta); - fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60, - (long)delta.tv_usec); + fprintf(stdout, "%02ld:%02d.%06ld\n", (long)(delta.tv_sec / 60), + (int)(delta.tv_sec % 60), (long)delta.tv_usec); hexdump(&message, octets_recvd); } diff --git a/third_party/libsrtp/src/test/rtpw.c b/third_party/libsrtp/src/test/rtpw.c --- a/third_party/libsrtp/src/test/rtpw.c +++ b/third_party/libsrtp/src/test/rtpw.c @@ -283,11 +283,21 @@ /* get port from arg */ port = atoi(argv[optind_s++]); /* set address */ -#ifdef HAVE_INET_ATON +#ifdef HAVE_INET_PTON + if (0 == inet_pton(AF_INET, address, &rcvr_addr)) { + fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], + address); + exit(1); + } + if (rcvr_addr.s_addr == INADDR_NONE) { + fprintf(stderr, "%s: address error", argv[0]); + exit(1); + } +#elif HAVE_INET_ATON if (0 == inet_aton(address, &rcvr_addr)) { fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address); exit(1); } @@ -471,18 +481,20 @@ expected_len = policy.rtp.cipher_key_len * 2; len = hex_string_to_octet_string(key, input_key, expected_len); } /* check that hex string is the right length */ if (len < expected_len) { - fprintf(stderr, "error: too few digits in key/salt " - "(should be %d digits, found %d)\n", + fprintf(stderr, + "error: too few digits in key/salt " + "(should be %d digits, found %d)\n", expected_len, len); exit(1); } if ((int)strlen(input_key) > policy.rtp.cipher_key_len * 2) { - fprintf(stderr, "error: too many digits in key/salt " - "(should be %d hexadecimal digits, found %u)\n", + fprintf(stderr, + "error: too many digits in key/salt " + "(should be %d hexadecimal digits, found %u)\n", policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key)); exit(1); } printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); diff --git a/third_party/libsrtp/src/test/rtpw_test.sh b/third_party/libsrtp/src/test/rtpw_test.sh --- a/third_party/libsrtp/src/test/rtpw_test.sh +++ b/third_party/libsrtp/src/test/rtpw_test.sh @@ -64,17 +64,17 @@ key=Ky7cUDT2GnI0XKWYbXv9AYmqbcLsqzL9mvdN9t/G ARGS="-b $key -a -e 128" -# First, we run "killall" to get rid of all existing rtpw processes. +# First, we run "pkill" to get rid of all existing rtpw processes. # This step also enables this script to clean up after itself; if this # script is interrupted after the rtpw processes are started but before # they are killed, those processes will linger. Re-running the script # will get rid of them. -killall rtpw 2>/dev/null +pkill -x rtpw 2>/dev/null if test -n $MESON_EXE_WRAPPER || test -x $RTPW; then echo $0 ": starting rtpw receiver process... " diff --git a/third_party/libsrtp/src/test/rtpw_test_gcm.sh b/third_party/libsrtp/src/test/rtpw_test_gcm.sh --- a/third_party/libsrtp/src/test/rtpw_test_gcm.sh +++ b/third_party/libsrtp/src/test/rtpw_test_gcm.sh @@ -60,17 +60,17 @@ RTPW=./rtpw$EXE [ -n "$MESON_EXE_WRAPPER" ] && RTPW="$MESON_EXE_WRAPPER $RTPW" DEST_PORT=9999 DURATION=3 -# First, we run "killall" to get rid of all existing rtpw processes. +# First, we run "pkill" to get rid of all existing rtpw processes. # This step also enables this script to clean up after itself; if this # script is interrupted after the rtpw processes are started but before # they are killed, those processes will linger. Re-running the script # will get rid of them. -killall rtpw 2>/dev/null +pkill -x rtpw 2>/dev/null if test -n $MESON_EXE_WRAPPER || test -x $RTPW; then GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -e 128" echo $0 ": starting GCM mode 128-bit rtpw receiver process... " diff --git a/third_party/libsrtp/src/test/srtp_driver.c b/third_party/libsrtp/src/test/srtp_driver.c --- a/third_party/libsrtp/src/test/srtp_driver.c +++ b/third_party/libsrtp/src/test/srtp_driver.c @@ -47,10 +47,11 @@ #include /* for malloc(), free() */ #include /* for print(), fflush() */ #include "getopt_s.h" /* for local getopt() */ #include "srtp_priv.h" +#include "stream_list_priv.h" #include "util.h" #ifdef HAVE_NETINET_IN_H #include #elif defined HAVE_WINSOCK2_H @@ -91,10 +92,12 @@ srtp_err_status_t srtp_test_protect_trailer_length(void); srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void); +srtp_err_status_t srtp_test_out_of_order_after_rollover(void); + srtp_err_status_t srtp_test_get_roc(void); srtp_err_status_t srtp_test_set_receiver_roc(void); srtp_err_status_t srtp_test_set_sender_roc(void); @@ -120,16 +123,19 @@ char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len); double mips_estimate(int num_trials, int *ignore); +srtp_err_status_t srtp_stream_list_test(void); + #define TEST_MKI_ID_SIZE 4 extern uint8_t test_key[46]; extern uint8_t test_key_2[46]; extern uint8_t test_mki_id[TEST_MKI_ID_SIZE]; extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE]; +extern uint8_t test_key_gcm[28]; // clang-format off srtp_master_key_t master_key_1 = { test_key, test_mki_id, @@ -148,25 +154,28 @@ }; // clang-format on void usage(char *prog_name) { - printf("usage: %s [ -t ][ -c ][ -v ][ -o ][-d ]* [ -l ]\n" - " -t run timing test\n" - " -r run rejection timing test\n" - " -c run codec timing test\n" - " -v run validation tests\n" - " -o output logging to stdout\n" - " -d turn on debugging module \n" - " -l list debugging modules\n", - prog_name); + printf( + "usage: %s [ -t ][ -c ][ -v ][ -s ][ -o ][-d ]* [ -l ]\n" + " -t run timing test\n" + " -r run rejection timing test\n" + " -c run codec timing test\n" + " -v run validation tests\n" + " -s run stream list tests only\n" + " -o output logging to stdout\n" + " -d turn on debugging module \n" + " -l list debugging modules\n", + prog_name); exit(1); } void log_handler(srtp_log_level_t level, const char *msg, void *data) { char level_char = '?'; + (void)data; switch (level) { case srtp_log_level_error: level_char = 'e'; break; case srtp_log_level_warning: @@ -211,22 +220,24 @@ int q; unsigned do_timing_test = 0; unsigned do_rejection_test = 0; unsigned do_codec_timing = 0; unsigned do_validation = 0; + unsigned do_stream_list = 0; unsigned do_list_mods = 0; unsigned do_log_stdout = 0; srtp_err_status_t status; + const size_t hdr_size = 12; /* * verify that the compiler has interpreted the header data * structure srtp_hdr_t correctly */ - if (sizeof(srtp_hdr_t) != 12) { + if (sizeof(srtp_hdr_t) != hdr_size) { printf("error: srtp_hdr_t has incorrect size" - "(size is %ld bytes, expected 12)\n", - (long)sizeof(srtp_hdr_t)); + "(size is %ld bytes, expected %ld)\n", + (long)sizeof(srtp_hdr_t), (long)hdr_size); exit(1); } /* initialize srtp library */ status = srtp_init(); @@ -244,11 +255,11 @@ exit(1); } /* process input arguments */ while (1) { - q = getopt_s(argc, argv, "trcvold:"); + q = getopt_s(argc, argv, "trcvsold:"); if (q == -1) { break; } switch (q) { case 't': @@ -260,10 +271,14 @@ case 'c': do_codec_timing = 1; break; case 'v': do_validation = 1; + do_stream_list = 1; + break; + case 's': + do_stream_list = 1; break; case 'o': do_log_stdout = 1; break; case 'l': @@ -280,11 +295,11 @@ usage(argv[0]); } } if (!do_validation && !do_timing_test && !do_codec_timing && - !do_list_mods && !do_rejection_test) { + !do_list_mods && !do_rejection_test && !do_stream_list) { usage(argv[0]); } if (do_log_stdout) { status = srtp_install_log_handler(log_handler, NULL); @@ -557,10 +572,18 @@ } else { printf("failed\n"); exit(1); } + printf("testing srtp_test_out_of_order_after_rollover()..."); + if (srtp_test_out_of_order_after_rollover() == srtp_err_status_ok) { + printf("passed\n"); + } else { + printf("failed\n"); + exit(1); + } + printf("testing srtp_test_get_roc()..."); if (srtp_test_get_roc() == srtp_err_status_ok) { printf("passed\n"); } else { printf("failed\n"); @@ -582,10 +605,20 @@ printf("failed\n"); exit(1); } } + if (do_stream_list) { + printf("testing srtp_stream_list..."); + if (srtp_stream_list_test() == srtp_err_status_ok) { + printf("passed\n"); + } else { + printf("failed\n"); + exit(1); + } + } + if (do_timing_test) { const srtp_policy_t **policy = policy_array; /* loop over policies, run timing test for each */ while (*policy != NULL) { @@ -1106,12 +1139,13 @@ err_check(srtp_get_protect_trailer_length(srtp_sender, use_mki, mki_index, &tag_length)); pkt_end = (uint8_t *)hdr + msg_len + tag_length; for (i = 0; i < 4; i++) { if (pkt_end[i] != 0xff) { - fprintf(stdout, "overwrite in srtp_protect() function " - "(expected %x, found %x in trailing octet %d)\n", + fprintf(stdout, + "overwrite in srtp_protect() function " + "(expected %x, found %x in trailing octet %d)\n", 0xff, ((uint8_t *)hdr)[i], i); free(hdr); free(hdr2); return srtp_err_status_algo_fail; } @@ -1321,12 +1355,13 @@ srtp_get_protect_rtcp_trailer_length(srtcp_sender, use_mki, mki_index, &tag_length); pkt_end = (uint8_t *)hdr + msg_len + tag_length; for (i = 0; i < 4; i++) { if (pkt_end[i] != 0xff) { - fprintf(stdout, "overwrite in srtp_protect_rtcp() function " - "(expected %x, found %x in trailing octet %d)\n", + fprintf(stdout, + "overwrite in srtp_protect_rtcp() function " + "(expected %x, found %x in trailing octet %d)\n", 0xff, ((uint8_t *)hdr)[i], i); free(hdr); free(hdr2); return srtp_err_status_algo_fail; } @@ -1450,105 +1485,97 @@ free(hdr2); free(rcvr_policy); return srtp_err_status_ok; } +struct srtp_session_print_stream_data { + // set by callback to indicate failure + srtp_err_status_t status; + // indicates if it is the template stream or a regular stream + int is_template; +}; + +int srtp_session_print_stream(srtp_stream_t stream, void *raw_data) +{ + static const char *serv_descr[4] = { "none", "confidentiality", + "authentication", + "confidentiality and authentication" }; + static const char *direction[3] = { "unknown", "outbound", "inbound" }; + + struct srtp_session_print_stream_data *data = + (struct srtp_session_print_stream_data *)raw_data; + srtp_session_keys_t *session_keys = &stream->session_keys[0]; + char ssrc_text[32]; + + if (!data->is_template && stream->rtp_services > sec_serv_conf_and_auth) { + data->status = srtp_err_status_bad_param; + return 1; + } + + if (data->is_template) { + snprintf(ssrc_text, sizeof(ssrc_text), "any %s", + direction[stream->direction]); + } else { + snprintf(ssrc_text, sizeof(ssrc_text), "0x%08x", stream->ssrc); + } + + printf("# SSRC: %s\r\n" + "# rtp cipher: %s\r\n" + "# rtp auth: %s\r\n" + "# rtp services: %s\r\n" + "# rtcp cipher: %s\r\n" + "# rtcp auth: %s\r\n" + "# rtcp services: %s\r\n" + "# window size: %lu\r\n" + "# tx rtx allowed:%s\r\n", + ssrc_text, session_keys->rtp_cipher->type->description, + session_keys->rtp_auth->type->description, + serv_descr[stream->rtp_services], + session_keys->rtcp_cipher->type->description, + session_keys->rtcp_auth->type->description, + serv_descr[stream->rtcp_services], + srtp_rdbx_get_window_size(&stream->rtp_rdbx), + stream->allow_repeat_tx ? "true" : "false"); + + printf("# Encrypted extension headers: "); + if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) { + int *enc_xtn_hdr = stream->enc_xtn_hdr; + int count = stream->enc_xtn_hdr_count; + while (count > 0) { + printf("%d ", *enc_xtn_hdr); + enc_xtn_hdr++; + count--; + } + printf("\n"); + } else { + printf("none\n"); + } + + return 0; +} + srtp_err_status_t srtp_session_print_policy(srtp_t srtp) { - char *serv_descr[4] = { "none", "confidentiality", "authentication", - "confidentiality and authentication" }; - char *direction[3] = { "unknown", "outbound", "inbound" }; - srtp_stream_t stream; - srtp_session_keys_t *session_keys = NULL; + struct srtp_session_print_stream_data data = { srtp_err_status_ok, 0 }; /* sanity checking */ if (srtp == NULL) { return srtp_err_status_fail; } /* if there's a template stream, print it out */ if (srtp->stream_template != NULL) { - stream = srtp->stream_template; - session_keys = &stream->session_keys[0]; - printf("# SSRC: any %s\r\n" - "# rtp cipher: %s\r\n" - "# rtp auth: %s\r\n" - "# rtp services: %s\r\n" - "# rtcp cipher: %s\r\n" - "# rtcp auth: %s\r\n" - "# rtcp services: %s\r\n" - "# window size: %lu\r\n" - "# tx rtx allowed:%s\r\n", - direction[stream->direction], - session_keys->rtp_cipher->type->description, - session_keys->rtp_auth->type->description, - serv_descr[stream->rtp_services], - session_keys->rtcp_cipher->type->description, - session_keys->rtcp_auth->type->description, - serv_descr[stream->rtcp_services], - srtp_rdbx_get_window_size(&stream->rtp_rdbx), - stream->allow_repeat_tx ? "true" : "false"); - - printf("# Encrypted extension headers: "); - if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) { - int *enc_xtn_hdr = stream->enc_xtn_hdr; - int count = stream->enc_xtn_hdr_count; - while (count > 0) { - printf("%d ", *enc_xtn_hdr); - enc_xtn_hdr++; - count--; - } - printf("\n"); - } else { - printf("none\n"); - } + data.is_template = 1; + srtp_session_print_stream(srtp->stream_template, &data); } /* loop over streams in session, printing the policy of each */ - stream = srtp->stream_list; - while (stream != NULL) { - if (stream->rtp_services > sec_serv_conf_and_auth) { - return srtp_err_status_bad_param; - } - session_keys = &stream->session_keys[0]; - - printf("# SSRC: 0x%08x\r\n" - "# rtp cipher: %s\r\n" - "# rtp auth: %s\r\n" - "# rtp services: %s\r\n" - "# rtcp cipher: %s\r\n" - "# rtcp auth: %s\r\n" - "# rtcp services: %s\r\n" - "# window size: %lu\r\n" - "# tx rtx allowed:%s\r\n", - stream->ssrc, session_keys->rtp_cipher->type->description, - session_keys->rtp_auth->type->description, - serv_descr[stream->rtp_services], - session_keys->rtcp_cipher->type->description, - session_keys->rtcp_auth->type->description, - serv_descr[stream->rtcp_services], - srtp_rdbx_get_window_size(&stream->rtp_rdbx), - stream->allow_repeat_tx ? "true" : "false"); - - printf("# Encrypted extension headers: "); - if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) { - int *enc_xtn_hdr = stream->enc_xtn_hdr; - int count = stream->enc_xtn_hdr_count; - while (count > 0) { - printf("%d ", *enc_xtn_hdr); - enc_xtn_hdr++; - count--; - } - printf("\n"); - } else { - printf("none\n"); - } - - /* advance to next stream in the list */ - stream = stream->next; - } - return srtp_err_status_ok; + data.is_template = 0; + srtp_stream_list_for_each(srtp->stream_list, srtp_session_print_stream, + &data); + + return data.status; } srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy) { srtp_err_status_t status; @@ -1592,25 +1619,26 @@ if ((hdr == NULL) || (pkt_octet_len > MTU)) { return NULL; } /* write packet into string */ - sprintf(packet_string, "(s)rtp packet: {\n" - " version:\t%d\n" - " p:\t\t%d\n" - " x:\t\t%d\n" - " cc:\t\t%d\n" - " m:\t\t%d\n" - " pt:\t\t%x\n" - " seq:\t\t%x\n" - " ts:\t\t%x\n" - " ssrc:\t%x\n" - " data:\t%s\n" - "} (%d octets in total)\n", - hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq, - hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len), - pkt_octet_len); + snprintf(packet_string, sizeof(packet_string), + "(s)rtp packet: {\n" + " version:\t%d\n" + " p:\t\t%d\n" + " x:\t\t%d\n" + " cc:\t\t%d\n" + " m:\t\t%d\n" + " pt:\t\t%x\n" + " seq:\t\t%x\n" + " ts:\t\t%x\n" + " ssrc:\t%x\n" + " data:\t%s\n" + "} (%d octets in total)\n", + hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq, + hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len), + pkt_octet_len); return packet_string; } /* @@ -1648,11 +1676,11 @@ * srtp_validate() verifies the correctness of libsrtp by comparing * some computed packets against some pre-computed reference values. * These packets were made with the default SRTP policy. */ -srtp_err_status_t srtp_validate() +srtp_err_status_t srtp_validate(void) { // clang-format off uint8_t srtp_plaintext_ref[28] = { 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, @@ -1808,11 +1836,11 @@ * some computed packets against some pre-computed reference values. * These packets were made with a policy that applies null encryption * and HMAC authentication. */ -srtp_err_status_t srtp_validate_null() +srtp_err_status_t srtp_validate_null(void) { // clang-format off uint8_t srtp_plaintext_ref[28] = { 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, @@ -1966,19 +1994,13 @@ #ifdef GCM /* * srtp_validate_gcm() verifies the correctness of libsrtp by comparing * an computed packet against the known ciphertext for the plaintext. */ -srtp_err_status_t srtp_validate_gcm() +srtp_err_status_t srtp_validate_gcm(void) { // clang-format off - unsigned char test_key_gcm[28] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab - }; uint8_t rtp_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 @@ -2134,11 +2156,11 @@ #endif /* * Test vectors taken from RFC 6904, Appendix A */ -srtp_err_status_t srtp_validate_encrypted_extensions_headers() +srtp_err_status_t srtp_validate_encrypted_extensions_headers(void) { // clang-format off unsigned char test_key_ext_headers[30] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, @@ -2257,11 +2279,11 @@ #ifdef GCM /* * Headers of test vectors taken from RFC 6904, Appendix A */ -srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm() +srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void) { // clang-format off unsigned char test_key_ext_headers[30] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, @@ -2380,11 +2402,11 @@ * 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. */ -srtp_err_status_t srtp_validate_aes_256() +srtp_err_status_t srtp_validate_aes_256(void) { // clang-format off unsigned char aes_256_test_key[46] = { 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, @@ -2539,11 +2561,11 @@ } return srtp_err_status_ok; } -srtp_err_status_t srtp_test_empty_payload() +srtp_err_status_t srtp_test_empty_payload(void) { srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; srtp_policy_t policy; @@ -2615,11 +2637,11 @@ return srtp_err_status_ok; } #ifdef GCM -srtp_err_status_t srtp_test_empty_payload_gcm() +srtp_err_status_t srtp_test_empty_payload_gcm(void) { srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; srtp_policy_t policy; @@ -2691,11 +2713,11 @@ return srtp_err_status_ok; } #endif // GCM -srtp_err_status_t srtp_test_remove_stream() +srtp_err_status_t srtp_test_remove_stream(void) { srtp_err_status_t status; srtp_policy_t *policy_list, policy; srtp_t session; srtp_stream_t stream; @@ -2804,11 +2826,11 @@ * As stated in https://tools.ietf.org/html/rfc3711#section-3.3.1 * the value of the ROC must not be reset after a rekey, this test * atempts to prove that srtp_update does not reset the ROC. */ -srtp_err_status_t srtp_test_update() +srtp_err_status_t srtp_test_update(void) { srtp_err_status_t status; uint32_t ssrc = 0x12121212; int msg_len_octets = 32; int protected_msg_len_octets; @@ -2821,20 +2843,20 @@ srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.deprecated_ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; policy.next = NULL; - policy.ssrc.type = ssrc_any_outbound; policy.key = test_key; /* create a send and recive ctx with defualt profile and test_key */ - status = srtp_create(&srtp_recv, &policy); + policy.ssrc.type = ssrc_any_outbound; + status = srtp_create(&srtp_snd, &policy); if (status) return status; policy.ssrc.type = ssrc_any_inbound; - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_recv, &policy); if (status) return status; /* protect and unprotect two msg's that will cause the ROC to be equal to 1 */ @@ -2976,10 +2998,13 @@ srtp_policy_t policy_mki; #ifdef GCM srtp_policy_t policy_aes_gcm; srtp_policy_t policy_aes_gcm_mki; +#else + (void)srtp_send_aes_gcm; + (void)srtp_send_aes_gcm_mki; #endif // GCM memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); @@ -3046,11 +3071,11 @@ #endif // GCM return srtp_err_status_ok; } -srtp_err_status_t srtp_test_protect_trailer_length() +srtp_err_status_t srtp_test_protect_trailer_length(void) { srtp_t srtp_send; srtp_t srtp_send_mki; srtp_t srtp_send_aes_gcm; srtp_t srtp_send_aes_gcm_mki; @@ -3103,11 +3128,11 @@ #endif return srtp_err_status_ok; } -srtp_err_status_t srtp_test_protect_rtcp_trailer_length() +srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void) { srtp_t srtp_send; srtp_t srtp_send_mki; srtp_t srtp_send_aes_gcm; srtp_t srtp_send_aes_gcm_mki; @@ -3161,11 +3186,229 @@ #endif return srtp_err_status_ok; } -srtp_err_status_t srtp_test_get_roc() +srtp_err_status_t srtp_test_out_of_order_after_rollover(void) +{ + srtp_err_status_t status; + + srtp_policy_t sender_policy; + srtp_t sender_session; + + srtp_policy_t receiver_policy; + srtp_t receiver_session; + + const uint32_t num_pkts = 5; + srtp_hdr_t *pkts[5]; + int pkt_len_octets[5]; + + uint32_t i; + uint32_t stream_roc; + + /* Create sender */ + memset(&sender_policy, 0, sizeof(sender_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtcp); + sender_policy.key = test_key_gcm; +#else + srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); + sender_policy.key = test_key; +#endif + sender_policy.ssrc.type = ssrc_specific; + sender_policy.ssrc.value = 0xcafebabe; + sender_policy.window_size = 128; + + status = srtp_create(&sender_session, &sender_policy); + if (status) { + return status; + } + + /* Create the receiver */ + memset(&receiver_policy, 0, sizeof(receiver_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtcp); + receiver_policy.key = test_key_gcm; +#else + srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); + receiver_policy.key = test_key; +#endif + receiver_policy.ssrc.type = ssrc_specific; + receiver_policy.ssrc.value = sender_policy.ssrc.value; + receiver_policy.window_size = 128; + + status = srtp_create(&receiver_session, &receiver_policy); + if (status) { + return status; + } + + /* Create and protect packets to get to get roc == 1 */ + pkts[0] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, + 65534, 0, &pkt_len_octets[0]); + status = srtp_protect(sender_session, pkts[0], &pkt_len_octets[0]); + if (status) { + return status; + } + status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 0) { + return srtp_err_status_fail; + } + + pkts[1] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, + 65535, 1, &pkt_len_octets[1]); + status = srtp_protect(sender_session, pkts[1], &pkt_len_octets[1]); + if (status) { + return status; + } + status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 0) { + return srtp_err_status_fail; + } + + pkts[2] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 0, + 2, &pkt_len_octets[2]); + status = srtp_protect(sender_session, pkts[2], &pkt_len_octets[2]); + if (status) { + return status; + } + status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + pkts[3] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 1, + 3, &pkt_len_octets[3]); + status = srtp_protect(sender_session, pkts[3], &pkt_len_octets[3]); + if (status) { + return status; + } + status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + pkts[4] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 2, + 4, &pkt_len_octets[4]); + status = srtp_protect(sender_session, pkts[4], &pkt_len_octets[4]); + if (status) { + return status; + } + status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + /* Unprotect packets in this seq order 65534, 0, 2, 1, 65535 which is + * equivalent to index 0, 2, 4, 3, 1*/ + status = srtp_unprotect(receiver_session, pkts[0], &pkt_len_octets[0]); + if (status) { + return status; + } + status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 0) { + return srtp_err_status_fail; + } + + status = srtp_unprotect(receiver_session, pkts[2], &pkt_len_octets[2]); + if (status) { + return status; + } + status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + status = srtp_unprotect(receiver_session, pkts[4], &pkt_len_octets[4]); + if (status) { + return status; + } + status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + status = srtp_unprotect(receiver_session, pkts[3], &pkt_len_octets[3]); + if (status) { + return status; + } + status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + status = srtp_unprotect(receiver_session, pkts[1], &pkt_len_octets[1]); + if (status) { + return status; + } + status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value, + &stream_roc); + if (status) { + return status; + } + if (stream_roc != 1) { + return srtp_err_status_fail; + } + + /* Cleanup */ + status = srtp_dealloc(sender_session); + if (status) { + return status; + } + + status = srtp_dealloc(receiver_session); + if (status) { + return status; + } + + for (i = 0; i < num_pkts; i++) { + free(pkts[i]); + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_test_get_roc(void) { srtp_err_status_t status; srtp_policy_t policy; srtp_t session; srtp_hdr_t *pkt; @@ -3245,33 +3488,42 @@ unsigned char *recv_pkt_2; uint32_t i; uint32_t ts; uint16_t seq; + uint16_t stride; int msg_len_octets = 32; int protected_msg_len_octets_1; int protected_msg_len_octets_2; /* Create sender */ memset(&sender_policy, 0, sizeof(sender_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtcp); + sender_policy.key = test_key_gcm; +#else srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); + sender_policy.key = test_key; +#endif sender_policy.ssrc.type = ssrc_specific; sender_policy.ssrc.value = 0xcafebabe; - sender_policy.key = test_key; sender_policy.window_size = 128; status = srtp_create(&sender_session, &sender_policy); if (status) { return status; } /* Create and protect packets */ + i = 0; seq = 0; ts = 0; - for (i = 0; i < packets; i++) { + stride = 0x4000; + while (i < packets) { srtp_hdr_t *tmp_pkt; int tmp_len; tmp_pkt = srtp_create_test_packet_extended( msg_len_octets, sender_policy.ssrc.value, seq, ts, &tmp_len); @@ -3279,11 +3531,16 @@ free(tmp_pkt); if (status) { return status; } - seq++; + while (stride > (packets - i) && stride > 1) { + stride >>= 1; + } + + i += stride; + seq += stride; ts++; } /* Create the first packet to decrypt and test for ROC change */ pkt_1 = srtp_create_test_packet_extended(msg_len_octets, @@ -3305,15 +3562,21 @@ return status; } /* Create the receiver */ memset(&receiver_policy, 0, sizeof(receiver_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtcp); + receiver_policy.key = test_key_gcm; +#else srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); + receiver_policy.key = test_key; +#endif receiver_policy.ssrc.type = ssrc_specific; receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.key = test_key; receiver_policy.window_size = 128; status = srtp_create(&receiver_session, &receiver_policy); if (status) { return status; @@ -3391,15 +3654,21 @@ int msg_len_octets = 32; int protected_msg_len_octets; /* Create sender */ memset(&sender_policy, 0, sizeof(sender_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtcp); + sender_policy.key = test_key_gcm; +#else srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); + sender_policy.key = test_key; +#endif sender_policy.ssrc.type = ssrc_specific; sender_policy.ssrc.value = 0xcafebabe; - sender_policy.key = test_key; sender_policy.window_size = 128; status = srtp_create(&sender_session, &sender_policy); if (status) { return status; @@ -3422,15 +3691,21 @@ return status; } /* Create the receiver */ memset(&receiver_policy, 0, sizeof(receiver_policy)); +#ifdef GCM + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtcp); + receiver_policy.key = test_key_gcm; +#else srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); + receiver_policy.key = test_key; +#endif receiver_policy.ssrc.type = ssrc_specific; receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.key = test_key; receiver_policy.window_size = 128; status = srtp_create(&receiver_session, &receiver_policy); if (status) { return status; @@ -3471,11 +3746,11 @@ free(recv_pkt); return srtp_err_status_ok; } -srtp_err_status_t srtp_test_set_receiver_roc() +srtp_err_status_t srtp_test_set_receiver_roc(void) { int packets; uint32_t roc; srtp_err_status_t status; @@ -3527,14 +3802,19 @@ status = test_set_receiver_roc(packets + 60000, roc); if (status) { return status; } + status = test_set_receiver_roc(packets + 65535, roc); + if (status) { + return status; + } + return srtp_err_status_ok; } -srtp_err_status_t srtp_test_set_sender_roc() +srtp_err_status_t srtp_test_set_sender_roc(void) { uint32_t roc; uint16_t seq; srtp_err_status_t status; @@ -3593,10 +3873,17 @@ 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6, 0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, 0x93, 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 }; +unsigned char test_key_gcm[28] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab +}; + unsigned char test_mki_id[TEST_MKI_ID_SIZE] = { 0xe1, 0xf9, 0x7a, 0x0d }; unsigned char test_mki_id_2[TEST_MKI_ID_SIZE] = { @@ -3665,24 +3952,24 @@ }; const srtp_policy_t hmac_only_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, 2, /* Number of Master keys associated with the policy */ NULL, /* indicates that EKT is not in use */ @@ -3820,24 +4107,24 @@ #endif const srtp_policy_t null_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_none /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_none /* security services flag */ }, { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_none /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_none /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ @@ -4010,5 +4297,242 @@ 0, /* retransmission not allowed */ NULL, /* no encrypted extension headers */ 0, /* list of encrypted extension headers is empty */ NULL }; + +static srtp_stream_t stream_list_test_create_stream(uint32_t ssrc) +{ + srtp_stream_t stream = malloc(sizeof(srtp_stream_ctx_t)); + stream->ssrc = ssrc; + return stream; +} + +static void stream_list_test_free_stream(srtp_stream_t stream) +{ + free(stream); +} + +int stream_list_test_count_cb(srtp_stream_t stream, void *data) +{ + int *count = (int *)data; + (*count)++; + (void)stream; + return 0; +} + +struct remove_one_data { + uint32_t ssrc; + srtp_stream_list_t list; +}; + +int stream_list_test_remove_one_cb(srtp_stream_t stream, void *data) +{ + struct remove_one_data *d = (struct remove_one_data *)data; + if (stream->ssrc == d->ssrc) { + srtp_stream_list_remove(d->list, stream); + stream_list_test_free_stream(stream); + return 1; + } + return 0; +} + +int stream_list_test_remove_all_cb(srtp_stream_t stream, void *data) +{ + srtp_stream_list_t *list = (srtp_stream_list_t *)data; + srtp_stream_list_remove(*list, stream); + stream_list_test_free_stream(stream); + return 0; +} + +srtp_err_status_t srtp_stream_list_test(void) +{ + srtp_stream_list_t list; + + if (srtp_stream_list_alloc(&list)) { + return srtp_err_status_fail; + } + + /* add 4 streams*/ + if (srtp_stream_list_insert(list, stream_list_test_create_stream(1))) { + return srtp_err_status_fail; + } + if (srtp_stream_list_insert(list, stream_list_test_create_stream(2))) { + return srtp_err_status_fail; + } + if (srtp_stream_list_insert(list, stream_list_test_create_stream(3))) { + return srtp_err_status_fail; + } + if (srtp_stream_list_insert(list, stream_list_test_create_stream(4))) { + return srtp_err_status_fail; + } + + /* find */ + if (srtp_stream_list_get(list, 3) == NULL) { + return srtp_err_status_fail; + } + if (srtp_stream_list_get(list, 1) == NULL) { + return srtp_err_status_fail; + } + if (srtp_stream_list_get(list, 2) == NULL) { + return srtp_err_status_fail; + } + if (srtp_stream_list_get(list, 4) == NULL) { + return srtp_err_status_fail; + } + + /* find not in list */ + if (srtp_stream_list_get(list, 5)) { + return srtp_err_status_fail; + } + + /* for each */ + int count = 0; + srtp_stream_list_for_each(list, stream_list_test_count_cb, &count); + if (count != 4) { + return srtp_err_status_fail; + } + + /* remove */ + srtp_stream_t stream = srtp_stream_list_get(list, 3); + if (stream == NULL) { + return srtp_err_status_fail; + } + srtp_stream_list_remove(list, stream); + stream_list_test_free_stream(stream); + + /* find after remove */ + if (srtp_stream_list_get(list, 3)) { + return srtp_err_status_fail; + } + + /* recount */ + count = 0; + srtp_stream_list_for_each(list, stream_list_test_count_cb, &count); + if (count != 3) { + return srtp_err_status_fail; + } + + /* remove one in for each */ + struct remove_one_data data = { 2, list }; + srtp_stream_list_for_each(list, stream_list_test_remove_one_cb, &data); + + /* find after remove */ + if (srtp_stream_list_get(list, 2)) { + return srtp_err_status_fail; + } + + /* recount */ + count = 0; + srtp_stream_list_for_each(list, stream_list_test_count_cb, &count); + if (count != 2) { + return srtp_err_status_fail; + } + + /* destroy non empty list */ + if (srtp_stream_list_dealloc(list) == srtp_err_status_ok) { + return srtp_err_status_fail; + } + + /* remove all in for each */ + srtp_stream_list_for_each(list, stream_list_test_remove_all_cb, &list); + + /* recount */ + count = 0; + srtp_stream_list_for_each(list, stream_list_test_count_cb, &count); + if (count != 0) { + return srtp_err_status_fail; + } + + /* destroy empty list */ + if (srtp_stream_list_dealloc(list)) { + return srtp_err_status_fail; + } + + return srtp_err_status_ok; +} + +#ifdef SRTP_USE_TEST_STREAM_LIST + +/* + * A srtp_stream_list_ctx_t implementation using a single linked list + * that does not use the internal next / prev fields. + */ + +struct test_list_node { + srtp_stream_t stream; + struct test_list_node *next; +}; +struct srtp_stream_list_ctx_t_ { + struct test_list_node *head; +}; + +srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr) +{ + struct srtp_stream_list_ctx_t_ *l = + malloc(sizeof(struct srtp_stream_list_ctx_t_)); + l->head = NULL; + *list_ptr = l; + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list) +{ + struct test_list_node *node = list->head; + if (node) { + return srtp_err_status_fail; + } + free(list); + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list, + srtp_stream_t stream) +{ + struct test_list_node *node = malloc(sizeof(struct test_list_node)); + node->stream = stream; + node->next = list->head; + list->head = node; + + return srtp_err_status_ok; +} + +srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc) +{ + struct test_list_node *node = list->head; + while (node != NULL) { + if (node->stream->ssrc == ssrc) + return node->stream; + node = node->next; + } + return NULL; +} + +void srtp_stream_list_remove(srtp_stream_list_t list, srtp_stream_t stream) +{ + struct test_list_node **node = &(list->head); + while ((*node) != NULL) { + if ((*node)->stream->ssrc == stream->ssrc) { + struct test_list_node *tmp = (*node); + (*node) = tmp->next; + free(tmp); + return; + } + node = &(*node)->next; + } +} + +void srtp_stream_list_for_each(srtp_stream_list_t list, + int (*callback)(srtp_stream_t, void *), + void *data) +{ + struct test_list_node *node = list->head; + while (node != NULL) { + struct test_list_node *tmp = node; + node = node->next; + if (callback(tmp->stream, data)) + break; + } +} + +#endif diff --git a/third_party/libsrtp/src/test/test_srtp.c b/third_party/libsrtp/src/test/test_srtp.c --- a/third_party/libsrtp/src/test/test_srtp.c +++ b/third_party/libsrtp/src/test/test_srtp.c @@ -76,28 +76,27 @@ srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output }, { "srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param()", srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param }, { "srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()", srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number }, - { NULL } /* End of tests */ }; + { 0 } /* End of tests */ }; /* * Implementation. */ -void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output() +void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output(void) { // Preconditions srtp_session_keys_t session_keys; v128_t init_vector; srtcp_hdr_t header; uint32_t sequence_num; // Postconditions srtp_err_status_t status; - const v128_t zero_vector; - memset((v128_t *)&zero_vector, 0, sizeof(v128_t)); + const v128_t zero_vector = { 0 }; // Given memset(&session_keys, 0, sizeof(srtp_session_keys_t)); memset(&init_vector, 0, sizeof(v128_t)); memset(&header, 0, sizeof(srtcp_hdr_t)); @@ -110,11 +109,11 @@ // Then TEST_CHECK(status == srtp_err_status_ok); TEST_CHECK(memcmp(&zero_vector, &init_vector, sizeof(v128_t)) == 0); } -void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param() +void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param(void) { // Preconditions srtp_session_keys_t session_keys; v128_t init_vector; srtcp_hdr_t header; @@ -142,11 +141,11 @@ * Srtcp IV calculation incorrectly masks high bit of sequence number for * little-endian platforms. * Ensure that for each valid sequence number where the most significant bit is * high that we get an expected and unique IV. */ -void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number() +void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number(void) { #define SAMPLE_COUNT (3) // Preconditions // Test each significant bit high in each full byte. srtp_session_keys_t session_keys; diff --git a/third_party/libsrtp/src/test/ut_sim.c b/third_party/libsrtp/src/test/ut_sim.c --- a/third_party/libsrtp/src/test/ut_sim.c +++ b/third_party/libsrtp/src/test/ut_sim.c @@ -52,10 +52,12 @@ #include "cipher_priv.h" int ut_compar(const void *a, const void *b) { uint8_t r; + (void)a; + (void)b; srtp_cipher_rand_for_tests(&r, sizeof(r)); return r > (UINT8_MAX / 2) ? -1 : 1; } void ut_init(ut_connection *utc) diff --git a/third_party/libsrtp/src/test/util.c b/third_party/libsrtp/src/test/util.c --- a/third_party/libsrtp/src/test/util.c +++ b/third_party/libsrtp/src/test/util.c @@ -99,12 +99,10 @@ case ('F'): return 0xf; default: return -1; /* this flags an error */ } - /* NOTREACHED */ - return -1; /* this keeps compilers from complaining */ } uint8_t nibble_to_hex_char(uint8_t nibble) { char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', @@ -127,11 +125,11 @@ while (hex_len < len) { tmp = hex_char_to_nibble(hex[0]); if (tmp == -1) { return hex_len; } - x = (tmp << 4); + x = (uint8_t)(tmp << 4); hex_len++; tmp = hex_char_to_nibble(hex[1]); if (tmp == -1) { return hex_len; } @@ -174,11 +172,11 @@ int i; for (i = 0; i < 4; i++) { char *p = strchr(b64chars, in[i]); if (p != NULL) { - sextets[i] = p - b64chars; + sextets[i] = (unsigned char)(p - b64chars); } else { j++; } }