| Index: test/srtp_driver.c
|
| diff --git a/test/srtp_driver.c b/test/srtp_driver.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..10103a1f9cc448fae04de59522f16b3b229c8195
|
| --- /dev/null
|
| +++ b/test/srtp_driver.c
|
| @@ -0,0 +1,2985 @@
|
| +/*
|
| + * srtp_driver.c
|
| + *
|
| + * a test driver for libSRTP
|
| + *
|
| + * David A. McGrew
|
| + * Cisco Systems, Inc.
|
| + */
|
| +/*
|
| + *
|
| + * Copyright (c) 2001-2006, Cisco Systems, Inc.
|
| + * All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions
|
| + * are met:
|
| + *
|
| + * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + *
|
| + * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following
|
| + * disclaimer in the documentation and/or other materials provided
|
| + * with the distribution.
|
| + *
|
| + * Neither the name of the Cisco Systems, Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived
|
| + * from this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
| + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
| + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
| + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
| + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
| + * OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + *
|
| + */
|
| +
|
| +
|
| +#include <string.h> /* for memcpy() */
|
| +#include <time.h> /* for clock() */
|
| +#include <stdlib.h> /* for malloc(), free() */
|
| +#include <stdio.h> /* for print(), fflush() */
|
| +#include "getopt_s.h" /* for local getopt() */
|
| +#include "util.h"
|
| +
|
| +#include "srtp_priv.h"
|
| +
|
| +#ifdef HAVE_NETINET_IN_H
|
| +# include <netinet/in.h>
|
| +#elif defined HAVE_WINSOCK2_H
|
| +# include <winsock2.h>
|
| +#endif
|
| +
|
| +#define PRINT_REFERENCE_PACKET 1
|
| +
|
| +srtp_err_status_t
|
| +srtp_validate(void);
|
| +
|
| +#ifdef OPENSSL
|
| +srtp_err_status_t
|
| +srtp_validate_gcm(void);
|
| +#endif
|
| +
|
| +srtp_err_status_t
|
| +srtp_validate_encrypted_extensions_headers(void);
|
| +
|
| +#ifdef OPENSSL
|
| +srtp_err_status_t
|
| +srtp_validate_encrypted_extensions_headers_gcm(void);
|
| +#endif
|
| +
|
| +srtp_err_status_t
|
| +srtp_validate_aes_256(void);
|
| +
|
| +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 OPENSSL
|
| +srtp_err_status_t
|
| +srtp_test_empty_payload_gcm(void);
|
| +#endif
|
| +
|
| +srtp_err_status_t
|
| +srtp_test_remove_stream(void);
|
| +
|
| +srtp_err_status_t
|
| +srtp_test_update(void);
|
| +
|
| +double
|
| +srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy);
|
| +
|
| +double
|
| +srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy);
|
| +
|
| +void
|
| +srtp_do_timing(const srtp_policy_t *policy);
|
| +
|
| +void
|
| +srtp_do_rejection_timing(const srtp_policy_t *policy);
|
| +
|
| +srtp_err_status_t
|
| +srtp_test(const srtp_policy_t *policy, int extension_header);
|
| +
|
| +srtp_err_status_t
|
| +srtcp_test(const srtp_policy_t *policy);
|
| +
|
| +srtp_err_status_t
|
| +srtp_session_print_policy(srtp_t srtp);
|
| +
|
| +srtp_err_status_t
|
| +srtp_print_policy(const srtp_policy_t *policy);
|
| +
|
| +char *
|
| +srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
|
| +
|
| +double
|
| +mips_estimate(int num_trials, int *ignore);
|
| +
|
| +extern uint8_t test_key[46];
|
| +
|
| +void
|
| +usage (char *prog_name)
|
| +{
|
| + printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
|
| + " -t run timing test\n"
|
| + " -r run rejection timing test\n"
|
| + " -c run codec timing test\n"
|
| + " -v run validation tests\n"
|
| + " -d <mod> turn on debugging module <mod>\n"
|
| + " -l list debugging modules\n", prog_name);
|
| + exit(1);
|
| +}
|
| +
|
| +/*
|
| + * The policy_array is a null-terminated array of policy structs. it
|
| + * is declared at the end of this file
|
| + */
|
| +
|
| +extern const srtp_policy_t *policy_array[];
|
| +
|
| +
|
| +/* the wildcard_policy is declared below; it has a wildcard ssrc */
|
| +
|
| +extern const srtp_policy_t wildcard_policy;
|
| +
|
| +/*
|
| + * mod_driver debug module - debugging module for this test driver
|
| + *
|
| + * we use the crypto_kernel debugging system in this driver, which
|
| + * makes the interface uniform and increases portability
|
| + */
|
| +
|
| +srtp_debug_module_t mod_driver = {
|
| + 0, /* debugging is off by default */
|
| + "driver" /* printable name for module */
|
| +};
|
| +
|
| +int
|
| +main (int argc, char *argv[])
|
| +{
|
| + int q;
|
| + unsigned do_timing_test = 0;
|
| + unsigned do_rejection_test = 0;
|
| + unsigned do_codec_timing = 0;
|
| + unsigned do_validation = 0;
|
| + unsigned do_list_mods = 0;
|
| + srtp_err_status_t status;
|
| +
|
| + /*
|
| + * verify that the compiler has interpreted the header data
|
| + * structure srtp_hdr_t correctly
|
| + */
|
| + if (sizeof(srtp_hdr_t) != 12) {
|
| + printf("error: srtp_hdr_t has incorrect size"
|
| + "(size is %ld bytes, expected 12)\n",
|
| + (long)sizeof(srtp_hdr_t));
|
| + exit(1);
|
| + }
|
| +
|
| + /* initialize srtp library */
|
| + status = srtp_init();
|
| + if (status) {
|
| + printf("error: srtp init failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + /* load srtp_driver debug module */
|
| + status = srtp_crypto_kernel_load_debug_module(&mod_driver);
|
| + if (status) {
|
| + printf("error: load of srtp_driver debug module failed "
|
| + "with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + /* process input arguments */
|
| + while (1) {
|
| + q = getopt_s(argc, argv, "trcvld:");
|
| + if (q == -1) {
|
| + break;
|
| + }
|
| + switch (q) {
|
| + case 't':
|
| + do_timing_test = 1;
|
| + break;
|
| + case 'r':
|
| + do_rejection_test = 1;
|
| + break;
|
| + case 'c':
|
| + do_codec_timing = 1;
|
| + break;
|
| + case 'v':
|
| + do_validation = 1;
|
| + break;
|
| + case 'l':
|
| + do_list_mods = 1;
|
| + break;
|
| + case 'd':
|
| + status = srtp_crypto_kernel_set_debug_module(optarg_s, 1);
|
| + if (status) {
|
| + printf("error: set debug module (%s) failed\n", optarg_s);
|
| + exit(1);
|
| + }
|
| + break;
|
| + default:
|
| + usage(argv[0]);
|
| + }
|
| + }
|
| +
|
| + if (!do_validation && !do_timing_test && !do_codec_timing
|
| + && !do_list_mods && !do_rejection_test) {
|
| + usage(argv[0]);
|
| + }
|
| +
|
| + if (do_list_mods) {
|
| + status = srtp_crypto_kernel_list_debug_modules();
|
| + if (status) {
|
| + printf("error: list of debug modules failed\n");
|
| + exit(1);
|
| + }
|
| + }
|
| +
|
| + if (do_validation) {
|
| + const srtp_policy_t **policy = policy_array;
|
| + srtp_policy_t *big_policy;
|
| +
|
| + /* loop over policy array, testing srtp and srtcp for each policy */
|
| + while (*policy != NULL) {
|
| + printf("testing srtp_protect and srtp_unprotect\n");
|
| + if (srtp_test(*policy, 0) == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| + printf("testing srtp_protect and srtp_unprotect with encrypted extensions headers\n");
|
| + if (srtp_test(*policy, 1) == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| + printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n");
|
| + if (srtcp_test(*policy) == 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, 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, 1) == 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);
|
| + }
|
| +
|
| + /* run test on wildcard policy */
|
| + printf("testing srtp_protect and srtp_unprotect on "
|
| + "wildcard ssrc policy\n");
|
| + if (srtp_test(&wildcard_policy, 0) == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| + printf("testing srtp_protect and srtp_unprotect on "
|
| + "wildcard ssrc policy and encrypted extensions headers\n");
|
| + if (srtp_test(&wildcard_policy, 1) == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +
|
| + /*
|
| + * run validation test against the reference packets - note
|
| + * that this test only covers the default policy
|
| + */
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "reference packet\n");
|
| + if (srtp_validate() == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +
|
| +#ifdef OPENSSL
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "reference packet using GCM\n");
|
| + if (srtp_validate_gcm() == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +#endif
|
| +
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "reference packet with encrypted extensions headers\n");
|
| + if (srtp_validate_encrypted_extensions_headers() == srtp_err_status_ok)
|
| + printf("passed\n\n");
|
| + else {
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +
|
| +#ifdef OPENSSL
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "reference packet with encrypted extension headers (GCM)\n");
|
| + if (srtp_validate_encrypted_extensions_headers_gcm() == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +#endif
|
| +
|
| + /*
|
| + * run validation test against the reference packets for
|
| + * AES-256
|
| + */
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "reference packet (AES-256)\n");
|
| + if (srtp_validate_aes_256() == srtp_err_status_ok) {
|
| + printf("passed\n\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +
|
| + /*
|
| + * test packets with empty payload
|
| + */
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "packet with empty payload\n");
|
| + if (srtp_test_empty_payload() == srtp_err_status_ok) {
|
| + printf("passed\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +#ifdef OPENSSL
|
| + printf("testing srtp_protect and srtp_unprotect against "
|
| + "packet with empty payload (GCM)\n");
|
| + if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) {
|
| + printf("passed\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +#endif
|
| +
|
| + /*
|
| + * test the function srtp_remove_stream()
|
| + */
|
| + printf("testing srtp_remove_stream()...");
|
| + if (srtp_test_remove_stream() == srtp_err_status_ok) {
|
| + printf("passed\n");
|
| + } else{
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| +
|
| + /*
|
| + * test the function srtp_update()
|
| + */
|
| + printf("testing srtp_update()...");
|
| + if (srtp_test_update() == srtp_err_status_ok) {
|
| + printf("passed\n");
|
| + } else {
|
| + printf("failed\n");
|
| + exit(1);
|
| + }
|
| + }
|
| +
|
| + if (do_timing_test) {
|
| + const srtp_policy_t **policy = policy_array;
|
| +
|
| + /* loop over policies, run timing test for each */
|
| + while (*policy != NULL) {
|
| + srtp_print_policy(*policy);
|
| + srtp_do_timing(*policy);
|
| + policy++;
|
| + }
|
| + }
|
| +
|
| + if (do_rejection_test) {
|
| + const srtp_policy_t **policy = policy_array;
|
| +
|
| + /* loop over policies, run rejection timing test for each */
|
| + while (*policy != NULL) {
|
| + srtp_print_policy(*policy);
|
| + srtp_do_rejection_timing(*policy);
|
| + policy++;
|
| + }
|
| + }
|
| +
|
| + if (do_codec_timing) {
|
| + srtp_policy_t policy;
|
| + int 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.ssrc.type = ssrc_specific;
|
| + policy.ssrc.value = 0xdecafbad;
|
| + policy.key = test_key;
|
| + policy.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + printf("mips estimate: %e\n", mips_value);
|
| +
|
| + printf("testing srtp processing time for voice codecs:\n");
|
| + printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n");
|
| + printf("G.711\t\t%d\t\t\t%e\n", 80,
|
| + (double)mips_value * (80 * 8) /
|
| + srtp_bits_per_second(80, &policy) / .01 );
|
| + printf("G.711\t\t%d\t\t\t%e\n", 160,
|
| + (double)mips_value * (160 * 8) /
|
| + srtp_bits_per_second(160, &policy) / .02);
|
| + printf("G.726-32\t%d\t\t\t%e\n", 40,
|
| + (double)mips_value * (40 * 8) /
|
| + srtp_bits_per_second(40, &policy) / .01 );
|
| + printf("G.726-32\t%d\t\t\t%e\n", 80,
|
| + (double)mips_value * (80 * 8) /
|
| + srtp_bits_per_second(80, &policy) / .02);
|
| + printf("G.729\t\t%d\t\t\t%e\n", 10,
|
| + (double)mips_value * (10 * 8) /
|
| + srtp_bits_per_second(10, &policy) / .01 );
|
| + printf("G.729\t\t%d\t\t\t%e\n", 20,
|
| + (double)mips_value * (20 * 8) /
|
| + srtp_bits_per_second(20, &policy) / .02 );
|
| + printf("Wideband\t%d\t\t\t%e\n", 320,
|
| + (double)mips_value * (320 * 8) /
|
| + srtp_bits_per_second(320, &policy) / .01 );
|
| + printf("Wideband\t%d\t\t\t%e\n", 640,
|
| + (double)mips_value * (640 * 8) /
|
| + srtp_bits_per_second(640, &policy) / .02 );
|
| + }
|
| +
|
| + status = srtp_shutdown();
|
| + if (status) {
|
| + printf("error: srtp shutdown failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +
|
| +/*
|
| + * srtp_create_test_packet(len, ssrc) returns a pointer to a
|
| + * (malloced) example RTP packet whose data field has the length given
|
| + * by pkt_octet_len and the SSRC value ssrc. The total length of the
|
| + * packet is twelve octets longer, since the header is at the
|
| + * beginning. There is room at the end of the packet for a trailer,
|
| + * and the four octets following the packet are filled with 0xff
|
| + * values to enable testing for overwrites.
|
| + *
|
| + * note that the location of the test packet can (and should) be
|
| + * deallocated with the free() call once it is no longer needed.
|
| + */
|
| +
|
| +srtp_hdr_t *
|
| +srtp_create_test_packet (int pkt_octet_len, uint32_t ssrc)
|
| +{
|
| + int i;
|
| + uint8_t *buffer;
|
| + srtp_hdr_t *hdr;
|
| + int bytes_in_hdr = 12;
|
| +
|
| + /* allocate memory for test packet */
|
| + hdr = (srtp_hdr_t*)malloc(pkt_octet_len + bytes_in_hdr
|
| + + SRTP_MAX_TRAILER_LEN + 4);
|
| + if (!hdr) {
|
| + return NULL;
|
| + }
|
| +
|
| + hdr->version = 2; /* RTP version two */
|
| + hdr->p = 0; /* no padding needed */
|
| + hdr->x = 0; /* no header extension */
|
| + hdr->cc = 0; /* no CSRCs */
|
| + hdr->m = 0; /* marker bit */
|
| + hdr->pt = 0xf; /* payload type */
|
| + hdr->seq = htons(0x1234); /* sequence number */
|
| + hdr->ts = htonl(0xdecafbad); /* timestamp */
|
| + hdr->ssrc = htonl(ssrc); /* synch. source */
|
| +
|
| + buffer = (uint8_t*)hdr;
|
| + buffer += bytes_in_hdr;
|
| +
|
| + /* set RTP data to 0xab */
|
| + for (i = 0; i < pkt_octet_len; i++) {
|
| + *buffer++ = 0xab;
|
| + }
|
| +
|
| + /* set post-data value to 0xffff to enable overrun checking */
|
| + for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++) {
|
| + *buffer++ = 0xff;
|
| + }
|
| +
|
| + return hdr;
|
| +}
|
| +
|
| +srtp_hdr_t *
|
| +srtp_create_test_packet_ext_hdr(int pkt_octet_len, uint32_t ssrc) {
|
| + int i;
|
| + uint8_t *buffer;
|
| + srtp_hdr_t *hdr;
|
| + int bytes_in_hdr = 12;
|
| + uint8_t extension_header[12] = {
|
| + /* one-byte header */
|
| + 0xbe, 0xde,
|
| + /* size */
|
| + 0x00, 0x02,
|
| + /* id 1, length 1 (i.e. 2 bytes) */
|
| + 0x11,
|
| + /* payload */
|
| + 0xca,
|
| + 0xfe,
|
| + /* padding */
|
| + 0x00,
|
| + /* id 2, length 0 (i.e. 1 byte) */
|
| + 0x20,
|
| + /* payload */
|
| + 0xba,
|
| + /* padding */
|
| + 0x00,
|
| + 0x00
|
| + };
|
| +
|
| + /* allocate memory for test packet */
|
| + hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr
|
| + + sizeof(extension_header) + SRTP_MAX_TRAILER_LEN + 4);
|
| + if (!hdr)
|
| + return NULL;
|
| +
|
| + hdr->version = 2; /* RTP version two */
|
| + hdr->p = 0; /* no padding needed */
|
| + hdr->x = 1; /* no header extension */
|
| + hdr->cc = 0; /* no CSRCs */
|
| + hdr->m = 0; /* marker bit */
|
| + hdr->pt = 0xf; /* payload type */
|
| + hdr->seq = htons(0x1234); /* sequence number */
|
| + hdr->ts = htonl(0xdecafbad); /* timestamp */
|
| + hdr->ssrc = htonl(ssrc); /* synch. source */
|
| +
|
| + buffer = (uint8_t *)hdr;
|
| + buffer += bytes_in_hdr;
|
| +
|
| + memcpy(buffer, extension_header, sizeof(extension_header));
|
| + buffer += sizeof(extension_header);
|
| +
|
| + /* set RTP data to 0xab */
|
| + for (i=0; i < pkt_octet_len; i++)
|
| + *buffer++ = 0xab;
|
| +
|
| + /* set post-data value to 0xffff to enable overrun checking */
|
| + for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++)
|
| + *buffer++ = 0xff;
|
| +
|
| + return hdr;
|
| +}
|
| +
|
| +void
|
| +srtp_do_timing (const srtp_policy_t *policy)
|
| +{
|
| + int len;
|
| +
|
| + /*
|
| + * note: the output of this function is formatted so that it
|
| + * can be used in gnuplot. '#' indicates a comment, and "\r\n"
|
| + * terminates a record
|
| + */
|
| +
|
| + printf("# testing srtp throughput:\r\n");
|
| + printf("# mesg length (octets)\tthroughput (megabits per second)\r\n");
|
| +
|
| + for (len = 16; len <= 2048; len *= 2) {
|
| + printf("%d\t\t\t%f\r\n", len,
|
| + srtp_bits_per_second(len, policy) / 1.0E6);
|
| + }
|
| +
|
| + /* these extra linefeeds let gnuplot know that a dataset is done */
|
| + printf("\r\n\r\n");
|
| +
|
| +}
|
| +
|
| +void
|
| +srtp_do_rejection_timing (const srtp_policy_t *policy)
|
| +{
|
| + int len;
|
| +
|
| + /*
|
| + * note: the output of this function is formatted so that it
|
| + * can be used in gnuplot. '#' indicates a comment, and "\r\n"
|
| + * terminates a record
|
| + */
|
| +
|
| + printf("# testing srtp rejection throughput:\r\n");
|
| + printf("# mesg length (octets)\trejections per second\r\n");
|
| +
|
| + for (len = 8; len <= 2048; len *= 2) {
|
| + printf("%d\t\t\t%e\r\n", len, srtp_rejections_per_second(len, policy));
|
| + }
|
| +
|
| + /* these extra linefeeds let gnuplot know that a dataset is done */
|
| + printf("\r\n\r\n");
|
| +
|
| +}
|
| +
|
| +
|
| +#define MAX_MSG_LEN 1024
|
| +
|
| +double
|
| +srtp_bits_per_second (int msg_len_octets, const srtp_policy_t *policy)
|
| +{
|
| + srtp_t srtp;
|
| + srtp_hdr_t *mesg;
|
| + int i;
|
| + clock_t timer;
|
| + int num_trials = 100000;
|
| + int len;
|
| + uint32_t ssrc;
|
| + srtp_err_status_t status;
|
| +
|
| + /*
|
| + * allocate and initialize an srtp session
|
| + */
|
| + status = srtp_create(&srtp, policy);
|
| + if (status) {
|
| + printf("error: srtp_create() failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + /*
|
| + * if the ssrc is unspecified, use a predetermined one
|
| + */
|
| + if (policy->ssrc.type != ssrc_specific) {
|
| + ssrc = 0xdeadbeef;
|
| + } else {
|
| + ssrc = policy->ssrc.value;
|
| + }
|
| +
|
| + /*
|
| + * create a test packet
|
| + */
|
| + mesg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (mesg == NULL) {
|
| + return 0.0; /* indicate failure by returning zero */
|
| +
|
| + }
|
| + timer = clock();
|
| + for (i = 0; i < num_trials; i++) {
|
| + len = msg_len_octets + 12; /* add in rtp header length */
|
| +
|
| + /* srtp protect message */
|
| + status = srtp_protect(srtp, mesg, &len);
|
| + if (status) {
|
| + printf("error: srtp_protect() failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + /* increment message number */
|
| + {
|
| + /* hack sequence to avoid problems with macros for htons/ntohs on some systems */
|
| + short new_seq = ntohs(mesg->seq) + 1;
|
| + mesg->seq = htons(new_seq);
|
| + }
|
| + }
|
| + timer = clock() - timer;
|
| +
|
| + free(mesg);
|
| +
|
| + status = srtp_dealloc(srtp);
|
| + if (status) {
|
| + printf("error: srtp_dealloc() failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + return (double)(msg_len_octets) * 8 *
|
| + num_trials * CLOCKS_PER_SEC / timer;
|
| +}
|
| +
|
| +double
|
| +srtp_rejections_per_second (int msg_len_octets, const srtp_policy_t *policy)
|
| +{
|
| + srtp_ctx_t *srtp;
|
| + srtp_hdr_t *mesg;
|
| + int i;
|
| + int len;
|
| + clock_t timer;
|
| + int num_trials = 1000000;
|
| + uint32_t ssrc = policy->ssrc.value;
|
| + srtp_err_status_t status;
|
| +
|
| + /*
|
| + * allocate and initialize an srtp session
|
| + */
|
| + status = srtp_create(&srtp, policy);
|
| + if (status) {
|
| + printf("error: srtp_create() failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + mesg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (mesg == NULL) {
|
| + return 0.0; /* indicate failure by returning zero */
|
| +
|
| + }
|
| + len = msg_len_octets;
|
| + srtp_protect(srtp, (srtp_hdr_t*)mesg, &len);
|
| +
|
| + timer = clock();
|
| + for (i = 0; i < num_trials; i++) {
|
| + len = msg_len_octets;
|
| + srtp_unprotect(srtp, (srtp_hdr_t*)mesg, &len);
|
| + }
|
| + timer = clock() - timer;
|
| +
|
| + free(mesg);
|
| +
|
| + status = srtp_dealloc(srtp);
|
| + if (status) {
|
| + printf("error: srtp_dealloc() failed with error code %d\n", status);
|
| + exit(1);
|
| + }
|
| +
|
| + return (double)num_trials * CLOCKS_PER_SEC / timer;
|
| +}
|
| +
|
| +
|
| +void
|
| +err_check (srtp_err_status_t s)
|
| +{
|
| + if (s == srtp_err_status_ok) {
|
| + return;
|
| + } else{
|
| + fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s);
|
| + }
|
| + exit(1);
|
| +}
|
| +
|
| +srtp_err_status_t
|
| +srtp_test (const srtp_policy_t *policy, int extension_header)
|
| +{
|
| + int i;
|
| + srtp_t srtp_sender;
|
| + srtp_t srtp_rcvr;
|
| + srtp_err_status_t status = srtp_err_status_ok;
|
| + srtp_hdr_t *hdr, *hdr2;
|
| + uint8_t hdr_enc[64];
|
| + uint8_t *pkt_end;
|
| + int msg_len_octets, msg_len_enc;
|
| + int len;
|
| + int tag_length = policy->rtp.auth_tag_len;
|
| + uint32_t ssrc;
|
| + srtp_policy_t *rcvr_policy;
|
| + srtp_policy_t tmp_policy;
|
| + int header = 1;
|
| +
|
| + if (extension_header) {
|
| + memcpy(&tmp_policy, policy, sizeof(srtp_policy_t));
|
| + tmp_policy.enc_xtn_hdr = &header;
|
| + tmp_policy.enc_xtn_hdr_count = 1;
|
| + err_check(srtp_create(&srtp_sender, &tmp_policy));
|
| + } else {
|
| + err_check(srtp_create(&srtp_sender, policy));
|
| + }
|
| +
|
| + /* print out policy */
|
| + err_check(srtp_session_print_policy(srtp_sender));
|
| +
|
| + /*
|
| + * initialize data buffer, using the ssrc in the policy unless that
|
| + * value is a wildcard, in which case we'll just use an arbitrary
|
| + * one
|
| + */
|
| + if (policy->ssrc.type != ssrc_specific) {
|
| + ssrc = 0xdecafbad;
|
| + } else{
|
| + ssrc = policy->ssrc.value;
|
| + }
|
| + msg_len_octets = 28;
|
| + if (extension_header) {
|
| + hdr = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc);
|
| + hdr2 = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc);
|
| + } else {
|
| + hdr = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + }
|
| +
|
| + if (hdr == NULL) {
|
| + free(hdr2);
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| + if (hdr2 == NULL) {
|
| + free(hdr);
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| +
|
| + /* set message length */
|
| + len = msg_len_octets;
|
| + if (extension_header) {
|
| + len += 12;
|
| + }
|
| +
|
| + debug_print(mod_driver, "before protection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +
|
| +#if PRINT_REFERENCE_PACKET
|
| + debug_print(mod_driver, "reference packet before protection:\n%s",
|
| + octet_string_hex_string((uint8_t*)hdr, len));
|
| +#endif
|
| + err_check(srtp_protect(srtp_sender, hdr, &len));
|
| +
|
| + debug_print(mod_driver, "after protection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +#if PRINT_REFERENCE_PACKET
|
| + debug_print(mod_driver, "after protection:\n%s",
|
| + octet_string_hex_string((uint8_t*)hdr, len));
|
| +#endif
|
| +
|
| + /* save protected message and length */
|
| + memcpy(hdr_enc, hdr, len);
|
| + msg_len_enc = len;
|
| +
|
| + /*
|
| + * check for overrun of the srtp_protect() function
|
| + *
|
| + * The packet is followed by a value of 0xfffff; if the value of the
|
| + * data following the packet is different, then we know that the
|
| + * protect function is overwriting the end of the packet.
|
| + */
|
| + pkt_end = (uint8_t*)hdr + sizeof(srtp_hdr_t)
|
| + + msg_len_octets + tag_length;
|
| + if (extension_header) {
|
| + pkt_end += 12;
|
| + }
|
| + for (i = 0; i < 4; i++) {
|
| + if (pkt_end[i] != 0xff) {
|
| + fprintf(stdout, "overwrite in srtp_protect() function "
|
| + "(expected %x, found %x in trailing octet %d)\n",
|
| + 0xff, ((uint8_t*)hdr)[i], i);
|
| + free(hdr);
|
| + free(hdr2);
|
| + return srtp_err_status_algo_fail;
|
| + }
|
| + }
|
| +
|
| + /*
|
| + * if the policy includes confidentiality, check that ciphertext is
|
| + * different than plaintext
|
| + *
|
| + * Note that this check will give false negatives, with some small
|
| + * probability, especially if the packets are short. For that
|
| + * 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)) {
|
| + printf("testing that ciphertext is distinct from plaintext...");
|
| + status = srtp_err_status_algo_fail;
|
| + for (i = 12; i < msg_len_octets + 12; i++) {
|
| + if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) {
|
| + status = srtp_err_status_ok;
|
| + }
|
| + }
|
| + if (status) {
|
| + printf("failed\n");
|
| + free(hdr);
|
| + free(hdr2);
|
| + return status;
|
| + }
|
| + printf("passed\n");
|
| + }
|
| +
|
| + /*
|
| + * if the policy uses a 'wildcard' ssrc, then we need to make a copy
|
| + * of the policy that changes the direction to inbound
|
| + *
|
| + * we always copy the policy into the rcvr_policy, since otherwise
|
| + * the compiler would fret about the constness of the policy
|
| + */
|
| + rcvr_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t));
|
| + if (rcvr_policy == NULL) {
|
| + free(hdr);
|
| + free(hdr2);
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| + if (extension_header) {
|
| + memcpy(rcvr_policy, &tmp_policy, sizeof(srtp_policy_t));
|
| + if (tmp_policy.ssrc.type == ssrc_any_outbound) {
|
| + rcvr_policy->ssrc.type = ssrc_any_inbound;
|
| + }
|
| + } else {
|
| + memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
|
| + if (policy->ssrc.type == ssrc_any_outbound) {
|
| + rcvr_policy->ssrc.type = ssrc_any_inbound;
|
| + }
|
| + }
|
| +
|
| + err_check(srtp_create(&srtp_rcvr, rcvr_policy));
|
| +
|
| + err_check(srtp_unprotect(srtp_rcvr, hdr, &len));
|
| +
|
| + debug_print(mod_driver, "after unprotection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +
|
| + /* verify that the unprotected packet matches the origial one */
|
| + for (i = 0; i < msg_len_octets; i++) {
|
| + if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) {
|
| + fprintf(stdout, "mismatch at octet %d\n", i);
|
| + status = srtp_err_status_algo_fail;
|
| + }
|
| + }
|
| + if (status) {
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * if the policy includes authentication, then test for false positives
|
| + */
|
| + if (policy->rtp.sec_serv & sec_serv_auth) {
|
| + char *data = ((char*)hdr) + 12;
|
| +
|
| + printf("testing for false positives in replay check...");
|
| +
|
| + /* set message length */
|
| + len = msg_len_enc;
|
| +
|
| + /* unprotect a second time - should fail with a replay error */
|
| + status = srtp_unprotect(srtp_rcvr, hdr_enc, &len);
|
| + if (status != srtp_err_status_replay_fail) {
|
| + printf("failed with error code %d\n", status);
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + } else {
|
| + printf("passed\n");
|
| + }
|
| +
|
| + printf("testing for false positives in auth check...");
|
| +
|
| + /* increment sequence number in header */
|
| + hdr->seq++;
|
| +
|
| + /* set message length */
|
| + len = msg_len_octets;
|
| + if (extension_header) {
|
| + len += 12;
|
| + }
|
| +
|
| + /* apply protection */
|
| + err_check(srtp_protect(srtp_sender, hdr, &len));
|
| +
|
| + /* flip bits in packet */
|
| + data[extension_header ? 12 : 0] ^= 0xff;
|
| +
|
| + /* unprotect, and check for authentication failure */
|
| + status = srtp_unprotect(srtp_rcvr, hdr, &len);
|
| + if (status != srtp_err_status_auth_fail) {
|
| + printf("failed\n");
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + } else {
|
| + printf("passed\n");
|
| + }
|
| +
|
| + }
|
| +
|
| + err_check(srtp_dealloc(srtp_sender));
|
| + err_check(srtp_dealloc(srtp_rcvr));
|
| +
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +
|
| +srtp_err_status_t
|
| +srtcp_test (const srtp_policy_t *policy)
|
| +{
|
| + int i;
|
| + srtp_t srtcp_sender;
|
| + srtp_t srtcp_rcvr;
|
| + srtp_err_status_t status = srtp_err_status_ok;
|
| + srtp_hdr_t *hdr, *hdr2;
|
| + uint8_t hdr_enc[64];
|
| + uint8_t *pkt_end;
|
| + int msg_len_octets, msg_len_enc;
|
| + int len;
|
| + int tag_length = policy->rtp.auth_tag_len;
|
| + uint32_t ssrc;
|
| + srtp_policy_t *rcvr_policy;
|
| +
|
| + err_check(srtp_create(&srtcp_sender, policy));
|
| +
|
| + /* print out policy */
|
| + err_check(srtp_session_print_policy(srtcp_sender));
|
| +
|
| + /*
|
| + * initialize data buffer, using the ssrc in the policy unless that
|
| + * value is a wildcard, in which case we'll just use an arbitrary
|
| + * one
|
| + */
|
| + if (policy->ssrc.type != ssrc_specific) {
|
| + ssrc = 0xdecafbad;
|
| + } else{
|
| + ssrc = policy->ssrc.value;
|
| + }
|
| + msg_len_octets = 28;
|
| + hdr = srtp_create_test_packet(msg_len_octets, ssrc);
|
| +
|
| + if (hdr == NULL) {
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| + hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (hdr2 == NULL) {
|
| + free(hdr);
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| +
|
| + /* set message length */
|
| + len = msg_len_octets;
|
| +
|
| + debug_print(mod_driver, "before protection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +
|
| +#if PRINT_REFERENCE_PACKET
|
| + debug_print(mod_driver, "reference packet before protection:\n%s",
|
| + octet_string_hex_string((uint8_t*)hdr, len));
|
| +#endif
|
| + err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
|
| +
|
| + debug_print(mod_driver, "after protection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +#if PRINT_REFERENCE_PACKET
|
| + debug_print(mod_driver, "after protection:\n%s",
|
| + octet_string_hex_string((uint8_t*)hdr, len));
|
| +#endif
|
| +
|
| + /* save protected message and length */
|
| + memcpy(hdr_enc, hdr, len);
|
| + msg_len_enc = len;
|
| +
|
| + /*
|
| + * check for overrun of the srtp_protect() function
|
| + *
|
| + * The packet is followed by a value of 0xfffff; if the value of the
|
| + * data following the packet is different, then we know that the
|
| + * protect function is overwriting the end of the packet.
|
| + */
|
| + pkt_end = (uint8_t*)hdr + sizeof(srtp_hdr_t)
|
| + + msg_len_octets + tag_length;
|
| + for (i = 0; i < 4; i++) {
|
| + if (pkt_end[i] != 0xff) {
|
| + fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
|
| + "(expected %x, found %x in trailing octet %d)\n",
|
| + 0xff, ((uint8_t*)hdr)[i], i);
|
| + free(hdr);
|
| + free(hdr2);
|
| + return srtp_err_status_algo_fail;
|
| + }
|
| + }
|
| +
|
| + /*
|
| + * if the policy includes confidentiality, check that ciphertext is
|
| + * different than plaintext
|
| + *
|
| + * Note that this check will give false negatives, with some small
|
| + * probability, especially if the packets are short. For that
|
| + * 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)) {
|
| + printf("testing that ciphertext is distinct from plaintext...");
|
| + status = srtp_err_status_algo_fail;
|
| + for (i = 12; i < msg_len_octets + 12; i++) {
|
| + if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) {
|
| + status = srtp_err_status_ok;
|
| + }
|
| + }
|
| + if (status) {
|
| + printf("failed\n");
|
| + free(hdr);
|
| + free(hdr2);
|
| + return status;
|
| + }
|
| + printf("passed\n");
|
| + }
|
| +
|
| + /*
|
| + * if the policy uses a 'wildcard' ssrc, then we need to make a copy
|
| + * of the policy that changes the direction to inbound
|
| + *
|
| + * we always copy the policy into the rcvr_policy, since otherwise
|
| + * the compiler would fret about the constness of the policy
|
| + */
|
| + rcvr_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t));
|
| + if (rcvr_policy == NULL) {
|
| + return srtp_err_status_alloc_fail;
|
| + }
|
| + memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
|
| + if (policy->ssrc.type == ssrc_any_outbound) {
|
| + rcvr_policy->ssrc.type = ssrc_any_inbound;
|
| + }
|
| +
|
| + err_check(srtp_create(&srtcp_rcvr, rcvr_policy));
|
| +
|
| + err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len));
|
| +
|
| + debug_print(mod_driver, "after unprotection:\n%s",
|
| + srtp_packet_to_string(hdr, len));
|
| +
|
| + /* verify that the unprotected packet matches the origial one */
|
| + for (i = 0; i < msg_len_octets; i++) {
|
| + if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) {
|
| + fprintf(stdout, "mismatch at octet %d\n", i);
|
| + status = srtp_err_status_algo_fail;
|
| + }
|
| + }
|
| + if (status) {
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * if the policy includes authentication, then test for false positives
|
| + */
|
| + if (policy->rtp.sec_serv & sec_serv_auth) {
|
| + char *data = ((char*)hdr) + 12;
|
| +
|
| + printf("testing for false positives in replay check...");
|
| +
|
| + /* set message length */
|
| + len = msg_len_enc;
|
| +
|
| + /* unprotect a second time - should fail with a replay error */
|
| + status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len);
|
| + if (status != srtp_err_status_replay_fail) {
|
| + printf("failed with error code %d\n", status);
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + } else {
|
| + printf("passed\n");
|
| + }
|
| +
|
| + printf("testing for false positives in auth check...");
|
| +
|
| + /* increment sequence number in header */
|
| + hdr->seq++;
|
| +
|
| + /* set message length */
|
| + len = msg_len_octets;
|
| +
|
| + /* apply protection */
|
| + err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
|
| +
|
| + /* flip bits in packet */
|
| + data[0] ^= 0xff;
|
| +
|
| + /* unprotect, and check for authentication failure */
|
| + status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len);
|
| + if (status != srtp_err_status_auth_fail) {
|
| + printf("failed\n");
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return status;
|
| + } else {
|
| + printf("passed\n");
|
| + }
|
| +
|
| + }
|
| +
|
| + err_check(srtp_dealloc(srtcp_sender));
|
| + err_check(srtp_dealloc(srtcp_rcvr));
|
| +
|
| + free(hdr);
|
| + free(hdr2);
|
| + free(rcvr_policy);
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +
|
| +srtp_err_status_t
|
| +srtp_session_print_policy (srtp_t srtp)
|
| +{
|
| + char *serv_descr[4] = {
|
| + "none",
|
| + "confidentiality",
|
| + "authentication",
|
| + "confidentiality and authentication"
|
| + };
|
| + char *direction[3] = {
|
| + "unknown",
|
| + "outbound",
|
| + "inbound"
|
| + };
|
| + srtp_stream_t stream;
|
| +
|
| + /* sanity checking */
|
| + if (srtp == NULL) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /* if there's a template stream, print it out */
|
| + if (srtp->stream_template != NULL) {
|
| + stream = srtp->stream_template;
|
| + printf("# SSRC: any %s\r\n"
|
| + "# rtp cipher: %s\r\n"
|
| + "# rtp auth: %s\r\n"
|
| + "# rtp services: %s\r\n"
|
| + "# rtcp cipher: %s\r\n"
|
| + "# rtcp auth: %s\r\n"
|
| + "# rtcp services: %s\r\n"
|
| + "# window size: %lu\r\n"
|
| + "# tx rtx allowed:%s\r\n",
|
| + direction[stream->direction],
|
| + stream->rtp_cipher->type->description,
|
| + stream->rtp_auth->type->description,
|
| + serv_descr[stream->rtp_services],
|
| + stream->rtcp_cipher->type->description,
|
| + stream->rtcp_auth->type->description,
|
| + serv_descr[stream->rtcp_services],
|
| + srtp_rdbx_get_window_size(&stream->rtp_rdbx),
|
| + stream->allow_repeat_tx ? "true" : "false");
|
| +
|
| + printf("# Encrypted extension headers: ");
|
| + if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
|
| + int* enc_xtn_hdr = stream->enc_xtn_hdr;
|
| + int count = stream->enc_xtn_hdr_count;
|
| + while (count > 0) {
|
| + printf("%d ", *enc_xtn_hdr);
|
| + enc_xtn_hdr++;
|
| + count--;
|
| + }
|
| + printf("\n");
|
| + } else {
|
| + printf("none\n");
|
| + }
|
| + }
|
| +
|
| + /* loop over streams in session, printing the policy of each */
|
| + stream = srtp->stream_list;
|
| + while (stream != NULL) {
|
| + if (stream->rtp_services > sec_serv_conf_and_auth) {
|
| + return srtp_err_status_bad_param;
|
| + }
|
| +
|
| + printf("# SSRC: 0x%08x\r\n"
|
| + "# rtp cipher: %s\r\n"
|
| + "# rtp auth: %s\r\n"
|
| + "# rtp services: %s\r\n"
|
| + "# rtcp cipher: %s\r\n"
|
| + "# rtcp auth: %s\r\n"
|
| + "# rtcp services: %s\r\n"
|
| + "# window size: %lu\r\n"
|
| + "# tx rtx allowed:%s\r\n",
|
| + stream->ssrc,
|
| + stream->rtp_cipher->type->description,
|
| + stream->rtp_auth->type->description,
|
| + serv_descr[stream->rtp_services],
|
| + stream->rtcp_cipher->type->description,
|
| + stream->rtcp_auth->type->description,
|
| + serv_descr[stream->rtcp_services],
|
| + srtp_rdbx_get_window_size(&stream->rtp_rdbx),
|
| + stream->allow_repeat_tx ? "true" : "false");
|
| +
|
| + printf("# Encrypted extension headers: ");
|
| + if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
|
| + int* enc_xtn_hdr = stream->enc_xtn_hdr;
|
| + int count = stream->enc_xtn_hdr_count;
|
| + while (count > 0) {
|
| + printf("%d ", *enc_xtn_hdr);
|
| + enc_xtn_hdr++;
|
| + count--;
|
| + }
|
| + printf("\n");
|
| + } else {
|
| + printf("none\n");
|
| + }
|
| +
|
| + /* advance to next stream in the list */
|
| + stream = stream->next;
|
| + }
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +srtp_err_status_t
|
| +srtp_print_policy (const srtp_policy_t *policy)
|
| +{
|
| + srtp_err_status_t status;
|
| + srtp_t session;
|
| +
|
| + status = srtp_create(&session, policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| + status = srtp_session_print_policy(session);
|
| + if (status) {
|
| + return status;
|
| + }
|
| + status = srtp_dealloc(session);
|
| + if (status) {
|
| + return status;
|
| + }
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +/*
|
| + * srtp_print_packet(...) is for debugging only
|
| + * it prints an RTP packet to the stdout
|
| + *
|
| + * note that this function is *not* threadsafe
|
| + */
|
| +
|
| +#include <stdio.h>
|
| +
|
| +#define MTU 2048
|
| +
|
| +char packet_string[MTU];
|
| +
|
| +char *
|
| +srtp_packet_to_string (srtp_hdr_t *hdr, int pkt_octet_len)
|
| +{
|
| + int octets_in_rtp_header = 12;
|
| + uint8_t *data = ((uint8_t*)hdr) + octets_in_rtp_header;
|
| + int hex_len = pkt_octet_len - octets_in_rtp_header;
|
| +
|
| + /* sanity checking */
|
| + if ((hdr == NULL) || (pkt_octet_len > MTU)) {
|
| + return NULL;
|
| + }
|
| +
|
| + /* write packet into string */
|
| + sprintf(packet_string,
|
| + "(s)rtp packet: {\n"
|
| + " version:\t%d\n"
|
| + " p:\t\t%d\n"
|
| + " x:\t\t%d\n"
|
| + " cc:\t\t%d\n"
|
| + " m:\t\t%d\n"
|
| + " pt:\t\t%x\n"
|
| + " seq:\t\t%x\n"
|
| + " ts:\t\t%x\n"
|
| + " ssrc:\t%x\n"
|
| + " data:\t%s\n"
|
| + "} (%d octets in total)\n",
|
| + hdr->version,
|
| + hdr->p,
|
| + hdr->x,
|
| + hdr->cc,
|
| + hdr->m,
|
| + hdr->pt,
|
| + hdr->seq,
|
| + hdr->ts,
|
| + hdr->ssrc,
|
| + octet_string_hex_string(data, hex_len),
|
| + pkt_octet_len);
|
| +
|
| + return packet_string;
|
| +}
|
| +
|
| +/*
|
| + * mips_estimate() is a simple function to estimate the number of
|
| + * instructions per second that the host can perform. note that this
|
| + * function can be grossly wrong; you may want to have a manual sanity
|
| + * check of its output!
|
| + *
|
| + * the 'ignore' pointer is there to convince the compiler to not just
|
| + * optimize away the function
|
| + */
|
| +
|
| +double
|
| +mips_estimate (int num_trials, int *ignore)
|
| +{
|
| + clock_t t;
|
| + volatile int i, sum;
|
| +
|
| + sum = 0;
|
| + t = clock();
|
| + for (i = 0; i < num_trials; i++) {
|
| + sum += i;
|
| + }
|
| + t = clock() - t;
|
| +
|
| +/* printf("%d\n", sum); */
|
| + *ignore = sum;
|
| +
|
| + return (double)num_trials * CLOCKS_PER_SEC / t;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * srtp_validate() verifies the correctness of libsrtp by comparing
|
| + * some computed packets against some pre-computed reference values.
|
| + * These packets were made with the default SRTP policy.
|
| + */
|
| +
|
| +
|
| +srtp_err_status_t
|
| +srtp_validate ()
|
| +{
|
| + uint8_t srtp_plaintext_ref[28] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab
|
| + };
|
| + uint8_t srtp_plaintext[38] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtp_ciphertext[38] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
|
| + 0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15,
|
| + 0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
|
| + 0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
|
| + };
|
| + uint8_t rtcp_plaintext_ref[24] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + };
|
| + uint8_t rtcp_plaintext[38] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtcp_ciphertext[38] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0x71, 0x28, 0x03, 0x5b, 0xe4, 0x87, 0xb9, 0xbd,
|
| + 0xbe, 0xf8, 0x90, 0x41, 0xf9, 0x77, 0xa5, 0xa8,
|
| + 0x80, 0x00, 0x00, 0x01, 0x99, 0x3e, 0x08, 0xcd,
|
| + 0x54, 0xd6, 0xc1, 0x23, 0x07, 0x98
|
| + };
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| +
|
| + /*
|
| + * 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * protect plaintext, then compare with ciphertext
|
| + */
|
| + len = 28;
|
| + status = srtp_protect(srtp_snd, srtp_plaintext, &len);
|
| + if (status || (len != 38)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + debug_print(mod_driver, "ciphertext:\n %s",
|
| + octet_string_hex_string(srtp_plaintext, len));
|
| + debug_print(mod_driver, "ciphertext reference:\n %s",
|
| + octet_string_hex_string(srtp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * protect plaintext rtcp, then compare with srtcp ciphertext
|
| + */
|
| + len = 24;
|
| + status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
|
| + if (status || (len != 38)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + debug_print(mod_driver, "srtcp ciphertext:\n %s",
|
| + octet_string_hex_string(rtcp_plaintext, len));
|
| + debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
|
| + octet_string_hex_string(srtcp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
|
| + if (status || (len != 28)) {
|
| + return status;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * unprotect srtcp ciphertext, then compare with rtcp plaintext
|
| + */
|
| + len = 38;
|
| + status = srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
|
| + if (status || (len != 24)) {
|
| + return status;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +#ifdef OPENSSL
|
| +/*
|
| + * srtp_validate_gcm() verifies the correctness of libsrtp by comparing
|
| + * an computed packet against the known ciphertext for the plaintext.
|
| + */
|
| +srtp_err_status_t
|
| +srtp_validate_gcm ()
|
| +{
|
| + unsigned char test_key_gcm[28] = {
|
| + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
| + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
| + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
| + 0xa8, 0xa9, 0xaa, 0xab
|
| + };
|
| + uint8_t rtp_plaintext_ref[28] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab
|
| + };
|
| + uint8_t rtp_plaintext[44] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtp_ciphertext[44] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xc5, 0x00, 0x2e, 0xde,
|
| + 0x04, 0xcf, 0xdd, 0x2e, 0xb9, 0x11, 0x59, 0xe0,
|
| + 0x88, 0x0a, 0xa0, 0x6e, 0xd2, 0x97, 0x68, 0x26,
|
| + 0xf7, 0x96, 0xb2, 0x01, 0xdf, 0x31, 0x31, 0xa1,
|
| + 0x27, 0xe8, 0xa3, 0x92
|
| + };
|
| + uint8_t rtcp_plaintext_ref[24] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + };
|
| + uint8_t rtcp_plaintext[44] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtcp_ciphertext[44] = {
|
| + 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
|
| + 0xc9, 0x8b, 0x8b, 0x5d, 0xf0, 0x39, 0x2a, 0x55,
|
| + 0x85, 0x2b, 0x6c, 0x21, 0xac, 0x8e, 0x70, 0x25,
|
| + 0xc5, 0x2c, 0x6f, 0xbe, 0xa2, 0xb3, 0xb4, 0x46,
|
| + 0xea, 0x31, 0x12, 0x3b, 0xa8, 0x8c, 0xe6, 0x1e,
|
| + 0x80, 0x00, 0x00, 0x01
|
| + };
|
| +
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| +
|
| + /*
|
| + * 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * protect plaintext rtp, then compare with srtp ciphertext
|
| + */
|
| + len = 28;
|
| + status = srtp_protect(srtp_snd, rtp_plaintext, &len);
|
| + if (status || (len != 44)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + debug_print(mod_driver, "srtp ciphertext:\n %s",
|
| + octet_string_hex_string(rtp_plaintext, len));
|
| + debug_print(mod_driver, "srtp ciphertext reference:\n %s",
|
| + octet_string_hex_string(srtp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(rtp_plaintext, srtp_ciphertext, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * protect plaintext rtcp, then compare with srtcp ciphertext
|
| + */
|
| + len = 24;
|
| + status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
|
| + if (status || (len != 44)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + debug_print(mod_driver, "srtcp ciphertext:\n %s",
|
| + octet_string_hex_string(rtcp_plaintext, len));
|
| + debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
|
| + octet_string_hex_string(srtcp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * unprotect srtp ciphertext, then compare with rtp plaintext
|
| + */
|
| + len = 44;
|
| + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
|
| + if (status || (len != 28)) {
|
| + return status;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtp_ciphertext, rtp_plaintext_ref, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * unprotect srtcp ciphertext, then compare with rtcp plaintext
|
| + */
|
| + len = 44;
|
| + status = srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
|
| + if (status || (len != 24)) {
|
| + return status;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| + * Test vectors taken from RFC 6904, Appendix A
|
| + */
|
| +srtp_err_status_t
|
| +srtp_validate_encrypted_extensions_headers() {
|
| + unsigned char test_key_ext_headers[30] = {
|
| + 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
|
| + 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
|
| + 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
|
| + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
|
| + };
|
| + uint8_t srtp_plaintext_ref[56] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x41, 0x42, 0x73, 0xA4, 0x75, 0x26, 0x27,
|
| + 0x48, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x8E, 0x46,
|
| + 0x55, 0x99, 0x63, 0x86, 0xB3, 0x95, 0xFB, 0x00,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab
|
| + };
|
| + uint8_t srtp_plaintext[66] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x41, 0x42, 0x73, 0xA4, 0x75, 0x26, 0x27,
|
| + 0x48, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x8E, 0x46,
|
| + 0x55, 0x99, 0x63, 0x86, 0xB3, 0x95, 0xFB, 0x00,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00
|
| + };
|
| + uint8_t srtp_ciphertext[66] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x58, 0x8A, 0x92, 0x70, 0xF4, 0xE1, 0x5E,
|
| + 0x1C, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x95, 0x46,
|
| + 0xA9, 0x94, 0xF0, 0xBC, 0x54, 0x78, 0x97, 0x00,
|
| + 0x4e, 0x55, 0xdc, 0x4c, 0xe7, 0x99, 0x78, 0xd8,
|
| + 0x8c, 0xa4, 0xd2, 0x15, 0x94, 0x9d, 0x24, 0x02,
|
| + 0x5a, 0x46, 0xb3, 0xca, 0x35, 0xc5, 0x35, 0xa8,
|
| + 0x91, 0xc7
|
| + };
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| + int headers[3] = {1, 3, 4};
|
| +
|
| + /*
|
| + * 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.enc_xtn_hdr = headers;
|
| + policy.enc_xtn_hdr_count = sizeof(headers) / sizeof(headers[0]);
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /*
|
| + * protect plaintext, then compare with ciphertext
|
| + */
|
| + len = sizeof(srtp_plaintext_ref);
|
| + status = srtp_protect(srtp_snd, srtp_plaintext, &len);
|
| + if (status || (len != sizeof(srtp_plaintext)))
|
| + return srtp_err_status_fail;
|
| +
|
| + debug_print(mod_driver, "ciphertext:\n %s",
|
| + srtp_octet_string_hex_string(srtp_plaintext, len));
|
| + debug_print(mod_driver, "ciphertext reference:\n %s",
|
| + srtp_octet_string_hex_string(srtp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
|
| + return srtp_err_status_fail;
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != sizeof(srtp_plaintext_ref)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status)
|
| + return status;
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status)
|
| + return status;
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +
|
| +#ifdef OPENSSL
|
| +
|
| +/*
|
| + * Headers of test vectors taken from RFC 6904, Appendix A
|
| + */
|
| +srtp_err_status_t
|
| +srtp_validate_encrypted_extensions_headers_gcm() {
|
| + unsigned char test_key_ext_headers[30] = {
|
| + 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
|
| + 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
|
| + 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
|
| + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
|
| + };
|
| + uint8_t srtp_plaintext_ref[56] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x41, 0x42, 0x73, 0xA4, 0x75, 0x26, 0x27,
|
| + 0x48, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x8E, 0x46,
|
| + 0x55, 0x99, 0x63, 0x86, 0xB3, 0x95, 0xFB, 0x00,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab
|
| + };
|
| + uint8_t srtp_plaintext[64] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x41, 0x42, 0x73, 0xA4, 0x75, 0x26, 0x27,
|
| + 0x48, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x8E, 0x46,
|
| + 0x55, 0x99, 0x63, 0x86, 0xB3, 0x95, 0xFB, 0x00,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtp_ciphertext[64] = {
|
| + 0x90, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xBE, 0xDE, 0x00, 0x06,
|
| + 0x17, 0x58, 0x8A, 0x92, 0x70, 0xF4, 0xE1, 0x5E,
|
| + 0x1C, 0x22, 0x00, 0x00, 0xC8, 0x30, 0x95, 0x46,
|
| + 0xA9, 0x94, 0xF0, 0xBC, 0x54, 0x78, 0x97, 0x00,
|
| + 0x0e, 0xca, 0x0c, 0xf9, 0x5e, 0xe9, 0x55, 0xb2,
|
| + 0x6c, 0xd3, 0xd2, 0x88, 0xb4, 0x9f, 0x6c, 0xa9,
|
| + 0xbb, 0x4e, 0x15, 0xc2, 0xe9, 0xf2, 0x66, 0x78
|
| + };
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| + int headers[3] = {1, 3, 4};
|
| +
|
| + /*
|
| + * 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_8_auth(&policy.rtp);
|
| + srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
|
| + policy.ssrc.type = ssrc_specific;
|
| + policy.ssrc.value = 0xcafebabe;
|
| + policy.key = test_key_ext_headers;
|
| + policy.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.enc_xtn_hdr = headers;
|
| + policy.enc_xtn_hdr_count = sizeof(headers) / sizeof(headers[0]);
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /*
|
| + * protect plaintext, then compare with ciphertext
|
| + */
|
| + len = sizeof(srtp_plaintext_ref);
|
| + status = srtp_protect(srtp_snd, srtp_plaintext, &len);
|
| + if (status || (len != sizeof(srtp_plaintext)))
|
| + return srtp_err_status_fail;
|
| +
|
| + debug_print(mod_driver, "ciphertext:\n %s",
|
| + srtp_octet_string_hex_string(srtp_plaintext, len));
|
| + debug_print(mod_driver, "ciphertext reference:\n %s",
|
| + srtp_octet_string_hex_string(srtp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
|
| + return srtp_err_status_fail;
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != sizeof(srtp_plaintext_ref)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status)
|
| + return status;
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status)
|
| + return status;
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| + * srtp_validate_aes_256() verifies the correctness of libsrtp by comparing
|
| + * some computed packets against some pre-computed reference values.
|
| + * These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy.
|
| + */
|
| +
|
| +
|
| +srtp_err_status_t
|
| +srtp_validate_aes_256 ()
|
| +{
|
| + unsigned char aes_256_test_key[46] = {
|
| + 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
|
| + 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
|
| + 0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
|
| + 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
|
| +
|
| + 0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
|
| + 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
|
| + };
|
| + uint8_t srtp_plaintext_ref[28] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab
|
| + };
|
| + uint8_t srtp_plaintext[38] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
| + 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
| + };
|
| + uint8_t srtp_ciphertext[38] = {
|
| + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
|
| + 0xca, 0xfe, 0xba, 0xbe, 0xf1, 0xd9, 0xde, 0x17,
|
| + 0xff, 0x25, 0x1f, 0xf1, 0xaa, 0x00, 0x77, 0x74,
|
| + 0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a,
|
| + 0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b
|
| + };
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| +
|
| + /*
|
| + * 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * protect plaintext, then compare with ciphertext
|
| + */
|
| + len = 28;
|
| + status = srtp_protect(srtp_snd, srtp_plaintext, &len);
|
| + if (status || (len != 38)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + debug_print(mod_driver, "ciphertext:\n %s",
|
| + octet_string_hex_string(srtp_plaintext, len));
|
| + debug_print(mod_driver, "ciphertext reference:\n %s",
|
| + octet_string_hex_string(srtp_ciphertext, len));
|
| +
|
| + if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
|
| + if (status || (len != 28)) {
|
| + return status;
|
| + }
|
| +
|
| + if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status) {
|
| + 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, *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);
|
| + }
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +srtp_err_status_t
|
| +srtp_test_empty_payload()
|
| +{
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| + srtp_hdr_t *mesg;
|
| +
|
| + /*
|
| + * 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + mesg = srtp_create_test_packet(0, policy.ssrc.value);
|
| + if (mesg == NULL) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + len = 12; /* only the header */
|
| + status = srtp_protect(srtp_snd, mesg, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != 12 + 10) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, mesg, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != 12) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + free(mesg);
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +#ifdef OPENSSL
|
| +srtp_err_status_t
|
| +srtp_test_empty_payload_gcm()
|
| +{
|
| + srtp_t srtp_snd, srtp_recv;
|
| + srtp_err_status_t status;
|
| + int len;
|
| + srtp_policy_t policy;
|
| + srtp_hdr_t *mesg;
|
| +
|
| + /*
|
| + * 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_8_auth(&policy.rtp);
|
| + srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
|
| + policy.ssrc.type = ssrc_specific;
|
| + policy.ssrc.value = 0xcafebabe;
|
| + policy.key = test_key;
|
| + policy.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + mesg = srtp_create_test_packet(0, policy.ssrc.value);
|
| + if (mesg == NULL) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + len = 12; /* only the header */
|
| + status = srtp_protect(srtp_snd, mesg, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != 12 + 8) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * create a receiver session context comparable to the one created
|
| + * above - we need to do this so that the replay checking doesn't
|
| + * complain
|
| + */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * unprotect ciphertext, then compare with plaintext
|
| + */
|
| + status = srtp_unprotect(srtp_recv, mesg, &len);
|
| + if (status) {
|
| + return status;
|
| + } else if (len != 12) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + free(mesg);
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +#endif // OPENSSL
|
| +
|
| +srtp_err_status_t
|
| +srtp_test_remove_stream ()
|
| +{
|
| + srtp_err_status_t status;
|
| + srtp_policy_t *policy_list, policy;
|
| + srtp_t session;
|
| + srtp_stream_t stream;
|
| +
|
| + /*
|
| + * srtp_get_stream() is a libSRTP internal function that we declare
|
| + * here so that we can use it to verify the correct operation of the
|
| + * library
|
| + */
|
| + extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
|
| +
|
| +
|
| + status = srtp_create_big_policy(&policy_list);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_create(&session, policy_list);
|
| + if (status) {
|
| + return status;
|
| + }
|
| +
|
| + /*
|
| + * check for false positives by trying to remove a stream that's not
|
| + * in the session
|
| + */
|
| + status = srtp_remove_stream(session, htonl(0xaaaaaaaa));
|
| + if (status != srtp_err_status_no_ctx) {
|
| + return srtp_err_status_fail;
|
| + }
|
| +
|
| + /*
|
| + * check for false negatives by removing stream 0x1, then
|
| + * searching for streams 0x0 and 0x2
|
| + */
|
| + status = srtp_remove_stream(session, htonl(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;
|
| + }
|
| +
|
| + status = srtp_dealloc_big_policy(policy_list);
|
| + if (status != srtp_err_status_ok) {
|
| + return status;
|
| + }
|
| +
|
| + /* 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| +
|
| + status = srtp_create(&session, NULL);
|
| + if (status != srtp_err_status_ok) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_add_stream(session, &policy);
|
| + if (status != srtp_err_status_ok) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_remove_stream(session, htonl(0xcafebabe));
|
| + if (status != srtp_err_status_ok) {
|
| + return status;
|
| + }
|
| +
|
| + status = srtp_dealloc(session);
|
| + if (status != srtp_err_status_ok) {
|
| + return status;
|
| + }
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +
|
| +unsigned char test_alt_key[46] = {
|
| + 0xe5, 0x19, 0x6f, 0x01, 0x5e, 0xf1, 0x9b, 0xe1,
|
| + 0xd7, 0x47, 0xa7, 0x27, 0x07, 0xd7, 0x47, 0x33,
|
| + 0x01, 0xc2, 0x35, 0x4d, 0x59, 0x6a, 0xf7, 0x84,
|
| + 0x96, 0x98, 0xeb, 0xaa, 0xac, 0xf6, 0xa1, 0x45,
|
| + 0xc7, 0x15, 0xe2, 0xea, 0xfe, 0x55, 0x67, 0x96,
|
| + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
|
| +};
|
| +
|
| +/*
|
| + * srtp_test_update() verifies updating/rekeying exsisting streams.
|
| + * As stated in https://tools.ietf.org/html/rfc3711#section-3.3.1
|
| + * the value of the ROC must not be reset after a rekey, this test
|
| + * atempts to prove that srtp_update does not reset the ROC.
|
| + */
|
| +
|
| +srtp_err_status_t
|
| +srtp_test_update() {
|
| +
|
| + srtp_err_status_t status;
|
| + uint32_t ssrc = 0x12121212;
|
| + int msg_len_octets = 32;
|
| + int protected_msg_len_octets;
|
| + srtp_hdr_t * msg;
|
| + 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.ekt = NULL;
|
| + policy.window_size = 128;
|
| + policy.allow_repeat_tx = 0;
|
| + policy.next = NULL;
|
| + policy.ssrc.type = ssrc_any_outbound;
|
| + policy.key = test_key;
|
| +
|
| + /* create a send and recive ctx with defualt profile and test_key */
|
| + status = srtp_create(&srtp_recv, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + policy.ssrc.type = ssrc_any_inbound;
|
| + status = srtp_create(&srtp_snd, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /* protect and unprotect two msg's that will cause the ROC to be equal to 1 */
|
| + msg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (msg == NULL)
|
| + return srtp_err_status_alloc_fail;
|
| + msg->seq = htons(65535);
|
| +
|
| + protected_msg_len_octets = msg_len_octets;
|
| + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return status;
|
| +
|
| + free(msg);
|
| +
|
| + msg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (msg == NULL)
|
| + return srtp_err_status_alloc_fail;
|
| + msg->seq = htons(1);
|
| +
|
| + protected_msg_len_octets = msg_len_octets;
|
| + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return status;
|
| +
|
| + 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);
|
| + if (status)
|
| + return status;
|
| +
|
| + msg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (msg == NULL)
|
| + return srtp_err_status_alloc_fail;
|
| + msg->seq = htons(2);
|
| +
|
| + protected_msg_len_octets = msg_len_octets;
|
| + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return status;
|
| +
|
| + 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);
|
| + if (status)
|
| + return status;
|
| +
|
| + /* create and protect msg with new key and ROC still equal to 1 */
|
| + msg = srtp_create_test_packet(msg_len_octets, ssrc);
|
| + if (msg == NULL)
|
| + return srtp_err_status_alloc_fail;
|
| + msg->seq = htons(3);
|
| +
|
| + protected_msg_len_octets = msg_len_octets;
|
| + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return srtp_err_status_fail;
|
| +
|
| + /* verify that recive ctx will fail to unprotect as it still uses test_key */
|
| + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets);
|
| + if (status == srtp_err_status_ok)
|
| + return srtp_err_status_fail;
|
| +
|
| + /* create a new recvieve ctx with test_alt_key but since it is new it will have ROC equal to 1
|
| + * and therefore should fail to unprotected */
|
| + {
|
| + 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);
|
| + if (status)
|
| + return status;
|
| +
|
| + status = srtp_unprotect(srtp_recv_roc_0, msg, &protected_msg_len_octets);
|
| + if (status == srtp_err_status_ok)
|
| + return srtp_err_status_fail;
|
| +
|
| + status = srtp_dealloc(srtp_recv_roc_0);
|
| + if (status)
|
| + return status;
|
| + }
|
| +
|
| + /* update recive ctx to use test_alt_key */
|
| + policy.ssrc.type = ssrc_any_inbound;
|
| + policy.key = test_alt_key;
|
| + status = srtp_update(srtp_recv, &policy);
|
| + if (status)
|
| + return status;
|
| +
|
| + /* verify that can still unprotect, therfore key is updated and ROC value is preserved */
|
| + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets);
|
| + if (status)
|
| + return status;
|
| +
|
| + free(msg);
|
| +
|
| + status = srtp_dealloc(srtp_snd);
|
| + if (status)
|
| + return status;
|
| +
|
| + status = srtp_dealloc(srtp_recv);
|
| + if (status)
|
| + return status;
|
| +
|
| + return srtp_err_status_ok;
|
| +}
|
| +
|
| +/*
|
| + * srtp policy definitions - these definitions are used above
|
| + */
|
| +
|
| +unsigned char test_key[46] = {
|
| + 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
|
| + 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
|
| + 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
|
| + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, 0xc1, 0x73,
|
| + 0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, 0x93,
|
| + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
|
| +};
|
| +
|
| +
|
| +const srtp_policy_t default_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_128_ICM, /* cipher type */
|
| + 30, /* 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_128_ICM, /* cipher type */
|
| + 30, /* 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, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t aes_only_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + {
|
| + SRTP_AES_128_ICM, /* cipher type */
|
| + 30, /* 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_128_ICM, /* cipher type */
|
| + 30, /* 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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t hmac_only_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 0, /* cipher key length in octets */
|
| + SRTP_HMAC_SHA1, /* authentication func type */
|
| + 20, /* auth key length in octets */
|
| + 4, /* auth tag length in octets */
|
| + sec_serv_auth /* security services flag */
|
| + },
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +#ifdef OPENSSL
|
| +const srtp_policy_t aes128_gcm_8_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_128_GCM, /* cipher type */
|
| + SRTP_AES_128_GCM_KEYSIZE_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_128_GCM, /* cipher type */
|
| + SRTP_AES_128_GCM_KEYSIZE_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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t aes128_gcm_8_cauth_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_128_GCM, /* cipher type */
|
| + SRTP_AES_128_GCM_KEYSIZE_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_128_GCM, /* cipher type */
|
| + SRTP_AES_128_GCM_KEYSIZE_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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t aes256_gcm_8_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_256_GCM, /* cipher type */
|
| + SRTP_AES_256_GCM_KEYSIZE_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_256_GCM, /* cipher type */
|
| + SRTP_AES_256_GCM_KEYSIZE_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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t aes256_gcm_8_cauth_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_256_GCM, /* cipher type */
|
| + SRTP_AES_256_GCM_KEYSIZE_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_256_GCM, /* cipher type */
|
| + SRTP_AES_256_GCM_KEYSIZE_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 */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +#endif
|
| +
|
| +const srtp_policy_t null_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 0, /* cipher key length in octets */
|
| + SRTP_NULL_AUTH, /* authentication func type */
|
| + 0, /* auth key length in octets */
|
| + 0, /* auth tag length in octets */
|
| + sec_serv_none /* security services flag */
|
| + },
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 0, /* cipher key length in octets */
|
| + SRTP_NULL_AUTH, /* authentication func type */
|
| + 0, /* auth key length in octets */
|
| + 0, /* auth tag length in octets */
|
| + sec_serv_none /* security services flag */
|
| + },
|
| + test_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +unsigned char test_256_key[46] = {
|
| + 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
|
| + 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
|
| + 0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
|
| + 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
|
| +
|
| + 0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
|
| + 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
|
| +};
|
| +
|
| +const srtp_policy_t aes_256_hmac_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_ICM, /* cipher type */
|
| + 46, /* 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, /* cipher type */
|
| + 46, /* 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 */
|
| + },
|
| + test_256_key,
|
| + NULL, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +uint8_t ekt_test_key[16] = {
|
| + 0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca,
|
| + 0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
|
| +};
|
| +
|
| +#include "ekt.h"
|
| +
|
| +srtp_ekt_policy_ctx_t ekt_test_policy = {
|
| + 0xa5a5, /* SPI */
|
| + SRTP_EKT_CIPHER_AES_128_ECB,
|
| + ekt_test_key,
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t hmac_only_with_ekt_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 0, /* cipher key length in octets */
|
| + SRTP_HMAC_SHA1, /* authentication func type */
|
| + 20, /* auth key length in octets */
|
| + 4, /* auth tag length in octets */
|
| + sec_serv_auth /* security services flag */
|
| + },
|
| + {
|
| + SRTP_NULL_CIPHER, /* cipher type */
|
| + 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 */
|
| + },
|
| + test_key,
|
| + &ekt_test_policy, /* indicates that EKT is not in use */
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
| +
|
| +
|
| +/*
|
| + * an array of pointers to the policies listed above
|
| + *
|
| + * This array is used to test various aspects of libSRTP for
|
| + * different cryptographic policies. The order of the elements
|
| + * matters - the timing test generates output that can be used
|
| + * in a plot (see the gnuplot script file 'timing'). If you
|
| + * add to this list, you should do it at the end.
|
| + */
|
| +
|
| +const srtp_policy_t *
|
| +policy_array[] = {
|
| + &hmac_only_policy,
|
| + &aes_only_policy,
|
| + &default_policy,
|
| +#ifdef OPENSSL
|
| + &aes128_gcm_8_policy,
|
| + &aes128_gcm_8_cauth_policy,
|
| + &aes256_gcm_8_policy,
|
| + &aes256_gcm_8_cauth_policy,
|
| +#endif
|
| + &null_policy,
|
| + &aes_256_hmac_policy,
|
| + &hmac_only_with_ekt_policy,
|
| + NULL
|
| +};
|
| +
|
| +const srtp_policy_t wildcard_policy = {
|
| + { ssrc_any_outbound, 0 }, /* SSRC */
|
| + { /* SRTP policy */
|
| + SRTP_AES_128_ICM, /* cipher type */
|
| + 30, /* 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_128_ICM, /* cipher type */
|
| + 30, /* 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,
|
| + 128, /* replay window size */
|
| + 0, /* retransmission not allowed */
|
| + NULL, /* no encrypted extension headers */
|
| + 0, /* list of encrypted extension headers is empty */
|
| + NULL
|
| +};
|
|
|