diff --git a/.gitignore b/.gitignore index 38d3a8f8f..dcc5c136d 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ test/rtp_decoder test/rtpw test/srtp_driver test/test_srtp +test/test_srtp_policy diff --git a/CMakeLists.txt b/CMakeLists.txt index 008f66631..d5eabbe37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ endif() set(SOURCES_C srtp/srtp.c + srtp/srtp_policy.c ) set(CIPHERS_SOURCES_C @@ -471,6 +472,17 @@ if(LIBSRTP_TEST_APPS) endif() target_link_libraries(test_srtp srtp3) add_test(test_srtp test_srtp) + + add_executable(test_srtp_policy test/test_srtp_policy.c test/util.c) + target_set_warnings( + TARGET + test_srtp_policy + ENABLE + ${ENABLE_WARNINGS} + AS_ERRORS + ${ENABLE_WARNINGS_AS_ERRORS}) + target_link_libraries(test_srtp_policy srtp3) + add_test(test_srtp_policy test_srtp_policy) endif() find_program(BASH_PROGRAM bash) diff --git a/Makefile.in b/Makefile.in index 7c7c5acc6..6d4954df1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -47,6 +47,7 @@ runtest: test $(FIND_LIBRARIES) crypto/test/cipher_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) crypto/test/kernel_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/test_srtp$(EXE) >/dev/null + $(FIND_LIBRARIES) test/test_srtp_policy$(EXE) >/dev/null $(FIND_LIBRARIES) test/rdbx_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/srtp_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/roc_driver$(EXE) -v >/dev/null @@ -61,6 +62,7 @@ endif runtest-valgrind: test @echo "running libsrtp3 test applications... (valgrind)" valgrind --error-exitcode=1 --leak-check=full --suppressions=./valgrind.supp test/test_srtp$(EXE) -v >/dev/null + valgrind --error-exitcode=1 --leak-check=full --suppressions=./valgrind.supp test/test_srtp_policy$(EXE) -v >/dev/null valgrind --error-exitcode=1 --leak-check=full --suppressions=./valgrind.supp test/srtp_driver$(EXE) -v >/dev/null @echo "libsrtp3 test applications passed. (valgrind)" @@ -156,7 +158,7 @@ cryptobj = $(ciphers) $(hashes) $(math) $(kernel) $(replay) # libsrtp3.a (implements srtp processing) -srtpobj = srtp/srtp.o +srtpobj = srtp/srtp.o srtp/srtp_policy.o libsrtp3.a: $(srtpobj) $(cryptobj) $(gdoi) $(AR) cr libsrtp3.a $^ @@ -187,7 +189,7 @@ crypto_testapp = $(AES_CALC) crypto/test/cipher_driver$(EXE) \ testapp = $(crypto_testapp) test/srtp_driver$(EXE) test/replay_driver$(EXE) \ test/roc_driver$(EXE) test/rdbx_driver$(EXE) test/rtpw$(EXE) \ - test/test_srtp$(EXE) + test/test_srtp$(EXE) test/test_srtp_policy$(EXE) ifeq (1, $(HAVE_PCAP)) testapp += test/rtp_decoder$(EXE) @@ -211,6 +213,9 @@ crypto/test/aes_calc$(EXE): crypto/test/aes_calc.c test/util.c test/test_srtp$(EXE): test/test_srtp.c $(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB) +test/test_srtp_policy$(EXE): test/test_srtp_policy.c test/util.c + $(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB) + crypto/test/datatypes_driver$(EXE): crypto/test/datatypes_driver.c test/util.c $(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB) diff --git a/README.md b/README.md index 06a99b613..9acb62065 100644 --- a/README.md +++ b/README.md @@ -136,24 +136,14 @@ receives from each sender. In libSRTP, a session is created using the function `srtp_create()`. The policy to be implemented in the session is passed into this -function as an `srtp_policy_t` structure. A single one of these -structures describes the policy of a single stream. These structures -can also be linked together to form an entire session policy. A linked -list of `srtp_policy_t` structures is equivalent to a session policy. -In such a policy, we refer to a single `srtp_policy_t` as an *element*. - -An `srtp_policy_t` structure contains two `srtp_crypto_policy_t` structures -that describe the cryptograhic policies for RTP and RTCP, as well as -the SRTP master key and the SSRC value. The SSRC describes what to -protect (e.g. which stream), and the `srtp_crypto_policy_t` structures -describe how to protect it. The key is contained in a policy element -because it simplifies the interface to the library. In many cases, it -is desirable to use the same cryptographic policies across all of the -streams in a session, but to use a distinct key for each stream. A -`srtp_crypto_policy_t` structure can be initialized by using either the -`srtp_crypto_policy_set_rtp_default()` or `srtp_crypto_policy_set_rtcp_default()` -functions, which set a crypto policy structure to the default policies -for RTP and RTCP protection, respectively. +function as an opaque `srtp_policy_t` handle. A single policy handle +describes one stream policy. To configure multiple streams, create a +session and add additional policies with `srtp_stream_add()`. + +A policy handle is configured with `srtp_policy_set_*` functions. At a +minimum, this includes SSRC selection, profile selection, and key/salt +material. The profile configures RTP/RTCP crypto policy settings, while the +SSRC selector identifies how and where that policy is applied. -------------------------------------------------------------------------------- @@ -181,7 +171,7 @@ traffic from a particular source a *stream*. Each stream has its own SSRC, sequence number, rollover counter, and other data. A particular choice of options, cryptographic mechanisms, and keys is called a *policy*. Each stream within a session can have a distinct policy -applied to it. A session policy is a collection of stream policies. +applied to it. A single policy can be used for all of the streams in a given session, though the case in which a single *key* is shared across multiple @@ -202,7 +192,7 @@ in which a key is used for both inbound and outbound data. This library supports all of the mandatory-to-implement features of SRTP (as defined in [RFC 3711](https://tools.ietf.org/html/rfc3711)). Some of these features can be selected (or de-selected) at run time by setting an -appropriate policy; this is done using the structure `srtp_policy_t`. +appropriate policy using an `srtp_policy_t` handle. Some other behaviors of the protocol can be adapted by defining an approriate event handler for the exceptional events; see the SRTPevents section in the generated documentation. @@ -467,11 +457,9 @@ set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC ## Example Code -This section provides a simple example of how to use libSRTP. The -example code lacks error checking, but is functional. Here we assume -that the value ssrc is already set to describe the SSRC of the stream -that we are sending, and that the functions `get_rtp_packet()` and -`send_srtp_packet()` are available to us. The former puts an RTP packet +This section provides a simple example of how to use libSRTP. Here we assume +that the functions `get_rtp_packet()` and `send_srtp_packet()` are available +to us. The former puts an RTP packet into the buffer and returns the number of octets written to that buffer. The latter sends the RTP packet in the buffer, given the length as its second argument. @@ -480,39 +468,41 @@ length as its second argument. srtp_t session; srtp_policy_t policy; -// Set key to predetermined value -uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D}; +// Set key/salt to predetermined values. +uint8_t master_key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; +uint8_t master_salt[14] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D}; -// initialize libSRTP +// Initialize libSRTP. srtp_init(); -// default policy values -memset(&policy, 0x0, sizeof(srtp_policy_t)); +// Create and configure an opaque policy handle. +srtp_policy_create(&policy); +srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ssrc_any_outbound, 0}); +srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80); +srtp_policy_add_key(policy, master_key, sizeof(master_key), + master_salt, sizeof(master_salt), NULL, 0); -// set policy to describe a policy for an SRTP stream -srtp_crypto_policy_set_rtp_default(&policy.rtp); -srtp_crypto_policy_set_rtcp_default(&policy.rtcp); -policy.ssrc = ssrc; -policy.key = key; -policy.next = NULL; +// Allocate and initialize the SRTP session. +srtp_create(&session, policy); -// allocate and initialize the SRTP session -srtp_create(&session, &policy); +srtp_policy_destroy(policy); -// main loop: get rtp packets, send srtp packets +// Main loop: get RTP packets, send SRTP packets. while (1) { char rtp_buffer[2048]; size_t rtp_len; char srtp_buffer[2048]; size_t srtp_len = sizeof(srtp_buffer); - len = get_rtp_packet(rtp_buffer); + rtp_len = get_rtp_packet(rtp_buffer); srtp_protect(session, rtp_buffer, rtp_len, srtp_buffer, &srtp_len); send_srtp_packet(srtp_buffer, srtp_len); } + +srtp_dealloc(session); +srtp_shutdown(); ~~~ -------------------------------------------------------------------------------- diff --git a/fuzzer/fuzzer.c b/fuzzer/fuzzer.c index 87c33e38e..b91091fdb 100644 --- a/fuzzer/fuzzer.c +++ b/fuzzer/fuzzer.c @@ -254,115 +254,102 @@ static uint8_t *extract_key(const uint8_t **data, return ret; } -static srtp_master_key_t *extract_master_key(const uint8_t **data, - size_t *size, - const size_t key_size, - bool simulate, - bool *success) +static bool extract_and_add_key(srtp_policy_t policy, + const uint8_t **data, + size_t *size, + size_t key_size, + size_t salt_size) { - srtp_master_key_t *ret = NULL; - uint16_t mki_id_size; - - if (simulate == true) { - *success = false; + bool added = false; + uint8_t *salt = NULL; + uint8_t *key = extract_key(data, size, key_size); + if (key == NULL) { + return false; } - EXTRACT_IF(&mki_id_size, *data, *size, sizeof(mki_id_size)); - - if (*size < key_size + mki_id_size) { + salt = extract_key(data, size, salt_size); + if (salt == NULL) { goto end; } - if (simulate == true) { - *data += key_size + mki_id_size; - *size -= key_size + mki_id_size; - *success = true; - goto end; + if (srtp_policy_add_key(policy, key, key_size, salt, salt_size, NULL, 0) == + srtp_err_status_ok) { + added = true; } - ret = fuzz_alloc_succeed(sizeof(srtp_master_key_t), false); - ret->key = fuzz_alloc_succeed(key_size, false); - - ret->mki_id = fuzz_alloc_succeed(mki_id_size, false); - - EXTRACT(ret->key, *data, *size, key_size); - EXTRACT(ret->mki_id, *data, *size, mki_id_size); end: - return ret; + fuzz_free(salt); + fuzz_free(key); + return added; } -static srtp_master_key_t **extract_master_keys(const uint8_t **data, - size_t *size, - const size_t key_size, - size_t *num_master_keys) +static bool extract_and_add_master_key(srtp_policy_t policy, + const uint8_t **data, + size_t *size, + size_t key_size, + size_t salt_size) { - const uint8_t *data_orig = *data; - size_t size_orig = *size; - size_t i = 0; - - srtp_master_key_t **ret = NULL; + bool added = false; + uint8_t *key = NULL; + uint8_t *salt = NULL; + uint16_t mki_id_size = 0; + const uint8_t *mki = NULL; + srtp_err_status_t status; - *num_master_keys = 0; - - /* First pass -- dry run, determine how many keys we want and can extract */ - while (1) { - uint8_t do_extract_master_key; - bool success; - if (*size < sizeof(do_extract_master_key)) { - goto next; - } - EXTRACT(&do_extract_master_key, *data, *size, - sizeof(do_extract_master_key)); - - /* Decide whether to extract another key */ - if ((do_extract_master_key % 2) == 0) { - break; - } - - extract_master_key(data, size, key_size, true, &success); - - if (success == false) { - break; - } + EXTRACT_IF(&mki_id_size, *data, *size, sizeof(mki_id_size)); - (*num_master_keys)++; + if (*size < key_size + salt_size + mki_id_size) { + return false; } -next: - *data = data_orig; - *size = size_orig; - - /* Allocate array of pointers */ - ret = fuzz_alloc_succeed(*num_master_keys * sizeof(srtp_master_key_t *), - false); + if (mki_id_size > SRTP_MAX_MKI_LEN) { + *data += key_size + salt_size + mki_id_size; + *size -= key_size + salt_size + mki_id_size; + return false; + } - /* Second pass -- perform the actual extractions */ - for (i = 0; i < *num_master_keys; i++) { - uint8_t do_extract_master_key; - EXTRACT_IF(&do_extract_master_key, *data, *size, - sizeof(do_extract_master_key)); + key = extract_key(data, size, key_size); + if (key == NULL) { + return false; + } + salt = extract_key(data, size, salt_size); + if (salt == NULL) { + goto end; + } + mki = *data; + *data += mki_id_size; + *size -= mki_id_size; - if ((do_extract_master_key % 2) == 0) { - break; + if (mki_id_size > 0) { + status = srtp_policy_use_mki(policy, mki_id_size); + if (status != srtp_err_status_ok) { + goto end; } + } - ret[i] = extract_master_key(data, size, key_size, false, NULL); - - if (ret[i] == NULL) { - /* Shouldn't happen */ - abort(); - } + status = srtp_policy_add_key(policy, key, key_size, salt, salt_size, mki, + mki_id_size); + if (status != srtp_err_status_ok) { + goto end; } + added = true; + end: - return ret; + fuzz_free(salt); + fuzz_free(key); + return added; } -static srtp_policy_t *extract_policy(const uint8_t **data, size_t *size) +static srtp_policy_t extract_policy(const uint8_t **data, size_t *size) { - srtp_policy_t *policy = NULL; + srtp_policy_t policy = NULL; + srtp_profile_t profile; + size_t key_size; + size_t salt_size; + srtp_err_status_t status; struct { - uint8_t srtp_crypto_policy_func; + uint8_t srtp_profile; size_t window_size; uint8_t allow_repeat_tx; uint8_t ssrc_type; @@ -374,80 +361,105 @@ static srtp_policy_t *extract_policy(const uint8_t **data, size_t *size) EXTRACT_IF(¶ms, *data, *size, sizeof(params)); - params.srtp_crypto_policy_func %= sizeof(fuzz_srtp_crypto_policies) / - sizeof(fuzz_srtp_crypto_policies[0]); + params.srtp_profile %= + sizeof(fuzz_srtp_profiles) / sizeof(fuzz_srtp_profiles[0]); params.allow_repeat_tx %= 2; params.ssrc_type %= sizeof(fuzz_ssrc_type_map) / sizeof(fuzz_ssrc_type_map[0]); + profile = fuzz_srtp_profiles[params.srtp_profile].profile; - policy = fuzz_alloc_succeed(sizeof(*policy), true); + status = srtp_policy_create(&policy); + if (status != srtp_err_status_ok || policy == NULL) { + return NULL; + } - fuzz_srtp_crypto_policies[params.srtp_crypto_policy_func] - .crypto_policy_func(&policy->rtp); - fuzz_srtp_crypto_policies[params.srtp_crypto_policy_func] - .crypto_policy_func(&policy->rtcp); + status = srtp_policy_set_profile(policy, profile); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(policy); + return NULL; + } - if (policy->rtp.cipher_key_len > MAX_KEY_LEN) { - /* Shouldn't happen */ + key_size = srtp_profile_get_master_key_length(profile); + salt_size = srtp_profile_get_master_salt_length(profile); + if (key_size + salt_size > SRTP_MAX_KEY_LEN) { + /* Shouldn't happen for a public profile. */ abort(); } - policy->ssrc.type = fuzz_ssrc_type_map[params.ssrc_type].srtp_ssrc_type; - policy->ssrc.value = params.ssrc_value; - - if ((params.do_extract_key % 2) == 0) { - policy->key = extract_key(data, size, policy->rtp.cipher_key_len); + status = srtp_policy_set_ssrc( + policy, (srtp_ssrc_t){ + .type = fuzz_ssrc_type_map[params.ssrc_type].srtp_ssrc_type, + .value = params.ssrc_value, + }); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(policy); + return NULL; + } - if (policy->key == NULL) { - fuzz_free(policy); + if (profile != srtp_profile_null_null && (params.do_extract_key % 2) == 0) { + if (!extract_and_add_key(policy, data, size, key_size, salt_size)) { + srtp_policy_destroy(policy); return NULL; } } if (params.num_xtn_hdr != 0) { - const size_t xtn_hdr_size = params.num_xtn_hdr * sizeof(int); + const size_t xtn_hdr_size = params.num_xtn_hdr; + size_t copy_size = xtn_hdr_size; if (*size < xtn_hdr_size) { - fuzz_free(policy->key); - fuzz_free(policy); + srtp_policy_destroy(policy); return NULL; } - policy->enc_xtn_hdr = fuzz_alloc_succeed(xtn_hdr_size, false); - EXTRACT(policy->enc_xtn_hdr, *data, *size, xtn_hdr_size); - policy->enc_xtn_hdr_count = params.num_xtn_hdr; - } - - if ((params.do_extract_master_keys % 2) == 0) { - policy->keys = extract_master_keys( - data, size, policy->rtp.cipher_key_len, &policy->num_master_keys); - if (policy->keys == NULL) { - fuzz_free(policy->key); - fuzz_free(policy->enc_xtn_hdr); - fuzz_free(policy); - return NULL; + if (copy_size > SRTP_MAX_NUM_ENC_HDR_XTND_IDS) { + copy_size = SRTP_MAX_NUM_ENC_HDR_XTND_IDS; } + for (size_t i = 0; i < copy_size; i++) { + (void)srtp_policy_add_enc_hdr_xtnd_id(policy, (*data)[i]); + } + *data += xtn_hdr_size; + *size -= xtn_hdr_size; } - policy->window_size = params.window_size; - policy->allow_repeat_tx = params.allow_repeat_tx; - policy->next = NULL; + if (profile != srtp_profile_null_null && + (params.do_extract_master_keys % 2) == 0) { + while (1) { + uint8_t do_extract_master_key; + EXTRACT_IF(&do_extract_master_key, *data, *size, + sizeof(do_extract_master_key)); -end: - return policy; -} + if ((do_extract_master_key % 2) == 0) { + break; + } -static srtp_policy_t *extract_policies(const uint8_t **data, size_t *size) -{ - srtp_policy_t *curpolicy = NULL, *policy_chain = NULL; + if (!extract_and_add_master_key(policy, data, size, key_size, + salt_size)) { + break; + } + } + } - curpolicy = extract_policy(data, size); - if (curpolicy == NULL) { + status = srtp_policy_set_window_size(policy, params.window_size); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(policy); + return NULL; + } + status = srtp_policy_set_allow_repeat_tx(policy, params.allow_repeat_tx); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(policy); return NULL; } - policy_chain = curpolicy; +end: + return policy; +} +static void extract_more_policies_to_session(const uint8_t **data, + size_t *size, + srtp_t srtp_ctx) +{ while (1) { uint8_t do_extract_policy; + srtp_policy_t policy = NULL; EXTRACT_IF(&do_extract_policy, *data, *size, sizeof(do_extract_policy)); /* Decide whether to extract another policy */ @@ -455,15 +467,19 @@ static srtp_policy_t *extract_policies(const uint8_t **data, size_t *size) break; } - curpolicy->next = extract_policy(data, size); - if (curpolicy->next == NULL) { + policy = extract_policy(data, size); + if (policy == NULL) { break; } - curpolicy = curpolicy->next; + + if (srtp_ctx != NULL) { + (void)srtp_stream_add(srtp_ctx, policy); + } + srtp_policy_destroy(policy); } end: - return policy_chain; + return; } static uint32_t *extract_remove_stream_ssrc(const uint8_t **data, @@ -527,28 +543,6 @@ static uint32_t *extract_set_roc(const uint8_t **data, return ret; } -static void free_policies(srtp_policy_t *curpolicy) -{ - size_t i; - while (curpolicy) { - srtp_policy_t *next = curpolicy->next; - - fuzz_free(curpolicy->key); - - for (i = 0; i < curpolicy->num_master_keys; i++) { - fuzz_free(curpolicy->keys[i]->key); - fuzz_free(curpolicy->keys[i]->mki_id); - fuzz_free(curpolicy->keys[i]); - } - - fuzz_free(curpolicy->keys); - fuzz_free(curpolicy->enc_xtn_hdr); - fuzz_free(curpolicy); - - curpolicy = next; - } -} - static uint8_t *run_srtp_func(const srtp_t srtp_ctx, const uint8_t **data, size_t *size) @@ -729,7 +723,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) uint8_t num_set_roc; uint32_t *set_roc = NULL; srtp_t srtp_ctx = NULL; - srtp_policy_t *policy_chain = NULL, *policy_chain_2 = NULL; + srtp_policy_t policy = NULL; + srtp_policy_t policy_2 = NULL; uint32_t randseed; static bool firstrun = true; @@ -751,22 +746,26 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) fuzz_mt19937_init(randseed); srand(randseed); - /* policy_chain is used to initialize the srtp context with */ - if ((policy_chain = extract_policies(&data, &size)) == NULL) { + /* policy is used to initialize the srtp context with */ + if ((policy = extract_policy(&data, &size)) == NULL) { goto end; } - /* policy_chain_2 is used as an argument to srtp_update later on */ - if ((policy_chain_2 = extract_policies(&data, &size)) == NULL) { + + /* Create context */ + if (srtp_create(&srtp_ctx, policy) != srtp_err_status_ok) { goto end; } - /* Create context */ - if (srtp_create(&srtp_ctx, policy_chain) != srtp_err_status_ok) { + /* Add additional policies extracted for initial stream setup */ + extract_more_policies_to_session(&data, &size, srtp_ctx); + + /* policy_2 is used as an argument for post-create stream additions */ + if ((policy_2 = extract_policy(&data, &size)) == NULL) { goto end; } - // free_policies(policy_chain); - // policy_chain = NULL; + /* Consume any additional policies from this second extraction phase */ + extract_more_policies_to_session(&data, &size, NULL); /* Don't check for NULL result -- no extractions is fine */ remove_stream_ssrc = @@ -807,19 +806,19 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) j += 2; } - if (policy_chain_2 != NULL) { - /* TODO srtp_update(srtp_ctx, policy_chain_2); */ + if (policy_2 != NULL) { + (void)srtp_stream_add(srtp_ctx, policy_2); /* Discard after using once */ - free_policies(policy_chain_2); - policy_chain_2 = NULL; + srtp_policy_destroy(policy_2); + policy_2 = NULL; } } } end: - free_policies(policy_chain); - free_policies(policy_chain_2); + srtp_policy_destroy(policy); + srtp_policy_destroy(policy_2); fuzz_free(remove_stream_ssrc); fuzz_free(set_roc); if (srtp_ctx != NULL) { diff --git a/fuzzer/fuzzer.h b/fuzzer/fuzzer.h index c8858b273..5da5269b4 100644 --- a/fuzzer/fuzzer.h +++ b/fuzzer/fuzzer.h @@ -1,4 +1,3 @@ -#define MAX_KEY_LEN 46 #define EXTRACT(dest, src, srcsize, copysize) \ { \ memcpy((dest), (src), (copysize)); \ @@ -24,22 +23,10 @@ #endif typedef srtp_err_status_t (*fuzz_srtp_func)(srtp_t, void *, size_t *, size_t); -typedef void (*fuzz_srtp_crypto_policy_func)(srtp_crypto_policy_t *); typedef srtp_err_status_t (*fuzz_srtp_get_length_func)(const srtp_t, size_t, size_t *); -struct fuzz_srtp_params { - uint8_t srtp_func; - uint8_t srtp_crypto_policy_func; - size_t window_size; - uint8_t allow_repeat_tx; - uint8_t ssrc_type; - uint32_t ssrc_value; - uint8_t key[MAX_KEY_LEN]; - uint8_t mki; -}; - static srtp_err_status_t fuzz_srtp_protect(srtp_t srtp_sender, void *hdr, size_t *len, @@ -78,40 +65,23 @@ const struct fuzz_srtp_func_ext srtp_funcs[] = { { fuzz_srtp_unprotect_rtcp, false, NULL } }; -struct fuzz_srtp_crypto_policy_func_ext { - fuzz_srtp_crypto_policy_func crypto_policy_func; +struct fuzz_srtp_profile_ext { + srtp_profile_t profile; const char *name; }; -const struct fuzz_srtp_crypto_policy_func_ext fuzz_srtp_crypto_policies[] = { - { srtp_crypto_policy_set_rtp_default, "" }, - { srtp_crypto_policy_set_rtcp_default, "" }, - { srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32, - "srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32" }, - { srtp_crypto_policy_set_aes_cm_128_null_auth, - "srtp_crypto_policy_set_aes_cm_128_null_auth" }, - { srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32, - "srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32" }, - { srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80, - "srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80" }, - { srtp_crypto_policy_set_aes_cm_256_null_auth, - "srtp_crypto_policy_set_aes_cm_256_null_auth" }, - { srtp_crypto_policy_set_null_cipher_hmac_null, - "srtp_crypto_policy_set_null_cipher_hmac_null" }, - { srtp_crypto_policy_set_null_cipher_hmac_sha1_80, - "srtp_crypto_policy_set_null_cipher_hmac_sha1_80" }, -#ifdef OPENSSL - { srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32, - "srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32" }, - { srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80, - "srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80" }, - { srtp_crypto_policy_set_aes_cm_192_null_auth, - "srtp_crypto_policy_set_aes_cm_192_null_auth" }, - { srtp_crypto_policy_set_aes_gcm_128_16_auth, - "srtp_crypto_policy_set_aes_gcm_128_16_auth" }, - { srtp_crypto_policy_set_aes_gcm_256_16_auth, - "srtp_crypto_policy_set_aes_gcm_256_16_auth" }, -#endif +const struct fuzz_srtp_profile_ext fuzz_srtp_profiles[] = { + { srtp_profile_null_null, "srtp_profile_null_null" }, + { srtp_profile_aes128_cm_sha1_80, "srtp_profile_aes128_cm_sha1_80" }, + { srtp_profile_aes128_cm_sha1_32, "srtp_profile_aes128_cm_sha1_32" }, + { srtp_profile_aes256_cm_sha1_80, "srtp_profile_aes256_cm_sha1_80" }, + { srtp_profile_aes256_cm_sha1_32, "srtp_profile_aes256_cm_sha1_32" }, + { srtp_profile_null_sha1_80, "srtp_profile_null_sha1_80" }, + { srtp_profile_null_sha1_32, "srtp_profile_null_sha1_32" }, + { srtp_profile_aes192_cm_sha1_80, "srtp_profile_aes192_cm_sha1_80" }, + { srtp_profile_aes192_cm_sha1_32, "srtp_profile_aes192_cm_sha1_32" }, + { srtp_profile_aead_aes_128_gcm, "srtp_profile_aead_aes_128_gcm" }, + { srtp_profile_aead_aes_256_gcm, "srtp_profile_aead_aes_256_gcm" }, }; struct fuzz_srtp_ssrc_type_ext { diff --git a/include/srtp.h b/include/srtp.h index 67cd19b95..8e0ab1fca 100644 --- a/include/srtp.h +++ b/include/srtp.h @@ -119,6 +119,8 @@ extern "C" { */ #define SRTP_MAX_NUM_MASTER_KEYS 16 +#define SRTP_MAX_NUM_ENC_HDR_XTND_IDS 16 + #define SRTP_SALT_LEN 14 /* @@ -235,30 +237,6 @@ typedef enum { sec_serv_conf_and_auth = 3 /**< confidentiality and authentication */ } srtp_sec_serv_t; -/** - * @brief srtp_crypto_policy_t describes a particular crypto policy that - * can be applied to an SRTP stream. - * - * A srtp_crypto_policy_t describes a particular cryptographic policy that - * can be applied to an SRTP or SRTCP stream. An SRTP session policy - * consists of a list of these policies, one for each SRTP stream - * in the session. - */ -typedef struct srtp_crypto_policy_t { - srtp_cipher_type_id_t cipher_type; /**< An integer representing */ - /**< the type of cipher. */ - size_t cipher_key_len; /**< The length of the cipher key */ - /**< in octets. */ - srtp_auth_type_id_t auth_type; /**< An integer representing the */ - /**< authentication function. */ - size_t auth_key_len; /**< The length of the authentication */ - /**< function key in octets. */ - size_t auth_tag_len; /**< The length of the authentication */ - /**< tag in octets. */ - srtp_sec_serv_t sec_serv; /**< The flag indicating the security */ - /**< services to be applied. */ -} srtp_crypto_policy_t; - /** * @brief srtp_ssrc_type_t describes the type of an SSRC. * @@ -291,71 +269,302 @@ typedef struct { /**< wildcard */ } srtp_ssrc_t; +/* + * @brief identifies a particular SRTP profile + * + * An srtp_profile_t enumeration is used to identify a particular SRTP + * profile (that is, a set of algorithms and parameters). + */ +typedef enum { + srtp_profile_reserved = 0, + srtp_profile_null_null = 1, + srtp_profile_aes128_cm_sha1_80 = 2, + srtp_profile_aes128_cm_sha1_32 = 3, + srtp_profile_aes192_cm_sha1_80 = 4, + srtp_profile_aes192_cm_sha1_32 = 5, + srtp_profile_aes256_cm_sha1_80 = 6, + srtp_profile_aes256_cm_sha1_32 = 7, + srtp_profile_null_sha1_80 = 8, + srtp_profile_null_sha1_32 = 9, + srtp_profile_aead_aes_128_gcm = 10, + srtp_profile_aead_aes_256_gcm = 11 +} srtp_profile_t; + +typedef struct srtp_policy_ctx_t_ srtp_policy_ctx_t; +typedef srtp_policy_ctx_t *srtp_policy_t; + +/** + * @brief Allocate a new policy handle. + * + * A policy handle describes one SRTP stream policy. Configure it with + * srtp_policy_set_ssrc(), srtp_policy_set_profile(), optional MKI and + * feature setters, and srtp_policy_add_key() before passing it to + * srtp_create() or srtp_stream_add(). + * + * @param policy output pointer that receives the allocated policy. + * + * @return + * - srtp_err_status_ok if allocation succeeded. + * - srtp_err_status_bad_param if policy is NULL. + * - srtp_err_status_alloc_fail if allocation failed. + */ +srtp_err_status_t srtp_policy_create(srtp_policy_t *policy); + +/** + * @brief Clone an existing policy handle. + * + * @param policy source policy to clone. + * @param cloned_policy output pointer that receives the cloned policy. + * + * This copies all fields of the source policy, including configured keys. The + * cloned policy can be modified independently from the source policy. + * + * @return + * - srtp_err_status_ok if cloning succeeded. + * - srtp_err_status_bad_param if either argument is NULL. + * - srtp_err_status_alloc_fail if allocation failed. + */ +srtp_err_status_t srtp_policy_clone(srtp_policy_t policy, + srtp_policy_t *cloned_policy); + +/** + * @brief Set the policy SSRC selector. + * + * @param policy policy handle. + * @param ssrc SSRC selector to apply. + * + * Valid selectors are ssrc_specific, ssrc_any_inbound, and ssrc_any_outbound. + * + * @return + * - srtp_err_status_ok if the SSRC selector was accepted. + * - srtp_err_status_bad_param if policy is NULL or ssrc.type is invalid. + */ +srtp_err_status_t srtp_policy_set_ssrc(srtp_policy_t policy, srtp_ssrc_t ssrc); + +/** + * @brief Set the SRTP profile and initialize RTP/RTCP crypto settings. + * + * @param policy policy handle. + * @param profile profile to apply. + * + * Call this before srtp_policy_set_sec_serv() and before validation. Keys + * added with srtp_policy_add_key() must match this profile's master key and + * salt lengths when the policy is validated. + * + * @return + * - srtp_err_status_ok if the profile was applied. + * - srtp_err_status_bad_param if policy is NULL or profile is invalid. + * - [other] if profile-to-crypto mapping failed. + */ +srtp_err_status_t srtp_policy_set_profile(srtp_policy_t policy, + srtp_profile_t profile); + +/** + * @brief Get the profile currently set on a policy. + * + * @param policy policy handle. + * @param profile output pointer that receives the configured profile. + * + * @return + * - srtp_err_status_ok if the profile was returned. + * - srtp_err_status_bad_param if any argument is NULL. + */ +srtp_err_status_t srtp_policy_get_profile(srtp_policy_t policy, + srtp_profile_t *profile); + +/** + * @brief Override security-service flags for RTP and RTCP. + * + * @param policy policy handle. + * @param rtp_sec_serv RTP security-service flags. + * @param rtcp_sec_serv RTCP security-service flags. + * + * The policy must already have a profile set with srtp_policy_set_profile(). + * + * @return + * - srtp_err_status_ok if flags were applied. + * - srtp_err_status_bad_param if policy is NULL or profile is unset. + */ +srtp_err_status_t srtp_policy_set_sec_serv(srtp_policy_t policy, + srtp_sec_serv_t rtp_sec_serv, + srtp_sec_serv_t rtcp_sec_serv); + +/** + * @brief Enable or disable MKI on the policy. + * + * @param policy policy handle. + * @param mki_len MKI length in octets (0 disables MKI). + * + * mki_len must be <= SRTP_MAX_MKI_LEN. + * Call this with mki_len > 0 before adding MKI-tagged keys via + * srtp_policy_add_key(). Call this with mki_len == 0 to disable MKI. + * + * @return + * - srtp_err_status_ok if MKI settings were applied. + * - srtp_err_status_bad_param if policy is NULL or mki_len is invalid. + */ +srtp_err_status_t srtp_policy_use_mki(srtp_policy_t policy, size_t mki_len); + +/** + * @brief Read the configured MKI length. + * + * @param policy policy handle. + * @param mki_len output pointer that receives MKI length in octets. + * + * @return + * - srtp_err_status_ok if MKI length was returned. + * - srtp_err_status_bad_param if any argument is NULL. + */ +srtp_err_status_t srtp_policy_get_mki_length(srtp_policy_t policy, + size_t *mki_len); + +/** + * @brief Add a master key and salt to a policy handle. + * + * @param policy policy handle. + * @param key pointer to key bytes. + * @param key_len key length in octets. + * @param salt pointer to salt bytes. + * @param salt_len salt length in octets. + * @param mki pointer to MKI bytes for this key. + * @param mki_len MKI length in octets for this key. + * + * key_len + salt_len must be <= SRTP_MAX_KEY_LEN. + * key and salt must not be NULL. + * mki must not be NULL when mki_len > 0. + * If MKI is enabled, mki_len must match the configured MKI length. + * If MKI is disabled, mki_len must be 0 and only one key can be configured. A + * policy can hold at most SRTP_MAX_NUM_MASTER_KEYS keys. + * + * The key and salt are stored separately in the policy. Validation requires + * their lengths to exactly match the configured profile. The null/null profile + * is valid only without keys and without MKI. + * + * @return + * - srtp_err_status_ok if key was added. + * - srtp_err_status_bad_param if policy is NULL, key/salt/MKI arguments are + * invalid, MKI state does not match mki_len, the non-MKI single-key limit + * or key limit is exceeded, or key/salt/MKI sizes exceed supported limits. + */ +srtp_err_status_t srtp_policy_add_key(srtp_policy_t policy, + const uint8_t *key, + size_t key_len, + const uint8_t *salt, + size_t salt_len, + const uint8_t *mki, + size_t mki_len); + +/** + * @brief Remove all configured master keys from a policy. + * + * @param policy policy handle. + * + * This clears the configured key material and resets key count to zero. + * Other policy settings (for example, profile, SSRC, and MKI mode) are + * unchanged. + * + * @return + * - srtp_err_status_ok if keys were removed. + * - srtp_err_status_bad_param if policy is NULL. + */ +srtp_err_status_t srtp_policy_remove_keys(srtp_policy_t policy); + +/** + * @brief Set replay-window size. + * + * @param policy policy handle. + * @param window_size replay window size in packets. + * + * window_size must be 0 or in [64, 0x7fff]. + * + * @return + * - srtp_err_status_ok if value was accepted. + * - srtp_err_status_bad_param if policy is NULL or value is invalid. + */ +srtp_err_status_t srtp_policy_set_window_size(srtp_policy_t policy, + size_t window_size); + +/** + * @brief Enable or disable repeat transmission for RTP. + * + * @param policy policy handle. + * @param allow true to allow repeat transmissions, false otherwise. + * + * @return + * - srtp_err_status_ok if value was applied. + * - srtp_err_status_bad_param if policy is NULL. + */ +srtp_err_status_t srtp_policy_set_allow_repeat_tx(srtp_policy_t policy, + bool allow); + +/** + * @brief Enable or disable cryptex for this policy. + * + * @param policy policy handle. + * @param use_cryptex true to enable cryptex, false to disable. + * + * @return + * - srtp_err_status_ok if value was applied. + * - srtp_err_status_bad_param if policy is NULL. + */ +srtp_err_status_t srtp_policy_set_cryptex(srtp_policy_t policy, + bool use_cryptex); + +/** + * @brief Add an encrypted header extension ID. + * + * @param policy policy handle. + * @param hdr_xtnd_id header extension ID to encrypt. + * + * Duplicate IDs are rejected. + * The number of configured IDs must be < SRTP_MAX_NUM_ENC_HDR_XTND_IDS. + * Policies with both cryptex and encrypted header extensions are rejected by + * srtp_policy_validate(). + * + * @return + * - srtp_err_status_ok if ID was added. + * - srtp_err_status_bad_param if policy is NULL, the ID already exists, or + * the list is full. + */ +srtp_err_status_t srtp_policy_add_enc_hdr_xtnd_id(srtp_policy_t policy, + uint8_t hdr_xtnd_id); + /** - * @brief srtp_master_key_t represents a master key. There will - * be a Master Key Index and the Master Key associated with the - * Master Key Index. - */ -typedef struct srtp_master_key_t { - uint8_t *key; - uint8_t *mki_id; -} srtp_master_key_t; - -/** - * @brief represents the policy for an SRTP session. - * - * A single srtp_policy_t struct represents the policy for a single - * SRTP stream, and a linked list of these elements represents the - * policy for an entire SRTP session. Each element contains the SRTP - * and SRTCP crypto policies for that stream, a pointer to the SRTP - * master key for that stream, the SSRC describing that stream, or a - * flag indicating a `wildcard' SSRC value, and a `next' field that - * holds a pointer to the next element in the list of policy elements, - * or NULL if it is the last element. - * - * The wildcard value SSRC_ANY_INBOUND matches any SSRC from an - * inbound stream that for which there is no explicit SSRC entry in - * another policy element. Similarly, the value SSRC_ANY_OUTBOUND - * will matches any SSRC from an outbound stream that does not appear - * in another policy element. Note that wildcard SSRCs &b cannot be - * used to match both inbound and outbound traffic. This restriction - * is intentional, and it allows libSRTP to ensure that no security - * lapses result from accidental re-use of SSRC values during key - * sharing. - * - * @warning The final element of the list @b must have its `next' pointer - * set to NULL. - */ - -typedef struct srtp_policy_t { - srtp_ssrc_t ssrc; /**< The SSRC value of stream, or the */ - /**< flags SSRC_ANY_INBOUND or */ - /**< SSRC_ANY_OUTBOUND if key sharing */ - /**< is used for this policy element. */ - srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ - srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ - uint8_t *key; /**< Pointer to the SRTP master key for */ - /**< this stream. */ - srtp_master_key_t **keys; /** Array of Master Key structures */ - size_t num_master_keys; /** Number of master keys */ - bool use_mki; /** Whether MKI is in use */ - size_t mki_size; /** Size of MKI when in use */ - size_t window_size; /**< The window size to use for replay */ - /**< protection. */ - bool allow_repeat_tx; /**< Whether retransmissions of */ - /**< packets with the same sequence */ - /**< number are allowed. */ - /**< (Note that such repeated */ - /**< transmissions must have the same */ - /**< RTP payload, or a severe security */ - /**< weakness is introduced!) */ - uint8_t *enc_xtn_hdr; /**< List of header ids to encrypt. */ - size_t enc_xtn_hdr_count; /**< Number of entries in list of header */ - /**< ids. */ - bool use_cryptex; /**< Encrypt header block and CSRCs with */ - /**< cryptex, RFC 9335. */ - struct srtp_policy_t *next; /**< Pointer to next stream policy. */ -} srtp_policy_t; + * @brief Remove all encrypted header extension IDs from a policy. + * + * @param policy policy handle. + * + * This clears the configured encrypted header extension IDs and resets the + * count to zero. + * + * @return + * - srtp_err_status_ok if IDs were removed. + * - srtp_err_status_bad_param if policy is NULL. + */ +srtp_err_status_t srtp_policy_remove_enc_hdr_xtnd_ids(srtp_policy_t policy); + +/** + * @brief Destroy a policy handle. + * + * @param policy policy handle. NULL is ignored. + */ +void srtp_policy_destroy(srtp_policy_t policy); + +/** + * @brief Validate that policy contains a usable configuration. + * + * @param policy policy handle. + * + * Validation checks include profile, SSRC selector, key/MKI consistency, + * key count, profile key/salt lengths, replay-window constraints, and invalid + * cryptex/encrypted-header-extension combinations. The null/null profile is + * valid without keys and invalid with configured keys or MKI. + * + * @return + * - srtp_err_status_ok if policy is valid. + * - srtp_err_status_bad_param if policy is NULL or configuration is invalid. + */ +srtp_err_status_t srtp_policy_validate(srtp_policy_t policy); /** * @brief An srtp_t points to an SRTP session structure. @@ -497,19 +706,16 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx, * @param session is a pointer to the SRTP session to which the policy is * to be added. * - * @param policy is the srtp_policy_t struct that describes the policy - * for the session. The struct may be a single element, or it may be - * the head of a list, in which case each element of the list is - * processed. It may also be NULL, in which case streams should be added - * later using srtp_stream_add(). The final element of the list @b must - * have its `next' field set to NULL. + * @param policy is an srtp_policy_t handle that describes one stream policy. + * It may be NULL, in which case streams can be added later using + * srtp_stream_add(). * * @return * - srtp_err_status_ok if creation succeeded. * - srtp_err_status_alloc_fail if allocation failed. * - srtp_err_status_init_fail if initialization failed. */ -srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t *policy); +srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t policy); /** * @brief srtp_stream_add() allocates and initializes an SRTP stream @@ -525,7 +731,7 @@ srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t *policy); * - srtp_err_status_alloc_fail if stream allocation failed * - srtp_err_status_init_fail if stream initialization failed. */ -srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t *policy); +srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t policy); /** * @brief srtp_stream_remove() deallocates an SRTP stream. @@ -565,11 +771,8 @@ srtp_err_status_t srtp_stream_remove(srtp_t session, uint32_t ssrc); * @param session is the SRTP session that contains the streams * to be updated. * - * @param policy is the srtp_policy_t struct that describes the policy - * for the session. The struct may be a single element, or it may be - * the head of a list, in which case each element of the list is - * processed. The final element of the list @b must - * have its `next' field set to NULL. + * @param policy is an srtp_policy_t handle that describes the update policy + * to apply to matching stream(s). * * @return * - srtp_err_status_ok if stream creation succeed. @@ -578,7 +781,7 @@ srtp_err_status_t srtp_stream_remove(srtp_t session, uint32_t ssrc); * - [other] otherwise. * */ -srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); +srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t policy); /** * @brief srtp_stream_update() updates a SRTP stream. @@ -591,8 +794,8 @@ srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); * @param session is the SRTP session that contains the streams * to be updated. * - * @param policy is the srtp_policy_t struct that describes the policy - * for the session. + * @param policy is an srtp_policy_t handle that describes the update policy + * to apply to matching stream(s). * * @return * - srtp_err_status_ok if stream creation succeeded. @@ -602,386 +805,7 @@ srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); * */ srtp_err_status_t srtp_stream_update(srtp_t session, - const srtp_policy_t *policy); - -/** - * @brief srtp_crypto_policy_set_rtp_default() sets a crypto policy - * structure to the SRTP default policy for RTP protection. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_rtp_default(&p) sets the - * srtp_crypto_policy_t at location p to the SRTP default policy for RTP - * protection, as defined in the specification. This function is a - * convenience that helps to avoid dealing directly with the policy - * data structure. You are encouraged to initialize policy elements - * with this function call. Doing so may allow your code to be - * forward compatible with later versions of libSRTP that include more - * elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_rtcp_default() sets a crypto policy - * structure to the SRTP default policy for RTCP protection. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_rtcp_default(&p) sets the - * srtp_crypto_policy_t at location p to the SRTP default policy for RTCP - * protection, as defined in the specification. This function is a - * convenience that helps to avoid dealing directly with the policy - * data structure. You are encouraged to initialize policy elements - * with this function call. Doing so may allow your code to be - * forward compatible with later versions of libSRTP that include more - * elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto - * policy structure to the SRTP default policy for RTP protection. - * - * @param p is a pointer to the policy structure to be set - * - * The function srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() is a - * synonym for srtp_crypto_policy_set_rtp_default(). It conforms to the - * naming convention used in RFC 4568 (SDP Security Descriptions for - * Media Streams). - * - * @return void. - * - */ -#define srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(p) \ - srtp_crypto_policy_set_rtp_default(p) - -/** - * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto - * policy structure to a short-authentication tag policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&p) - * sets the srtp_crypto_policy_t at location p to use policy - * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568. - * This policy uses AES-128 - * Counter Mode encryption and HMAC-SHA1 authentication, with an - * authentication tag that is only 32 bits long. This length is - * considered adequate only for protecting audio and video media that - * use a stateless playback function. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This crypto policy is intended for use in SRTP, but not in - * SRTCP. It is recommended that a policy that uses longer - * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_128_null_auth() sets a crypto - * policy structure to an encryption-only policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_128_null_auth(&p) sets - * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-128 Counter Mode), but to use no authentication method. This - * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 - * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This policy is NOT RECOMMENDED for SRTP unless it is - * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see - * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto - * policy structure to an authentication-only policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&p) - * sets the srtp_crypto_policy_t at location p to use HMAC-SHA1 with an 80 - * bit authentication tag to provide message authentication, but to - * use no encryption. This policy is NOT RECOMMENDED for SRTP unless - * there is a requirement to forgo encryption. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This policy is NOT RECOMMENDED for SRTP unless there is a - * requirement to forgo encryption. - * - * @return void. - * - */ -void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_null_cipher_hmac_null() sets a crypto - * policy structure to use no encryption or authentication. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_null_cipher_hmac_null(&p) - * sets the srtp_crypto_policy_t at location p to use no encryption and - * no authentication. This policy should only be used for testing and - * troubleshooting. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This policy is NOT RECOMMENDED for SRTP unless there is a - * requirement to forgo encryption and authentication. - * - * @return void. - * - */ -void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto - * policy structure to a encryption and authentication policy using AES-256 - * for RTP protection. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&p) - * sets the srtp_crypto_policy_t at location p to use policy - * AES_CM_256_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-256 - * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit - * authentication tag. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto - * policy structure to a short-authentication tag policy using AES-256 - * encryption. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&p) - * sets the srtp_crypto_policy_t at location p to use policy - * AES_CM_256_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-256 - * Counter Mode encryption and HMAC-SHA1 authentication, with an - * authentication tag that is only 32 bits long. This length is - * considered adequate only for protecting audio and video media that - * use a stateless playback function. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This crypto policy is intended for use in SRTP, but not in - * SRTCP. It is recommended that a policy that uses longer - * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_256_null_auth() sets a crypto - * policy structure to an encryption-only policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_256_null_auth(&p) sets - * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-256 Counter Mode), but to use no authentication method. This - * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 - * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This policy is NOT RECOMMENDED for SRTP unless it is - * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see - * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80() sets a crypto - * policy structure to a encryption and authentication policy using AES-192 - * for RTP protection. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&p) - * sets the srtp_crypto_policy_t at location p to use policy - * AES_CM_192_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-192 - * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit - * authentication tag. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32() sets a crypto - * policy structure to a short-authentication tag policy using AES-192 - * encryption. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&p) - * sets the srtp_crypto_policy_t at location p to use policy - * AES_CM_192_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-192 - * Counter Mode encryption and HMAC-SHA1 authentication, with an - * authentication tag that is only 32 bits long. This length is - * considered adequate only for protecting audio and video media that - * use a stateless playback function. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This crypto policy is intended for use in SRTP, but not in - * SRTCP. It is recommended that a policy that uses longer - * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 - * (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_cm_192_null_auth() sets a crypto - * policy structure to an encryption-only policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_cm_192_null_auth(&p) sets - * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-192 Counter Mode), but to use no authentication method. This - * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 - * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @warning This policy is NOT RECOMMENDED for SRTP unless it is - * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see - * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_gcm_128_16_auth() sets a crypto - * policy structure to an AEAD encryption policy. - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_gcm_128_16_auth(&p) sets - * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-128 Galois Counter Mode) with 16 octet auth tag. This - * policy applies confidentiality and authentication to both the - * RTP and RTCP packets. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); - -/** - * @brief srtp_crypto_policy_set_aes_gcm_256_16_auth() sets a crypto - * policy structure to an AEAD encryption policy - * - * @param p is a pointer to the policy structure to be set - * - * The function call srtp_crypto_policy_set_aes_gcm_256_16_auth(&p) sets - * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-256 Galois Counter Mode) with 16 octet auth tag. This - * policy applies confidentiality and authentication to both the - * RTP and RTCP packets. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return void. - * - */ -void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); + const srtp_policy_t policy); /** * @brief srtp_dealloc() deallocates storage for an SRTP session @@ -1000,76 +824,6 @@ void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); */ srtp_err_status_t srtp_dealloc(srtp_t s); -/* - * @brief identifies a particular SRTP profile - * - * An srtp_profile_t enumeration is used to identify a particular SRTP - * profile (that is, a set of algorithms and parameters). - */ -typedef enum { - srtp_profile_reserved = 0, - srtp_profile_aes128_cm_sha1_80 = 1, - srtp_profile_aes128_cm_sha1_32 = 2, - srtp_profile_null_sha1_80 = 5, - srtp_profile_null_sha1_32 = 6, - srtp_profile_aead_aes_128_gcm = 7, - srtp_profile_aead_aes_256_gcm = 8 -} srtp_profile_t; - -/** - * @brief srtp_crypto_policy_set_from_profile_for_rtp() sets a crypto policy - * structure to the appropriate value for RTP based on an srtp_profile_t - * - * @param policy is a pointer to the policy structure to be set - * - * @param profile is an enumeration for the policy to be set - * - * The function call srtp_crypto_policy_set_rtp_default(&policy, profile) - * sets the srtp_crypto_policy_t at location policy to the policy for RTP - * protection, as defined by the srtp_profile_t profile. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return values - * - srtp_err_status_ok no problems were encountered - * - srtp_err_status_bad_param the profile is not supported - * - */ -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( - srtp_crypto_policy_t *policy, - srtp_profile_t profile); - -/** - * @brief srtp_crypto_policy_set_from_profile_for_rtcp() sets a crypto policy - * structure to the appropriate value for RTCP based on an srtp_profile_t - * - * @param policy is a pointer to the policy structure to be set - * - * @param profile is an enumeration for the policy to be set - * - * The function call srtp_crypto_policy_set_rtcp_default(&policy, profile) - * sets the srtp_crypto_policy_t at location policy to the policy for RTCP - * protection, as defined by the srtp_profile_t profile. - * - * This function is a convenience that helps to avoid dealing directly - * with the policy data structure. You are encouraged to initialize - * policy elements with this function call. Doing so may allow your - * code to be forward compatible with later versions of libSRTP that - * include more elements in the srtp_crypto_policy_t datatype. - * - * @return values - * - srtp_err_status_ok no problems were encountered - * - srtp_err_status_bad_param the profile is not supported - * - */ -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( - srtp_crypto_policy_t *policy, - srtp_profile_t profile); - /** * @brief returns the master key length for a given SRTP profile */ @@ -1090,6 +844,7 @@ size_t srtp_profile_get_master_salt_length(srtp_profile_t profile); * @warning There must be at least bytes_in_salt + bytes_in_key bytes * available at the location pointed to by key. * + * */ void srtp_append_salt_to_key(uint8_t *key, size_t bytes_in_key, diff --git a/include/srtp_priv.h b/include/srtp_priv.h index 86f6fcafa..575c0f41e 100644 --- a/include/srtp_priv.h +++ b/include/srtp_priv.h @@ -69,6 +69,66 @@ 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; +typedef struct srtp_crypto_policy_t { + srtp_cipher_type_id_t cipher_type; + size_t cipher_key_len; + srtp_auth_type_id_t auth_type; + size_t auth_key_len; + size_t auth_tag_len; + srtp_sec_serv_t sec_serv; +} srtp_crypto_policy_t; + +typedef struct srtp_master_key_t { + uint8_t key[SRTP_MAX_KEY_LEN]; + size_t key_len; + size_t salt_len; + uint8_t mki_id[SRTP_MAX_MKI_LEN]; + size_t mki_id_len; +} srtp_master_key_t; + +typedef struct srtp_policy_ctx_t_ { + srtp_profile_t profile; /**< The SRTP profile that this policy applies to */ + srtp_ssrc_t ssrc; /**< The SSRC value of stream, or the */ + /**< flags SSRC_ANY_INBOUND or */ + /**< SSRC_ANY_OUTBOUND if key sharing */ + /**< is used for this policy element. */ + srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ + srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ + srtp_master_key_t master_keys[SRTP_MAX_NUM_MASTER_KEYS]; + size_t num_master_keys; /** Number of master keys */ + bool use_mki; /** Whether MKI is in use */ + size_t mki_size; /** Size of MKI when in use */ + size_t window_size; /**< The window size to use for replay */ + /**< protection. */ + bool allow_repeat_tx; /**< Whether retransmissions of */ + /**< packets with the same sequence */ + /**< number are allowed. */ + /**< (Note that such repeated */ + /**< transmissions must have the same */ + /**< RTP payload, or a severe security */ + /**< weakness is introduced!) */ + uint8_t enc_xtn_hdr[SRTP_MAX_NUM_ENC_HDR_XTND_IDS]; /**< List of header ids + to encrypt. */ + size_t enc_xtn_hdr_count; /**< Number of entries in list of header */ + /**< ids. */ + bool use_cryptex; /**< Encrypt header block and CSRCs with */ + /**< cryptex, RFC 9335. */ +} srtp_policy_ctx_t_; + +static inline bool srtp_policy_is_null_cipher_null_auth( + const srtp_policy_t policy) +{ + return policy != NULL && policy->rtp.cipher_type == SRTP_NULL_CIPHER && + policy->rtp.auth_type == SRTP_NULL_AUTH && + policy->rtcp.cipher_type == SRTP_NULL_CIPHER && + policy->rtcp.auth_type == SRTP_NULL_AUTH; +} + +static inline bool srtp_policy_is_valid_window_size(size_t window_size) +{ + return window_size == 0 || (window_size >= 64 && window_size < 0x8000); +} + /* * the following declarations are libSRTP internal functions */ diff --git a/meson.build b/meson.build index 9e40ae97d..233bfeb05 100644 --- a/meson.build +++ b/meson.build @@ -203,6 +203,7 @@ endif sources = files( 'srtp/srtp.c', + 'srtp/srtp_policy.c' ) ciphers_sources = files( diff --git a/srtp.def b/srtp.def index bf3142775..bd4524f96 100644 --- a/srtp.def +++ b/srtp.def @@ -9,23 +9,24 @@ srtp_stream_remove srtp_update srtp_stream_update srtp_get_stream -srtp_crypto_policy_set_rtp_default -srtp_crypto_policy_set_rtcp_default -srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32 -srtp_crypto_policy_set_aes_cm_128_null_auth -srtp_crypto_policy_set_null_cipher_hmac_sha1_80 -srtp_crypto_policy_set_null_cipher_hmac_null -srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80 -srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32 -srtp_crypto_policy_set_aes_cm_192_null_auth -srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80 -srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32 -srtp_crypto_policy_set_aes_cm_256_null_auth -srtp_crypto_policy_set_aes_gcm_128_16_auth -srtp_crypto_policy_set_aes_gcm_256_16_auth +srtp_policy_create +srtp_policy_clone +srtp_policy_destroy +srtp_policy_validate +srtp_policy_set_ssrc +srtp_policy_set_profile +srtp_policy_get_profile +srtp_policy_set_sec_serv +srtp_policy_use_mki +srtp_policy_get_mki_length +srtp_policy_add_key +srtp_policy_remove_keys +srtp_policy_set_window_size +srtp_policy_set_allow_repeat_tx +srtp_policy_set_cryptex +srtp_policy_add_enc_hdr_xtnd_id +srtp_policy_remove_enc_hdr_xtnd_ids srtp_dealloc -srtp_crypto_policy_set_from_profile_for_rtp -srtp_crypto_policy_set_from_profile_for_rtcp srtp_profile_get_master_key_length srtp_profile_get_master_salt_length srtp_append_salt_to_key diff --git a/srtp/srtp.c b/srtp/srtp.c index 41a34e23c..3d14d3364 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -551,59 +551,14 @@ static srtp_err_status_t srtp_remove_and_dealloc_streams( return data.status; } -static srtp_err_status_t srtp_valid_policy(const srtp_policy_t *policy) -{ - if (policy == NULL) { - return srtp_err_status_bad_param; - } - - if (policy->key == NULL) { - if (policy->num_master_keys <= 0) { - return srtp_err_status_bad_param; - } - - if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) { - return srtp_err_status_bad_param; - } - - if (policy->use_mki) { - if (policy->mki_size == 0 || policy->mki_size > SRTP_MAX_MKI_LEN) { - return srtp_err_status_bad_param; - } - } else if (policy->mki_size != 0) { - return srtp_err_status_bad_param; - } - - for (size_t i = 0; i < policy->num_master_keys; i++) { - if (policy->keys[i]->key == NULL) { - return srtp_err_status_bad_param; - } - if (policy->use_mki && policy->keys[i]->mki_id == NULL) { - return srtp_err_status_bad_param; - } - } - } else { - if (policy->use_mki || policy->mki_size != 0) { - return srtp_err_status_bad_param; - } - } - - return srtp_err_status_ok; -} - static srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, - const srtp_policy_t *p) + const srtp_policy_t p) { srtp_stream_ctx_t *str; srtp_err_status_t stat; size_t i = 0; srtp_session_keys_t *session_keys = NULL; - stat = srtp_valid_policy(p); - if (stat != srtp_err_status_ok) { - return stat; - } - /* * This function allocates the stream context, rtp and rtcp ciphers * and auth functions, and key limit structure. If there is a @@ -621,23 +576,28 @@ static srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, *str_ptr = str; /* - *To keep backwards API compatible if someone is using multiple master + * To keep backwards API compatible if someone is using multiple master * keys then key should be set to NULL */ - if (p->key != NULL) { + if (p->num_master_keys > 0) { + str->num_master_keys = p->num_master_keys; + } else if (srtp_policy_is_null_cipher_null_auth(p)) { + /* Protect/unprotect paths still require a runtime session key slot. */ str->num_master_keys = 1; } else { - str->num_master_keys = p->num_master_keys; + srtp_stream_dealloc(str, NULL); + return srtp_err_status_bad_param; } - str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( - sizeof(srtp_session_keys_t) * str->num_master_keys); + if (str->num_master_keys) { + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( + sizeof(srtp_session_keys_t) * str->num_master_keys); - if (str->session_keys == NULL) { - srtp_stream_dealloc(str, NULL); - return srtp_err_status_alloc_fail; + if (str->session_keys == NULL) { + srtp_stream_dealloc(str, NULL); + return srtp_err_status_alloc_fail; + } } - for (i = 0; i < str->num_master_keys; i++) { session_keys = &str->session_keys[i]; @@ -691,7 +651,7 @@ static srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, } } - if (p->enc_xtn_hdr && p->enc_xtn_hdr_count > 0) { + if (p->enc_xtn_hdr_count > 0) { srtp_cipher_type_id_t enc_xtn_hdr_cipher_type; size_t enc_xtn_hdr_cipher_key_len; @@ -1251,11 +1211,10 @@ srtp_err_status_t srtp_stream_init_keys(srtp_session_keys_t *session_keys, srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL); if (mki_size != 0) { - if (master_key->mki_id == NULL) { + if (master_key->mki_id_len == 0 || master_key->mki_id_len != mki_size) { return srtp_err_status_bad_param; } session_keys->mki_id = srtp_crypto_alloc(mki_size); - if (session_keys->mki_id == NULL) { return srtp_err_status_init_fail; } @@ -1607,55 +1566,67 @@ srtp_err_status_t srtp_stream_init_keys(srtp_session_keys_t *session_keys, } srtp_err_status_t srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, - const srtp_policy_t *p) + const srtp_policy_t p) { srtp_err_status_t status = srtp_err_status_ok; - if (p->key != NULL) { - if (p->use_mki) { - return srtp_err_status_bad_param; - } - srtp_master_key_t single_master_key; - srtp->num_master_keys = 1; - srtp->use_mki = false; - srtp->mki_size = 0; - single_master_key.key = p->key; - single_master_key.mki_id = NULL; - status = srtp_stream_init_keys(&srtp->session_keys[0], - &single_master_key, 0); - } else { - if (p->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) { - return srtp_err_status_bad_param; - } - if (p->use_mki && p->mki_size == 0) { + if (p->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) { + return srtp_err_status_bad_param; + } + if (p->use_mki && p->mki_size == 0) { + return srtp_err_status_bad_param; + } + + srtp->use_mki = p->use_mki; + srtp->mki_size = p->mki_size; + + if (p->num_master_keys == 0) { + srtp_session_keys_t *session_keys; + + if (!srtp_policy_is_null_cipher_null_auth(p) || p->use_mki || + srtp->num_master_keys != 1) { return srtp_err_status_bad_param; } - srtp->num_master_keys = p->num_master_keys; - srtp->use_mki = p->use_mki; - srtp->mki_size = p->mki_size; + session_keys = &srtp->session_keys[0]; + srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL); - for (size_t i = 0; i < srtp->num_master_keys; i++) { - status = srtp_stream_init_keys(&srtp->session_keys[i], p->keys[i], - srtp->mki_size); + status = srtp_cipher_init(session_keys->rtp_cipher, NULL); + if (status) { + return status; + } + status = srtp_auth_init(session_keys->rtp_auth, NULL); + if (status) { + return status; + } + if (session_keys->rtp_xtn_hdr_cipher != NULL) { + status = srtp_cipher_init(session_keys->rtp_xtn_hdr_cipher, NULL); if (status) { return status; } } + status = srtp_cipher_init(session_keys->rtcp_cipher, NULL); + if (status) { + return status; + } + return srtp_auth_init(session_keys->rtcp_auth, NULL); + } + + for (size_t i = 0; i < srtp->num_master_keys; i++) { + status = srtp_stream_init_keys(&srtp->session_keys[i], + &(p->master_keys[i]), srtp->mki_size); + if (status) { + return status; + } } return status; } static srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp, - const srtp_policy_t *p) + const srtp_policy_t p) { srtp_err_status_t err; - err = srtp_valid_policy(p); - if (err != srtp_err_status_ok) { - return err; - } - debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", (unsigned int)p->ssrc.value); @@ -1667,9 +1638,9 @@ static srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp, * Let a window size of 0 imply the default value. */ - if (p->window_size != 0 && - (p->window_size < 64 || p->window_size >= 0x8000)) + if (!srtp_policy_is_valid_window_size(p->window_size)) { return srtp_err_status_bad_param; + } if (p->window_size != 0) { err = srtp_rdbx_init(&srtp->rtp_rdbx, p->window_size); @@ -3261,7 +3232,7 @@ srtp_err_status_t srtp_dealloc(srtp_t session) return srtp_err_status_ok; } -srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t *policy) +srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t policy) { srtp_err_status_t status; srtp_stream_t tmp; @@ -3271,7 +3242,7 @@ srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t *policy) return srtp_err_status_bad_param; } - status = srtp_valid_policy(policy); + status = srtp_policy_validate(policy); if (status != srtp_err_status_ok) { return status; } @@ -3331,7 +3302,7 @@ srtp_err_status_t srtp_stream_add(srtp_t session, const srtp_policy_t *policy) } srtp_err_status_t srtp_create(srtp_t *session, /* handle for session */ - const srtp_policy_t *policy) + const srtp_policy_t policy) { /* SRTP policy (list) */ srtp_err_status_t stat; srtp_ctx_t *ctx; @@ -3342,7 +3313,7 @@ srtp_err_status_t srtp_create(srtp_t *session, /* handle for session */ } if (policy) { - stat = srtp_valid_policy(policy); + stat = srtp_policy_validate(policy); if (stat != srtp_err_status_ok) { return stat; } @@ -3372,7 +3343,7 @@ srtp_err_status_t srtp_create(srtp_t *session, /* handle for session */ * loop over elements in the policy list, allocating and * initializing a stream for each element */ - while (policy != NULL) { + if (policy != NULL) { stat = srtp_stream_add(ctx, policy); if (stat) { /* clean up everything */ @@ -3380,9 +3351,6 @@ srtp_err_status_t srtp_create(srtp_t *session, /* handle for session */ *session = NULL; return stat; } - - /* set policy to next item in list */ - policy = policy->next; } return srtp_err_status_ok; @@ -3415,7 +3383,7 @@ srtp_err_status_t srtp_stream_remove(srtp_t session, uint32_t ssrc) return srtp_err_status_ok; } -srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy) +srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t policy) { srtp_err_status_t stat; @@ -3424,19 +3392,16 @@ srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy) return srtp_err_status_bad_param; } - stat = srtp_valid_policy(policy); + stat = srtp_policy_validate(policy); if (stat != srtp_err_status_ok) { return stat; } - while (policy != NULL) { + if (policy != NULL) { stat = srtp_stream_update(session, policy); if (stat) { return stat; } - - /* set policy to next item in list */ - policy = policy->next; } return srtp_err_status_ok; } @@ -3499,9 +3464,8 @@ static bool update_template_stream_cb(srtp_stream_t stream, void *raw_data) return true; } -static srtp_err_status_t is_update_policy_compatable( - srtp_stream_t stream, - const srtp_policy_t *policy) +static srtp_err_status_t is_update_policy_compatable(srtp_stream_t stream, + const srtp_policy_t policy) { if (stream->use_mki != policy->use_mki) { return srtp_err_status_bad_param; @@ -3515,17 +3479,12 @@ static srtp_err_status_t is_update_policy_compatable( } static srtp_err_status_t update_template_streams(srtp_t session, - const srtp_policy_t *policy) + const srtp_policy_t policy) { srtp_err_status_t status; srtp_stream_t new_stream_template; srtp_stream_list_t new_stream_list; - status = srtp_valid_policy(policy); - if (status != srtp_err_status_ok) { - return status; - } - if (session->stream_template == NULL) { return srtp_err_status_bad_param; } @@ -3582,18 +3541,13 @@ static srtp_err_status_t update_template_streams(srtp_t session, } static srtp_err_status_t stream_update(srtp_t session, - const srtp_policy_t *policy) + const srtp_policy_t policy) { srtp_err_status_t status; srtp_xtd_seq_num_t old_index; srtp_rdb_t old_rtcp_rdb; srtp_stream_t stream; - status = srtp_valid_policy(policy); - if (status != srtp_err_status_ok) { - return status; - } - stream = srtp_get_stream(session, htonl(policy->ssrc.value)); if (stream == NULL) { return srtp_err_status_bad_param; @@ -3630,8 +3584,7 @@ static srtp_err_status_t stream_update(srtp_t session, return srtp_err_status_ok; } -srtp_err_status_t srtp_stream_update(srtp_t session, - const srtp_policy_t *policy) +srtp_err_status_t srtp_stream_update(srtp_t session, const srtp_policy_t policy) { srtp_err_status_t status; @@ -3640,7 +3593,7 @@ srtp_err_status_t srtp_stream_update(srtp_t session, return srtp_err_status_bad_param; } - status = srtp_valid_policy(policy); + status = srtp_policy_validate(policy); if (status != srtp_err_status_ok) { return status; } @@ -3661,218 +3614,6 @@ srtp_err_status_t srtp_stream_update(srtp_t session, return status; } -/* - * The default policy - provides a convenient way for callers to use - * the default security policy - * - * The default policy is defined in RFC 3711 - * (Section 5. Default and mandatory-to-implement Transforms) - * - */ - -/* - * NOTE: cipher_key_len is really key len (128 bits) plus salt len - * (112 bits) - */ -/* There are hard-coded 16's for base_key_len in the key generation code */ - -void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = - SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = - SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 4568 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_128; - 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; /* 160 bit key */ - p->auth_tag_len = 4; /* 32 bit tag */ - p->sec_serv = sec_serv_conf_and_auth; -} - -void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 4568 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_128; - 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_conf; -} - -void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 4568 - */ - - p->cipher_type = SRTP_NULL_CIPHER; - 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; -} - -void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p) -{ - /* - * Should only be used for testing - */ - - p->cipher_type = SRTP_NULL_CIPHER; - p->cipher_key_len = 0; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_none; -} - -void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 6188 - */ - - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 6188 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -/* - * AES-256 with no authentication. - */ -void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_conf; -} - -void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 6188 - */ - - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p) -{ - /* - * corresponds to RFC 6188 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; -} - -/* - * AES-192 with no authentication. - */ -void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_conf; -} - -/* - * AES-128 GCM mode with 16 octet auth tag. - */ -void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_GCM_128; - p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 16; /* 16 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; -} - -/* - * AES-256 GCM mode with 16 octet auth tag. - */ -void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) -{ - p->cipher_type = SRTP_AES_GCM_256; - p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 16; /* 16 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; -} - /* * secure rtcp functions */ @@ -4859,72 +4600,6 @@ void *srtp_get_user_data(srtp_t ctx) return ctx->user_data; } -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( - srtp_crypto_policy_t *policy, - srtp_profile_t profile) -{ - /* set SRTP policy from the SRTP profile in the key set */ - switch (profile) { - case srtp_profile_aes128_cm_sha1_80: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_aes128_cm_sha1_32: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy); - break; - case srtp_profile_null_sha1_80: - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); - break; -#ifdef GCM - case srtp_profile_aead_aes_128_gcm: - srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); - break; - case srtp_profile_aead_aes_256_gcm: - srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); - break; -#endif - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return srtp_err_status_bad_param; - } - - return srtp_err_status_ok; -} - -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( - srtp_crypto_policy_t *policy, - srtp_profile_t profile) -{ - /* set SRTP policy from the SRTP profile in the key set */ - switch (profile) { - case srtp_profile_aes128_cm_sha1_80: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_aes128_cm_sha1_32: - /* We do not honor the 32-bit auth tag request since - * this is not compliant with RFC 3711 */ - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_null_sha1_80: - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); - break; -#ifdef GCM - case srtp_profile_aead_aes_128_gcm: - srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); - break; - case srtp_profile_aead_aes_256_gcm: - srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); - break; -#endif - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return srtp_err_status_bad_param; - } - - return srtp_err_status_ok; -} - void srtp_append_salt_to_key(uint8_t *key, size_t bytes_in_key, uint8_t *salt, @@ -4936,51 +4611,51 @@ void srtp_append_salt_to_key(uint8_t *key, size_t srtp_profile_get_master_key_length(srtp_profile_t profile) { switch (profile) { + case srtp_profile_reserved: + return 0; /* indicate error by returning a zero */ + case srtp_profile_null_null: + return 0; case srtp_profile_aes128_cm_sha1_80: - return SRTP_AES_128_KEY_LEN; - break; case srtp_profile_aes128_cm_sha1_32: return SRTP_AES_128_KEY_LEN; - break; + case srtp_profile_aes192_cm_sha1_80: + case srtp_profile_aes192_cm_sha1_32: + return SRTP_AES_192_KEY_LEN; + case srtp_profile_aes256_cm_sha1_80: + case srtp_profile_aes256_cm_sha1_32: + return SRTP_AES_256_KEY_LEN; case srtp_profile_null_sha1_80: + case srtp_profile_null_sha1_32: return SRTP_AES_128_KEY_LEN; - break; case srtp_profile_aead_aes_128_gcm: return SRTP_AES_128_KEY_LEN; - break; case srtp_profile_aead_aes_256_gcm: return SRTP_AES_256_KEY_LEN; - break; - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return 0; /* indicate error by returning a zero */ } + return 0; /* indicate error by returning a zero */ } size_t srtp_profile_get_master_salt_length(srtp_profile_t profile) { switch (profile) { + case srtp_profile_reserved: + return 0; /* indicate error by returning a zero */ + case srtp_profile_null_null: + return 0; case srtp_profile_aes128_cm_sha1_80: - return SRTP_SALT_LEN; - break; case srtp_profile_aes128_cm_sha1_32: - return SRTP_SALT_LEN; - break; + case srtp_profile_aes192_cm_sha1_80: + case srtp_profile_aes192_cm_sha1_32: + case srtp_profile_aes256_cm_sha1_80: + case srtp_profile_aes256_cm_sha1_32: case srtp_profile_null_sha1_80: + case srtp_profile_null_sha1_32: return SRTP_SALT_LEN; - break; case srtp_profile_aead_aes_128_gcm: - return SRTP_AEAD_SALT_LEN; - break; case srtp_profile_aead_aes_256_gcm: return SRTP_AEAD_SALT_LEN; - break; - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return 0; /* indicate error by returning a zero */ } + return 0; /* indicate error by returning a zero */ } srtp_err_status_t stream_get_protect_trailer_length(srtp_stream_ctx_t *stream, diff --git a/srtp/srtp_policy.c b/srtp/srtp_policy.c new file mode 100644 index 000000000..36d71d920 --- /dev/null +++ b/srtp/srtp_policy.c @@ -0,0 +1,1167 @@ +/* + * srtp_policy.c + * + * extensible policy API for libSRTP + */ +/* + * + * Copyright (c) 2026 + * 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. + * + * 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. + * + */ + +#include "srtp_priv.h" + +#include + +#include "alloc.h" + +/** + * @brief srtp_crypto_policy_set_rtp_default() sets a crypto policy + * structure to the SRTP default policy for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_rtp_default(&p) sets the + * srtp_crypto_policy_t at location p to the SRTP default policy for RTP + * protection, as defined in the specification. This function is a + * convenience that helps to avoid dealing directly with the policy + * data structure. You are encouraged to initialize policy elements + * with this function call. Doing so may allow your code to be + * forward compatible with later versions of libSRTP that include more + * elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_rtcp_default() sets a crypto policy + * structure to the SRTP default policy for RTCP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_rtcp_default(&p) sets the + * srtp_crypto_policy_t at location p to the SRTP default policy for RTCP + * protection, as defined in the specification. This function is a + * convenience that helps to avoid dealing directly with the policy + * data structure. You are encouraged to initialize policy elements + * with this function call. Doing so may allow your code to be + * forward compatible with later versions of libSRTP that include more + * elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto + * policy structure to the SRTP default policy for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() is a + * synonym for srtp_crypto_policy_set_rtp_default(). It conforms to the + * naming convention used in RFC 4568 (SDP Security Descriptions for + * Media Streams). + * + * @return void. + * + */ +#define srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(p) \ + srtp_crypto_policy_set_rtp_default(p) + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568. + * This policy uses AES-128 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_128_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto + * policy structure to an authentication-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use HMAC-SHA1 with an 80 + * bit authentication tag to provide message authentication, but to + * use no encryption. This policy is NOT RECOMMENDED for SRTP unless + * there is a requirement to forgo encryption. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless there is a + * requirement to forgo encryption. + * + * @return void. + * + */ +void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_null_cipher_hmac_null() sets a crypto + * policy structure to use no encryption or authentication. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_null_cipher_hmac_null(&p) + * sets the srtp_crypto_policy_t at location p to use no encryption and + * no authentication. This policy should only be used for testing and + * troubleshooting. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless there is a + * requirement to forgo encryption and authentication. + * + * @return void. + * + */ +void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto + * policy structure to a encryption and authentication policy using AES-256 + * for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_256_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-256 + * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit + * authentication tag. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy using AES-256 + * encryption. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_256_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-256 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80() sets a crypto + * policy structure to a encryption and authentication policy using AES-192 + * for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_192_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-192 + * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit + * authentication tag. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy using AES-192 + * encryption. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_192_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-192 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-192 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_128_16_auth() sets a crypto + * policy structure to an AEAD encryption policy. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_128_16_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Galois Counter Mode) with 16 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_256_16_auth() sets a crypto + * policy structure to an AEAD encryption policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_256_16_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Galois Counter Mode) with 16 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_from_profile_for_rtp() sets a crypto policy + * structure to the appropriate value for RTP based on an srtp_profile_t + * + * @param policy is a pointer to the policy structure to be set + * + * @param profile is an enumeration for the policy to be set + * + * The function call srtp_crypto_policy_set_rtp_default(&policy, profile) + * sets the srtp_crypto_policy_t at location policy to the policy for RTP + * protection, as defined by the srtp_profile_t profile. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return values + * - srtp_err_status_ok no problems were encountered + * - srtp_err_status_bad_param the profile is not supported + * + */ +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); + +/** + * @brief srtp_crypto_policy_set_from_profile_for_rtcp() sets a crypto policy + * structure to the appropriate value for RTCP based on an srtp_profile_t + * + * @param policy is a pointer to the policy structure to be set + * + * @param profile is an enumeration for the policy to be set + * + * The function call srtp_crypto_policy_set_rtcp_default(&policy, profile) + * sets the srtp_crypto_policy_t at location policy to the policy for RTCP + * protection, as defined by the srtp_profile_t profile. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return values + * - srtp_err_status_ok no problems were encountered + * - srtp_err_status_bad_param the profile is not supported + * + */ +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); + +/* + * The default policy - provides a convenient way for callers to use + * the default security policy + * + * The default policy is defined in RFC 3711 + * (Section 5. Default and mandatory-to-implement Transforms) + * + */ + +/* + * NOTE: cipher_key_len is really key len (128 bits) plus salt len + * (112 bits) + */ +/* There are hard-coded 16's for base_key_len in the key generation code */ + +void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ + + p->cipher_type = SRTP_AES_ICM_128; + 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; /* 160 bit key */ + p->auth_tag_len = 4; /* 32 bit tag */ + p->sec_serv = sec_serv_conf_and_auth; +} + +void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ + + p->cipher_type = SRTP_AES_ICM_128; + 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_conf; +} + +void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + */ + + p->cipher_type = SRTP_NULL_CIPHER; + 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; +} + +void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p) +{ + /* + * Should only be used for testing + */ + + p->cipher_type = SRTP_NULL_CIPHER; + p->cipher_key_len = 0; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_none; +} + +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + */ + + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ + + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +/* + * AES-256 with no authentication. + */ +void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_conf; +} + +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + */ + + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ + + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; +} + +/* + * AES-192 with no authentication. + */ +void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_conf; +} + +/* + * AES-128 GCM mode with 16 octet auth tag. + */ +void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_128; + p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 16; /* 16 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; +} + +/* + * AES-256 GCM mode with 16 octet auth tag. + */ +void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_256; + p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 16; /* 16 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; +} + +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile) +{ + /* set SRTP policy from the SRTP profile in the key set */ + switch (profile) { + case srtp_profile_reserved: + return srtp_err_status_bad_param; + case srtp_profile_null_null: + srtp_crypto_policy_set_null_cipher_hmac_null(policy); + return srtp_err_status_ok; + case srtp_profile_aes128_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes128_cm_sha1_32: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy); + return srtp_err_status_ok; + case srtp_profile_aes192_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes192_cm_sha1_32: + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(policy); + return srtp_err_status_ok; + case srtp_profile_aes256_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes256_cm_sha1_32: + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(policy); + return srtp_err_status_ok; + case srtp_profile_null_sha1_80: + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + return srtp_err_status_ok; +#ifdef GCM + case srtp_profile_aead_aes_128_gcm: + srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); + return srtp_err_status_ok; + case srtp_profile_aead_aes_256_gcm: + srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); + return srtp_err_status_ok; +#else + case srtp_profile_aead_aes_128_gcm: + return srtp_err_status_bad_param; + case srtp_profile_aead_aes_256_gcm: + return srtp_err_status_bad_param; +#endif + case srtp_profile_null_sha1_32: + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + policy->auth_tag_len = 4; + return srtp_err_status_ok; + } + + return srtp_err_status_bad_param; +} + +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile) +{ + /* set SRTP policy from the SRTP profile in the key set */ + switch (profile) { + case srtp_profile_reserved: + return srtp_err_status_bad_param; + case srtp_profile_null_null: + srtp_crypto_policy_set_null_cipher_hmac_null(policy); + return srtp_err_status_ok; + case srtp_profile_aes128_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes128_cm_sha1_32: + /* We do not honor the 32-bit auth tag request since + * this is not compliant with RFC 3711 */ + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes192_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes192_cm_sha1_32: + /* We do not honor the 32-bit auth tag request since + * this is not compliant with RFC 3711 */ + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes256_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_aes256_cm_sha1_32: + /* We do not honor the 32-bit auth tag request since + * this is not compliant with RFC 6188 */ + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(policy); + return srtp_err_status_ok; + case srtp_profile_null_sha1_80: + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + return srtp_err_status_ok; +#ifdef GCM + case srtp_profile_aead_aes_128_gcm: + srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); + return srtp_err_status_ok; + case srtp_profile_aead_aes_256_gcm: + srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); + return srtp_err_status_ok; +#else + case srtp_profile_aead_aes_128_gcm: + return srtp_err_status_bad_param; + case srtp_profile_aead_aes_256_gcm: + return srtp_err_status_bad_param; +#endif + case srtp_profile_null_sha1_32: + /* We do not honor the 32-bit auth tag request since + * this is not compliant with RFC 3711 */ + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + return srtp_err_status_ok; + } + + return srtp_err_status_bad_param; +} + +srtp_err_status_t srtp_policy_create(srtp_policy_t *policy) +{ + srtp_policy_t p; + + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + p = (srtp_policy_t)srtp_crypto_alloc(sizeof(*p)); + if (p == NULL) { + *policy = NULL; + return srtp_err_status_alloc_fail; + } + + *policy = p; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_clone(srtp_policy_t policy, + srtp_policy_t *cloned_policy) +{ + if (policy == NULL || cloned_policy == NULL) { + return srtp_err_status_bad_param; + } + + srtp_policy_t p; + srtp_err_status_t status = srtp_policy_create(&p); + if (status != srtp_err_status_ok) { + return status; + } + + memcpy(p, policy, sizeof(*p)); + + *cloned_policy = p; + + return srtp_err_status_ok; +} + +void srtp_policy_destroy(srtp_policy_t policy) +{ + if (policy == NULL) { + return; + } + + octet_string_set_to_zero(policy->master_keys, sizeof(policy->master_keys)); + srtp_crypto_free(policy); +} + +srtp_err_status_t srtp_policy_validate(srtp_policy_t policy) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (policy->profile == srtp_profile_reserved) { + return srtp_err_status_bad_param; + } + + if (policy->ssrc.type == ssrc_undefined) { + return srtp_err_status_bad_param; + } + + bool null_cipher_null_auth = srtp_policy_is_null_cipher_null_auth(policy); + + if (null_cipher_null_auth) { + if (policy->num_master_keys != 0 || policy->use_mki || + policy->mki_size != 0) { + return srtp_err_status_bad_param; + } + } else if (policy->num_master_keys == 0) { + return srtp_err_status_bad_param; + } + + if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) { + return srtp_err_status_bad_param; + } + + if (policy->use_mki) { + if (policy->mki_size == 0 || policy->mki_size > SRTP_MAX_MKI_LEN) { + return srtp_err_status_bad_param; + } + } else if (policy->mki_size != 0) { + return srtp_err_status_bad_param; + } + + if (!policy->use_mki && policy->num_master_keys > 1) { + return srtp_err_status_bad_param; + } + + size_t expected_key_len = + srtp_profile_get_master_key_length(policy->profile); + size_t expected_salt_len = + srtp_profile_get_master_salt_length(policy->profile); + + for (size_t i = 0; i < policy->num_master_keys; i++) { + if (policy->master_keys[i].key_len == 0) { + return srtp_err_status_bad_param; + } + if (policy->master_keys[i].key_len != expected_key_len || + policy->master_keys[i].salt_len != expected_salt_len) { + return srtp_err_status_bad_param; + } + if (policy->use_mki && + policy->mki_size != policy->master_keys[i].mki_id_len) { + return srtp_err_status_bad_param; + } + if (!policy->use_mki && policy->master_keys[i].mki_id_len != 0) { + return srtp_err_status_bad_param; + } + } + + if (!srtp_policy_is_valid_window_size(policy->window_size)) { + return srtp_err_status_bad_param; + } + + // Not a valid combination + if (policy->enc_xtn_hdr_count > 0 && policy->use_cryptex) { + return srtp_err_status_bad_param; + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_ssrc(srtp_policy_t policy, srtp_ssrc_t ssrc) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (ssrc.type != ssrc_any_inbound && ssrc.type != ssrc_any_outbound && + ssrc.type != ssrc_specific) { + return srtp_err_status_bad_param; + } + + policy->ssrc = ssrc; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_profile(srtp_policy_t policy, + srtp_profile_t profile) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + srtp_err_status_t status; + status = srtp_crypto_policy_set_from_profile_for_rtp(&policy->rtp, profile); + if (status != srtp_err_status_ok) { + return status; + } + status = + srtp_crypto_policy_set_from_profile_for_rtcp(&policy->rtcp, profile); + if (status != srtp_err_status_ok) { + return status; + } + + policy->profile = profile; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_get_profile(srtp_policy_t policy, + srtp_profile_t *profile) +{ + if (policy == NULL || profile == NULL) { + return srtp_err_status_bad_param; + } + + *profile = policy->profile; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_sec_serv(srtp_policy_t policy, + srtp_sec_serv_t rtp_sec_serv, + srtp_sec_serv_t rtcp_sec_serv) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (policy->profile == srtp_profile_reserved) { + return srtp_err_status_bad_param; + } + + policy->rtp.sec_serv = rtp_sec_serv; + policy->rtcp.sec_serv = rtcp_sec_serv; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_use_mki(srtp_policy_t policy, size_t mki_len) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (mki_len > SRTP_MAX_MKI_LEN) { + return srtp_err_status_bad_param; + } + + policy->use_mki = mki_len != 0; + policy->mki_size = mki_len; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_get_mki_length(srtp_policy_t policy, + size_t *mki_len) +{ + if (policy == NULL || mki_len == NULL) { + return srtp_err_status_bad_param; + } + + *mki_len = policy->mki_size; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_add_key(srtp_policy_t policy, + const uint8_t *key, + size_t key_len, + const uint8_t *salt, + size_t salt_len, + const uint8_t *mki, + size_t mki_len) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + if (key == NULL || salt == NULL) { + return srtp_err_status_bad_param; + } + if (mki_len > 0 && mki == NULL) { + return srtp_err_status_bad_param; + } + + if (policy->use_mki) { + if (mki_len != policy->mki_size) { + return srtp_err_status_bad_param; + } + } else { + if (mki_len != 0) { + return srtp_err_status_bad_param; + } + if (policy->num_master_keys > 0) { + return srtp_err_status_bad_param; + } + } + + if (key_len + salt_len > SRTP_MAX_KEY_LEN) { + return srtp_err_status_bad_param; + } + + if (mki_len > SRTP_MAX_MKI_LEN) { + return srtp_err_status_bad_param; + } + + if (policy->num_master_keys >= SRTP_MAX_NUM_MASTER_KEYS) { + return srtp_err_status_bad_param; + } + + size_t key_index = policy->num_master_keys; + memcpy(policy->master_keys[key_index].key, key, key_len); + policy->master_keys[key_index].key_len = key_len; + memcpy(policy->master_keys[key_index].key + key_len, salt, salt_len); + policy->master_keys[key_index].salt_len = salt_len; + if (mki_len > 0) { + memcpy(policy->master_keys[key_index].mki_id, mki, mki_len); + } + policy->master_keys[key_index].mki_id_len = mki_len; + policy->num_master_keys++; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_remove_keys(srtp_policy_t policy) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + octet_string_set_to_zero(policy->master_keys, sizeof(policy->master_keys)); + policy->num_master_keys = 0; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_window_size(srtp_policy_t policy, + size_t window_size) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (!srtp_policy_is_valid_window_size(window_size)) { + return srtp_err_status_bad_param; + } + + policy->window_size = window_size; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_allow_repeat_tx(srtp_policy_t policy, + bool allow) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + policy->allow_repeat_tx = allow; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_set_cryptex(srtp_policy_t policy, + bool use_cryptex) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + policy->use_cryptex = use_cryptex; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_add_enc_hdr_xtnd_id(srtp_policy_t policy, + uint8_t hdr_xtnd_id) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + if (policy->enc_xtn_hdr_count >= SRTP_MAX_NUM_ENC_HDR_XTND_IDS) { + return srtp_err_status_bad_param; + } + + for (size_t i = 0; i < policy->enc_xtn_hdr_count; i++) { + if (policy->enc_xtn_hdr[i] == hdr_xtnd_id) { + return srtp_err_status_bad_param; + } + } + + policy->enc_xtn_hdr[policy->enc_xtn_hdr_count] = hdr_xtnd_id; + policy->enc_xtn_hdr_count++; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_policy_remove_enc_hdr_xtnd_ids(srtp_policy_t policy) +{ + if (policy == NULL) { + return srtp_err_status_bad_param; + } + + octet_string_set_to_zero(policy->enc_xtn_hdr, sizeof(policy->enc_xtn_hdr)); + policy->enc_xtn_hdr_count = 0; + + return srtp_err_status_ok; +} diff --git a/test/meson.build b/test/meson.build index 6f0511859..c8c2054f2 100644 --- a/test/meson.build +++ b/test/meson.build @@ -11,6 +11,7 @@ test_apps = [ ['roc_driver', {'extra_sources': 'ut_sim.c', 'run_args': '-v'}], ['rdbx_driver', {'extra_sources': 'ut_sim.c', 'run_args': '-v'}], ['test_srtp', {'run_args': '-v'}], + ['test_srtp_policy', {'extra_sources': 'util.c', 'run_args': '-v'}], ['rtpw', {'extra_sources': ['rtp.c', 'util.c', '../crypto/math/datatypes.c'], 'define_test': false}], ] diff --git a/test/rtp.c b/test/rtp.c index 0c965b0f8..d60f7f974 100644 --- a/test/rtp.c +++ b/test/rtp.c @@ -195,7 +195,7 @@ srtp_err_status_t rtp_receiver_init(rtp_receiver_t rcvr, } srtp_err_status_t rtp_sender_init_srtp(rtp_sender_t sender, - const srtp_policy_t *policy) + const srtp_policy_t policy) { return srtp_create(&sender->srtp_ctx, policy); } @@ -206,7 +206,7 @@ srtp_err_status_t rtp_sender_deinit_srtp(rtp_sender_t sender) } srtp_err_status_t rtp_receiver_init_srtp(rtp_receiver_t sender, - const srtp_policy_t *policy) + const srtp_policy_t policy) { return srtp_create(&sender->srtp_ctx, policy); } diff --git a/test/rtp.h b/test/rtp.h index 510e45090..fd0248613 100644 --- a/test/rtp.h +++ b/test/rtp.h @@ -115,12 +115,12 @@ srtp_err_status_t rtp_sender_init(rtp_sender_t sender, uint32_t ssrc); srtp_err_status_t rtp_sender_init_srtp(rtp_sender_t sender, - const srtp_policy_t *policy); + const srtp_policy_t policy); srtp_err_status_t rtp_sender_deinit_srtp(rtp_sender_t sender); srtp_err_status_t rtp_receiver_init_srtp(rtp_receiver_t sender, - const srtp_policy_t *policy); + const srtp_policy_t policy); srtp_err_status_t rtp_receiver_deinit_srtp(rtp_receiver_t sender); diff --git a/test/rtp_decoder.c b/test/rtp_decoder.c index eb513e7d5..92ea69667 100644 --- a/test/rtp_decoder.c +++ b/test/rtp_decoder.c @@ -95,9 +95,6 @@ struct srtp_crypto_suite { }; static struct srtp_crypto_suite srtp_crypto_suites[] = { -#if 0 - {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = false, .key_size = 128, .tag_size = 4}, -#endif { .can_name = "AES_CM_128_HMAC_SHA1_32", .gcm_on = false, .key_size = 128, @@ -164,25 +161,24 @@ int main(int argc, char *argv[]) #if BEW struct sockaddr_in local; #endif - srtp_sec_serv_t sec_servs = sec_serv_none; int c; - struct srtp_crypto_suite scs, *i_scsp; - scs.key_size = 128; - scs.tag_size = 0; - bool gcm_on = false; + struct srtp_crypto_suite *i_scsp; + policy_params_t policy_params; + policy_params.key_size = 128; + policy_params.tag_size = 0; + policy_params.gcm_on = false; + policy_params.sec_servs = sec_serv_none; char *input_key = NULL; int b64_input = 0; uint8_t key[MAX_KEY_LEN]; size_t mki_size = 0; uint8_t mki[SRTP_MAX_MKI_LEN]; - srtp_master_key_t masterKey; - srtp_master_key_t *masterKeys[1]; struct bpf_program fp; char filter_exp[MAX_FILTER] = ""; char pcap_file[MAX_FILE] = "-"; size_t rtp_packet_offset = DEFAULT_RTP_OFFSET; rtp_decoder_t dec; - srtp_policy_t policy = { 0 }; + srtp_policy_t policy; rtp_decoder_mode_t mode = mode_rtp; srtp_ssrc_t ssrc = { ssrc_any_inbound, 0 }; uint32_t roc = 0; @@ -227,27 +223,28 @@ int main(int argc, char *argv[]) hex_string_to_octet_string(mki, optarg_s, strlen(optarg_s)) / 2; break; case 'e': - scs.key_size = atoi(optarg_s); - if (scs.key_size != 128 && scs.key_size != 192 && - scs.key_size != 256) { + policy_params.key_size = atoi(optarg_s); + if (policy_params.key_size != 128 && + policy_params.key_size != 192 && + policy_params.key_size != 256) { fprintf(stderr, "error: encryption key size must be 128, 192 or 256 " "(%zu)\n", - scs.key_size); + policy_params.key_size); exit(1); } - input_key = malloc(scs.key_size); - sec_servs |= sec_serv_conf; + input_key = malloc(policy_params.key_size); + policy_params.sec_servs |= sec_serv_conf; break; case 't': - scs.tag_size = atoi(optarg_s); + policy_params.tag_size = atoi(optarg_s); break; case 'a': - sec_servs |= sec_serv_auth; + policy_params.sec_servs |= sec_serv_auth; break; case 'g': - gcm_on = true; - sec_servs |= sec_serv_auth; + policy_params.gcm_on = true; + policy_params.sec_servs |= sec_serv_auth; break; case 'd': status = srtp_set_debug_module(optarg_s, true); @@ -281,10 +278,11 @@ int main(int argc, char *argv[]) optarg_s); exit(1); } - scs = *i_scsp; - input_key = malloc(scs.key_size); - sec_servs |= sec_serv_conf | sec_serv_auth; - gcm_on = scs.gcm_on; + policy_params.key_size = i_scsp->key_size; + input_key = malloc(policy_params.key_size); + policy_params.tag_size = i_scsp->tag_size; + policy_params.sec_servs |= sec_serv_conf | sec_serv_auth; + policy_params.gcm_on = i_scsp->gcm_on; break; case 'm': if (strcasecmp("rtp", optarg_s) == 0) { @@ -322,22 +320,24 @@ int main(int argc, char *argv[]) } } - if (scs.tag_size == 0) { - if (gcm_on) { - scs.tag_size = 16; + if (policy_params.tag_size == 0) { + if (policy_params.gcm_on) { + policy_params.tag_size = 16; } else { - scs.tag_size = 10; + policy_params.tag_size = 10; } } - if (gcm_on && scs.tag_size != 16) { - fprintf(stderr, "error: GCM tag size must be 16 (%zu)\n", scs.tag_size); + if (policy_params.gcm_on && policy_params.tag_size != 16) { + fprintf(stderr, "error: GCM tag size must be 16 (%zu)\n", + policy_params.tag_size); exit(1); } - if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) { + if (!policy_params.gcm_on && policy_params.tag_size != 4 && + policy_params.tag_size != 10) { fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%zu)\n", - scs.tag_size); + policy_params.tag_size); exit(1); } @@ -350,7 +350,8 @@ int main(int argc, char *argv[]) return 0; } - if ((sec_servs && !input_key) || (!sec_servs && input_key)) { + if ((policy_params.sec_servs && !input_key) || + (!policy_params.sec_servs && input_key)) { /* * a key must be provided if and only if security services have * been requested @@ -358,7 +359,7 @@ int main(int argc, char *argv[]) if (input_key == NULL) { fprintf(stderr, "key not provided\n"); } - if (!sec_servs) { + if (!policy_params.sec_servs) { fprintf(stderr, "no secservs\n"); } fprintf(stderr, "provided\n"); @@ -367,186 +368,42 @@ int main(int argc, char *argv[]) /* report security services selected on the command line */ fprintf(stderr, "security services: "); - if (sec_servs & sec_serv_conf) { + if (policy_params.sec_servs & sec_serv_conf) { fprintf(stderr, "confidentiality "); } - if (sec_servs & sec_serv_auth) { + if (policy_params.sec_servs & sec_serv_auth) { fprintf(stderr, "message authentication"); } - if (sec_servs == sec_serv_none) { + if (policy_params.sec_servs == sec_serv_none) { fprintf(stderr, "none"); } fprintf(stderr, "\n"); /* set up the srtp policy and master key */ - if (sec_servs) { + if (policy_params.sec_servs) { /* * create policy structure, using the default mechanisms but * with only the security services requested on the command line, * using the right SSRC value */ - switch (sec_servs) { - case sec_serv_conf_and_auth: - if (gcm_on) { -#ifdef OPENSSL - switch (scs.key_size) { - case 128: - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - break; - case 256: - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); - break; - } -#else - fprintf(stderr, "error: GCM mode only supported when using the " - "OpenSSL crypto engine.\n"); - return 0; -#endif - } else { - switch (scs.key_size) { - case 128: - if (scs.tag_size == 4) { - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( - &policy.rtcp); - } else { - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( - &policy.rtcp); - } - break; - case 192: -#ifdef OPENSSL - if (scs.tag_size == 4) { - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( - &policy.rtcp); - } else { - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( - &policy.rtcp); - } -#else - fprintf(stderr, - "error: AES 192 mode only supported when using the " - "OpenSSL crypto engine.\n"); - return 0; -#endif - break; - case 256: - if (scs.tag_size == 4) { - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( - &policy.rtcp); - } else { - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( - &policy.rtp); - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( - &policy.rtcp); - } - break; - } - } - break; - case sec_serv_conf: - if (gcm_on) { - fprintf( - stderr, - "error: GCM mode must always be used with auth enabled\n"); - return -1; - } else { - switch (scs.key_size) { - case 128: - srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( - &policy.rtcp); - break; - case 192: -#ifdef OPENSSL - srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp); - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( - &policy.rtcp); -#else - fprintf(stderr, - "error: AES 192 mode only supported when using the " - "OpenSSL crypto engine.\n"); - return 0; - -#endif - break; - case 256: - srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( - &policy.rtcp); - break; - } - } - break; - case sec_serv_auth: - if (gcm_on) { -#ifdef OPENSSL - switch (scs.key_size) { - case 128: - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - policy.rtp.sec_serv = sec_serv_auth; - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.rtcp.sec_serv = sec_serv_auth; - break; - case 256: - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); - policy.rtp.sec_serv = sec_serv_auth; - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); - policy.rtcp.sec_serv = sec_serv_auth; - break; - } -#else - printf("error: GCM mode only supported when using the OpenSSL " - "crypto engine.\n"); - return 0; -#endif - } else { - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - } - break; - default: - fprintf(stderr, "error: unknown security service requested\n"); - return -1; + if (create_policy_from_params(&policy, &policy_params) != + srtp_err_status_ok) { + fprintf(stderr, "error: failed to create policy from params\n"); + exit(1); } - masterKey.key = key; + fprintf(stderr, "setting tag len %zu\n", policy_params.tag_size); - if (mki_size) { - policy.use_mki = true; - policy.mki_size = mki_size; - masterKey.mki_id = mki; + srtp_profile_t profile; + if (srtp_policy_get_profile(policy, &profile) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to get profile from policy\n"); + exit(1); } + size_t key_len = srtp_profile_get_master_key_length(profile); + size_t salt_len = srtp_profile_get_master_salt_length(profile); - masterKeys[0] = &masterKey; - policy.keys = masterKeys; - policy.num_master_keys = 1; - - policy.next = NULL; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.rtp.sec_serv = sec_servs; - policy.rtcp.sec_serv = - sec_servs; // sec_serv_none; /* we don't do RTCP anyway */ - fprintf(stderr, "setting tag len %zu\n", scs.tag_size); - policy.rtp.auth_tag_len = scs.tag_size; - - if (gcm_on && scs.tag_size != 8) { - fprintf(stderr, "set tag len %zu\n", scs.tag_size); - policy.rtp.auth_tag_len = scs.tag_size; - } + size_t input_key_len = key_len + salt_len; /* * read key from hexadecimal or base64 on command line into an octet @@ -554,11 +411,11 @@ int main(int argc, char *argv[]) */ if (b64_input) { int pad; - expected_len = policy.rtp.cipher_key_len * 4 / 3; + expected_len = input_key_len * 4 / 3; len = base64_string_to_octet_string(key, &pad, input_key, strlen(input_key)); } else { - expected_len = policy.rtp.cipher_key_len * 2; + expected_len = input_key_len * 2; len = hex_string_to_octet_string(key, input_key, expected_len); } /* check that hex string is the right length */ @@ -569,24 +426,38 @@ int main(int argc, char *argv[]) expected_len, len); exit(1); } - if (strlen(input_key) > policy.rtp.cipher_key_len * 2) { + if (strlen(input_key) > input_key_len * 2) { fprintf(stderr, "error: too many digits in key/salt " "(should be %zu hexadecimal digits, found %zu)\n", - policy.rtp.cipher_key_len * 2, strlen(input_key)); + input_key_len * 2, strlen(input_key)); exit(1); } - size_t key_octets = (scs.key_size / 8); - size_t salt_octets = policy.rtp.cipher_key_len - key_octets; fprintf(stderr, "set master key/salt to %s/", - octet_string_hex_string(key, key_octets)); + octet_string_hex_string(key, key_len)); fprintf(stderr, "%s\n", - octet_string_hex_string(key + key_octets, salt_octets)); + octet_string_hex_string(key + key_len, salt_len)); if (mki_size) { fprintf(stderr, "set mki to %s\n", octet_string_hex_string(mki, mki_size)); + if (srtp_policy_use_mki(policy, mki_size) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to set MKI in policy\n"); + exit(1); + } + if (srtp_policy_add_key(policy, key, key_len, key + key_len, + salt_len, mki, + mki_size) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to set key in policy\n"); + exit(1); + } + } else { + if (srtp_policy_add_key(policy, key, key_len, key + key_len, + salt_len, NULL, 0) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to set key in policy\n"); + exit(1); + } } } else { @@ -595,9 +466,12 @@ int main(int argc, char *argv[]) exit(1); } - policy.ssrc = ssrc; + if (srtp_policy_set_ssrc(policy, ssrc) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to set SSRC in policy\n"); + exit(1); + } - if (roc != 0 && policy.ssrc.type != ssrc_specific) { + if (roc != 0 && ssrc.type != ssrc_specific) { fprintf(stderr, "error: setting ROC (-r) requires -s \n"); exit(1); } @@ -625,7 +499,8 @@ int main(int argc, char *argv[]) exit(1); } fprintf(stderr, "Starting decoder\n"); - if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset, roc)) { + if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset, ssrc.value, + roc)) { fprintf(stderr, "error: init failed\n"); exit(1); } @@ -695,9 +570,14 @@ void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) srtp_err_status_t rtp_decoder_deinit(rtp_decoder_t decoder) { + if (decoder->policy) { + srtp_policy_destroy(decoder->policy); + } + if (decoder->srtp_ctx) { return srtp_dealloc(decoder->srtp_ctx); } + return srtp_err_status_ok; } @@ -705,6 +585,7 @@ srtp_err_status_t rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy, rtp_decoder_mode_t mode, size_t rtp_packet_offset, + uint32_t ssrc, uint32_t roc) { dcdr->rtp_offset = rtp_packet_offset; @@ -718,13 +599,13 @@ srtp_err_status_t rtp_decoder_init(rtp_decoder_t dcdr, dcdr->mode = mode; dcdr->policy = policy; - srtp_err_status_t result = srtp_create(&dcdr->srtp_ctx, &dcdr->policy); + srtp_err_status_t result = srtp_create(&dcdr->srtp_ctx, dcdr->policy); if (result != srtp_err_status_ok) { return result; } - if (policy.ssrc.type == ssrc_specific && roc != 0) { - result = srtp_stream_set_roc(dcdr->srtp_ctx, policy.ssrc.value, roc); + if (roc != 0) { + result = srtp_stream_set_roc(dcdr->srtp_ctx, ssrc, roc); if (result != srtp_err_status_ok) { return result; } diff --git a/test/rtp_decoder.h b/test/rtp_decoder.h index 7c0b6b8ee..88ba20492 100644 --- a/test/rtp_decoder.h +++ b/test/rtp_decoder.h @@ -103,6 +103,7 @@ srtp_err_status_t rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy, rtp_decoder_mode_t mode, size_t rtp_packet_offset, + uint32_t ssrc, uint32_t roc); srtp_err_status_t rtp_decoder_deinit(rtp_decoder_t decoder); diff --git a/test/rtpw.c b/test/rtpw.c index 646bc457f..5cb78f97b 100644 --- a/test/rtpw.c +++ b/test/rtpw.c @@ -175,8 +175,6 @@ int main(int argc, char *argv[]) } #endif - memset(&policy, 0x0, sizeof(srtp_policy_t)); - printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); if (setup_signal_handler(argv[0]) != 0) { @@ -375,99 +373,32 @@ int main(int argc, char *argv[]) * with only the security services requested on the command line, * using the right SSRC value */ - switch (sec_servs) { - case sec_serv_conf_and_auth: - if (gcm_on) { -#ifdef GCM - switch (key_size) { - case 128: - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - break; - case 256: - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); - break; - } -#else - printf("error: GCM mode only supported when using the OpenSSL " - "or NSS crypto engine.\n"); - return 0; -#endif - } else { - switch (key_size) { - case 128: - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - break; - case 256: - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - break; - } - } - break; - case sec_serv_conf: - if (gcm_on) { - printf( - "error: GCM mode must always be used with auth enabled\n"); - return -1; - } else { - switch (key_size) { - case 128: - srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - break; - case 256: - srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - break; - } - } - break; - case sec_serv_auth: - if (gcm_on) { -#ifdef GCM - switch (key_size) { - case 128: - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - policy.rtp.sec_serv = sec_serv_auth; - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.rtcp.sec_serv = sec_serv_auth; - break; - case 256: - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); - policy.rtp.sec_serv = sec_serv_auth; - srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); - policy.rtcp.sec_serv = sec_serv_auth; - break; - } -#else - printf("error: GCM mode only supported when using the OpenSSL " - "crypto engine.\n"); - return 0; -#endif - } else { - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - } - break; - default: - printf("error: unknown security service requested\n"); - return -1; + policy_params_t params; + params.sec_servs = sec_servs; + params.gcm_on = gcm_on; + params.key_size = key_size; + params.tag_size = tag_size; + if (create_policy_from_params(&policy, ¶ms) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to create policy from parameters\n"); + exit(1); } - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = ssrc; - policy.key = key; - policy.next = NULL; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.rtp.sec_serv = sec_servs; - policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ - - if (gcm_on && tag_size != 8) { - policy.rtp.auth_tag_len = tag_size; + + if (srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, ssrc }) != + srtp_err_status_ok) { + fprintf(stderr, "error: failed to set SSRC in policy\n"); + exit(1); + } + + srtp_profile_t profile; + if (srtp_policy_get_profile(policy, &profile) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to get profile from policy\n"); + exit(1); } + size_t key_len = srtp_profile_get_master_key_length(profile); + size_t salt_len = srtp_profile_get_master_salt_length(profile); + + size_t input_key_len = key_len + salt_len; /* * read key from hexadecimal or base64 on command line into an octet @@ -475,7 +406,7 @@ int main(int argc, char *argv[]) */ if (b64_input) { int pad; - expected_len = (policy.rtp.cipher_key_len * 4) / 3; + expected_len = (input_key_len * 4) / 3; len = base64_string_to_octet_string(key, &pad, input_key, expected_len); if (pad != 0) { @@ -483,7 +414,7 @@ int main(int argc, char *argv[]) exit(1); } } else { - expected_len = policy.rtp.cipher_key_len * 2; + expected_len = input_key_len * 2; len = hex_string_to_octet_string(key, input_key, expected_len); } /* check that hex string is the right length */ @@ -494,35 +425,22 @@ int main(int argc, char *argv[]) expected_len, len); exit(1); } - if (strlen(input_key) > policy.rtp.cipher_key_len * 2) { + if (strlen(input_key) > input_key_len * 2) { fprintf(stderr, "error: too many digits in key/salt " "(should be %zu hexadecimal digits, found %zu)\n", - policy.rtp.cipher_key_len * 2, strlen(input_key)); + input_key_len * 2, strlen(input_key)); exit(1); } printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); printf("%s\n", octet_string_hex_string(key + 16, 14)); - } else { - /* - * we're not providing security services, so set the policy to the - * null policy - * - * Note that this policy does not conform to the SRTP - * specification, since RTCP authentication is required. However, - * the effect of this policy is to turn off SRTP, so that this - * application is now a vanilla-flavored RTP application. - */ - srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp); - srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp); - policy.key = (uint8_t *)key; - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = ssrc; - policy.window_size = 0; - policy.allow_repeat_tx = false; - policy.next = NULL; + if (srtp_policy_add_key(policy, key, key_len, key + key_len, salt_len, + NULL, 0) != srtp_err_status_ok) { + fprintf(stderr, "error: failed to set key in policy\n"); + exit(1); + } } if (prog_type == sender) { @@ -546,7 +464,7 @@ int main(int argc, char *argv[]) exit(1); } rtp_sender_init(snd, sock, name, ssrc); - status = rtp_sender_init_srtp(snd, &policy); + status = rtp_sender_init_srtp(snd, policy); if (status) { fprintf(stderr, "error: srtp_create() failed with code %d\n", status); @@ -599,7 +517,7 @@ int main(int argc, char *argv[]) exit(1); } rtp_receiver_init(rcvr, sock, name, ssrc); - status = rtp_receiver_init_srtp(rcvr, &policy); + status = rtp_receiver_init_srtp(rcvr, policy); if (status) { fprintf(stderr, "error: srtp_create() failed with code %d\n", status); @@ -632,6 +550,8 @@ int main(int argc, char *argv[]) perror(""); } + srtp_policy_destroy(policy); + status = srtp_shutdown(); if (status) { printf("error: srtp shutdown failed with error code %d\n", status); diff --git a/test/srtp_driver.c b/test/srtp_driver.c index bd1f411f7..1e354013d 100644 --- a/test/srtp_driver.c +++ b/test/srtp_driver.c @@ -60,6 +60,21 @@ #define PRINT_REFERENCE_PACKET 1 +typedef struct test_master_key_t { + uint8_t *key; + uint8_t *mki_id; +} test_master_key_t; + +typedef struct test_policy_t { + srtp_ssrc_t ssrc; + srtp_profile_t profile; + srtp_sec_serv_t rtp_sec_serv; + srtp_sec_serv_t rtcp_sec_serv; + test_master_key_t **keys; + size_t num_master_keys; + size_t mki_size; +} test_policy_t; + srtp_err_status_t srtp_validate(void); srtp_err_status_t srtp_validate_mki(void); @@ -88,10 +103,6 @@ srtp_err_status_t srtp_validate_aes_256(void); srtp_err_status_t srtp_validate_aes_192(void); #endif -srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list); - -srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list); - srtp_err_status_t srtp_test_empty_payload(void); #ifdef GCM @@ -121,41 +132,41 @@ srtp_err_status_t srtp_test_roc_mismatch(void); srtp_err_status_t srtp_test_set_sender_roc(void); srtp_err_status_t srtp_test_cryptex_csrc_but_no_extension_header(void); - srtp_err_status_t srtp_test_cryptex_disable(void); srtp_err_status_t srtp_test_missing_session_keys(void); -double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy); +double srtp_bits_per_second(size_t msg_len_octets, + const test_policy_t *test_policy); double srtp_rejections_per_second(size_t msg_len_octets, - const srtp_policy_t *policy); + const test_policy_t *policy); -void srtp_do_timing(const srtp_policy_t *policy); +void srtp_do_timing(const test_policy_t *policy); -void srtp_do_rejection_timing(const srtp_policy_t *policy); +void srtp_do_rejection_timing(const test_policy_t *policy); -srtp_err_status_t srtp_test(const srtp_policy_t *policy, +srtp_err_status_t srtp_test(const test_policy_t *policy, bool test_extension_headers, bool use_mki, size_t mki_index); -srtp_err_status_t srtp_test_io_lengths(const srtp_policy_t *policy, +srtp_err_status_t srtp_test_io_lengths(const test_policy_t *policy, bool test_extension_headers, bool use_mki, size_t mki_index); -srtp_err_status_t srtcp_test(const srtp_policy_t *policy, +srtp_err_status_t srtcp_test(const test_policy_t *policy, bool use_mki, size_t mki_index); -srtp_err_status_t srtcp_test_io_lengths(const srtp_policy_t *policy, +srtp_err_status_t srtcp_test_io_lengths(const test_policy_t *policy, bool use_mki, size_t mki_index); srtp_err_status_t srtp_session_print_policy(srtp_t srtp); -srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy); +srtp_err_status_t srtp_print_policy(const test_policy_t *policy); char *srtp_packet_to_string(uint8_t *packet, size_t packet_len); char *srtp_rtcp_packet_to_string(uint8_t *packet, size_t pkt_octet_len); @@ -164,6 +175,11 @@ double mips_estimate(size_t num_trials, size_t *ignore); srtp_err_status_t srtp_stream_list_test(void); +srtp_err_status_t policy_set_key(srtp_policy_t policy, const uint8_t *key); +srtp_err_status_t policy_add_keys(srtp_policy_t policy, + test_master_key_t **keys, + size_t num_keys); + const uint8_t rtp_test_packet_extension_header[12] = { /* one-byte header */ 0xbe, 0xde, @@ -198,17 +214,17 @@ 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_master_key_t master_key_1 = { test_key, test_mki_id }; -srtp_master_key_t master_key_2 = { +test_master_key_t master_key_2 = { test_key_2, test_mki_id_2 }; -srtp_master_key_t *test_keys[2] = { +test_master_key_t *test_keys[2] = { &master_key_1, &master_key_2 }; @@ -383,12 +399,12 @@ void log_handler(srtp_log_level_t level, const char *msg, void *data) * policy structs. They is declared at the end of this file. */ -extern const srtp_policy_t *policy_array[]; -extern const srtp_policy_t *invalid_policy_array[]; +extern const test_policy_t *policy_array[]; +extern const test_policy_t *invalid_policy_array[]; /* the wildcard_policy is declared below; it has a wildcard ssrc */ -extern const srtp_policy_t wildcard_policy; +extern const test_policy_t wildcard_policy; /* * mod_driver debug module - debugging module for this test driver @@ -509,14 +525,14 @@ int main(int argc, char *argv[]) } if (do_validation) { - const srtp_policy_t **policy = policy_array; - srtp_policy_t *big_policy; + const test_policy_t **test_policy = policy_array; srtp_t srtp_sender; /* loop over policy array, testing srtp and srtcp for each policy */ - while (*policy != NULL) { + while (*test_policy != NULL) { printf("testing srtp_protect and srtp_unprotect\n"); - if (srtp_test(*policy, false, false, 0) == srtp_err_status_ok) { + if (srtp_test(*test_policy, false, false, 0) == + srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -524,7 +540,7 @@ int main(int argc, char *argv[]) } printf("testing srtp_protect and srtp_unprotect io lengths\n"); - if (srtp_test_io_lengths(*policy, false, false, 0) == + if (srtp_test_io_lengths(*test_policy, false, false, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { @@ -534,7 +550,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect and srtp_unprotect with encrypted " "extensions headers\n"); - if (srtp_test(*policy, true, false, 0) == srtp_err_status_ok) { + if (srtp_test(*test_policy, true, false, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -543,7 +559,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect and srtp_unprotect io lengths with " "encrypted extension headers\n"); - if (srtp_test_io_lengths(*policy, true, false, 0) == + if (srtp_test_io_lengths(*test_policy, true, false, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { @@ -552,7 +568,7 @@ int main(int argc, char *argv[]) } printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n"); - if (srtcp_test(*policy, false, 0) == srtp_err_status_ok) { + if (srtcp_test(*test_policy, false, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -561,7 +577,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp io " "lengths\n"); - if (srtcp_test_io_lengths(*policy, false, 0) == + if (srtcp_test_io_lengths(*test_policy, false, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { @@ -571,7 +587,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI " "index set to 0\n"); - if (srtp_test(*policy, false, true, 0) == srtp_err_status_ok) { + if (srtp_test(*test_policy, false, true, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -579,7 +595,7 @@ int main(int argc, char *argv[]) } printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI " "index set to 1\n"); - if (srtp_test(*policy, false, true, 1) == srtp_err_status_ok) { + if (srtp_test(*test_policy, false, true, 1) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -588,7 +604,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect and srtp_unprotect io lengths with " "MKI\n"); - if (srtp_test_io_lengths(*policy, false, true, 1) == + if (srtp_test_io_lengths(*test_policy, false, true, 1) == srtp_err_status_ok) { printf("passed\n\n"); } else { @@ -598,7 +614,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI " "index set to 0\n"); - if (srtcp_test(*policy, true, 0) == srtp_err_status_ok) { + if (srtcp_test(*test_policy, true, 0) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -607,7 +623,7 @@ int main(int argc, char *argv[]) printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI " "index set to 1\n"); - if (srtcp_test(*policy, true, 1) == srtp_err_status_ok) { + if (srtcp_test(*test_policy, true, 1) == srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); @@ -616,56 +632,40 @@ int main(int argc, char *argv[]) printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp io " "lengths with MKI\n"); - if (srtcp_test_io_lengths(*policy, true, 1) == srtp_err_status_ok) { + if (srtcp_test_io_lengths(*test_policy, true, 1) == + srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); exit(1); } - policy++; + test_policy++; } /* loop over invalid policy array, testing that an SRTP context cannot * be created with the policy */ - policy = invalid_policy_array; - while (*policy != NULL) { + test_policy = invalid_policy_array; + while (*test_policy != NULL) { printf("testing srtp_create fails with invalid policy\n"); - if (srtp_create(&srtp_sender, *policy) != srtp_err_status_ok) { + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_ssrc(policy, (*test_policy)->ssrc)); + CHECK_OK(srtp_policy_set_profile(policy, (*test_policy)->profile)); + if ((*test_policy)->keys) { + CHECK_OK(policy_add_keys(policy, (*test_policy)->keys, + (*test_policy)->num_master_keys)); + } + status = srtp_create(&srtp_sender, policy); + srtp_policy_destroy(policy); + if (status != srtp_err_status_ok) { printf("passed\n\n"); } else { printf("failed\n"); exit(1); } - policy++; - } - - /* create a big policy list and run tests on it */ - status = srtp_create_big_policy(&big_policy); - if (status) { - printf("unexpected failure with error code %d\n", status); - exit(1); - } - printf("testing srtp_protect and srtp_unprotect with big policy\n"); - if (srtp_test(big_policy, false, false, 0) == srtp_err_status_ok) { - printf("passed\n\n"); - } else { - printf("failed\n"); - exit(1); - } - printf("testing srtp_protect and srtp_unprotect with big policy and " - "encrypted extensions headers\n"); - if (srtp_test(big_policy, true, false, 0) == srtp_err_status_ok) { - printf("passed\n\n"); - } else { - printf("failed\n"); - exit(1); - } - status = srtp_dealloc_big_policy(big_policy); - if (status) { - printf("unexpected failure with error code %d\n", status); - exit(1); + test_policy++; } /* run test on wildcard policy */ @@ -970,7 +970,7 @@ int main(int argc, char *argv[]) } if (do_timing_test) { - const srtp_policy_t **policy = policy_array; + const test_policy_t **policy = policy_array; /* loop over policies, run timing test for each */ while (*policy != NULL) { @@ -981,7 +981,7 @@ int main(int argc, char *argv[]) } if (do_rejection_test) { - const srtp_policy_t **policy = policy_array; + const test_policy_t **policy = policy_array; /* loop over policies, run rejection timing test for each */ while (*policy != NULL) { @@ -992,19 +992,16 @@ int main(int argc, char *argv[]) } if (do_codec_timing) { - srtp_policy_t policy; + test_policy_t policy; size_t ignore; double mips_value = mips_estimate(1000000000, &ignore); memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + policy.profile = srtp_profile_aes128_cm_sha1_80; policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + policy.keys = test_keys; + policy.num_master_keys = 1; printf("mips estimate: %e\n", mips_value); @@ -1045,6 +1042,61 @@ int main(int argc, char *argv[]) return 0; } +srtp_err_status_t policy_set_key(srtp_policy_t policy, const uint8_t *key) +{ + CHECK_OK(srtp_policy_remove_keys(policy)); + srtp_profile_t profile; + CHECK_OK(srtp_policy_get_profile(policy, &profile)); + size_t key_len = srtp_profile_get_master_key_length(profile); + size_t salt_len = srtp_profile_get_master_salt_length(profile); + return srtp_policy_add_key(policy, key, key_len, key + key_len, salt_len, + NULL, 0); +} + +srtp_err_status_t policy_add_keys(srtp_policy_t policy, + test_master_key_t **keys, + size_t num_keys) +{ + srtp_profile_t profile; + CHECK_OK(srtp_policy_get_profile(policy, &profile)); + size_t key_len = srtp_profile_get_master_key_length(profile); + size_t salt_len = srtp_profile_get_master_salt_length(profile); + size_t mki_len; + CHECK_OK(srtp_policy_get_mki_length(policy, &mki_len)); + for (size_t i = 0; i < num_keys; i++) { + test_master_key_t *mkey = keys[i]; + CHECK_OK(srtp_policy_add_key(policy, mkey->key, key_len, + mkey->key + key_len, salt_len, + mkey->mki_id, mki_len)); + } + return srtp_err_status_ok; +} + +srtp_err_status_t policy_from_test_policy(srtp_policy_t *policy, + const test_policy_t *test_policy, + bool enable_mki) +{ + CHECK_OK(srtp_policy_create(policy)); + CHECK_OK(srtp_policy_set_ssrc(*policy, test_policy->ssrc)); + CHECK_OK(srtp_policy_set_profile(*policy, test_policy->profile)); + CHECK_OK(srtp_policy_set_sec_serv(*policy, test_policy->rtp_sec_serv, + test_policy->rtcp_sec_serv)); + + if (enable_mki) { + CHECK_OK(srtp_policy_use_mki(*policy, test_policy->mki_size)); + } + if (test_policy->keys) { + if (enable_mki) { + CHECK_OK(policy_add_keys(*policy, test_policy->keys, + test_policy->num_master_keys)); + } else if (test_policy->num_master_keys > 0 && test_policy->keys[0]) { + CHECK_OK(policy_set_key(*policy, test_policy->keys[0]->key)); + } + } + + return srtp_err_status_ok; +} + /* * create_rtp_test_packet returns a pointer to a (malloced) example * RTP packet whose data field has the length given by payload_len. @@ -1174,7 +1226,7 @@ static uint16_t get_xtn_profile(const uint8_t *packet) return ntohs(xtn_hdr->profile_specific); } -void srtp_do_timing(const srtp_policy_t *policy) +void srtp_do_timing(const test_policy_t *policy) { int len; @@ -1196,7 +1248,7 @@ void srtp_do_timing(const srtp_policy_t *policy) printf("\r\n\r\n"); } -void srtp_do_rejection_timing(const srtp_policy_t *policy) +void srtp_do_rejection_timing(const test_policy_t *policy) { int len; @@ -1219,9 +1271,11 @@ void srtp_do_rejection_timing(const srtp_policy_t *policy) #define MAX_MSG_LEN 1024 -double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy) +double srtp_bits_per_second(size_t msg_len_octets, + const test_policy_t *test_policy) { srtp_t srtp; + srtp_policy_t policy; uint8_t *mesg; clock_t timer; size_t num_trials = 100000; @@ -1229,6 +1283,8 @@ double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy) uint32_t ssrc; srtp_err_status_t status; + CHECK_OK(policy_from_test_policy(&policy, test_policy, false)); + /* * allocate and initialize an srtp session */ @@ -1238,13 +1294,15 @@ double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy) exit(1); } + srtp_policy_destroy(policy); + /* * if the ssrc is unspecified, use a predetermined one */ - if (policy->ssrc.type != ssrc_specific) { + if (test_policy->ssrc.type != ssrc_specific) { ssrc = 0xdeadbeef; } else { - ssrc = policy->ssrc.value; + ssrc = test_policy->ssrc.value; } /* @@ -1288,16 +1346,19 @@ double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy) } double srtp_rejections_per_second(size_t msg_len_octets, - const srtp_policy_t *policy) + const test_policy_t *test_policy) { srtp_ctx_t *srtp; + srtp_policy_t policy; uint8_t *mesg; size_t len; clock_t timer; size_t num_trials = 1000000; - uint32_t ssrc = policy->ssrc.value; + uint32_t ssrc = test_policy->ssrc.value; srtp_err_status_t status; + CHECK_OK(policy_from_test_policy(&policy, test_policy, false)); + /* * allocate and initialize an srtp session */ @@ -1307,6 +1368,8 @@ double srtp_rejections_per_second(size_t msg_len_octets, exit(1); } + srtp_policy_destroy(policy); + mesg = create_rtp_test_packet(msg_len_octets, ssrc, 1, 1, false, &len, NULL); if (mesg == NULL) { @@ -1332,7 +1395,7 @@ double srtp_rejections_per_second(size_t msg_len_octets, return (double)num_trials * CLOCKS_PER_SEC / timer; } -srtp_err_status_t srtp_test(const srtp_policy_t *policy, +srtp_err_status_t srtp_test(const test_policy_t *policy, bool test_extension_headers, bool use_mki, size_t mki_index) @@ -1342,7 +1405,7 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, srtp_t srtp_rcvr; srtp_err_status_t status = srtp_err_status_ok; uint8_t *hdr, *hdr2; - uint8_t hdr_enc[64]; + uint8_t hdr_enc[128]; size_t msg_len_octets, msg_len_enc, msg_len; size_t len, len2; size_t tag_length; @@ -1352,19 +1415,13 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, srtp_policy_t rcvr_policy; uint8_t header = 1; - memcpy(&send_policy, policy, sizeof(srtp_policy_t)); - - send_policy.use_mki = use_mki; - if (!use_mki) { - send_policy.mki_size = 0; - } + CHECK_OK(policy_from_test_policy(&send_policy, policy, use_mki)); if (test_extension_headers) { - send_policy.enc_xtn_hdr = &header; - send_policy.enc_xtn_hdr_count = 1; + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(send_policy, header)); } - CHECK_OK(srtp_create(&srtp_sender, &send_policy)); + CHECK_OK(srtp_create(&srtp_sender, send_policy)); /* print out policy */ CHECK_OK(srtp_session_print_policy(srtp_sender)); @@ -1437,7 +1494,7 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, * reason, we skip this check if the plaintext is less than four * octets long. */ - if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { + if ((policy->rtp_sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { printf("testing that ciphertext is distinct from plaintext..."); status = srtp_err_status_algo_fail; for (i = 12; i < msg_len_octets + 12; i++) { @@ -1454,10 +1511,11 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, printf("passed\n"); } - memcpy(&rcvr_policy, &send_policy, sizeof(srtp_policy_t)); - rcvr_policy.ssrc.type = ssrc_any_inbound; + CHECK_OK(srtp_policy_clone(send_policy, &rcvr_policy)); + CHECK_OK(srtp_policy_set_ssrc(rcvr_policy, + (srtp_ssrc_t){ ssrc_any_inbound, 0 })); - CHECK_OK(srtp_create(&srtp_rcvr, &rcvr_policy)); + CHECK_OK(srtp_create(&srtp_rcvr, rcvr_policy)); CHECK_OK(call_srtp_unprotect(srtp_rcvr, hdr, &len)); @@ -1480,7 +1538,7 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, /* * if the policy includes authentication, then test for false positives */ - if (policy->rtp.sec_serv & sec_serv_auth) { + if (policy->rtp_sec_serv & sec_serv_auth) { uint8_t *data = hdr + (test_extension_headers ? 24 : 12); printf("testing for false positives in replay check..."); @@ -1523,12 +1581,15 @@ srtp_err_status_t srtp_test(const srtp_policy_t *policy, CHECK_OK(srtp_dealloc(srtp_sender)); CHECK_OK(srtp_dealloc(srtp_rcvr)); + srtp_policy_destroy(send_policy); + srtp_policy_destroy(rcvr_policy); + free(hdr); free(hdr2); return srtp_err_status_ok; } -srtp_err_status_t srtp_test_io_lengths(const srtp_policy_t *policy, +srtp_err_status_t srtp_test_io_lengths(const test_policy_t *policy, bool test_extension_headers, bool use_mki, size_t mki_index) @@ -1543,20 +1604,14 @@ srtp_err_status_t srtp_test_io_lengths(const srtp_policy_t *policy, size_t rtp_header_len = 12; uint8_t xtn_header_id = 1; - memcpy(&send_policy, policy, sizeof(srtp_policy_t)); - - send_policy.use_mki = use_mki; - if (!use_mki) { - send_policy.mki_size = 0; - } + CHECK_OK(policy_from_test_policy(&send_policy, policy, use_mki)); if (test_extension_headers) { - send_policy.enc_xtn_hdr = &xtn_header_id; - send_policy.enc_xtn_hdr_count = 1; + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(send_policy, xtn_header_id)); rtp_header_len += sizeof(rtp_test_packet_extension_header); } - CHECK_OK(srtp_create(&srtp_sender, &send_policy)); + CHECK_OK(srtp_create(&srtp_sender, send_policy)); // get required trailer length size_t trailer_len; @@ -1685,10 +1740,11 @@ srtp_err_status_t srtp_test_io_lengths(const srtp_policy_t *policy, srtp_t srtp_receiver; srtp_policy_t receive_policy; - memcpy(&receive_policy, &send_policy, sizeof(srtp_policy_t)); - receive_policy.ssrc.type = ssrc_any_inbound; + CHECK_OK(srtp_policy_clone(send_policy, &receive_policy)); + CHECK_OK(srtp_policy_set_ssrc(receive_policy, + (srtp_ssrc_t){ ssrc_any_inbound, 0 })); - CHECK_OK(srtp_create(&srtp_receiver, &receive_policy)); + CHECK_OK(srtp_create(&srtp_receiver, receive_policy)); // unprotect zero byte input rtp_len = buffer_len; @@ -1730,10 +1786,13 @@ srtp_err_status_t srtp_test_io_lengths(const srtp_policy_t *policy, CHECK_OK(srtp_dealloc(srtp_receiver)); + srtp_policy_destroy(send_policy); + srtp_policy_destroy(receive_policy); + return srtp_err_status_ok; } -srtp_err_status_t srtcp_test(const srtp_policy_t *policy, +srtp_err_status_t srtcp_test(const test_policy_t *policy, bool use_mki, size_t mki_index) { @@ -1741,7 +1800,7 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, srtp_t srtcp_rcvr; srtp_err_status_t status = srtp_err_status_ok; uint8_t *hdr, *hdr2; - uint8_t hdr_enc[64]; + uint8_t hdr_enc[128]; size_t msg_len_octets, msg_len_enc, msg_len; size_t len, len2; size_t buffer_len; @@ -1750,14 +1809,9 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, srtp_policy_t send_policy; srtp_policy_t rcvr_policy; - memcpy(&send_policy, policy, sizeof(srtp_policy_t)); + CHECK_OK(policy_from_test_policy(&send_policy, policy, use_mki)); - send_policy.use_mki = use_mki; - if (!use_mki) { - send_policy.mki_size = 0; - } - - CHECK_OK(srtp_create(&srtcp_sender, &send_policy)); + CHECK_OK(srtp_create(&srtcp_sender, send_policy)); /* print out policy */ CHECK_OK(srtp_session_print_policy(srtcp_sender)); @@ -1825,7 +1879,7 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, * reason, we skip this check if the plaintext is less than four * octets long. */ - if ((policy->rtcp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { + if ((policy->rtcp_sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { printf("testing that ciphertext is distinct from plaintext..."); status = srtp_err_status_algo_fail; for (size_t i = 12; i < msg_len_octets + 12; i++) { @@ -1842,12 +1896,13 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, printf("passed\n"); } - memcpy(&rcvr_policy, &send_policy, sizeof(srtp_policy_t)); - if (send_policy.ssrc.type == ssrc_any_outbound) { - rcvr_policy.ssrc.type = ssrc_any_inbound; + CHECK_OK(srtp_policy_clone(send_policy, &rcvr_policy)); + if (policy->ssrc.type == ssrc_any_outbound) { + CHECK_OK(srtp_policy_set_ssrc(rcvr_policy, + (srtp_ssrc_t){ ssrc_any_inbound, 0 })); } - CHECK_OK(srtp_create(&srtcp_rcvr, &rcvr_policy)); + CHECK_OK(srtp_create(&srtcp_rcvr, rcvr_policy)); CHECK_OK(call_srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len)); @@ -1870,7 +1925,7 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, /* * if the policy includes authentication, then test for false positives */ - if (policy->rtp.sec_serv & sec_serv_auth) { + if (policy->rtcp_sec_serv & sec_serv_auth) { uint8_t *data = hdr + 12; printf("testing for false positives in replay check..."); @@ -1910,12 +1965,15 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, CHECK_OK(srtp_dealloc(srtcp_sender)); CHECK_OK(srtp_dealloc(srtcp_rcvr)); + srtp_policy_destroy(send_policy); + srtp_policy_destroy(rcvr_policy); + free(hdr); free(hdr2); return srtp_err_status_ok; } -srtp_err_status_t srtcp_test_io_lengths(const srtp_policy_t *policy, +srtp_err_status_t srtcp_test_io_lengths(const test_policy_t *policy, bool use_mki, size_t mki_index) { @@ -1926,14 +1984,9 @@ srtp_err_status_t srtcp_test_io_lengths(const srtp_policy_t *policy, size_t rtcp_len, buffer_len, srtcp_len; size_t rtcp_header_len = 8; - memcpy(&send_policy, policy, sizeof(srtp_policy_t)); - - send_policy.use_mki = use_mki; - if (!use_mki) { - send_policy.mki_size = 0; - } + CHECK_OK(policy_from_test_policy(&send_policy, policy, use_mki)); - CHECK_OK(srtp_create(&srtp_sender, &send_policy)); + CHECK_OK(srtp_create(&srtp_sender, send_policy)); // get required trailer length size_t trailer_len; @@ -2054,10 +2107,11 @@ srtp_err_status_t srtcp_test_io_lengths(const srtp_policy_t *policy, srtp_t srtp_receiver; srtp_policy_t receive_policy; - memcpy(&receive_policy, &send_policy, sizeof(srtp_policy_t)); - receive_policy.ssrc.type = ssrc_any_inbound; + CHECK_OK(srtp_policy_clone(send_policy, &receive_policy)); + CHECK_OK(srtp_policy_set_ssrc(receive_policy, + (srtp_ssrc_t){ ssrc_any_inbound, 0 })); - CHECK_OK(srtp_create(&srtp_receiver, &receive_policy)); + CHECK_OK(srtp_create(&srtp_receiver, receive_policy)); // unprotect zero byte input rtcp_len = buffer_len; @@ -2103,6 +2157,9 @@ srtp_err_status_t srtcp_test_io_lengths(const srtp_policy_t *policy, CHECK_OK(srtp_dealloc(srtp_receiver)); + srtp_policy_destroy(send_policy); + srtp_policy_destroy(receive_policy); + return srtp_err_status_ok; } @@ -2199,10 +2256,12 @@ srtp_err_status_t srtp_session_print_policy(srtp_t srtp) return data.status; } -srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy) +srtp_err_status_t srtp_print_policy(const test_policy_t *test_policy) { srtp_err_status_t status; + srtp_policy_t policy; srtp_t session; + CHECK_OK(policy_from_test_policy(&policy, test_policy, false)); status = srtp_create(&session, policy); if (status) { @@ -2412,17 +2471,13 @@ srtp_err_status_t srtp_validate(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -2468,7 +2523,7 @@ srtp_err_status_t srtp_validate(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -2508,6 +2563,8 @@ srtp_err_status_t srtp_validate(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -2574,20 +2631,14 @@ srtp_err_status_t srtp_validate_mki(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.keys = test_keys; - policy.num_master_keys = 2; - policy.use_mki = true; - policy.mki_size = TEST_MKI_ID_SIZE; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(srtp_policy_use_mki(policy, TEST_MKI_ID_SIZE)); + CHECK_OK(policy_add_keys(policy, test_keys, 2)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -2643,7 +2694,7 @@ srtp_err_status_t srtp_validate_mki(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -2684,6 +2735,8 @@ srtp_err_status_t srtp_validate_mki(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -2747,17 +2800,13 @@ srtp_err_status_t srtp_validate_null_sha1_80(void) * create a session with a single stream using the null cipher * and sha1_80 policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_null_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -2803,7 +2852,7 @@ srtp_err_status_t srtp_validate_null_sha1_80(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -2843,6 +2892,8 @@ srtp_err_status_t srtp_validate_null_sha1_80(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -2902,23 +2953,14 @@ srtp_err_status_t srtp_validate_null_null(void) * create a session with a single stream using the null cipher * and null hmac policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp); - srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - /* - * We need some non-zero value set here - */ - policy.key = (void *)(uintptr_t)-1; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_null_null)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); - status = srtp_create(&srtp_snd, &policy); - if (status) { - return status; - } + CHECK_OK(srtp_policy_validate(policy)); + + CHECK_OK(srtp_create(&srtp_snd, policy)); /* * protect plaintext, then compare with ciphertext @@ -2967,10 +3009,7 @@ srtp_err_status_t srtp_validate_null_null(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); - if (status) { - return status; - } + CHECK_OK(srtp_create(&srtp_recv, policy)); /* * unprotect ciphertext, then compare with plaintext @@ -2995,9 +3034,6 @@ srtp_err_status_t srtp_validate_null_null(void) if (!status && (len != 24)) { status = srtp_err_status_fail; } - if (status) { - return status; - } if (!srtp_octet_string_equal(srtcp_ciphertext, rtcp_plaintext_ref, len)) { return srtp_err_status_fail; @@ -3013,6 +3049,8 @@ srtp_err_status_t srtp_validate_null_null(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -3220,16 +3258,12 @@ srtp_err_status_t srtp_validate_cryptex(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.use_cryptex = true; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); for (size_t i = 0; i < num_vectors; ++i) { uint8_t packet[1400]; @@ -3253,7 +3287,7 @@ srtp_err_status_t srtp_validate_cryptex(void) */ debug_print(mod_driver, "test vector: %s\n", vectors[i].name); - CHECK_OK(srtp_create(&srtp_snd, &policy)); + CHECK_OK(srtp_create(&srtp_snd, policy)); CHECK_OK(call_srtp_protect(srtp_snd, packet, &len, 0)); CHECK(len == enc_len); @@ -3267,7 +3301,7 @@ srtp_err_status_t srtp_validate_cryptex(void) CHECK_OK(srtp_dealloc(srtp_snd)); - CHECK_OK(srtp_create(&srtp_recv, &policy)); + CHECK_OK(srtp_create(&srtp_recv, policy)); /* * unprotect ciphertext, then compare with plaintext @@ -3280,6 +3314,8 @@ srtp_err_status_t srtp_validate_cryptex(void) CHECK_OK(srtp_dealloc(srtp_recv)); } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -3304,19 +3340,17 @@ srtp_err_status_t srtp_test_cryptex_csrc_but_no_extension_header(void) * policy and with the SSRC value 0xcafebabe */ srtp_policy_t policy; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.use_cryptex = true; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); srtp_t srtp_snd; - CHECK_OK(srtp_create(&srtp_snd, &policy)); + CHECK_OK(srtp_create(&srtp_snd, policy)); + + srtp_policy_destroy(policy); uint8_t packet[1400]; size_t packet_len = @@ -3332,25 +3366,24 @@ srtp_err_status_t srtp_test_cryptex_csrc_but_no_extension_header(void) srtp_err_status_t srtp_test_cryptex_disable(void) { + const uint32_t test_ssrc = 0xcafebabe; srtp_policy_t policy; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.use_cryptex = true; - policy.next = NULL; - srtp_t srtp_snd, srtp_recv; - CHECK_OK(srtp_create(&srtp_snd, &policy)); - CHECK_OK(srtp_create(&srtp_recv, &policy)); + + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, test_ssrc })); + CHECK_OK(policy_set_key(policy, test_key)); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); + + CHECK_OK(srtp_create(&srtp_snd, policy)); + CHECK_OK(srtp_create(&srtp_recv, policy)); size_t packet_len; - uint8_t *packet = create_rtp_test_packet(100, policy.ssrc.value, 1, 1000, - true, &packet_len, NULL); + uint8_t *packet = create_rtp_test_packet(100, test_ssrc, 1, 1000, true, + &packet_len, NULL); + uint8_t clear_text[1400]; memcpy(clear_text, packet, packet_len); size_t clear_text_len = packet_len; @@ -3373,9 +3406,9 @@ srtp_err_status_t srtp_test_cryptex_disable(void) hdr->seq = htons(ntohs(hdr->seq) + 1); memcpy(clear_text, packet, packet_len); - // disbale cryptex at sender only - policy.use_cryptex = false; - CHECK_OK(srtp_update(srtp_snd, &policy)); + // disable cryptex at sender only + CHECK_OK(srtp_policy_set_cryptex(policy, false)); + CHECK_OK(srtp_update(srtp_snd, policy)); CHECK_OK(call_srtp_protect(srtp_snd, packet, &packet_len, 0)); CHECK(packet_len > clear_text_len); @@ -3394,12 +3427,16 @@ srtp_err_status_t srtp_test_cryptex_disable(void) free(packet); CHECK_OK(srtp_dealloc(srtp_snd)); CHECK_OK(srtp_dealloc(srtp_recv)); + srtp_policy_destroy(policy); return srtp_err_status_ok; } srtp_err_status_t srtp_test_missing_session_keys(void) { + // Not sure if this test is valid as this is not a state that should be + // possible to reach with the public API. + srtp_t srtp_receiver; srtp_policy_t policy; srtp_stream_ctx_t *stream; @@ -3409,15 +3446,13 @@ srtp_err_status_t srtp_test_missing_session_keys(void) size_t packet_len; size_t buffer_len; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_any_inbound; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 })); + CHECK_OK(policy_set_key(policy, test_key)); - CHECK_OK(srtp_create(&srtp_receiver, &policy)); + CHECK_OK(srtp_create(&srtp_receiver, policy)); CHECK(srtp_receiver->stream_template != NULL); stream = srtp_receiver->stream_template; @@ -3438,6 +3473,7 @@ srtp_err_status_t srtp_test_missing_session_keys(void) free(packet); CHECK_OK(srtp_dealloc(srtp_receiver)); + srtp_policy_destroy(policy); return srtp_err_status_ok; } @@ -3504,17 +3540,13 @@ srtp_err_status_t srtp_validate_gcm(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key_gcm; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key_gcm)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -3560,7 +3592,7 @@ srtp_err_status_t srtp_validate_gcm(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -3607,6 +3639,8 @@ srtp_err_status_t srtp_validate_gcm(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -3828,18 +3862,14 @@ srtp_err_status_t srtp_validate_gcm_cryptex(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key_gcm_cryptex; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.use_cryptex = true; - policy.next = NULL; - - CHECK_OK(srtp_create(&srtp_snd, &policy)); + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key_gcm_cryptex)); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); + + CHECK_OK(srtp_create(&srtp_snd, policy)); for (size_t i = 0; i < num_vectors; ++i) { uint8_t packet[1400]; @@ -3886,7 +3916,7 @@ srtp_err_status_t srtp_validate_gcm_cryptex(void) * above - we need to do this so that the replay checking doesn't * complain */ - CHECK_OK(srtp_create(&srtp_recv, &policy)); + CHECK_OK(srtp_create(&srtp_recv, policy)); /* * unprotect ciphertext, then compare with plaintext @@ -3901,6 +3931,8 @@ srtp_err_status_t srtp_validate_gcm_cryptex(void) CHECK_OK(srtp_dealloc(srtp_snd)); + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -3961,19 +3993,16 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key_ext_headers; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.enc_xtn_hdr = headers; - policy.enc_xtn_hdr_count = sizeof(headers) / sizeof(headers[0]); - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key_ext_headers)); + for (size_t i = 0; i < sizeof(headers) / sizeof(headers[0]); i++) { + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, headers[i])); + } - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -4001,7 +4030,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4030,6 +4059,8 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -4089,19 +4120,16 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key_ext_headers; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.enc_xtn_hdr = headers; - policy.enc_xtn_hdr_count = sizeof(headers) / sizeof(headers[0]); - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key_ext_headers)); + for (size_t i = 0; i < sizeof(headers) / sizeof(headers[0]); i++) { + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, headers[i])); + } - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -4129,7 +4157,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4158,6 +4186,8 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -4213,17 +4243,13 @@ srtp_err_status_t srtp_validate_aes_192(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0x00000000; - policy.key = aes_192_test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; - - CHECK_OK(srtp_create(&srtp_snd, &policy)); + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes192_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0x00000000 })); + CHECK_OK(policy_set_key(policy, aes_192_test_key)); + + CHECK_OK(srtp_create(&srtp_snd, policy)); /* * protect plaintext, then compare with ciphertext @@ -4244,7 +4270,7 @@ srtp_err_status_t srtp_validate_aes_192(void) * above - we need to do this so that the replay checking doesn't * complain */ - CHECK_OK(srtp_create(&srtp_recv, &policy)); + CHECK_OK(srtp_create(&srtp_recv, policy)); /* * unprotect ciphertext, then compare with plaintext @@ -4257,6 +4283,8 @@ srtp_err_status_t srtp_validate_aes_192(void) CHECK_OK(srtp_dealloc(srtp_snd)); CHECK_OK(srtp_dealloc(srtp_recv)); + srtp_policy_destroy(policy); + return srtp_err_status_ok; } #endif @@ -4310,17 +4338,13 @@ srtp_err_status_t srtp_validate_aes_256(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = aes_256_test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes256_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, aes_256_test_key)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } @@ -4348,7 +4372,7 @@ srtp_err_status_t srtp_validate_aes_256(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4375,52 +4399,7 @@ srtp_err_status_t srtp_validate_aes_256(void) return status; } - return srtp_err_status_ok; -} - -srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list) -{ - extern const srtp_policy_t *policy_array[]; - srtp_policy_t *p = NULL; - srtp_policy_t *tmp; - int i = 0; - uint32_t ssrc = 0; - - /* sanity checking */ - if ((list == NULL) || (policy_array[0] == NULL)) { - return srtp_err_status_bad_param; - } - - /* - * loop over policy list, mallocing a new list and copying values - * into it (and incrementing the SSRC value as we go along) - */ - tmp = NULL; - while (policy_array[i] != NULL) { - p = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); - if (p == NULL) { - return srtp_err_status_bad_param; - } - memcpy(p, policy_array[i], sizeof(srtp_policy_t)); - p->ssrc.type = ssrc_specific; - p->ssrc.value = ssrc++; - p->next = tmp; - tmp = p; - i++; - } - *list = p; - - return srtp_err_status_ok; -} - -srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list) -{ - srtp_policy_t *p, *next; - - for (p = list; p != NULL; p = next) { - next = p->next; - free(p); - } + srtp_policy_destroy(policy); return srtp_err_status_ok; } @@ -4437,23 +4416,18 @@ srtp_err_status_t srtp_test_empty_payload(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } - mesg = - create_rtp_test_packet(0, policy.ssrc.value, 1, 1, false, &len, NULL); + mesg = create_rtp_test_packet(0, 0xcafebabe, 1, 1, false, &len, NULL); if (mesg == NULL) { return srtp_err_status_fail; } @@ -4470,7 +4444,7 @@ srtp_err_status_t srtp_test_empty_payload(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4495,6 +4469,8 @@ srtp_err_status_t srtp_test_empty_payload(void) return status; } + srtp_policy_destroy(policy); + free(mesg); return srtp_err_status_ok; @@ -4513,23 +4489,18 @@ srtp_err_status_t srtp_test_empty_payload_gcm(void) * create a session with a single stream using the default srtp * policy and with the SSRC value 0xcafebabe */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); + CHECK_OK(policy_set_key(policy, test_key)); - status = srtp_create(&srtp_snd, &policy); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } - mesg = - create_rtp_test_packet(0, policy.ssrc.value, 1, 1, false, &len, NULL); + mesg = create_rtp_test_packet(0, 0xcafebabe, 1, 1, false, &len, NULL); if (mesg == NULL) { return srtp_err_status_fail; } @@ -4546,7 +4517,7 @@ srtp_err_status_t srtp_test_empty_payload_gcm(void) * above - we need to do this so that the replay checking doesn't * complain */ - status = srtp_create(&srtp_recv, &policy); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4571,6 +4542,8 @@ srtp_err_status_t srtp_test_empty_payload_gcm(void) return status; } + srtp_policy_destroy(policy); + free(mesg); return srtp_err_status_ok; @@ -4584,16 +4557,14 @@ srtp_err_status_t srtp_test_short_packet_gcm_mki(void) size_t packet_len; size_t buffer_len; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_any_inbound; - policy.keys = test_keys; - policy.num_master_keys = 2; - policy.use_mki = true; - policy.mki_size = TEST_MKI_ID_SIZE; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 })); + CHECK_OK(srtp_policy_use_mki(policy, TEST_MKI_ID_SIZE)); + CHECK_OK(policy_add_keys(policy, test_keys, 2)); - CHECK_OK(srtp_create(&srtp_receiver, &policy)); + CHECK_OK(srtp_create(&srtp_receiver, policy)); packet = create_rtp_test_packet(0, 0, 1, 1, false, &packet_len, &buffer_len); @@ -4608,6 +4579,7 @@ srtp_err_status_t srtp_test_short_packet_gcm_mki(void) free(packet); CHECK_OK(srtp_dealloc(srtp_receiver)); + srtp_policy_destroy(policy); return srtp_err_status_ok; } @@ -4615,10 +4587,8 @@ srtp_err_status_t srtp_test_short_packet_gcm_mki(void) srtp_err_status_t srtp_test_remove_stream(void) { - srtp_err_status_t status; - srtp_policy_t *policy_list, policy; + srtp_policy_t policy; srtp_t session; - srtp_stream_t stream; /* * srtp_get_stream() is a libSRTP internal function that we declare @@ -4627,82 +4597,48 @@ srtp_err_status_t srtp_test_remove_stream(void) */ extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); - status = srtp_create_big_policy(&policy_list); - if (status) { - return status; - } + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(policy, test_key)); - status = srtp_create(&session, policy_list); - if (status) { - return status; + CHECK_OK(srtp_create(&session, NULL)); + + for (uint32_t i = 0; i < 3; i++) { + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_specific, i })); + CHECK_OK(srtp_stream_add(session, policy)); } /* * check for false positives by trying to remove a stream that's not * in the session */ - status = srtp_stream_remove(session, 0xaaaaaaaa); - if (status != srtp_err_status_no_ctx) { - return srtp_err_status_fail; - } + CHECK_RETURN(srtp_stream_remove(session, 0xaaaaaaaa), + srtp_err_status_no_ctx); /* * check for false negatives by removing stream 0x1, then * searching for streams 0x0 and 0x2 */ - status = srtp_stream_remove(session, 0x1); - if (status != srtp_err_status_ok) { - return srtp_err_status_fail; - } - stream = srtp_get_stream(session, htonl(0x0)); - if (stream == NULL) { - return srtp_err_status_fail; - } - stream = srtp_get_stream(session, htonl(0x2)); - if (stream == NULL) { - return srtp_err_status_fail; - } - - status = srtp_dealloc(session); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_stream_remove(session, 0x1)); + CHECK(srtp_get_stream(session, htonl(0x0)) != NULL); + CHECK(srtp_get_stream(session, htonl(0x2)) != NULL); - status = srtp_dealloc_big_policy(policy_list); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_dealloc(session)); /* Now test adding and removing a single stream */ - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; - - status = srtp_create(&session, NULL); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_policy_set_ssrc(policy, + (srtp_ssrc_t){ ssrc_specific, 0xcafebabe })); - status = srtp_stream_add(session, &policy); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_create(&session, NULL)); - status = srtp_stream_remove(session, 0xcafebabe); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_stream_add(session, policy)); - status = srtp_dealloc(session); - if (status != srtp_err_status_ok) { - return status; - } + CHECK_OK(srtp_stream_remove(session, 0xcafebabe)); + + CHECK_OK(srtp_dealloc(session)); + + srtp_policy_destroy(policy); return srtp_err_status_ok; } @@ -4735,23 +4671,21 @@ srtp_err_status_t srtp_test_update(void) srtp_t srtp_snd, srtp_recv; srtp_policy_t policy; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; - policy.key = test_key; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(policy, test_key)); /* create a send and receive ctx with default profile and test_key */ - policy.ssrc.type = ssrc_any_outbound; - status = srtp_create(&srtp_snd, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + status = srtp_create(&srtp_snd, policy); if (status) { return status; } - policy.ssrc.type = ssrc_any_inbound; - status = srtp_create(&srtp_recv, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 })); + status = srtp_create(&srtp_recv, policy); if (status) { return status; } @@ -4797,9 +4731,10 @@ srtp_err_status_t srtp_test_update(void) free(msg); /* update send ctx with same test_key t verify update works*/ - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; - status = srtp_update(srtp_snd, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(policy_set_key(policy, test_key)); + status = srtp_update(srtp_snd, policy); if (status) { return status; } @@ -4824,9 +4759,10 @@ srtp_err_status_t srtp_test_update(void) free(msg); /* update send ctx to use test_alt_key */ - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_alt_key; - status = srtp_update(srtp_snd, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(policy_set_key(policy, test_alt_key)); + status = srtp_update(srtp_snd, policy); if (status) { return status; } @@ -4857,9 +4793,10 @@ srtp_err_status_t srtp_test_update(void) { srtp_t srtp_recv_roc_0; - policy.ssrc.type = ssrc_any_inbound; - policy.key = test_alt_key; - status = srtp_create(&srtp_recv_roc_0, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 })); + CHECK_OK(policy_set_key(policy, test_alt_key)); + status = srtp_create(&srtp_recv_roc_0, policy); if (status) { return status; } @@ -4877,9 +4814,10 @@ srtp_err_status_t srtp_test_update(void) } /* update receive ctx to use test_alt_key */ - policy.ssrc.type = ssrc_any_inbound; - policy.key = test_alt_key; - status = srtp_update(srtp_recv, &policy); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 })); + CHECK_OK(policy_set_key(policy, test_alt_key)); + status = srtp_update(srtp_recv, policy); if (status) { return status; } @@ -4903,6 +4841,8 @@ srtp_err_status_t srtp_test_update(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -4912,40 +4852,35 @@ srtp_err_status_t srtp_test_update_mki(void) srtp_t srtp; srtp_policy_t policy; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_any_outbound; - policy.keys = test_keys; - policy.num_master_keys = 1; - policy.use_mki = true; - policy.mki_size = 1; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_use_mki(policy, 1)); + CHECK_OK(policy_add_keys(policy, test_keys, 1)); - status = srtp_create(&srtp, &policy); + status = srtp_create(&srtp, policy); if (status) { return status; } /* can not turn off mki */ - policy.use_mki = false; - policy.mki_size = 0; - status = srtp_update(srtp, &policy); + CHECK_OK(srtp_policy_use_mki(policy, 0)); + status = srtp_update(srtp, policy); if (status == srtp_err_status_ok) { return srtp_err_status_fail; } /* update same values still ok*/ - policy.use_mki = true; - policy.mki_size = 1; - status = srtp_update(srtp, &policy); + CHECK_OK(srtp_policy_use_mki(policy, 1)); + status = srtp_update(srtp, policy); if (status) { return status; } /* can not change mki size*/ - policy.use_mki = true; - policy.mki_size = 2; - status = srtp_update(srtp, &policy); + CHECK_OK(srtp_policy_use_mki(policy, 2)); + status = srtp_update(srtp, policy); if (status == srtp_err_status_ok) { return srtp_err_status_fail; } @@ -4955,6 +4890,8 @@ srtp_err_status_t srtp_test_update_mki(void) return status; } + srtp_policy_destroy(policy); + return srtp_err_status_ok; } @@ -4976,73 +4913,64 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( (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); - policy.window_size = 128; - policy.allow_repeat_tx = false; - policy.next = NULL; - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; - - memset(&policy_mki, 0, sizeof(policy_mki)); - srtp_crypto_policy_set_rtp_default(&policy_mki.rtp); - srtp_crypto_policy_set_rtcp_default(&policy_mki.rtcp); - policy_mki.window_size = 128; - policy_mki.allow_repeat_tx = false; - policy_mki.next = NULL; - policy_mki.ssrc.type = ssrc_any_outbound; - policy_mki.key = NULL; - policy_mki.keys = test_keys; - policy_mki.num_master_keys = 2; - policy_mki.use_mki = true; - policy_mki.mki_size = TEST_MKI_ID_SIZE; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(policy_set_key(policy, test_key)); + + CHECK_OK(srtp_policy_create(&policy_mki)); + CHECK_OK( + srtp_policy_set_profile(policy_mki, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_set_ssrc(policy_mki, + (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_use_mki(policy_mki, TEST_MKI_ID_SIZE)); + CHECK_OK(policy_add_keys(policy_mki, test_keys, 2)); #ifdef GCM - memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); - policy_aes_gcm.window_size = 128; - policy_aes_gcm.allow_repeat_tx = false; - policy_aes_gcm.next = NULL; - policy_aes_gcm.ssrc.type = ssrc_any_outbound; - policy_aes_gcm.key = test_key; - - memset(&policy_aes_gcm_mki, 0, sizeof(policy_aes_gcm_mki)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtcp); - policy_aes_gcm_mki.window_size = 128; - policy_aes_gcm_mki.allow_repeat_tx = false; - policy_aes_gcm_mki.next = NULL; - policy_aes_gcm_mki.ssrc.type = ssrc_any_outbound; - policy_aes_gcm_mki.key = NULL; - policy_aes_gcm_mki.keys = test_keys; - policy_aes_gcm_mki.num_master_keys = 2; - policy_aes_gcm_mki.use_mki = true; - policy_aes_gcm_mki.mki_size = TEST_MKI_ID_SIZE; + CHECK_OK(srtp_policy_create(&policy_aes_gcm)); + CHECK_OK( + srtp_policy_set_profile(policy_aes_gcm, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy_aes_gcm, + (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(policy_set_key(policy_aes_gcm, test_key)); + + CHECK_OK(srtp_policy_create(&policy_aes_gcm_mki)); + CHECK_OK(srtp_policy_set_profile(policy_aes_gcm_mki, + srtp_profile_aead_aes_128_gcm)); + CHECK_OK(srtp_policy_set_ssrc(policy_aes_gcm_mki, + (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_use_mki(policy_aes_gcm_mki, TEST_MKI_ID_SIZE)); + CHECK_OK(policy_add_keys(policy_aes_gcm_mki, test_keys, 2)); + #endif // GCM /* create a send ctx with defualt profile and test_key */ - status = srtp_create(srtp_send, &policy); + status = srtp_create(srtp_send, policy); if (status) { return status; } - status = srtp_create(srtp_send_mki, &policy_mki); + status = srtp_create(srtp_send_mki, policy_mki); if (status) { return status; } + srtp_policy_destroy(policy); + srtp_policy_destroy(policy_mki); #ifdef GCM - status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); + status = srtp_create(srtp_send_aes_gcm, policy_aes_gcm); if (status) { return status; } - status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); + status = srtp_create(srtp_send_aes_gcm_mki, policy_aes_gcm_mki); if (status) { return status; } + + srtp_policy_destroy(policy_aes_gcm); + srtp_policy_destroy(policy_aes_gcm_mki); #endif // GCM return srtp_err_status_ok; @@ -5194,59 +5122,57 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) const uint32_t num_pkts = 5; uint8_t *pkts[5]; size_t pkt_len_octets[5]; + uint32_t ssrc = 0xcafebabe; uint32_t i; uint32_t stream_roc; /* Create the sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(sender_policy, 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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(sender_policy, test_key)); #endif - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(sender_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&sender_session, &sender_policy); + status = srtp_create(&sender_session, sender_policy); if (status) { return status; } /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(receiver_policy, 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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(receiver_policy, test_key)); #endif - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(receiver_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&receiver_session, &receiver_policy); + status = srtp_create(&receiver_session, receiver_policy); if (status) { return status; } /* Create and protect packets to get to get roc == 1 */ - pkts[0] = create_rtp_test_packet(64, sender_policy.ssrc.value, 65534, 0, - false, &pkt_len_octets[0], NULL); + pkts[0] = create_rtp_test_packet(64, ssrc, 65534, 0, false, + &pkt_len_octets[0], NULL); status = call_srtp_protect(sender_session, pkts[0], &pkt_len_octets[0], 0); if (status) { return status; } - status = srtp_stream_get_roc(sender_session, sender_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(sender_session, ssrc, &stream_roc); if (status) { return status; } @@ -5254,14 +5180,13 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) return srtp_err_status_fail; } - pkts[1] = create_rtp_test_packet(64, sender_policy.ssrc.value, 65535, 1, - false, &pkt_len_octets[1], NULL); + pkts[1] = create_rtp_test_packet(64, ssrc, 65535, 1, false, + &pkt_len_octets[1], NULL); status = call_srtp_protect(sender_session, pkts[1], &pkt_len_octets[1], 0); if (status) { return status; } - status = srtp_stream_get_roc(sender_session, sender_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(sender_session, ssrc, &stream_roc); if (status) { return status; } @@ -5269,14 +5194,13 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) return srtp_err_status_fail; } - pkts[2] = create_rtp_test_packet(64, sender_policy.ssrc.value, 0, 2, false, - &pkt_len_octets[2], NULL); + pkts[2] = + create_rtp_test_packet(64, ssrc, 0, 2, false, &pkt_len_octets[2], NULL); status = call_srtp_protect(sender_session, pkts[2], &pkt_len_octets[2], 0); if (status) { return status; } - status = srtp_stream_get_roc(sender_session, sender_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(sender_session, ssrc, &stream_roc); if (status) { return status; } @@ -5284,14 +5208,13 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) return srtp_err_status_fail; } - pkts[3] = create_rtp_test_packet(64, sender_policy.ssrc.value, 1, 3, false, - &pkt_len_octets[3], NULL); + pkts[3] = + create_rtp_test_packet(64, ssrc, 1, 3, false, &pkt_len_octets[3], NULL); status = call_srtp_protect(sender_session, pkts[3], &pkt_len_octets[3], 0); if (status) { return status; } - status = srtp_stream_get_roc(sender_session, sender_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(sender_session, ssrc, &stream_roc); if (status) { return status; } @@ -5299,14 +5222,13 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) return srtp_err_status_fail; } - pkts[4] = create_rtp_test_packet(64, sender_policy.ssrc.value, 2, 4, false, - &pkt_len_octets[4], NULL); + pkts[4] = + create_rtp_test_packet(64, ssrc, 2, 4, false, &pkt_len_octets[4], NULL); status = call_srtp_protect(sender_session, pkts[4], &pkt_len_octets[4], 0); if (status) { return status; } - status = srtp_stream_get_roc(sender_session, sender_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(sender_session, ssrc, &stream_roc); if (status) { return status; } @@ -5320,8 +5242,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) if (status) { return status; } - status = srtp_stream_get_roc(receiver_session, receiver_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(receiver_session, ssrc, &stream_roc); if (status) { return status; } @@ -5333,8 +5254,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) if (status) { return status; } - status = srtp_stream_get_roc(receiver_session, receiver_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(receiver_session, ssrc, &stream_roc); if (status) { return status; } @@ -5346,8 +5266,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) if (status) { return status; } - status = srtp_stream_get_roc(receiver_session, receiver_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(receiver_session, ssrc, &stream_roc); if (status) { return status; } @@ -5359,8 +5278,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) if (status) { return status; } - status = srtp_stream_get_roc(receiver_session, receiver_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(receiver_session, ssrc, &stream_roc); if (status) { return status; } @@ -5372,8 +5290,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) if (status) { return status; } - status = srtp_stream_get_roc(receiver_session, receiver_policy.ssrc.value, - &stream_roc); + status = srtp_stream_get_roc(receiver_session, ssrc, &stream_roc); if (status) { return status; } @@ -5396,6 +5313,9 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void) free(pkts[i]); } + srtp_policy_destroy(sender_policy); + srtp_policy_destroy(receiver_policy); + return srtp_err_status_ok; } @@ -5409,38 +5329,39 @@ srtp_err_status_t srtp_test_get_roc(void) uint32_t roc; uint32_t ts; uint16_t seq; + uint32_t ssrc = 0xcafebabe; size_t msg_len_octets = 32; size_t protected_msg_len_octets; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(policy, test_key)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_specific, ssrc })); /* Create a sender session */ - status = srtp_create(&session, &policy); + status = srtp_create(&session, policy); if (status) { return status; } + srtp_policy_destroy(policy); + /* Set start sequence so we roll over */ seq = 65535; ts = 0; for (i = 0; i < 2; i++) { - pkt = create_rtp_test_packet(msg_len_octets, policy.ssrc.value, seq, ts, - false, &protected_msg_len_octets, NULL); + pkt = create_rtp_test_packet(msg_len_octets, ssrc, seq, ts, false, + &protected_msg_len_octets, NULL); status = call_srtp_protect(session, pkt, &protected_msg_len_octets, 0); free(pkt); if (status) { return status; } - status = srtp_stream_get_roc(session, policy.ssrc.value, &roc); + status = srtp_stream_get_roc(session, ssrc, &roc); if (status) { return status; } @@ -5488,22 +5409,23 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, size_t protected_msg_len_octets_1; size_t protected_msg_len_octets_2; + uint32_t ssrc = 0xcafebabe; + /* Create the sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(sender_policy, 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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(sender_policy, test_key)); #endif - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(sender_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&sender_session, &sender_policy); + status = srtp_create(&sender_session, sender_policy); if (status) { return status; } @@ -5517,9 +5439,8 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, uint8_t *tmp_pkt; size_t tmp_len; - tmp_pkt = - create_rtp_test_packet(msg_len_octets, sender_policy.ssrc.value, - seq, ts, false, &tmp_len, NULL); + tmp_pkt = create_rtp_test_packet(msg_len_octets, ssrc, seq, ts, false, + &tmp_len, NULL); status = call_srtp_protect(sender_session, tmp_pkt, &tmp_len, 0); free(tmp_pkt); if (status) { @@ -5536,9 +5457,8 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, } /* Create the first packet to decrypt and test for ROC change */ - pkt_1 = - create_rtp_test_packet(msg_len_octets, sender_policy.ssrc.value, seq, - ts, false, &protected_msg_len_octets_1, NULL); + pkt_1 = create_rtp_test_packet(msg_len_octets, ssrc, seq, ts, false, + &protected_msg_len_octets_1, NULL); status = call_srtp_protect(sender_session, pkt_1, &protected_msg_len_octets_1, 0); if (status) { @@ -5548,9 +5468,8 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, /* Create the second packet to decrypt and test for ROC change */ seq++; ts++; - pkt_2 = - create_rtp_test_packet(msg_len_octets, sender_policy.ssrc.value, seq, - ts, false, &protected_msg_len_octets_2, NULL); + pkt_2 = create_rtp_test_packet(msg_len_octets, ssrc, seq, ts, false, + &protected_msg_len_octets_2, NULL); status = call_srtp_protect(sender_session, pkt_2, &protected_msg_len_octets_2, 0); if (status) { @@ -5558,21 +5477,20 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, } /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(receiver_policy, 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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(receiver_policy, test_key)); #endif - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(receiver_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&receiver_session, &receiver_policy); + status = srtp_create(&receiver_session, receiver_policy); if (status) { return status; } @@ -5592,8 +5510,7 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, memcpy(recv_pkt_2, pkt_2, protected_msg_len_octets_2); /* Set the ROC to the wanted value */ - status = srtp_stream_set_roc(receiver_session, receiver_policy.ssrc.value, - roc_to_set); + status = srtp_stream_set_roc(receiver_session, ssrc, roc_to_set); if (status) { return status; } @@ -5623,6 +5540,9 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, return status; } + srtp_policy_destroy(sender_policy); + srtp_policy_destroy(receiver_policy); + free(pkt_1); free(recv_pkt_1); free(pkt_2); @@ -5649,37 +5569,37 @@ static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) size_t msg_len_octets = 32; size_t protected_msg_len_octets; + uint32_t ssrc = 0xcafebabe; + /* Create the sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(sender_policy, 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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(sender_policy, test_key)); #endif - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(sender_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&sender_session, &sender_policy); + status = srtp_create(&sender_session, sender_policy); if (status) { return status; } /* Set the ROC before encrypting the first packet */ - status = srtp_stream_set_roc(sender_session, sender_policy.ssrc.value, - roc_to_set); + status = srtp_stream_set_roc(sender_session, ssrc, roc_to_set); if (status != srtp_err_status_ok) { return status; } /* Create the packet to decrypt */ ts = 0; - pkt = create_rtp_test_packet(msg_len_octets, sender_policy.ssrc.value, seq, - ts, false, &protected_msg_len_octets, NULL); + pkt = create_rtp_test_packet(msg_len_octets, ssrc, seq, ts, false, + &protected_msg_len_octets, NULL); status = call_srtp_protect(sender_session, pkt, &protected_msg_len_octets, 0); if (status) { @@ -5687,21 +5607,20 @@ static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) } /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(receiver_policy, 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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(receiver_policy, test_key)); #endif - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(receiver_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - status = srtp_create(&receiver_session, &receiver_policy); + status = srtp_create(&receiver_session, receiver_policy); if (status) { return status; } @@ -5714,8 +5633,7 @@ static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) memcpy(recv_pkt, pkt, protected_msg_len_octets); /* Set the ROC to the wanted value */ - status = srtp_stream_set_roc(receiver_session, receiver_policy.ssrc.value, - roc_to_set); + status = srtp_stream_set_roc(receiver_session, ssrc, roc_to_set); if (status) { return status; } @@ -5737,6 +5655,9 @@ static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) return status; } + srtp_policy_destroy(sender_policy); + srtp_policy_destroy(receiver_policy); + free(pkt); free(recv_pkt); @@ -5873,45 +5794,44 @@ srtp_err_status_t srtp_test_roc_mismatch(void) const uint16_t seq = 0xffff; uint32_t i; + uint32_t ssrc = 0xcafebabe; + /* Create the sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(sender_policy, 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; + CHECK_OK( + srtp_policy_set_profile(sender_policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(sender_policy, test_key)); #endif - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(sender_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - CHECK_OK(srtp_create(&sender_session, &sender_policy)); + CHECK_OK(srtp_create(&sender_session, sender_policy)); /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); + CHECK_OK(srtp_policy_create(&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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aead_aes_128_gcm)); + CHECK_OK(policy_set_key(receiver_policy, 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; + CHECK_OK(srtp_policy_set_profile(receiver_policy, + srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(policy_set_key(receiver_policy, test_key)); #endif - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.window_size = 128; + CHECK_OK(srtp_policy_set_ssrc(receiver_policy, + (srtp_ssrc_t){ ssrc_specific, ssrc })); - CHECK_OK(srtp_create(&receiver_session, &receiver_policy)); + CHECK_OK(srtp_create(&receiver_session, receiver_policy)); /* Create and protect packets to get to get ROC == 1 */ for (i = 0; i < num_pkts; i++) { - pkts[i] = create_rtp_test_packet(64, sender_policy.ssrc.value, - (uint16_t)(seq + i), 0, false, - &pkt_len_octets[i], NULL); + pkts[i] = create_rtp_test_packet(64, ssrc, (uint16_t)(seq + i), 0, + false, &pkt_len_octets[i], NULL); CHECK_OK( call_srtp_protect(sender_session, pkts[i], &pkt_len_octets[i], 0)); } @@ -5933,6 +5853,10 @@ srtp_err_status_t srtp_test_roc_mismatch(void) } CHECK_OK(srtp_dealloc(sender_session)); CHECK_OK(srtp_dealloc(receiver_session)); + + srtp_policy_destroy(sender_policy); + srtp_policy_destroy(receiver_policy); + return srtp_err_status_ok; } @@ -5975,264 +5899,86 @@ uint8_t test_mki_id_2[TEST_MKI_ID_SIZE] = { }; // clang-format on -const srtp_policy_t default_policy = { +const test_policy_t default_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL + srtp_profile_aes128_cm_sha1_80, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t aes_only_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_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_conf /* security services flag */ - }, - { - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_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_conf /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes_only_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aes128_cm_sha1_80, + sec_serv_conf, + sec_serv_conf, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t hmac_only_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - 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 */ - 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 */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t hmac_only_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_null_sha1_32, + sec_serv_auth, + sec_serv_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; #ifdef GCM -const srtp_policy_t aes128_gcm_8_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_GCM_128, /* cipher type */ - SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_GCM_128, /* cipher type */ - SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes128_gcm_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aead_aes_128_gcm, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t aes128_gcm_8_cauth_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_GCM_128, /* cipher type */ - SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_GCM_128, /* cipher type */ - SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 8, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes128_gcm_cauth_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aead_aes_128_gcm, + sec_serv_conf_and_auth, + sec_serv_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t aes256_gcm_8_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_GCM_256, /* 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 */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_GCM_256, /* 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 */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes256_gcm_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aead_aes_256_gcm, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t aes256_gcm_8_cauth_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_GCM_256, /* 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 */ - 8, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_GCM_256, /* 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 */ - 8, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes256_gcm_cauth_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aead_aes_256_gcm, + sec_serv_conf_and_auth, + sec_serv_auth, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; #endif -const srtp_policy_t null_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - 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 */ - 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 */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t null_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aes256_cm_sha1_80, + sec_serv_none, + sec_serv_none, + (test_master_key_t **)test_keys, + 2, + TEST_MKI_ID_SIZE, }; // clang-format off @@ -6255,119 +6001,49 @@ uint8_t test_256_key_2[46] = { 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 }; -srtp_master_key_t master_256_key_1 = { +test_master_key_t master_256_key_1 = { test_256_key, test_mki_id }; -srtp_master_key_t master_256_key_2 = { +test_master_key_t master_256_key_2 = { test_256_key_2, test_mki_id_2 }; -srtp_master_key_t *test_256_keys[2] = { +test_master_key_t *test_256_keys[2] = { &master_key_1, &master_key_2 }; // clang-format on -const srtp_policy_t aes_256_hmac_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_ICM_256, /* cipher type */ - SRTP_AES_ICM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_ICM_256, /* cipher type */ - SRTP_AES_ICM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_256_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - false, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes_256_hmac_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aes256_cm_sha1_80, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_256_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t aes_256_hmac_32_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_ICM_256, /* cipher type */ - SRTP_AES_ICM_256_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_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_ICM_256, /* cipher type */ - SRTP_AES_ICM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 10, /* auth tag length in octets. - 80 bits per RFC 3711. */ - sec_serv_conf_and_auth /* security services flag */ - }, - NULL, - (srtp_master_key_t **)test_256_keys, - 2, /* indicates the number of Master keys */ - true, /* no mki */ - TEST_MKI_ID_SIZE, /* mki size */ - 128, /* replay window size */ - false, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL +const test_policy_t aes_256_hmac_32_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aes256_cm_sha1_32, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_256_keys, + 2, + TEST_MKI_ID_SIZE, }; -const srtp_policy_t hmac_only_with_no_master_key = { - { 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 */ - 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 */ - }, - NULL, - NULL, /* no master keys*/ - 0, /* indicates the number of Master keys */ - false, /* no mki */ - 0, /* mki size */ - 128, /* replay window size */ - false, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL -}; +const test_policy_t hmac_only_with_no_master_key = { { ssrc_any_outbound, 0 }, + srtp_profile_null_sha1_32, + sec_serv_auth, + sec_serv_auth, + NULL, + 0, + 0 }; /* * an array of pointers to the policies listed above @@ -6380,17 +6056,17 @@ const srtp_policy_t hmac_only_with_no_master_key = { */ // clang-format off -const srtp_policy_t *policy_array[] = { +const test_policy_t *policy_array[] = { &hmac_only_policy, &aes_only_policy, &default_policy, #ifdef GCM - &aes128_gcm_8_policy, - &aes128_gcm_8_cauth_policy, - &aes256_gcm_8_policy, - &aes256_gcm_8_cauth_policy, + &aes128_gcm_policy, + &aes128_gcm_cauth_policy, + &aes256_gcm_policy, + &aes256_gcm_cauth_policy, #endif - &null_policy, + &null_policy, //what happens ? &aes_256_hmac_policy, &aes_256_hmac_32_policy, NULL @@ -6398,43 +6074,20 @@ const srtp_policy_t *policy_array[] = { // clang-format on // clang-format off -const srtp_policy_t *invalid_policy_array[] = { +const test_policy_t *invalid_policy_array[] = { &hmac_only_with_no_master_key, NULL }; // clang-format on -const srtp_policy_t wildcard_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { - /* SRTP policy */ - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - { - /* SRTCP policy */ - SRTP_AES_ICM_128, /* cipher type */ - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ - }, - test_key, - NULL, +const test_policy_t wildcard_policy = { + { ssrc_any_outbound, 0 }, + srtp_profile_aes128_cm_sha1_80, + sec_serv_conf_and_auth, + sec_serv_conf_and_auth, + (test_master_key_t **)test_keys, + 1, 0, - false, /* no mki */ - 0, /* mki size */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ - false, /* cryptex */ - NULL }; static srtp_stream_t stream_list_test_create_stream(uint32_t ssrc) diff --git a/test/test_srtp_policy.c b/test/test_srtp_policy.c new file mode 100644 index 000000000..fea0c2367 --- /dev/null +++ b/test/test_srtp_policy.c @@ -0,0 +1,739 @@ +/* + * test_srtp_policy.c + * + * Unit tests for srtp_policy API + * + */ +/* + * + * Copyright (c) 2026 + * 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. + * + * 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. + * + */ + +#include "cutest.h" + +#include "srtp.h" +#include "util.h" + +static const uint8_t base_master_key[16] = { + 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, + 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, +}; +static const uint8_t base_master_salt[14] = { + 0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, + 0x93, 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, +}; +static const uint8_t alt_master_key[16] = { + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, + 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x00, +}; +static const uint8_t alt_master_salt[14] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, + 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, +}; +static const uint8_t long_master_key[17] = { + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, + 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x00, 0x11, +}; +static const uint8_t long_master_salt[15] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, +}; +static const uint8_t mki4[4] = { 0x01, 0x02, 0x03, 0x04 }; +static const uint8_t mki3[3] = { 0x09, 0x08, 0x07 }; + +static void create_valid_policy(srtp_policy_t *policy) +{ + CHECK_OK(srtp_policy_create(policy)); + CHECK_OK( + srtp_policy_set_ssrc(*policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(*policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_add_key(*policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), NULL, 0)); +} + +static void create_policy_with_profile(srtp_policy_t *policy, + srtp_profile_t profile) +{ + CHECK_OK(srtp_policy_create(policy)); + CHECK_OK( + srtp_policy_set_ssrc(*policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(*policy, profile)); +} + +static void assert_policy_creates_session(srtp_policy_t policy) +{ + srtp_t srtp; + CHECK_OK(srtp_init()); + CHECK_OK(srtp_create(&srtp, policy)); + CHECK_OK(srtp_dealloc(srtp)); + CHECK_OK(srtp_shutdown()); +} + +static void srtp_policy_create_destroy_ok(void) +{ + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK(policy != NULL); + srtp_policy_destroy(policy); +} + +static void srtp_policy_create_null_fails(void) +{ + CHECK_RETURN(srtp_policy_create(NULL), srtp_err_status_bad_param); +} + +static void srtp_policy_empty_not_valid(void) +{ + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_minimal(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + CHECK_OK(srtp_policy_validate(policy)); + assert_policy_creates_session(policy); + srtp_policy_destroy(policy); +} + +static void srtp_policy_clone_success_and_independent(void) +{ + srtp_policy_t policy; + srtp_policy_t cloned = NULL; + + create_valid_policy(&policy); + CHECK_OK(srtp_policy_clone(policy, &cloned)); + CHECK(cloned != NULL); + CHECK_OK(srtp_policy_validate(cloned)); + + /* mutating original to invalid state must not affect clone */ + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki4))); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + CHECK_OK(srtp_policy_validate(cloned)); + + assert_policy_creates_session(cloned); + srtp_policy_destroy(cloned); + srtp_policy_destroy(policy); +} + +static void srtp_policy_clone_null_output_fails(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + CHECK_RETURN(srtp_policy_clone(policy, NULL), srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_ssrc_invalid_type_fails(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + CHECK_RETURN( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_undefined, 0 }), + srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_get_profile_roundtrip(void) +{ + srtp_policy_t policy; + srtp_profile_t profile = srtp_profile_reserved; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes256_cm_sha1_80)); + CHECK_OK(srtp_policy_get_profile(policy, &profile)); + CHECK(profile == srtp_profile_aes256_cm_sha1_80); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_profile_reserved_fails(void) +{ + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_RETURN(srtp_policy_set_profile(policy, srtp_profile_reserved), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_sec_serv_requires_profile(void) +{ + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_RETURN(srtp_policy_set_sec_serv(policy, sec_serv_conf_and_auth, + sec_serv_conf_and_auth), + srtp_err_status_bad_param); + + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), NULL, 0)); + CHECK_OK(srtp_policy_set_sec_serv(policy, sec_serv_auth, sec_serv_none)); + CHECK_OK(srtp_policy_validate(policy)); + assert_policy_creates_session(policy); + srtp_policy_destroy(policy); +} + +static void assert_null_sha1_profile_accepts_128_bit_key(srtp_profile_t profile) +{ + srtp_policy_t policy; + + CHECK(srtp_profile_get_master_key_length(profile) == 16); + CHECK(srtp_profile_get_master_salt_length(profile) == 14); + + create_policy_with_profile(&policy, profile); + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), NULL, 0)); + CHECK_OK(srtp_policy_validate(policy)); + assert_policy_creates_session(policy); + + srtp_policy_destroy(policy); +} + +static void assert_null_sha1_profile_rejects_key_salt(srtp_profile_t profile, + const uint8_t *key, + size_t key_len, + const uint8_t *salt, + size_t salt_len) +{ + srtp_policy_t policy; + + create_policy_with_profile(&policy, profile); + CHECK_OK( + srtp_policy_add_key(policy, key, key_len, salt, salt_len, NULL, 0)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void assert_null_sha1_profile_requires_128_bit_key( + srtp_profile_t profile) +{ + assert_null_sha1_profile_accepts_128_bit_key(profile); + assert_null_sha1_profile_rejects_key_salt( + profile, base_master_key, sizeof(base_master_key) - 1, base_master_salt, + sizeof(base_master_salt)); + assert_null_sha1_profile_rejects_key_salt( + profile, long_master_key, sizeof(long_master_key), base_master_salt, + sizeof(base_master_salt)); + assert_null_sha1_profile_rejects_key_salt( + profile, base_master_key, sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt) - 1); + assert_null_sha1_profile_rejects_key_salt( + profile, base_master_key, sizeof(base_master_key), long_master_salt, + sizeof(long_master_salt)); +} + +static void srtp_policy_null_sha1_80_requires_128_bit_key(void) +{ + assert_null_sha1_profile_requires_128_bit_key(srtp_profile_null_sha1_80); +} + +static void srtp_policy_null_sha1_32_requires_128_bit_key(void) +{ + assert_null_sha1_profile_requires_128_bit_key(srtp_profile_null_sha1_32); +} + +static void srtp_policy_add_key_oversize_fails(void) +{ + uint8_t long_key[SRTP_MAX_KEY_LEN]; + uint8_t salt[1] = { 0 }; + srtp_policy_t policy; + + CHECK_OK(srtp_policy_create(&policy)); + CHECK_RETURN(srtp_policy_add_key(policy, long_key, sizeof(long_key), salt, + sizeof(salt), NULL, 0), + srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_mki_length_transitions_and_limits(void) +{ + srtp_policy_t policy; + size_t mki_len = 99; + create_valid_policy(&policy); + + CHECK_OK(srtp_policy_get_mki_length(policy, &mki_len)); + CHECK(mki_len == 0); + + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki4))); + CHECK_OK(srtp_policy_get_mki_length(policy, &mki_len)); + CHECK(mki_len == sizeof(mki4)); + + CHECK_OK(srtp_policy_use_mki(policy, 0)); + CHECK_OK(srtp_policy_get_mki_length(policy, &mki_len)); + CHECK(mki_len == 0); + + CHECK_RETURN(srtp_policy_use_mki(policy, SRTP_MAX_MKI_LEN + 1), + srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_add_key_edges(void) +{ + uint8_t too_long_key[SRTP_MAX_KEY_LEN]; + uint8_t one_byte_salt[1] = { 0 }; + srtp_policy_t policy; + + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + + /* non-MKI mode supports exactly one key via add_key */ + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), mki4, 0)); + CHECK_RETURN(srtp_policy_add_key(policy, alt_master_key, + sizeof(alt_master_key), alt_master_salt, + sizeof(alt_master_salt), mki4, 0), + srtp_err_status_bad_param); + CHECK_OK(srtp_policy_validate(policy)); + + /* MKI key requires explicit MKI mode first */ + CHECK_RETURN(srtp_policy_add_key(policy, alt_master_key, + sizeof(alt_master_key), alt_master_salt, + sizeof(alt_master_salt), mki4, + sizeof(mki4)), + srtp_err_status_bad_param); + srtp_policy_destroy(policy); + create_valid_policy(&policy); + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki4))); + CHECK_RETURN(srtp_policy_add_key(policy, too_long_key, sizeof(too_long_key), + one_byte_salt, sizeof(one_byte_salt), mki4, + sizeof(mki4)), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key(policy, alt_master_key, + sizeof(alt_master_key), alt_master_salt, + sizeof(alt_master_salt), mki4, 0), + srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_add_key_mki_mismatch_fails(void) +{ + srtp_policy_t policy; + + create_valid_policy(&policy); + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki4))); + CHECK_RETURN(srtp_policy_add_key(policy, alt_master_key, + sizeof(alt_master_key), alt_master_salt, + sizeof(alt_master_salt), mki3, + sizeof(mki3)), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key(policy, alt_master_key, + sizeof(alt_master_key), alt_master_salt, + sizeof(alt_master_salt), mki4, 0), + srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_add_key_strict_null_checks(void) +{ + srtp_policy_t policy; + uint8_t key[1] = { 0x01 }; + uint8_t salt[1] = { 0x02 }; + uint8_t mki[1] = { 0x03 }; + + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_RETURN(srtp_policy_add_key(policy, NULL, sizeof(key), salt, + sizeof(salt), NULL, 0), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key(policy, key, sizeof(key), NULL, + sizeof(salt), NULL, 0), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key(policy, key, sizeof(key), salt, + sizeof(salt), NULL, sizeof(mki)), + srtp_err_status_bad_param); + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki))); + CHECK_RETURN(srtp_policy_add_key(policy, key, sizeof(key), salt, + sizeof(salt), NULL, sizeof(mki)), + srtp_err_status_bad_param); + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), mki, sizeof(mki))); + CHECK_OK(srtp_policy_validate(policy)); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_add_key_max_master_keys_limit(void) +{ + srtp_policy_t policy; + uint8_t key[sizeof(base_master_key)]; + uint8_t salt[sizeof(base_master_salt)]; + uint8_t mki; + + CHECK_OK(srtp_policy_create(&policy)); + CHECK_OK( + srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_aes128_cm_sha1_80)); + CHECK_OK(srtp_policy_use_mki(policy, 1)); + + for (size_t i = 0; i < SRTP_MAX_NUM_MASTER_KEYS; i++) { + memcpy(key, base_master_key, sizeof(key)); + memcpy(salt, base_master_salt, sizeof(salt)); + key[0] ^= (uint8_t)i; + salt[0] ^= (uint8_t)i; + mki = (uint8_t)i; + + CHECK_OK(srtp_policy_add_key(policy, key, sizeof(key), salt, + sizeof(salt), &mki, sizeof(mki))); + } + + CHECK_OK(srtp_policy_validate(policy)); + + memcpy(key, base_master_key, sizeof(key)); + memcpy(salt, base_master_salt, sizeof(salt)); + key[0] ^= 0xA5; + salt[0] ^= 0x5A; + mki = 0xFF; + CHECK_RETURN(srtp_policy_add_key(policy, key, sizeof(key), salt, + sizeof(salt), &mki, sizeof(mki)), + srtp_err_status_bad_param); + + CHECK_OK(srtp_policy_validate(policy)); + srtp_policy_destroy(policy); +} + +static void srtp_policy_remove_keys_simple(void) +{ + srtp_policy_t policy; + + create_valid_policy(&policy); + CHECK_OK(srtp_policy_validate(policy)); + + CHECK_OK(srtp_policy_remove_keys(policy)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), NULL, 0)); + CHECK_OK(srtp_policy_validate(policy)); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_window_size_invalid_values_fail(void) +{ + srtp_policy_t policy; + CHECK_OK(srtp_policy_create(&policy)); + CHECK_RETURN(srtp_policy_set_window_size(policy, 1), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_window_size(policy, 63), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_window_size(policy, 0x8000), + srtp_err_status_bad_param); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_window_size_valid_values_ok(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + + CHECK_OK(srtp_policy_set_window_size(policy, 0)); + CHECK_OK(srtp_policy_validate(policy)); + CHECK_OK(srtp_policy_set_window_size(policy, 64)); + CHECK_OK(srtp_policy_validate(policy)); + CHECK_OK(srtp_policy_set_window_size(policy, 0x7fff)); + CHECK_OK(srtp_policy_validate(policy)); + + assert_policy_creates_session(policy); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_allow_repeat_tx_values_ok(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + + CHECK_OK(srtp_policy_set_allow_repeat_tx(policy, true)); + CHECK_OK(srtp_policy_validate(policy)); + CHECK_OK(srtp_policy_set_allow_repeat_tx(policy, false)); + CHECK_OK(srtp_policy_validate(policy)); + + assert_policy_creates_session(policy); + srtp_policy_destroy(policy); +} + +static void srtp_policy_set_cryptex_values_ok(void) +{ + srtp_policy_t policy; + create_valid_policy(&policy); + + CHECK_OK(srtp_policy_set_cryptex(policy, true)); + CHECK_OK(srtp_policy_validate(policy)); + CHECK_OK(srtp_policy_set_cryptex(policy, false)); + CHECK_OK(srtp_policy_validate(policy)); + + assert_policy_creates_session(policy); + srtp_policy_destroy(policy); +} + +static void srtp_policy_cryptex_and_enc_hdr_xtnd_ids_invalid(void) +{ + srtp_policy_t policy; + uint8_t hdr_id = 1; + + create_valid_policy(&policy); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, hdr_id)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_enc_hdr_xtnd_ids_add_remove_boundaries(void) +{ + srtp_policy_t policy; + uint8_t hdr_id = 0; + uint8_t duplicate_id = 3; + + create_valid_policy(&policy); + + for (size_t i = 0; i < SRTP_MAX_NUM_ENC_HDR_XTND_IDS; i++) { + hdr_id = (uint8_t)i; + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, hdr_id)); + } + CHECK_RETURN(srtp_policy_add_enc_hdr_xtnd_id(policy, hdr_id), + srtp_err_status_bad_param); + + CHECK_OK(srtp_policy_remove_enc_hdr_xtnd_ids(policy)); + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, duplicate_id)); + CHECK_RETURN(srtp_policy_add_enc_hdr_xtnd_id(policy, duplicate_id), + srtp_err_status_bad_param); + + CHECK_OK(srtp_policy_remove_enc_hdr_xtnd_ids(policy)); + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, duplicate_id)); + CHECK_OK(srtp_policy_validate(policy)); + assert_policy_creates_session(policy); + + srtp_policy_destroy(policy); +} + +static void create_null_null_policy(srtp_policy_t *policy) +{ + CHECK_OK(srtp_policy_create(policy)); + CHECK_OK( + srtp_policy_set_ssrc(*policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 })); + CHECK_OK(srtp_policy_set_profile(*policy, srtp_profile_null_null)); +} + +static void srtp_policy_null_null_no_key_valid(void) +{ + srtp_policy_t policy; + + create_null_null_policy(&policy); + CHECK_OK(srtp_policy_validate(policy)); + assert_policy_creates_session(policy); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_null_null_with_key_rejected(void) +{ + srtp_policy_t policy; + + create_null_null_policy(&policy); + CHECK_OK(srtp_policy_add_key(policy, base_master_key, + sizeof(base_master_key), base_master_salt, + sizeof(base_master_salt), NULL, 0)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_null_null_after_key_rejected(void) +{ + srtp_policy_t policy; + + create_valid_policy(&policy); + CHECK_OK(srtp_policy_set_profile(policy, srtp_profile_null_null)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_null_null_no_key_cryptex_enc_hdr_rejected(void) +{ + srtp_policy_t policy; + + create_null_null_policy(&policy); + CHECK_OK(srtp_policy_set_cryptex(policy, true)); + CHECK_OK(srtp_policy_add_enc_hdr_xtnd_id(policy, 1)); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_null_null_no_key_mki_rejected(void) +{ + srtp_policy_t policy; + + create_null_null_policy(&policy); + CHECK_OK(srtp_policy_use_mki(policy, sizeof(mki4))); + CHECK_RETURN(srtp_policy_validate(policy), srtp_err_status_bad_param); + + srtp_policy_destroy(policy); +} + +static void srtp_policy_all_functions_null_policy(void) +{ + srtp_policy_t cloned; + srtp_ssrc_t ssrc = { 0, 0 }; + srtp_profile_t profile; + uint8_t key[1] = { 0x01 }; + uint8_t salt[1] = { 0x02 }; + uint8_t mki[1] = { 0x03 }; + size_t mki_len; + uint8_t hdr_id = 1; + + CHECK_RETURN(srtp_policy_clone(NULL, &cloned), srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_validate(NULL), srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_ssrc(NULL, ssrc), srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_profile(NULL, srtp_profile_aes128_cm_sha1_80), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_get_profile(NULL, &profile), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_get_profile((srtp_policy_t)1, NULL), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_sec_serv(NULL, sec_serv_conf_and_auth, + sec_serv_conf_and_auth), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_use_mki(NULL, sizeof(mki)), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_get_mki_length(NULL, &mki_len), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_get_mki_length((srtp_policy_t)1, NULL), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key(NULL, key, sizeof(key), salt, sizeof(salt), + mki, sizeof(mki)), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key((srtp_policy_t)1, NULL, sizeof(key), salt, + sizeof(salt), NULL, 0), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key((srtp_policy_t)1, key, sizeof(key), NULL, + sizeof(salt), NULL, 0), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_key((srtp_policy_t)1, key, sizeof(key), salt, + sizeof(salt), NULL, sizeof(mki)), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_remove_keys(NULL), srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_window_size(NULL, 128), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_allow_repeat_tx(NULL, true), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_set_cryptex(NULL, true), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_add_enc_hdr_xtnd_id(NULL, hdr_id), + srtp_err_status_bad_param); + CHECK_RETURN(srtp_policy_remove_enc_hdr_xtnd_ids(NULL), + srtp_err_status_bad_param); + + /* void API should be no-op on NULL */ + srtp_policy_destroy(NULL); +} + +TEST_LIST = { + { "srtp_policy_create_destroy_ok()", srtp_policy_create_destroy_ok }, + { "srtp_policy_create_null_fails()", srtp_policy_create_null_fails }, + { "srtp_policy_empty_not_valid()", srtp_policy_empty_not_valid }, + { "srtp_policy_minimal()", srtp_policy_minimal }, + { "srtp_policy_clone_success_and_independent()", + srtp_policy_clone_success_and_independent }, + { "srtp_policy_clone_null_output_fails()", + srtp_policy_clone_null_output_fails }, + { "srtp_policy_set_ssrc_invalid_type_fails()", + srtp_policy_set_ssrc_invalid_type_fails }, + { "srtp_policy_set_get_profile_roundtrip()", + srtp_policy_set_get_profile_roundtrip }, + { "srtp_policy_set_profile_reserved_fails()", + srtp_policy_set_profile_reserved_fails }, + { "srtp_policy_set_sec_serv_requires_profile()", + srtp_policy_set_sec_serv_requires_profile }, + { "srtp_policy_null_sha1_80_requires_128_bit_key()", + srtp_policy_null_sha1_80_requires_128_bit_key }, + { "srtp_policy_null_sha1_32_requires_128_bit_key()", + srtp_policy_null_sha1_32_requires_128_bit_key }, + { "srtp_policy_add_key_oversize_fails()", + srtp_policy_add_key_oversize_fails }, + { "srtp_policy_mki_length_transitions_and_limits()", + srtp_policy_mki_length_transitions_and_limits }, + { "srtp_policy_add_key_edges()", srtp_policy_add_key_edges }, + { "srtp_policy_add_key_mki_mismatch_fails()", + srtp_policy_add_key_mki_mismatch_fails }, + { "srtp_policy_add_key_strict_null_checks()", + srtp_policy_add_key_strict_null_checks }, + { "srtp_policy_add_key_max_master_keys_limit()", + srtp_policy_add_key_max_master_keys_limit }, + { "srtp_policy_remove_keys_simple()", srtp_policy_remove_keys_simple }, + { "srtp_policy_set_window_size_invalid_values_fail()", + srtp_policy_set_window_size_invalid_values_fail }, + { "srtp_policy_set_window_size_valid_values_ok()", + srtp_policy_set_window_size_valid_values_ok }, + { "srtp_policy_set_allow_repeat_tx_values_ok()", + srtp_policy_set_allow_repeat_tx_values_ok }, + { "srtp_policy_set_cryptex_values_ok()", + srtp_policy_set_cryptex_values_ok }, + { "srtp_policy_cryptex_and_enc_hdr_xtnd_ids_invalid()", + srtp_policy_cryptex_and_enc_hdr_xtnd_ids_invalid }, + { "srtp_policy_enc_hdr_xtnd_ids_add_remove_boundaries()", + srtp_policy_enc_hdr_xtnd_ids_add_remove_boundaries }, + { "srtp_policy_null_null_no_key_valid()", + srtp_policy_null_null_no_key_valid }, + { "srtp_policy_null_null_with_key_rejected()", + srtp_policy_null_null_with_key_rejected }, + { "srtp_policy_null_null_after_key_rejected()", + srtp_policy_null_null_after_key_rejected }, + { "srtp_policy_null_null_no_key_cryptex_enc_hdr_rejected()", + srtp_policy_null_null_no_key_cryptex_enc_hdr_rejected }, + { "srtp_policy_null_null_no_key_mki_rejected()", + srtp_policy_null_null_no_key_mki_rejected }, + { "srtp_policy_all_functions_null_policy()", + srtp_policy_all_functions_null_policy }, + { 0 } +}; diff --git a/test/util.c b/test/util.c index 3ee4e7b67..51abf6a25 100644 --- a/test/util.c +++ b/test/util.c @@ -345,3 +345,74 @@ size_t base64_string_to_octet_string(uint8_t *out, *pad = (int)j; return i; } + +srtp_err_status_t create_policy_from_params(srtp_policy_t *policy, + const policy_params_t *params) +{ + if (policy == NULL || params == NULL) { + return srtp_err_status_bad_param; + } + + srtp_policy_t p; + srtp_err_status_t status = srtp_policy_create(&p); + if (status != srtp_err_status_ok) { + return status; + } + + srtp_profile_t profile = srtp_profile_reserved; + if (params->gcm_on) { + switch (params->key_size) { + case 128: + profile = srtp_profile_aead_aes_128_gcm; + break; + case 256: + profile = srtp_profile_aead_aes_256_gcm; + break; + default: + srtp_policy_destroy(p); + return srtp_err_status_bad_param; + } + } else { + switch (params->key_size) { + case 128: + if (params->tag_size == 4) { + profile = srtp_profile_aes128_cm_sha1_32; + } else { + profile = srtp_profile_aes128_cm_sha1_80; + } + break; + case 192: + if (params->tag_size == 4) { + profile = srtp_profile_aes192_cm_sha1_32; + } else { + profile = srtp_profile_aes192_cm_sha1_80; + } + break; + case 256: + if (params->tag_size == 4) { + profile = srtp_profile_aes256_cm_sha1_32; + } else { + profile = srtp_profile_aes256_cm_sha1_80; + } + break; + default: + srtp_policy_destroy(p); + return srtp_err_status_bad_param; + } + } + + status = srtp_policy_set_profile(p, profile); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(p); + return status; + } + + status = srtp_policy_set_sec_serv(p, params->sec_servs, params->sec_servs); + if (status != srtp_err_status_ok) { + srtp_policy_destroy(p); + return status; + } + + *policy = p; + return srtp_err_status_ok; +} diff --git a/test/util.h b/test/util.h index 4f86552b9..851e57970 100644 --- a/test/util.h +++ b/test/util.h @@ -86,4 +86,14 @@ size_t base64_string_to_octet_string(uint8_t *raw, const char *base64, size_t len); +typedef struct policy_params_t { + bool gcm_on; + size_t key_size; + size_t tag_size; + srtp_sec_serv_t sec_servs; +} policy_params_t; + +srtp_err_status_t create_policy_from_params(srtp_policy_t *policy, + const policy_params_t *params); + #endif