/*
* srtp_driver . c
*
* a test driver for libSRTP
*
* David A . McGrew
* Cisco Systems , Inc .
*/
/*
*
* Copyright ( c ) 2001 - 2017 , 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 "srtp_priv.h"
#include "util.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 );
srtp_err_status_t srtp_validate_null(void );
#ifdef GCM
srtp_err_status_t srtp_validate_gcm(void );
#endif
srtp_err_status_t srtp_validate_encrypted_extensions_headers(void );
#ifdef GCM
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 GCM
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 );
srtp_err_status_t srtp_test_protect_trailer_length(void );
srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void );
srtp_err_status_t srtp_test_get_roc(void );
srtp_err_status_t srtp_test_set_receiver_roc(void );
srtp_err_status_t srtp_test_set_sender_roc(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,
int mki_index);
srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int 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);
char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
double mips_estimate(int num_trials, int *ignore);
#define TEST_MKI_ID_SIZE 4
extern uint8_t test_key[46 ];
extern uint8_t test_key_2[46 ];
extern uint8_t test_mki_id[TEST_MKI_ID_SIZE];
extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE];
// clang-format off
srtp_master_key_t master_key_1 = {
test_key,
test_mki_id,
TEST_MKI_ID_SIZE
};
srtp_master_key_t master_key_2 = {
test_key_2,
test_mki_id_2,
TEST_MKI_ID_SIZE
};
srtp_master_key_t *test_keys[2 ] = {
&master_key_1,
&master_key_2
};
// clang-format on
void usage(char *prog_name)
{
printf("usage: %s [ -t ][ -c ][ -v ][ -o ][-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"
" -o output logging to stdout\n"
" -d <mod> turn on debugging module <mod>\n"
" -l list debugging modules\n" ,
prog_name);
exit (1 );
}
void log_handler(srtp_log_level_t level, const char *msg, void *data)
{
char level_char = '?' ;
switch (level) {
case srtp_log_level_error:
level_char = 'e' ;
break ;
case srtp_log_level_warning:
level_char = 'w' ;
break ;
case srtp_log_level_info:
level_char = 'i' ;
break ;
case srtp_log_level_debug:
level_char = 'd' ;
break ;
}
printf("SRTP-LOG [%c]: %s\n" , level_char, msg);
}
/*
* The policy_array and invalid_policy_array are null - terminated arrays of
* 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[];
/* 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 ;
unsigned do_log_stdout = 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, "trcvold:" );
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 'o' :
do_log_stdout = 1 ;
break ;
case 'l' :
do_list_mods = 1 ;
break ;
case 'd' :
status = srtp_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_log_stdout) {
status = srtp_install_log_handler(log_handler, NULL);
if (status) {
printf("error: install log handler failed\n" );
exit (1 );
}
}
if (do_list_mods) {
status = srtp_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;
srtp_t srtp_sender;
/* 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 , -1 ) == 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 , -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, -1 ) == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI "
"index set to 0\n" );
if (srtp_test(*policy, 0 , 0 ) == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI "
"index set to 1\n" );
if (srtp_test(*policy, 0 , 1 ) == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI "
"index set to 0\n" );
if (srtcp_test(*policy, 0 ) == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI "
"index set to 1\n" );
if (srtcp_test(*policy, 1 ) == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
policy++;
}
/* loop over invalid policy array, testing that an SRTP context cannot
* be created with the policy */
policy = invalid_policy_array;
while (*policy != NULL) {
printf("testing srtp_create fails with invalid policy\n" );
if (srtp_create(&srtp_sender, *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 , -1 ) == 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 , -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 , -1 ) == 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 , -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 );
}
printf("testing srtp_protect and srtp_unprotect against "
"reference packet using null cipher and HMAC\n" );
if (srtp_validate_null() == srtp_err_status_ok) {
printf("passed\n\n" );
} else {
printf("failed\n" );
exit (1 );
}
#ifdef GCM
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 GCM
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 GCM
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 );
}
/*
* test the functions srtp_get_protect_trailer_length
* and srtp_get_protect_rtcp_trailer_length
*/
printf("testing srtp_get_protect_trailer_length()..." );
if (srtp_test_protect_trailer_length() == srtp_err_status_ok) {
printf("passed\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_get_protect_rtcp_trailer_length()..." );
if (srtp_test_protect_rtcp_trailer_length() == srtp_err_status_ok) {
printf("passed\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_test_get_roc()..." );
if (srtp_test_get_roc() == srtp_err_status_ok) {
printf("passed\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_test_set_receiver_roc()..." );
if (srtp_test_set_receiver_roc() == srtp_err_status_ok) {
printf("passed\n" );
} else {
printf("failed\n" );
exit (1 );
}
printf("testing srtp_test_set_sender_roc()..." );
if (srtp_test_set_sender_roc() == 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 = 0 xdecafbad;
policy.key = test_key;
policy.deprecated_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 0 xff
* 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 *pkt_len)
{
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 = 0 xf; /* payload type */
hdr->seq = htons(0 x1234); /* sequence number */
hdr->ts = htonl(0 xdecafbad); /* 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++ = 0 xab;
}
/* set post-data value to 0xffff to enable overrun checking */
for (i = 0 ; i < SRTP_MAX_TRAILER_LEN + 4 ; i++) {
*buffer++ = 0 xff;
}
*pkt_len = bytes_in_hdr + pkt_octet_len;
return hdr;
}
static srtp_hdr_t *srtp_create_test_packet_extended(int pkt_octet_len,
uint32_t ssrc,
uint16_t seq,
uint32_t ts,
int *pkt_len)
{
srtp_hdr_t *hdr;
hdr = srtp_create_test_packet(pkt_octet_len, ssrc, pkt_len);
if (hdr == NULL)
return hdr;
hdr->seq = htons(seq);
hdr->ts = htonl(ts);
return hdr;
}
srtp_hdr_t *srtp_create_test_packet_ext_hdr(int pkt_octet_len,
uint32_t ssrc,
int *pkt_len)
{
int i;
uint8_t *buffer;
srtp_hdr_t *hdr;
int bytes_in_hdr = 12 ;
uint8_t extension_header[12 ] = { /* one-byte header */
0 xbe, 0 xde,
/* size */
0 x00, 0 x02,
/* id 1, length 1 (i.e. 2 bytes) */
0 x11,
/* payload */
0 xca, 0 xfe,
/* padding */
0 x00,
/* id 2, length 0 (i.e. 1 byte) */
0 x20,
/* payload */
0 xba,
/* padding */
0 x00, 0 x00
};
/* 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 = 0 xf; /* payload type */
hdr->seq = htons(0 x1234); /* sequence number */
hdr->ts = htonl(0 xdecafbad); /* 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++ = 0 xab;
/* set post-data value to 0xffff to enable overrun checking */
for (i = 0 ; i < SRTP_MAX_TRAILER_LEN + 4 ; i++)
*buffer++ = 0 xff;
*pkt_len = bytes_in_hdr + sizeof (extension_header) + pkt_octet_len;
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 .0 E6);
}
/* 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 input_len, 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 = 0 xdeadbeef;
} else {
ssrc = policy->ssrc.value;
}
/*
* create a test packet
*/
mesg = srtp_create_test_packet(msg_len_octets, ssrc, &input_len);
if (mesg == NULL) {
return 0 .0 ; /* indicate failure by returning zero */
}
timer = clock();
for (i = 0 ; i < num_trials; i++) {
len = input_len;
/* 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, &len);
if (mesg == NULL) {
return 0 .0 ; /* indicate failure by returning zero */
}
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) {
fprintf(stderr, "error: unexpected srtp failure (code %d)\n" , s);
exit (1 );
}
}
srtp_err_status_t srtp_test_call_protect(srtp_t srtp_sender,
srtp_hdr_t *hdr,
int *len,
int mki_index)
{
if (mki_index == -1 ) {
return srtp_protect(srtp_sender, hdr, len);
} else {
return srtp_protect_mki(srtp_sender, hdr, len, 1 , mki_index);
}
}
srtp_err_status_t srtp_test_call_protect_rtcp(srtp_t srtp_sender,
srtp_hdr_t *hdr,
int *len,
int mki_index)
{
if (mki_index == -1 ) {
return srtp_protect_rtcp(srtp_sender, hdr, len);
} else {
return srtp_protect_rtcp_mki(srtp_sender, hdr, len, 1 , mki_index);
}
}
srtp_err_status_t srtp_test_call_unprotect(srtp_t srtp_sender,
srtp_hdr_t *hdr,
int *len,
int use_mki)
{
if (use_mki == -1 ) {
return srtp_unprotect(srtp_sender, hdr, len);
} else {
return srtp_unprotect_mki(srtp_sender, hdr, len, use_mki);
}
}
srtp_err_status_t srtp_test_call_unprotect_rtcp(srtp_t srtp_sender,
srtp_hdr_t *hdr,
int *len,
int use_mki)
{
if (use_mki == -1 ) {
return srtp_unprotect_rtcp(srtp_sender, hdr, len);
} else {
return srtp_unprotect_rtcp_mki(srtp_sender, hdr, len, use_mki);
}
}
srtp_err_status_t srtp_test(const srtp_policy_t *policy,
int extension_header,
int mki_index)
{
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, msg_len;
int len, len2;
uint32_t tag_length;
uint32_t ssrc;
srtp_policy_t *rcvr_policy;
srtp_policy_t tmp_policy;
int header = 1 ;
int use_mki = 0 ;
if (mki_index >= 0 )
use_mki = 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 = 0 xdecafbad;
} else {
ssrc = policy->ssrc.value;
}
msg_len_octets = 28 ;
if (extension_header) {
hdr = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len);
hdr2 = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len2);
} else {
hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len);
hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2);
}
/* save original msg len */
msg_len = len;
if (hdr == NULL) {
free(hdr2);
return srtp_err_status_alloc_fail;
}
if (hdr2 == NULL) {
free(hdr);
return srtp_err_status_alloc_fail;
}
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_test_call_protect(srtp_sender, hdr, &len, mki_index));
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 0 xfffff ; 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 .
*/
err_check(srtp_get_protect_trailer_length(srtp_sender, use_mki, mki_index,
&tag_length));
pkt_end = (uint8_t *)hdr + msg_len + tag_length;
for (i = 0 ; i < 4 ; i++) {
if (pkt_end[i] != 0 xff) {
fprintf(stdout, "overwrite in srtp_protect() function "
"(expected %x, found %x in trailing octet %d)\n" ,
0 xff, ((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_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki));
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 < len; 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) + (extension_header ? 24 : 12 );
printf("testing for false positives in replay check..." );
/* unprotect a second time - should fail with a replay error */
status =
srtp_test_call_unprotect(srtp_rcvr, hdr, &msg_len_enc, use_mki);
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++;
/* apply protection */
err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index));
/* flip bits in packet */
data[0 ] ^= 0 xff;
/* unprotect, and check for authentication failure */
status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki);
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 mki_index)
{
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, msg_len;
int len, len2;
uint32_t tag_length;
uint32_t ssrc;
srtp_policy_t *rcvr_policy;
int use_mki = 0 ;
if (mki_index >= 0 )
use_mki = 1 ;
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 = 0 xdecafbad;
} else {
ssrc = policy->ssrc.value;
}
msg_len_octets = 28 ;
hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len);
/* save message len */
msg_len = len;
if (hdr == NULL) {
return srtp_err_status_alloc_fail;
}
hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2);
if (hdr2 == NULL) {
free(hdr);
return srtp_err_status_alloc_fail;
}
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_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));
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 0 xfffff ; 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 .
*/
srtp_get_protect_rtcp_trailer_length(srtcp_sender, use_mki, mki_index,
&tag_length);
pkt_end = (uint8_t *)hdr + msg_len + tag_length;
for (i = 0 ; i < 4 ; i++) {
if (pkt_end[i] != 0 xff) {
fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
"(expected %x, found %x in trailing octet %d)\n" ,
0 xff, ((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->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 (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;
}
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_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki));
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 < len; 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..." );
/* unprotect a second time - should fail with a replay error */
status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &msg_len_enc,
use_mki);
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++;
/* apply protection */
err_check(
srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));
/* flip bits in packet */
data[0 ] ^= 0 xff;
/* unprotect, and check for authentication failure */
status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki);
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;
srtp_session_keys_t *session_keys = NULL;
/* sanity checking */
if (srtp == NULL) {
return srtp_err_status_fail;
}
/* if there's a template stream, print it out */
if (srtp->stream_template != NULL) {
stream = srtp->stream_template;
session_keys = &stream->session_keys[0 ];
printf("# SSRC: any %s\r\n"
"# rtp cipher: %s\r\n"
"# rtp auth: %s\r\n"
"# rtp services: %s\r\n"
"# rtcp cipher: %s\r\n"
"# rtcp auth: %s\r\n"
"# rtcp services: %s\r\n"
"# window size: %lu\r\n"
"# tx rtx allowed:%s\r\n" ,
direction[stream->direction],
session_keys->rtp_cipher->type->description,
session_keys->rtp_auth->type->description,
serv_descr[stream->rtp_services],
session_keys->rtcp_cipher->type->description,
session_keys->rtcp_auth->type->description,
serv_descr[stream->rtcp_services],
srtp_rdbx_get_window_size(&stream->rtp_rdbx),
stream->allow_repeat_tx ? "true" : "false" );
printf("# Encrypted extension headers: " );
if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0 ) {
int *enc_xtn_hdr = stream->enc_xtn_hdr;
int count = stream->enc_xtn_hdr_count;
while (count > 0 ) {
printf("%d " , *enc_xtn_hdr);
enc_xtn_hdr++;
count--;
}
printf("\n" );
} else {
printf("none\n" );
}
}
/* loop over streams in session, printing the policy of each */
stream = srtp->stream_list;
while (stream != NULL) {
if (stream->rtp_services > sec_serv_conf_and_auth) {
return srtp_err_status_bad_param;
}
session_keys = &stream->session_keys[0 ];
printf("# SSRC: 0x%08x\r\n"
"# rtp cipher: %s\r\n"
"# rtp auth: %s\r\n"
"# rtp services: %s\r\n"
"# rtcp cipher: %s\r\n"
"# rtcp auth: %s\r\n"
"# rtcp services: %s\r\n"
"# window size: %lu\r\n"
"# tx rtx allowed:%s\r\n" ,
stream->ssrc, session_keys->rtp_cipher->type->description,
session_keys->rtp_auth->type->description,
serv_descr[stream->rtp_services],
session_keys->rtcp_cipher->type->description,
session_keys->rtcp_auth->type->description,
serv_descr[stream->rtcp_services],
srtp_rdbx_get_window_size(&stream->rtp_rdbx),
stream->allow_repeat_tx ? "true" : "false" );
printf("# Encrypted extension headers: " );
if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0 ) {
int *enc_xtn_hdr = stream->enc_xtn_hdr;
int count = stream->enc_xtn_hdr_count;
while (count > 0 ) {
printf("%d " , *enc_xtn_hdr);
enc_xtn_hdr++;
count--;
}
printf("\n" );
} else {
printf("none\n" );
}
/* advance to next stream in the list */
stream = stream->next;
}
return srtp_err_status_ok;
}
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;
if (t < 1 ) {
t = 1 ;
}
/* 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()
{
// clang-format off
uint8_t srtp_plaintext_ref[28 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab
};
uint8_t srtp_plaintext[38 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtp_ciphertext[38 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 x4e, 0 x55, 0 xdc, 0 x4c,
0 xe7, 0 x99, 0 x78, 0 xd8, 0 x8c, 0 xa4, 0 xd2, 0 x15,
0 x94, 0 x9d, 0 x24, 0 x02, 0 xb7, 0 x8d, 0 x6a, 0 xcc,
0 x99, 0 xea, 0 x17, 0 x9b, 0 x8d, 0 xbb
};
uint8_t rtcp_plaintext_ref[24 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
};
uint8_t rtcp_plaintext[38 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtcp_ciphertext[38 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 x71, 0 x28, 0 x03, 0 x5b, 0 xe4, 0 x87, 0 xb9, 0 xbd,
0 xbe, 0 xf8, 0 x90, 0 x41, 0 xf9, 0 x77, 0 xa5, 0 xa8,
0 x80, 0 x00, 0 x00, 0 x01, 0 x99, 0 x3e, 0 x08, 0 xcd,
0 x54, 0 xd6, 0 xc1, 0 x23, 0 x07, 0 x98
};
// clang-format on
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 0 xcafebabe
*/
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 = 0 xcafebabe;
policy.key = test_key;
policy.deprecated_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 (srtp_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 (srtp_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 (srtp_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 (srtp_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;
}
/*
* srtp_validate_null ( ) verifies the correctness of libsrtp by comparing
* some computed packets against some pre - computed reference values .
* These packets were made with a policy that applies null encryption
* and HMAC authentication .
*/
srtp_err_status_t srtp_validate_null()
{
// clang-format off
uint8_t srtp_plaintext_ref[28 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab
};
uint8_t srtp_plaintext[38 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtp_ciphertext[38 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xa1, 0 x36, 0 x27,
0 x0b, 0 x67, 0 x91, 0 x34, 0 xce, 0 x9b
};
uint8_t rtcp_plaintext_ref[24 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
};
uint8_t rtcp_plaintext[38 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtcp_ciphertext[38 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x01, 0 xfe, 0 x88, 0 xc7, 0 xfd,
0 xfd, 0 x37, 0 xeb, 0 xce, 0 x61, 0 x5d,
};
// clang-format on
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 0 xcafebabe
*/
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 = 0 xcafebabe;
policy.key = test_key;
policy.deprecated_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 (srtp_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 (srtp_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 (srtp_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 (srtp_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 GCM
/*
* srtp_validate_gcm ( ) verifies the correctness of libsrtp by comparing
* an computed packet against the known ciphertext for the plaintext .
*/
srtp_err_status_t srtp_validate_gcm()
{
// clang-format off
unsigned char test_key_gcm[28 ] = {
0 x00, 0 x01, 0 x02, 0 x03, 0 x04, 0 x05, 0 x06, 0 x07,
0 x08, 0 x09, 0 x0a, 0 x0b, 0 x0c, 0 x0d, 0 x0e, 0 x0f,
0 xa0, 0 xa1, 0 xa2, 0 xa3, 0 xa4, 0 xa5, 0 xa6, 0 xa7,
0 xa8, 0 xa9, 0 xaa, 0 xab
};
uint8_t rtp_plaintext_ref[28 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab
};
uint8_t rtp_plaintext[44 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtp_ciphertext[44 ] = {
0 x80, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xc5, 0 x00, 0 x2e, 0 xde,
0 x04, 0 xcf, 0 xdd, 0 x2e, 0 xb9, 0 x11, 0 x59, 0 xe0,
0 x88, 0 x0a, 0 xa0, 0 x6e, 0 xd2, 0 x97, 0 x68, 0 x26,
0 xf7, 0 x96, 0 xb2, 0 x01, 0 xdf, 0 x31, 0 x31, 0 xa1,
0 x27, 0 xe8, 0 xa3, 0 x92
};
uint8_t rtcp_plaintext_ref[24 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
};
uint8_t rtcp_plaintext[44 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtcp_ciphertext[44 ] = {
0 x81, 0 xc8, 0 x00, 0 x0b, 0 xca, 0 xfe, 0 xba, 0 xbe,
0 xc9, 0 x8b, 0 x8b, 0 x5d, 0 xf0, 0 x39, 0 x2a, 0 x55,
0 x85, 0 x2b, 0 x6c, 0 x21, 0 xac, 0 x8e, 0 x70, 0 x25,
0 xc5, 0 x2c, 0 x6f, 0 xbe, 0 xa2, 0 xb3, 0 xb4, 0 x46,
0 xea, 0 x31, 0 x12, 0 x3b, 0 xa8, 0 x8c, 0 xe6, 0 x1e,
0 x80, 0 x00, 0 x00, 0 x01
};
// clang-format on
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 0 xcafebabe
*/
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 = 0 xcafebabe;
policy.key = test_key_gcm;
policy.deprecated_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 (srtp_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 (srtp_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 (srtp_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 (srtp_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()
{
// clang-format off
unsigned char test_key_ext_headers[30 ] = {
0 xe1, 0 xf9, 0 x7a, 0 x0d, 0 x3e, 0 x01, 0 x8b, 0 xe0,
0 xd6, 0 x4f, 0 xa3, 0 x2c, 0 x06, 0 xde, 0 x41, 0 x39,
0 x0e, 0 xc6, 0 x75, 0 xad, 0 x49, 0 x8a, 0 xfe, 0 xeb,
0 xb6, 0 x96, 0 x0b, 0 x3a, 0 xab, 0 xe6
};
uint8_t srtp_plaintext_ref[56 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x41, 0 x42, 0 x73, 0 xA4, 0 x75, 0 x26, 0 x27,
0 x48, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 x8E, 0 x46,
0 x55, 0 x99, 0 x63, 0 x86, 0 xB3, 0 x95, 0 xFB, 0 x00,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab
};
uint8_t srtp_plaintext[66 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x41, 0 x42, 0 x73, 0 xA4, 0 x75, 0 x26, 0 x27,
0 x48, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 x8E, 0 x46,
0 x55, 0 x99, 0 x63, 0 x86, 0 xB3, 0 x95, 0 xFB, 0 x00,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00
};
uint8_t srtp_ciphertext[66 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x58, 0 x8A, 0 x92, 0 x70, 0 xF4, 0 xE1, 0 x5E,
0 x1C, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 x95, 0 x46,
0 xA9, 0 x94, 0 xF0, 0 xBC, 0 x54, 0 x78, 0 x97, 0 x00,
0 x4e, 0 x55, 0 xdc, 0 x4c, 0 xe7, 0 x99, 0 x78, 0 xd8,
0 x8c, 0 xa4, 0 xd2, 0 x15, 0 x94, 0 x9d, 0 x24, 0 x02,
0 x5a, 0 x46, 0 xb3, 0 xca, 0 x35, 0 xc5, 0 x35, 0 xa8,
0 x91, 0 xc7
};
// clang-format on
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 0 xcafebabe
*/
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 = 0 xcafebabe;
policy.key = test_key_ext_headers;
policy.deprecated_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 (srtp_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 (srtp_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 GCM
/*
* Headers of test vectors taken from RFC 6904 , Appendix A
*/
srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm()
{
// clang-format off
unsigned char test_key_ext_headers[30 ] = {
0 xe1, 0 xf9, 0 x7a, 0 x0d, 0 x3e, 0 x01, 0 x8b, 0 xe0,
0 xd6, 0 x4f, 0 xa3, 0 x2c, 0 x06, 0 xde, 0 x41, 0 x39,
0 x0e, 0 xc6, 0 x75, 0 xad, 0 x49, 0 x8a, 0 xfe, 0 xeb,
0 xb6, 0 x96, 0 x0b, 0 x3a, 0 xab, 0 xe6
};
uint8_t srtp_plaintext_ref[56 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x41, 0 x42, 0 x73, 0 xA4, 0 x75, 0 x26, 0 x27,
0 x48, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 x8E, 0 x46,
0 x55, 0 x99, 0 x63, 0 x86, 0 xB3, 0 x95, 0 xFB, 0 x00,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab
};
uint8_t srtp_plaintext[64 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x41, 0 x42, 0 x73, 0 xA4, 0 x75, 0 x26, 0 x27,
0 x48, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 x8E, 0 x46,
0 x55, 0 x99, 0 x63, 0 x86, 0 xB3, 0 x95, 0 xFB, 0 x00,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab, 0 xab,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
uint8_t srtp_ciphertext[64 ] = {
0 x90, 0 x0f, 0 x12, 0 x34, 0 xde, 0 xca, 0 xfb, 0 xad,
0 xca, 0 xfe, 0 xba, 0 xbe, 0 xBE, 0 xDE, 0 x00, 0 x06,
0 x17, 0 x12, 0 xe0, 0 x20, 0 x5b, 0 xfa, 0 x94, 0 x9b,
0 x1C, 0 x22, 0 x00, 0 x00, 0 xC8, 0 x30, 0 xbb, 0 x46,
0 x73, 0 x27, 0 x78, 0 xd9, 0 x92, 0 x9a, 0 xab, 0 x00,
0 x0e, 0 xca, 0 x0c, 0 xf9, 0 x5e, 0 xe9, 0 x55, 0 xb2,
0 x6c, 0 xd3, 0 xd2, 0 x88, 0 xb4, 0 x9f, 0 x6c, 0 xa9,
0 xf4, 0 xb1, 0 xb7, 0 x59, 0 x71, 0 x9e, 0 xb5, 0 xbc
};
// clang-format on
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 0 xcafebabe
*/
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 = 0 xcafebabe;
policy.key = test_key_ext_headers;
policy.deprecated_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 (srtp_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 (srtp_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 ( )
{
/ / clang - format off
unsigned char aes_256_test_key [ 46 ] = {
0 xf0 , 0 xf0 , 0 x49 , 0 x14 , 0 xb5 , 0 x13 , 0 xf2 , 0 x76 ,
0 x3a , 0 x1b , 0 x1f , 0 xa1 , 0 x30 , 0 xf1 , 0 x0e , 0 x29 ,
0 x98 , 0 xf6 , 0 xf6 , 0 xe4 , 0 x3e , 0 x43 , 0 x09 , 0 xd1 ,
0 xe6 , 0 x22 , 0 xa0 , 0 xe3 , 0 x32 , 0 xb9 , 0 xf1 , 0 xb6 ,
0 x3b , 0 x04 , 0 x80 , 0 x3d , 0 xe5 , 0 x1e , 0 xe7 , 0 xc9 ,
0 x64 , 0 x23 , 0 xab , 0 x5b , 0 x78 , 0 xd2
} ;
uint8_t srtp_plaintext_ref [ 28 ] = {
0 x80 , 0 x0f , 0 x12 , 0 x34 , 0 xde , 0 xca , 0 xfb , 0 xad ,
0 xca , 0 xfe , 0 xba , 0 xbe , 0 xab , 0 xab , 0 xab , 0 xab ,
0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab ,
0 xab , 0 xab , 0 xab , 0 xab
} ;
uint8_t srtp_plaintext [ 38 ] = {
0 x80 , 0 x0f , 0 x12 , 0 x34 , 0 xde , 0 xca , 0 xfb , 0 xad ,
0 xca , 0 xfe , 0 xba , 0 xbe , 0 xab , 0 xab , 0 xab , 0 xab ,
0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab , 0 xab ,
0 xab , 0 xab , 0 xab , 0 xab , 0 x00 , 0 x00 , 0 x00 , 0 x00 ,
0 x00 , 0 x00 , 0 x00 , 0 x00 , 0 x00 , 0 x00
} ;
uint8_t srtp_ciphertext [ 38 ] = {
0 x80 , 0 x0f , 0 x12 , 0 x34 , 0 xde , 0 xca , 0 xfb , 0 xad ,
0 xca , 0 xfe , 0 xba , 0 xbe , 0 xf1 , 0 xd9 , 0 xde , 0 x17 ,
0 xff , 0 x25 , 0 x1f , 0 xf1 , 0 xaa , 0 x00 , 0 x77 , 0 x74 ,
0 xb0 , 0 xb4 , 0 xb4 , 0 x0d , 0 xa0 , 0 x8d , 0 x9d , 0 x9a ,
0 x5b , 0 x3a , 0 x55 , 0 xd8 , 0 x87 , 0 x3b
} ;
/ / clang - format on
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 0 xcafebabe
* /
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 = 0 xcafebabe ;
policy . key = aes_256_test_key ;
policy . deprecated_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 ( srtp_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 ( srtp_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 = 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 ) ;
}
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 0 xcafebabe
* /
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 = 0 xcafebabe ;
policy . key = test_key ;
policy . deprecated_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 , & len ) ;
if ( mesg = = NULL ) {
return srtp_err_status_fail ;
}
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 GCM
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 0 xcafebabe
* /
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 = 0 xcafebabe ;
policy . key = test_key ;
policy . deprecated_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 , & len ) ;
if ( mesg = = NULL ) {
return srtp_err_status_fail ;
}
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 / / GCM
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 ( 0 xaaaaaaaa ) ) ;
if ( status ! = srtp_err_status_no_ctx ) {
return srtp_err_status_fail ;
}
/ *
* check for false negatives by removing stream 0 x1 , then
* searching for streams 0 x0 and 0 x2
* /
status = srtp_remove_stream ( session , htonl ( 0 x1 ) ) ;
if ( status ! = srtp_err_status_ok ) {
return srtp_err_status_fail ;
}
stream = srtp_get_stream ( session , htonl ( 0 x0 ) ) ;
if ( stream = = NULL ) {
return srtp_err_status_fail ;
}
stream = srtp_get_stream ( session , htonl ( 0 x2 ) ) ;
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 = 0 xcafebabe ;
policy . key = test_key ;
policy . deprecated_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 ( 0 xcafebabe ) ) ;
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 ;
}
/ / clang - format off
unsigned char test_alt_key [ 46 ] = {
0 xe5 , 0 x19 , 0 x6f , 0 x01 , 0 x5e , 0 xf1 , 0 x9b , 0 xe1 ,
0 xd7 , 0 x47 , 0 xa7 , 0 x27 , 0 x07 , 0 xd7 , 0 x47 , 0 x33 ,
0 x01 , 0 xc2 , 0 x35 , 0 x4d , 0 x59 , 0 x6a , 0 xf7 , 0 x84 ,
0 x96 , 0 x98 , 0 xeb , 0 xaa , 0 xac , 0 xf6 , 0 xa1 , 0 x45 ,
0 xc7 , 0 x15 , 0 xe2 , 0 xea , 0 xfe , 0 x55 , 0 x67 , 0 x96 ,
0 xb6 , 0 x96 , 0 x0b , 0 x3a , 0 xab , 0 xe6
} ;
/ / clang - format on
/ *
* 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 = 0 x12121212 ;
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 . deprecated_ekt = NULL ;
policy . window_size = 128 ;
policy . allow_repeat_tx = 0 ;
policy . next = NULL ;
policy . ssrc . type = ssrc_any_outbound ;
policy . key = test_key ;
/ * create a send and recive ctx with defualt profile and test_key * /
status = srtp_create ( & srtp_recv , & policy ) ;
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 ,
& protected_msg_len_octets ) ;
if ( msg = = NULL )
return srtp_err_status_alloc_fail ;
msg - > seq = htons ( 65535 ) ;
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 ,
& protected_msg_len_octets ) ;
if ( msg = = NULL )
return srtp_err_status_alloc_fail ;
msg - > seq = htons ( 1 ) ;
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 ,
& protected_msg_len_octets ) ;
if ( msg = = NULL )
return srtp_err_status_alloc_fail ;
msg - > seq = htons ( 2 ) ;
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 ,
& protected_msg_len_octets ) ;
if ( msg = = NULL )
return srtp_err_status_alloc_fail ;
msg - > seq = htons ( 3 ) ;
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_err_status_t srtp_test_setup_protect_trailer_streams (
srtp_t * srtp_send ,
srtp_t * srtp_send_mki ,
srtp_t * srtp_send_aes_gcm ,
srtp_t * srtp_send_aes_gcm_mki )
{
srtp_err_status_t status ;
srtp_policy_t policy ;
srtp_policy_t policy_mki ;
# ifdef GCM
srtp_policy_t policy_aes_gcm ;
srtp_policy_t policy_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 . deprecated_ekt = NULL ;
policy . window_size = 128 ;
policy . allow_repeat_tx = 0 ;
policy . next = NULL ;
policy . ssrc . type = ssrc_any_outbound ;
policy . key = test_key ;
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 . deprecated_ekt = NULL ;
policy_mki . window_size = 128 ;
policy_mki . allow_repeat_tx = 0 ;
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 ;
# 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 . deprecated_ekt = NULL ;
policy_aes_gcm . window_size = 128 ;
policy_aes_gcm . allow_repeat_tx = 0 ;
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 . deprecated_ekt = NULL ;
policy_aes_gcm_mki . window_size = 128 ;
policy_aes_gcm_mki . allow_repeat_tx = 0 ;
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 ;
# endif / / GCM
/ * create a send ctx with defualt profile and test_key * /
status = srtp_create ( srtp_send , & policy ) ;
if ( status )
return status ;
status = srtp_create ( srtp_send_mki , & policy_mki ) ;
if ( status )
return status ;
# ifdef 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 ) ;
if ( status )
return status ;
# endif / / GCM
return srtp_err_status_ok ;
}
srtp_err_status_t srtp_test_protect_trailer_length ( )
{
srtp_t srtp_send ;
srtp_t srtp_send_mki ;
srtp_t srtp_send_aes_gcm ;
srtp_t srtp_send_aes_gcm_mki ;
uint32_t length = 0 ;
srtp_err_status_t status ;
srtp_test_setup_protect_trailer_streams (
& srtp_send , & srtp_send_mki , & srtp_send_aes_gcm , & srtp_send_aes_gcm_mki ) ;
status = srtp_get_protect_trailer_length ( srtp_send , 0 , 0 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 10 bytes * /
if ( length ! = 10 )
return srtp_err_status_fail ;
status = srtp_get_protect_trailer_length ( srtp_send_mki , 1 , 1 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 10 bytes + MKI length : 4 bytes * /
if ( length ! = 14 )
return srtp_err_status_fail ;
# ifdef GCM
status = srtp_get_protect_trailer_length ( srtp_send_aes_gcm , 0 , 0 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 16 bytes * /
if ( length ! = 16 )
return srtp_err_status_fail ;
status =
srtp_get_protect_trailer_length ( srtp_send_aes_gcm_mki , 1 , 1 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 16 bytes + MKI length : 4 bytes * /
if ( length ! = 20 )
return srtp_err_status_fail ;
# endif / / GCM
srtp_dealloc ( srtp_send ) ;
srtp_dealloc ( srtp_send_mki ) ;
# ifdef GCM
srtp_dealloc ( srtp_send_aes_gcm ) ;
srtp_dealloc ( srtp_send_aes_gcm_mki ) ;
# endif
return srtp_err_status_ok ;
}
srtp_err_status_t srtp_test_protect_rtcp_trailer_length ( )
{
srtp_t srtp_send ;
srtp_t srtp_send_mki ;
srtp_t srtp_send_aes_gcm ;
srtp_t srtp_send_aes_gcm_mki ;
uint32_t length = 0 ;
srtp_err_status_t status ;
srtp_test_setup_protect_trailer_streams (
& srtp_send , & srtp_send_mki , & srtp_send_aes_gcm , & srtp_send_aes_gcm_mki ) ;
status = srtp_get_protect_rtcp_trailer_length ( srtp_send , 0 , 0 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 10 bytes + SRTCP Trailer 4 bytes * /
if ( length ! = 14 )
return srtp_err_status_fail ;
status = srtp_get_protect_rtcp_trailer_length ( srtp_send_mki , 1 , 1 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 10 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes * /
if ( length ! = 18 )
return srtp_err_status_fail ;
# ifdef GCM
status =
srtp_get_protect_rtcp_trailer_length ( srtp_send_aes_gcm , 0 , 0 , & length ) ;
if ( status )
return status ;
/ * TAG Length : 16 bytes + SRTCP Trailer 4 bytes * /
if ( length ! = 20 )
return srtp_err_status_fail ;
status = srtp_get_protect_rtcp_trailer_length ( srtp_send_aes_gcm_mki , 1 , 1 ,
& length ) ;
if ( status )
return status ;
/ * TAG Length : 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes * /
if ( length ! = 24 )
return srtp_err_status_fail ;
# endif / / GCM
srtp_dealloc ( srtp_send ) ;
srtp_dealloc ( srtp_send_mki ) ;
# ifdef GCM
srtp_dealloc ( srtp_send_aes_gcm ) ;
srtp_dealloc ( srtp_send_aes_gcm_mki ) ;
# endif
return srtp_err_status_ok ;
}
srtp_err_status_t srtp_test_get_roc ( )
{
srtp_err_status_t status ;
srtp_policy_t policy ;
srtp_t session ;
srtp_hdr_t * pkt ;
uint32_t i ;
uint32_t roc ;
uint32_t ts ;
uint16_t seq ;
int msg_len_octets = 32 ;
int 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 = 0 xcafebabe ;
policy . key = test_key ;
policy . window_size = 128 ;
/ * Create a sender session * /
status = srtp_create ( & session , & policy ) ;
if ( status ) {
return status ;
}
/ * Set start sequence so we roll over * /
seq = 65535 ;
ts = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
pkt = srtp_create_test_packet_extended ( msg_len_octets ,
policy . ssrc . value , seq , ts ,
& protected_msg_len_octets ) ;
status = srtp_protect ( session , pkt , & protected_msg_len_octets ) ;
free ( pkt ) ;
if ( status ) {
return status ;
}
status = srtp_get_stream_roc ( session , policy . ssrc . value , & roc ) ;
if ( status ) {
return status ;
}
if ( roc ! = i ) {
return srtp_err_status_fail ;
}
seq + + ;
ts + + ;
}
/ * Cleanup * /
status = srtp_dealloc ( session ) ;
if ( status ) {
return status ;
}
return srtp_err_status_ok ;
}
static srtp_err_status_t test_set_receiver_roc ( uint32_t packets ,
uint32_t roc_to_set )
{
srtp_err_status_t status ;
srtp_policy_t sender_policy ;
srtp_t sender_session ;
srtp_policy_t receiver_policy ;
srtp_t receiver_session ;
srtp_hdr_t * pkt_1 ;
unsigned char * recv_pkt_1 ;
srtp_hdr_t * pkt_2 ;
unsigned char * recv_pkt_2 ;
uint32_t i ;
uint32_t ts ;
uint16_t seq ;
int msg_len_octets = 32 ;
int protected_msg_len_octets_1 ;
int protected_msg_len_octets_2 ;
/ * Create sender * /
memset ( & sender_policy , 0 , sizeof ( sender_policy ) ) ;
srtp_crypto_policy_set_rtp_default ( & sender_policy . rtp ) ;
srtp_crypto_policy_set_rtcp_default ( & sender_policy . rtcp ) ;
sender_policy . ssrc . type = ssrc_specific ;
sender_policy . ssrc . value = 0 xcafebabe ;
sender_policy . key = test_key ;
sender_policy . window_size = 128 ;
status = srtp_create ( & sender_session , & sender_policy ) ;
if ( status ) {
return status ;
}
/ * Create and protect packets * /
seq = 0 ;
ts = 0 ;
for ( i = 0 ; i < packets ; i + + ) {
srtp_hdr_t * tmp_pkt ;
int tmp_len ;
tmp_pkt = srtp_create_test_packet_extended (
msg_len_octets , sender_policy . ssrc . value , seq , ts , & tmp_len ) ;
status = srtp_protect ( sender_session , tmp_pkt , & tmp_len ) ;
free ( tmp_pkt ) ;
if ( status ) {
return status ;
}
seq + + ;
ts + + ;
}
/ * Create the first packet to decrypt and test for ROC change * /
pkt_1 = srtp_create_test_packet_extended ( msg_len_octets ,
sender_policy . ssrc . value , seq , ts ,
& protected_msg_len_octets_1 ) ;
status = srtp_protect ( sender_session , pkt_1 , & protected_msg_len_octets_1 ) ;
if ( status ) {
return status ;
}
/ * Create the second packet to decrypt and test for ROC change * /
seq + + ;
ts + + ;
pkt_2 = srtp_create_test_packet_extended ( msg_len_octets ,
sender_policy . ssrc . value , seq , ts ,
& protected_msg_len_octets_2 ) ;
status = srtp_protect ( sender_session , pkt_2 , & protected_msg_len_octets_2 ) ;
if ( status ) {
return status ;
}
/ * Create the receiver * /
memset ( & receiver_policy , 0 , sizeof ( receiver_policy ) ) ;
srtp_crypto_policy_set_rtp_default ( & receiver_policy . rtp ) ;
srtp_crypto_policy_set_rtcp_default ( & receiver_policy . rtcp ) ;
receiver_policy . ssrc . type = ssrc_specific ;
receiver_policy . ssrc . value = sender_policy . ssrc . value ;
receiver_policy . key = test_key ;
receiver_policy . window_size = 128 ;
status = srtp_create ( & receiver_session , & receiver_policy ) ;
if ( status ) {
return status ;
}
/ * Make a copy of the first sent protected packet * /
recv_pkt_1 = malloc ( protected_msg_len_octets_1 ) ;
if ( recv_pkt_1 = = NULL ) {
return srtp_err_status_fail ;
}
memcpy ( recv_pkt_1 , pkt_1 , protected_msg_len_octets_1 ) ;
/ * Make a copy of the second sent protected packet * /
recv_pkt_2 = malloc ( protected_msg_len_octets_2 ) ;
if ( recv_pkt_2 = = NULL ) {
return srtp_err_status_fail ;
}
memcpy ( recv_pkt_2 , pkt_2 , protected_msg_len_octets_2 ) ;
/ * Set the ROC to the wanted value * /
status = srtp_set_stream_roc ( receiver_session , receiver_policy . ssrc . value ,
roc_to_set ) ;
if ( status ) {
return status ;
}
/ * Unprotect the first packet * /
status = srtp_unprotect ( receiver_session , recv_pkt_1 ,
& protected_msg_len_octets_1 ) ;
if ( status ) {
return status ;
}
/ * Unprotect the second packet * /
status = srtp_unprotect ( receiver_session , recv_pkt_2 ,
& protected_msg_len_octets_2 ) ;
if ( status ) {
return status ;
}
/ * Cleanup * /
status = srtp_dealloc ( sender_session ) ;
if ( status ) {
return status ;
}
status = srtp_dealloc ( receiver_session ) ;
if ( status ) {
return status ;
}
free ( pkt_1 ) ;
free ( recv_pkt_1 ) ;
free ( pkt_2 ) ;
free ( recv_pkt_2 ) ;
return srtp_err_status_ok ;
}
static srtp_err_status_t test_set_sender_roc ( uint16_t seq , uint32_t roc_to_set )
{
srtp_err_status_t status ;
srtp_policy_t sender_policy ;
srtp_t sender_session ;
srtp_policy_t receiver_policy ;
srtp_t receiver_session ;
srtp_hdr_t * pkt ;
unsigned char * recv_pkt ;
uint32_t ts ;
int msg_len_octets = 32 ;
int protected_msg_len_octets ;
/ * Create sender * /
memset ( & sender_policy , 0 , sizeof ( sender_policy ) ) ;
srtp_crypto_policy_set_rtp_default ( & sender_policy . rtp ) ;
srtp_crypto_policy_set_rtcp_default ( & sender_policy . rtcp ) ;
sender_policy . ssrc . type = ssrc_specific ;
sender_policy . ssrc . value = 0 xcafebabe ;
sender_policy . key = test_key ;
sender_policy . window_size = 128 ;
status = srtp_create ( & sender_session , & sender_policy ) ;
if ( status ) {
return status ;
}
/ * Set the ROC before encrypting the first packet * /
status = srtp_set_stream_roc ( sender_session , sender_policy . ssrc . value ,
roc_to_set ) ;
if ( status ! = srtp_err_status_ok ) {
return status ;
}
/ * Create the packet to decrypt * /
ts = 0 ;
pkt = srtp_create_test_packet_extended ( msg_len_octets ,
sender_policy . ssrc . value , seq , ts ,
& protected_msg_len_octets ) ;
status = srtp_protect ( sender_session , pkt , & protected_msg_len_octets ) ;
if ( status ) {
return status ;
}
/ * Create the receiver * /
memset ( & receiver_policy , 0 , sizeof ( receiver_policy ) ) ;
srtp_crypto_policy_set_rtp_default ( & receiver_policy . rtp ) ;
srtp_crypto_policy_set_rtcp_default ( & receiver_policy . rtcp ) ;
receiver_policy . ssrc . type = ssrc_specific ;
receiver_policy . ssrc . value = sender_policy . ssrc . value ;
receiver_policy . key = test_key ;
receiver_policy . window_size = 128 ;
status = srtp_create ( & receiver_session , & receiver_policy ) ;
if ( status ) {
return status ;
}
/ * Make a copy of the sent protected packet * /
recv_pkt = malloc ( protected_msg_len_octets ) ;
if ( recv_pkt = = NULL ) {
return srtp_err_status_fail ;
}
memcpy ( recv_pkt , pkt , protected_msg_len_octets ) ;
/ * Set the ROC to the wanted value * /
status = srtp_set_stream_roc ( receiver_session , receiver_policy . ssrc . value ,
roc_to_set ) ;
if ( status ) {
return status ;
}
status =
srtp_unprotect ( receiver_session , recv_pkt , & protected_msg_len_octets ) ;
if ( status ) {
return status ;
}
/ * Cleanup * /
status = srtp_dealloc ( sender_session ) ;
if ( status ) {
return status ;
}
status = srtp_dealloc ( receiver_session ) ;
if ( status ) {
return status ;
}
free ( pkt ) ;
free ( recv_pkt ) ;
return srtp_err_status_ok ;
}
srtp_err_status_t srtp_test_set_receiver_roc ( )
{
int packets ;
uint32_t roc ;
srtp_err_status_t status ;
/ * First test does not rollover * /
packets = 1 ;
roc = 0 ;
status = test_set_receiver_roc ( packets - 1 , roc ) ;
if ( status ) {
return status ;
}
status = test_set_receiver_roc ( packets , roc ) ;
if ( status ) {
return status ;
}
status = test_set_receiver_roc ( packets + 1 , roc ) ;
if ( status ) {
return status ;
}
status = test_set_receiver_roc ( packets + 60000 , roc ) ;
if ( status ) {
return status ;
}
/ * Second test should rollover * /
packets = 65535 ;
roc = 0 ;
status = test_set_receiver_roc ( packets - 1 , roc ) ;
if ( status ) {
return status ;
}
status = test_set_receiver_roc ( packets , roc ) ;
if ( status ) {
return status ;
}
/ * Now the rollover counter should be 1 * /
roc = 1 ;
status = test_set_receiver_roc ( packets + 1 , roc ) ;
if ( status ) {
return status ;
}
status = test_set_receiver_roc ( packets + 60000 , roc ) ;
if ( status ) {
return status ;
}
return srtp_err_status_ok ;
}
srtp_err_status_t srtp_test_set_sender_roc ( )
{
uint32_t roc ;
uint16_t seq ;
srtp_err_status_t status ;
seq = 43210 ;
roc = 0 ;
status = test_set_sender_roc ( seq , roc ) ;
if ( status ) {
return status ;
}
roc = 65535 ;
status = test_set_sender_roc ( seq , roc ) ;
if ( status ) {
return status ;
}
roc = 0 xffff ;
status = test_set_sender_roc ( seq , roc ) ;
if ( status ) {
return status ;
}
roc = 0 xffff00 ;
status = test_set_sender_roc ( seq , roc ) ;
if ( status ) {
return status ;
}
roc = 0 xfffffff0 ;
status = test_set_sender_roc ( seq , roc ) ;
if ( status ) {
return status ;
}
return srtp_err_status_ok ;
}
/ *
* srtp policy definitions - these definitions are used above
* /
/ / clang - format off
unsigned char test_key [ 46 ] = {
0 xe1 , 0 xf9 , 0 x7a , 0 x0d , 0 x3e , 0 x01 , 0 x8b , 0 xe0 ,
0 xd6 , 0 x4f , 0 xa3 , 0 x2c , 0 x06 , 0 xde , 0 x41 , 0 x39 ,
0 x0e , 0 xc6 , 0 x75 , 0 xad , 0 x49 , 0 x8a , 0 xfe , 0 xeb ,
0 xb6 , 0 x96 , 0 x0b , 0 x3a , 0 xab , 0 xe6 , 0 xc1 , 0 x73 ,
0 xc3 , 0 x17 , 0 xf2 , 0 xda , 0 xbe , 0 x35 , 0 x77 , 0 x93 ,
0 xb6 , 0 x96 , 0 x0b , 0 x3a , 0 xab , 0 xe6
} ;
unsigned char test_key_2 [ 46 ] = {
0 xf0 , 0 xf0 , 0 x49 , 0 x14 , 0 xb5 , 0 x13 , 0 xf2 , 0 x76 ,
0 x3a , 0 x1b , 0 x1f , 0 xa1 , 0 x30 , 0 xf1 , 0 x0e , 0 x29 ,
0 x98 , 0 xf6 , 0 xf6 , 0 xe4 , 0 x3e , 0 x43 , 0 x09 , 0 xd1 ,
0 xe6 , 0 x22 , 0 xa0 , 0 xe3 , 0 x32 , 0 xb9 , 0 xf1 , 0 xb6 ,
0 xc3 , 0 x17 , 0 xf2 , 0 xda , 0 xbe , 0 x35 , 0 x77 , 0 x93 ,
0 xb6 , 0 x96 , 0 x0b , 0 x3a , 0 xab , 0 xe6
} ;
unsigned char test_mki_id [ TEST_MKI_ID_SIZE ] = {
0 xe1 , 0 xf9 , 0 x7a , 0 x0d
} ;
unsigned char test_mki_id_2 [ TEST_MKI_ID_SIZE ] = {
0 xf3 , 0 xa1 , 0 x46 , 0 x71
} ;
/ / clang - format on
const srtp_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 * /
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_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 * /
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 * /
} ,
NULL ,
( srtp_master_key_t * * ) test_keys ,
2 , / * Number of Master keys associated with the policy * /
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 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 * /
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_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 * /
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_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 * /
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_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 * /
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 * /
} ,
NULL ,
( srtp_master_key_t * * ) test_keys ,
2 , / * indicates the number of Master keys * /
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
} ;
/ / clang - format off
unsigned char test_256_key [ 46 ] = {
0 xf0 , 0 xf0 , 0 x49 , 0 x14 , 0 xb5 , 0 x13 , 0 xf2 , 0 x76 ,
0 x3a , 0 x1b , 0 x1f , 0 xa1 , 0 x30 , 0 xf1 , 0 x0e , 0 x29 ,
0 x98 , 0 xf6 , 0 xf6 , 0 xe4 , 0 x3e , 0 x43 , 0 x09 , 0 xd1 ,
0 xe6 , 0 x22 , 0 xa0 , 0 xe3 , 0 x32 , 0 xb9 , 0 xf1 , 0 xb6 ,
0 x3b , 0 x04 , 0 x80 , 0 x3d , 0 xe5 , 0 x1e , 0 xe7 , 0 xc9 ,
0 x64 , 0 x23 , 0 xab , 0 x5b , 0 x78 , 0 xd2
} ;
unsigned char test_256_key_2 [ 46 ] = {
0 xe1 , 0 xf9 , 0 x7a , 0 x0d , 0 x3e , 0 x01 , 0 x8b , 0 xe0 ,
0 xd6 , 0 x4f , 0 xa3 , 0 x2c , 0 x06 , 0 xde , 0 x41 , 0 x39 ,
0 x0e , 0 xc6 , 0 x75 , 0 xad , 0 x49 , 0 x8a , 0 xfe , 0 xeb ,
0 xb6 , 0 x96 , 0 x0b , 0 x3a , 0 xab , 0 xe6 , 0 xc1 , 0 x73 ,
0 x3b , 0 x04 , 0 x80 , 0 x3d , 0 xe5 , 0 x1e , 0 xe7 , 0 xc9 ,
0 x64 , 0 x23 , 0 xab , 0 x5b , 0 x78 , 0 xd2
} ;
srtp_master_key_t master_256_key_1 = {
test_256_key ,
test_mki_id ,
TEST_MKI_ID_SIZE
} ;
srtp_master_key_t master_256_key_2 = {
test_256_key_2 ,
test_mki_id_2 ,
TEST_MKI_ID_SIZE
} ;
srtp_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 * /
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
} ;
char ekt_test_policy = ' x ' ;
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 * /
} ,
NULL ,
( srtp_master_key_t * * ) test_keys ,
2 , / * indicates the number of Master keys * /
& ekt_test_policy , / * requests deprecated EKT functionality * /
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 .
* /
/ / clang - format off
const srtp_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 ,
# endif
& null_policy ,
& aes_256_hmac_policy ,
NULL
} ;
/ / clang - format on
/ / clang - format off
const srtp_policy_t * invalid_policy_array [ ] = {
& hmac_only_with_ekt_policy ,
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 ,
0 ,
NULL ,
128 , / * replay window size * /
0 , / * retransmission not allowed * /
NULL , / * no encrypted extension headers * /
0 , / * list of encrypted extension headers is empty * /
NULL
} ;
Messung V0.5 in Prozent C=96 H=94 G=94
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.187Bemerkung:
¤
*Bot Zugriff