diff options
Diffstat (limited to 'third_party/srtp/test')
-rw-r--r-- | third_party/srtp/test/dtls_srtp_driver.c | 22 | ||||
-rw-r--r-- | third_party/srtp/test/lfsr.c | 35 | ||||
-rw-r--r-- | third_party/srtp/test/rdbx_driver.c | 106 | ||||
-rw-r--r-- | third_party/srtp/test/replay_driver.c | 58 | ||||
-rw-r--r-- | third_party/srtp/test/roc_driver.c | 10 | ||||
-rw-r--r-- | third_party/srtp/test/rtp.c | 76 | ||||
-rw-r--r-- | third_party/srtp/test/rtp_decoder.c | 515 | ||||
-rw-r--r-- | third_party/srtp/test/rtp_decoder.h | 119 | ||||
-rw-r--r-- | third_party/srtp/test/rtpw.c | 243 | ||||
-rw-r--r-- | third_party/srtp/test/rtpw_test.sh | 95 | ||||
-rw-r--r-- | third_party/srtp/test/rtpw_test_gcm.sh | 237 | ||||
-rw-r--r-- | third_party/srtp/test/srtp_driver.c | 479 |
12 files changed, 1907 insertions, 88 deletions
diff --git a/third_party/srtp/test/dtls_srtp_driver.c b/third_party/srtp/test/dtls_srtp_driver.c index a8eddc08..48e72fbf 100644 --- a/third_party/srtp/test/dtls_srtp_driver.c +++ b/third_party/srtp/test/dtls_srtp_driver.c @@ -47,7 +47,7 @@ #include "srtp_priv.h" err_status_t -test_dtls_srtp(); +test_dtls_srtp(void); srtp_hdr_t * srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc); @@ -63,7 +63,7 @@ usage(char *prog_name) { int main(int argc, char *argv[]) { unsigned do_list_mods = 0; - char q; + int q; err_status_t err; printf("dtls_srtp_driver\n"); @@ -112,12 +112,19 @@ main(int argc, char *argv[]) { } printf("passed\n"); + /* shut down srtp library */ + err = srtp_shutdown(); + if (err) { + printf("error: srtp shutdown failed with error code %d\n", err); + exit(1); + } + return 0; } err_status_t -test_dtls_srtp() { +test_dtls_srtp(void) { srtp_hdr_t *test_packet; int test_packet_len = 80; srtp_t s; @@ -183,12 +190,21 @@ test_dtls_srtp() { err = crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile); if (err) return err; policy.ssrc.type = ssrc_any_inbound; + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; policy.next = NULL; err = srtp_add_stream(s, &policy); if (err) return err; + err = srtp_dealloc(s); + if (err) + return err; + + free(test_packet); + return err_status_ok; } diff --git a/third_party/srtp/test/lfsr.c b/third_party/srtp/test/lfsr.c index 28ea02eb..240590c5 100644 --- a/third_party/srtp/test/lfsr.c +++ b/third_party/srtp/test/lfsr.c @@ -3,6 +3,41 @@ * */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ #include <stdio.h> #include "datatypes.h" diff --git a/third_party/srtp/test/rdbx_driver.c b/third_party/srtp/test/rdbx_driver.c index 7db67a2b..90bd72e7 100644 --- a/third_party/srtp/test/rdbx_driver.c +++ b/third_party/srtp/test/rdbx_driver.c @@ -43,6 +43,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* for printf() */ #include "getopt_s.h" /* for local getopt() */ @@ -55,10 +59,10 @@ #include "ut_sim.h" err_status_t -test_replay_dbx(int num_trials); +test_replay_dbx(int num_trials, unsigned long ws); double -rdbx_check_adds_per_second(int num_trials); +rdbx_check_adds_per_second(int num_trials, unsigned long ws); void usage(char *prog_name) { @@ -70,7 +74,7 @@ int main (int argc, char *argv[]) { double rate; err_status_t status; - char q; + int q; unsigned do_timing_test = 0; unsigned do_validation = 0; @@ -99,9 +103,18 @@ main (int argc, char *argv[]) { usage(argv[0]); if (do_validation) { - printf("testing rdbx_t...\n"); + printf("testing rdbx_t (ws=128)...\n"); + + status = test_replay_dbx(1 << 12, 128); + if (status) { + printf("failed\n"); + exit(1); + } + printf("passed\n"); - status = test_replay_dbx(1 << 12); + printf("testing rdbx_t (ws=1024)...\n"); + + status = test_replay_dbx(1 << 12, 1024); if (status) { printf("failed\n"); exit(1); @@ -110,8 +123,10 @@ main (int argc, char *argv[]) { } if (do_timing_test) { - rate = rdbx_check_adds_per_second(1 << 18); - printf("rdbx_check/replay_adds per second: %e\n", rate); + rate = rdbx_check_adds_per_second(1 << 18, 128); + printf("rdbx_check/replay_adds per second (ws=128): %e\n", rate); + rate = rdbx_check_adds_per_second(1 << 18, 1024); + printf("rdbx_check/replay_adds per second (ws=1024): %e\n", rate); } return 0; @@ -119,8 +134,11 @@ main (int argc, char *argv[]) { void print_rdbx(rdbx_t *rdbx) { + char buf[2048]; printf("rdbx: {%llu, %s}\n", - (unsigned long long)(rdbx->index), v128_bit_string(&rdbx->bitmask)); + (unsigned long long)(rdbx->index), + bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf)) +); } @@ -183,28 +201,38 @@ rdbx_check_expect_failure(rdbx_t *rdbx, uint32_t idx) { } err_status_t -rdbx_check_unordered(rdbx_t *rdbx, uint32_t idx) { +rdbx_check_add_unordered(rdbx_t *rdbx, uint32_t idx) { + int delta; + xtd_seq_num_t est; err_status_t rstat; - rstat = rdbx_check(rdbx, idx); + delta = index_guess(&rdbx->index, &est, idx); + + rstat = rdbx_check(rdbx, delta); if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) { - printf("replay_check_unordered failed at index %u\n", idx); + printf("replay_check_add_unordered failed at index %u\n", idx); return err_status_algo_fail; } + if (rstat == err_status_replay_old) { + return err_status_ok; + } + if (rdbx_add_index(rdbx, delta) != err_status_ok) { + printf("rdbx_add_index failed at index %u\n", idx); + return err_status_algo_fail; + } + return err_status_ok; } -#define MAX_IDX 160 - err_status_t -test_replay_dbx(int num_trials) { +test_replay_dbx(int num_trials, unsigned long ws) { rdbx_t rdbx; uint32_t idx, ircvd; ut_connection utc; err_status_t status; int num_fp_trials; - status = rdbx_init(&rdbx); + status = rdbx_init(&rdbx, ws); if (status) { printf("replay_init failed with error code %d\n", status); exit(1); @@ -214,7 +242,7 @@ test_replay_dbx(int num_trials) { * test sequential insertion */ printf("\ttesting sequential insertion..."); - for (idx=0; idx < num_trials; idx++) { + for (idx=0; (int) idx < num_trials; idx++) { status = rdbx_check_add(&rdbx, idx); if (status) return status; @@ -233,7 +261,7 @@ test_replay_dbx(int num_trials) { printf("warning: no false positive tests performed\n"); } printf("\ttesting for false positives..."); - for (idx=0; idx < num_fp_trials; idx++) { + for (idx=0; (int) idx < num_fp_trials; idx++) { status = rdbx_check_expect_failure(&rdbx, idx); if (status) return status; @@ -241,7 +269,9 @@ test_replay_dbx(int num_trials) { printf("passed\n"); /* re-initialize */ - if (rdbx_init(&rdbx) != err_status_ok) { + rdbx_dealloc(&rdbx); + + if (rdbx_init(&rdbx, ws) != err_status_ok) { printf("replay_init failed\n"); return err_status_init_fail; } @@ -255,14 +285,42 @@ test_replay_dbx(int num_trials) { ut_init(&utc); printf("\ttesting non-sequential insertion..."); - for (idx=0; idx < num_trials; idx++) { + for (idx=0; (int) idx < num_trials; idx++) { ircvd = ut_next_index(&utc); - status = rdbx_check_unordered(&rdbx, ircvd); + status = rdbx_check_add_unordered(&rdbx, ircvd); if (status) return status; + status = rdbx_check_expect_failure(&rdbx, ircvd); + if (status) + return status; } printf("passed\n"); + /* re-initialize */ + rdbx_dealloc(&rdbx); + + if (rdbx_init(&rdbx, ws) != err_status_ok) { + printf("replay_init failed\n"); + return err_status_init_fail; + } + + /* + * test insertion with large gaps. + * check for false positives for each insertion. + */ + printf("\ttesting insertion with large gaps..."); + for (idx=0, ircvd=0; (int) idx < num_trials; idx++, ircvd += (1 << (rand() % 12))) { + status = rdbx_check_add(&rdbx, ircvd); + if (status) + return status; + status = rdbx_check_expect_failure(&rdbx, ircvd); + if (status) + return status; + } + printf("passed\n"); + + rdbx_dealloc(&rdbx); + return err_status_ok; } @@ -272,7 +330,7 @@ test_replay_dbx(int num_trials) { #include <stdlib.h> /* for random() */ double -rdbx_check_adds_per_second(int num_trials) { +rdbx_check_adds_per_second(int num_trials, unsigned long ws) { uint32_t i; int delta; rdbx_t rdbx; @@ -280,14 +338,14 @@ rdbx_check_adds_per_second(int num_trials) { clock_t timer; int failures; /* count number of failures */ - if (rdbx_init(&rdbx) != err_status_ok) { + if (rdbx_init(&rdbx, ws) != err_status_ok) { printf("replay_init failed\n"); exit(1); } failures = 0; timer = clock(); - for(i=0; i < num_trials; i++) { + for(i=0; (int) i < num_trials; i++) { delta = index_guess(&rdbx.index, &est, i); @@ -301,6 +359,8 @@ rdbx_check_adds_per_second(int num_trials) { printf("number of failures: %d \n", failures); + rdbx_dealloc(&rdbx); + return (double) CLOCKS_PER_SEC * num_trials / timer; } diff --git a/third_party/srtp/test/replay_driver.c b/third_party/srtp/test/replay_driver.c index 369a77a4..e4d17015 100644 --- a/third_party/srtp/test/replay_driver.c +++ b/third_party/srtp/test/replay_driver.c @@ -43,6 +43,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> #include "rdb.h" @@ -114,15 +118,23 @@ rdb_check_expect_failure(rdb_t *rdb, uint32_t idx) { } err_status_t -rdb_check_unordered(rdb_t *rdb, uint32_t idx) { +rdb_check_add_unordered(rdb_t *rdb, uint32_t idx) { err_status_t rstat; /* printf("index: %u\n", idx); */ rstat = rdb_check(rdb, idx); if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) { - printf("rdb_check_unordered failed at index %u\n", idx); + printf("rdb_check_add_unordered failed at index %u\n", idx); return rstat; } + if (rstat == err_status_replay_old) { + return err_status_ok; + } + if (rdb_add_index(rdb, idx) != err_status_ok) { + printf("rdb_add_index failed at index %u\n", idx); + return err_status_fail; + } + return err_status_ok; } @@ -163,11 +175,51 @@ test_rdb_db() { for (idx=0; idx < num_trials; idx++) { ircvd = ut_next_index(&utc); - err = rdb_check_unordered(&rdb, ircvd); + err = rdb_check_add_unordered(&rdb, ircvd); if (err) return err; + err = rdb_check_expect_failure(&rdb, ircvd); + if (err) + return err; + } + + /* re-initialize */ + if (rdb_init(&rdb) != err_status_ok) { + printf("rdb_init failed\n"); + return err_status_fail; + } + + /* test insertion with large gaps */ + for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 10))) { + err = rdb_check_add(&rdb, ircvd); + if (err) + return err; + err = rdb_check_expect_failure(&rdb, ircvd); + if (err) + return err; } + /* re-initialize */ + if (rdb_init(&rdb) != err_status_ok) { + printf("rdb_init failed\n"); + return err_status_fail; + } + + /* test loss of first 513 packets */ + for (idx=0; idx < num_trials; idx++) { + err = rdb_check_add(&rdb, idx + 513); + if (err) + return err; + } + + /* test for false positives */ + for (idx=0; idx < num_trials + 513; idx++) { + err = rdb_check_expect_failure(&rdb, idx); + if (err) + return err; + } + + return err_status_ok; } diff --git a/third_party/srtp/test/roc_driver.c b/third_party/srtp/test/roc_driver.c index 396c9a79..6fdc6f19 100644 --- a/third_party/srtp/test/roc_driver.c +++ b/third_party/srtp/test/roc_driver.c @@ -44,6 +44,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* @@ -138,6 +142,12 @@ roc_test(int num_trials) { ref, local, est, ircvd, delta); #endif + if (local + delta != est) { + printf(" *bad delta*: local %llu + delta %d != est %llu\n", + (unsigned long long)local, delta, (unsigned long long)est); + return err_status_algo_fail; + } + /* now update local xtd_seq_num_t as necessary */ if (delta > 0) index_advance(&local, delta); diff --git a/third_party/srtp/test/rtp.c b/third_party/srtp/test/rtp.c index 69968f3f..20c50f46 100644 --- a/third_party/srtp/test/rtp.c +++ b/third_party/srtp/test/rtp.c @@ -7,6 +7,41 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ #include "rtp_priv.h" @@ -21,7 +56,7 @@ #define PRINT_DEBUG 0 /* set to 1 to print out debugging data */ #define VERBOSE_DEBUG 0 /* set to 1 to print out more data */ -unsigned int +int rtp_sendto(rtp_sender_t sender, const void* msg, int len) { int octets_sent; err_status_t stat; @@ -61,7 +96,7 @@ rtp_sendto(rtp_sender_t sender, const void* msg, int len) { return octets_sent; } -unsigned int +int rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) { int octets_recvd; err_status_t stat; @@ -69,6 +104,11 @@ rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) { octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message, *len, 0, (struct sockaddr *) NULL, 0); + if (octets_recvd == -1) { + *len = 0; + return -1; + } + /* verify rtp header */ if (receiver->message.header.version != 2) { *len = 0; @@ -100,7 +140,7 @@ rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) { int rtp_sender_init(rtp_sender_t sender, - int socket, + int sock, struct sockaddr_in addr, unsigned int ssrc) { @@ -116,7 +156,7 @@ rtp_sender_init(rtp_sender_t sender, sender->message.header.cc = 0; /* set other stuff */ - sender->socket = socket; + sender->socket = sock; sender->addr = addr; return 0; @@ -124,7 +164,7 @@ rtp_sender_init(rtp_sender_t sender, int rtp_receiver_init(rtp_receiver_t rcvr, - int socket, + int sock, struct sockaddr_in addr, unsigned int ssrc) { @@ -140,7 +180,7 @@ rtp_receiver_init(rtp_receiver_t rcvr, rcvr->message.header.cc = 0; /* set other stuff */ - rcvr->socket = socket; + rcvr->socket = sock; rcvr->addr = addr; return 0; @@ -152,16 +192,36 @@ rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy) { } int +rtp_sender_deinit_srtp(rtp_sender_t sender) { + return srtp_dealloc(sender->srtp_ctx); +} + +int rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy) { return srtp_create(&sender->srtp_ctx, policy); } +int +rtp_receiver_deinit_srtp(rtp_receiver_t sender) { + return srtp_dealloc(sender->srtp_ctx); +} + rtp_sender_t -rtp_sender_alloc() { +rtp_sender_alloc(void) { return (rtp_sender_t)malloc(sizeof(rtp_sender_ctx_t)); } +void +rtp_sender_dealloc(rtp_sender_t rtp_ctx) { + free(rtp_ctx); +} + rtp_receiver_t -rtp_receiver_alloc() { +rtp_receiver_alloc(void) { return (rtp_receiver_t)malloc(sizeof(rtp_receiver_ctx_t)); } + +void +rtp_receiver_dealloc(rtp_receiver_t rtp_ctx) { + free(rtp_ctx); +} diff --git a/third_party/srtp/test/rtp_decoder.c b/third_party/srtp/test/rtp_decoder.c new file mode 100644 index 00000000..57e2d331 --- /dev/null +++ b/third_party/srtp/test/rtp_decoder.c @@ -0,0 +1,515 @@ +/* + * rtp_decoder.c + * + * decoder structures and functions for SRTP pcap decoder + * + * Example: + * $ wget --no-check-certificate https://raw.githubusercontent.com/gteissier/srtp-decrypt/master/marseillaise-srtp.pcap + * $ ./test/rtp_decoder -a -t 0 -e 128 -b aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz \ + * < ~/marseillaise-srtp.pcap | text2pcap -t "%M:%S." -u 10000,10000 - - > ./marseillaise-rtp.pcap + * + * Bernardo Torres <bernardo@torresautomacao.com.br> + * + * Some structure and code from https://github.com/gteissier/srtp-decrypt + */ +/* + * + * Copyright (c) 2001-2006 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "getopt_s.h" /* for local getopt() */ +#include <assert.h> /* for assert() */ + +#include <pcap.h> +#include "rtp_decoder.h" + +#define MAX_KEY_LEN 96 +#define MAX_FILTER 256 + +int +main (int argc, char *argv[]) { + char errbuf[PCAP_ERRBUF_SIZE]; + bpf_u_int32 pcap_net = 0; + pcap_t *pcap_handle; +#if BEW + struct sockaddr_in local; +#endif + sec_serv_t sec_servs = sec_serv_none; + int c; + int key_size = 128; + int tag_size = 8; + int gcm_on = 0; + char *input_key = NULL; + int b64_input = 0; + char key[MAX_KEY_LEN]; + struct bpf_program fp; + char filter_exp[MAX_FILTER] = ""; + rtp_decoder_t dec; + srtp_policy_t policy; + err_status_t status; + int len; + int expected_len; + int do_list_mods = 0; + + fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); + + /* initialize srtp library */ + status = srtp_init(); + if (status) { + fprintf(stderr, "error: srtp initialization failed with error code %d\n", status); + exit(1); + } + + /* check args */ + while (1) { + c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:"); + if (c == -1) { + break; + } + switch (c) { + case 'b': + b64_input = 1; + /* fall thru */ + case 'k': + input_key = optarg_s; + break; + case 'e': + key_size = atoi(optarg_s); + if (key_size != 128 && key_size != 256) { + fprintf(stderr, "error: encryption key size must be 128 or 256 (%d)\n", key_size); + exit(1); + } + input_key = malloc(key_size); + sec_servs |= sec_serv_conf; + break; + case 't': + tag_size = atoi(optarg_s); + if (tag_size != 8 && tag_size != 16) { + fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", tag_size); + //exit(1); + } + break; + case 'a': + sec_servs |= sec_serv_auth; + break; + case 'g': + gcm_on = 1; + sec_servs |= sec_serv_auth; + break; + case 'd': + status = crypto_kernel_set_debug_module(optarg_s, 1); + if (status) { + fprintf(stderr, "error: set debug module (%s) failed\n", optarg_s); + exit(1); + } + break; + case 'f': + if(strlen(optarg_s) > MAX_FILTER){ + fprintf(stderr, "error: filter bigger than %d characters\n", MAX_FILTER); + exit(1); + } + fprintf(stderr, "Setting filter as %s\n", optarg_s); + strcpy(filter_exp, optarg_s); + break; + case 'l': + do_list_mods = 1; + break; + default: + usage(argv[0]); + } + } + + if (do_list_mods) { + status = crypto_kernel_list_debug_modules(); + if (status) { + fprintf(stderr, "error: list of debug modules failed\n"); + exit(1); + } + return 0; + } + + if ((sec_servs && !input_key) || (!sec_servs && input_key)) { + /* + * a key must be provided if and only if security services have + * been requested + */ + if(input_key == NULL){ + fprintf(stderr, "key not provided\n"); + } + if(!sec_servs){ + fprintf(stderr, "no secservs\n"); + } + fprintf(stderr, "provided\n"); + usage(argv[0]); + } + + + + /* report security services selected on the command line */ + fprintf(stderr, "security services: "); + if (sec_servs & sec_serv_conf) + fprintf(stderr, "confidentiality "); + if (sec_servs & sec_serv_auth) + fprintf(stderr, "message authentication"); + if (sec_servs == sec_serv_none) + fprintf(stderr, "none"); + fprintf(stderr, "\n"); + + /* set up the srtp policy and master key */ + if (sec_servs) { + /* + * create policy structure, using the default mechanisms but + * with only the security services requested on the command line, + * using the right SSRC value + */ + switch (sec_servs) { + case sec_serv_conf_and_auth: + if (gcm_on) { +#ifdef OPENSSL + switch (key_size) { + case 128: + crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); + crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); + crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); + break; + } +#else + fprintf(stderr, "error: GCM mode only supported when using the OpenSSL crypto engine.\n"); + return 0; +#endif + } else { + switch (key_size) { + case 128: + crypto_policy_set_rtp_default(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + } + } + break; + case sec_serv_conf: + if (gcm_on) { + fprintf(stderr, "error: GCM mode must always be used with auth enabled\n"); + return -1; + } else { + switch (key_size) { + case 128: + crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + } + } + break; + case sec_serv_auth: + if (gcm_on) { +#ifdef OPENSSL + switch (key_size) { + case 128: + crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); + crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); + crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp); + break; + } +#else + printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n"); + return 0; +#endif + } else { + crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + } + break; + default: + fprintf(stderr, "error: unknown security service requested\n"); + return -1; + } + + policy.key = (uint8_t *) key; + policy.ekt = NULL; + policy.next = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.rtp.sec_serv = sec_servs; + policy.rtcp.sec_serv = sec_servs; //sec_serv_none; /* we don't do RTCP anyway */ + fprintf(stderr, "setting tag len %d\n", tag_size); +policy.rtp.auth_tag_len = tag_size; + + if (gcm_on && tag_size != 8) { + fprintf(stderr, "setted tag len %d\n", tag_size); + policy.rtp.auth_tag_len = tag_size; + } + + /* + * read key from hexadecimal or base64 on command line into an octet string + */ + if (b64_input) { + int pad; + expected_len = policy.rtp.cipher_key_len*4/3; + len = base64_string_to_octet_string(key, &pad, input_key, expected_len); + if (pad != 0) { + fprintf(stderr, "error: padding in base64 unexpected\n"); + exit(1); + } + } else { + expected_len = policy.rtp.cipher_key_len*2; + len = hex_string_to_octet_string(key, input_key, expected_len); + } + /* check that hex string is the right length */ + if (len < expected_len) { + fprintf(stderr, + "error: too few digits in key/salt " + "(should be %d digits, found %d)\n", + expected_len, len); + exit(1); + } + if (strlen(input_key) > policy.rtp.cipher_key_len*2) { + fprintf(stderr, + "error: too many digits in key/salt " + "(should be %d hexadecimal digits, found %u)\n", + policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key)); + exit(1); + } + + fprintf(stderr, "set master key/salt to %s/", octet_string_hex_string(key, 16)); + fprintf(stderr, "%s\n", octet_string_hex_string(key+16, 14)); + + } else { + /* + * we're not providing security services, so set the policy to the + * null policy + * + * Note that this policy does not conform to the SRTP + * specification, since RTCP authentication is required. However, + * the effect of this policy is to turn off SRTP, so that this + * application is now a vanilla-flavored RTP application. + */ + policy.key = (uint8_t *)key; + policy.ssrc.type = ssrc_specific; + policy.rtp.cipher_type = NULL_CIPHER; + policy.rtp.cipher_key_len = 0; + policy.rtp.auth_type = NULL_AUTH; + policy.rtp.auth_key_len = 0; + policy.rtp.auth_tag_len = 0; + policy.rtp.sec_serv = sec_serv_none; + policy.rtcp.cipher_type = NULL_CIPHER; + policy.rtcp.cipher_key_len = 0; + policy.rtcp.auth_type = NULL_AUTH; + policy.rtcp.auth_key_len = 0; + policy.rtcp.auth_tag_len = 0; + policy.rtcp.sec_serv = sec_serv_none; + policy.window_size = 0; + policy.allow_repeat_tx = 0; + policy.ekt = NULL; + policy.next = NULL; + } + + pcap_handle = pcap_open_offline("-", errbuf); + + if (!pcap_handle) { + fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); + exit(1); + } + assert(pcap_handle != NULL); + if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1){ + fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, + pcap_geterr(pcap_handle)); + return (2); + } + if (pcap_setfilter(pcap_handle, &fp) == -1){ + fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp, + pcap_geterr(pcap_handle)); + return (2); + } + dec = rtp_decoder_alloc(); + if (dec == NULL) { + fprintf(stderr, "error: malloc() failed\n"); + exit(1); + } + fprintf(stderr, "Starting decoder\n"); + rtp_decoder_init(dec, policy); + + pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); + + rtp_decoder_deinit_srtp(dec); + rtp_decoder_dealloc(dec); + + status = srtp_shutdown(); + if (status) { + fprintf(stderr, "error: srtp shutdown failed with error code %d\n", status); + exit(1); + } + + return 0; +} + + +void +usage(char *string) { + + fprintf(stderr, "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\n" + "or %s -l\n" + "where -a use message authentication\n" + " -e <key size> use encryption (use 128 or 256 for key size)\n" + " -g Use AES-GCM mode (must be used with -e)\n" + " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n" + " -k <key> sets the srtp master key given in hexadecimal\n" + " -b <key> sets the srtp master key given in base64\n" + " -l list debug modules\n" + " -f \"<pcap filter>\" to filter only the desired SRTP packets\n" + " -d <debug> turn on debugging for module <debug>\n", + string, string); + exit(1); + +} + +rtp_decoder_t +rtp_decoder_alloc(void) { + return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t)); +} + +void +rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) { + free(rtp_ctx); +} + +err_status_t +rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc) { + decoder->policy.ssrc.value = htonl(ssrc); + return srtp_create(&decoder->srtp_ctx, &decoder->policy); +} + +int +rtp_decoder_deinit_srtp(rtp_decoder_t decoder) { + return srtp_dealloc(decoder->srtp_ctx); +} + +int +rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy){ + dcdr->rtp_offset = DEFAULT_RTP_OFFSET; + dcdr->srtp_ctx = NULL; + dcdr->start_tv.tv_usec = 0; + dcdr->start_tv.tv_sec = 0; + dcdr->frame_nr = -1; + dcdr->policy = policy; + dcdr->policy.ssrc.type = ssrc_specific; + return 0; +} + +/* + * decodes key as base64 + */ + +void hexdump(const void *ptr, size_t size) { + int i, j; + const unsigned char *cptr = ptr; + + for (i = 0; i < size; i += 16) { + fprintf(stdout, "%04x ", i); + for (j = 0; j < 16 && i+j < size; j++) { + fprintf(stdout, "%02x ", cptr[i+j]); + } + fprintf(stdout, "\n"); + } +} + +void +rtp_decoder_handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr, + const u_char *bytes){ + rtp_decoder_t dcdr = (rtp_decoder_t)arg; + int pktsize; + struct timeval delta; + int octets_recvd; + err_status_t status; + dcdr->frame_nr++; + + if (dcdr->start_tv.tv_sec == 0 && dcdr->start_tv.tv_sec == 0) { + dcdr->start_tv = hdr->ts; + } + + if (hdr->caplen < dcdr->rtp_offset) { + return; + } + const void *rtp_packet = bytes + dcdr->rtp_offset; + + memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset); + pktsize = hdr->caplen - dcdr->rtp_offset; + octets_recvd = pktsize; + + if (octets_recvd == -1) { + return; + } + + /* verify rtp header */ + if (dcdr->message.header.version != 2) { + return; //return -1; + } + if(dcdr->srtp_ctx == NULL){ + status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc); + if (status) { + exit(1); + } + } + if(dcdr->srtp_ctx != NULL){ + } + status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd); + if (status){ + return; + } + timersub(&hdr->ts, &dcdr->start_tv, &delta); + fprintf(stdout, "%02ld:%02ld.%06lu\n", delta.tv_sec/60, delta.tv_sec%60, delta.tv_usec); + hexdump(&dcdr->message, pktsize); +} + +void rtp_print_error(err_status_t status, char *message){ + fprintf(stderr, + "error: %s %d%s\n", message, status, + status == err_status_replay_fail ? " (replay check failed)" : + status == err_status_bad_param ? " (bad param)" : + status == err_status_no_ctx ? " (no context)" : + status == err_status_cipher_fail ? " (cipher failed)" : + status == err_status_key_expired ? " (key expired)" : + status == err_status_auth_fail ? " (auth check failed)" : ""); +} diff --git a/third_party/srtp/test/rtp_decoder.h b/third_party/srtp/test/rtp_decoder.h new file mode 100644 index 00000000..3a92d8aa --- /dev/null +++ b/third_party/srtp/test/rtp_decoder.h @@ -0,0 +1,119 @@ +/* + * rtp_decoder.h + * + * decoder structures and functions for SRTP pcap decoder + * + * Bernardo Torres <bernardo@torresautomacao.com.br> + * + * Some structure and code from https://github.com/gteissier/srtp-decrypt + * + */ +/* + * + * Copyright (c) 2001-2006 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef RTP_DECODER_H +#define RTP_DECODER_H + +#include "srtp_priv.h" +#include "rtp_priv.h" +#include "rtp.h" +#include "datatypes.h" + +#define DEFAULT_RTP_OFFSET 42 + +typedef struct rtp_decoder_ctx_t { + srtp_policy_t policy; + srtp_ctx_t *srtp_ctx; + int rtp_offset; + struct timeval start_tv; + int frame_nr; + rtp_msg_t message; +} rtp_decoder_ctx_t; + +typedef struct rtp_decoder_ctx_t *rtp_decoder_t; + +/* + * error to string + */ + +void rtp_print_error(err_status_t status, char *message); + +/* + * prints the output of a random buffer in hexadecimal + */ + +void +hexdump(const void *ptr, size_t size); + +/* + * the function usage() prints an error message describing how this + * program should be called, then calls exit() + */ + +void +usage(char *prog_name); + +/* + * transforms base64 key into octet + */ + +char *decode_sdes(char *in, char *out); + +/* + * pcap handling + */ + +void +rtp_decoder_handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr, + const u_char *bytes); + +rtp_decoder_t +rtp_decoder_alloc(void); + +void +rtp_decoder_dealloc(rtp_decoder_t rtp_ctx); + +int +rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy); + +err_status_t +rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc); + +int +rtp_decoder_deinit_srtp(rtp_decoder_t decoder); + +#endif /* RTP_DECODER_H */ diff --git a/third_party/srtp/test/rtpw.c b/third_party/srtp/test/rtpw.c index e477a779..9d560b6d 100644 --- a/third_party/srtp/test/rtpw.c +++ b/third_party/srtp/test/rtpw.c @@ -51,16 +51,27 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "datatypes.h" #include "getopt_s.h" /* for local getopt() */ #include <stdio.h> /* for printf, fprintf */ #include <stdlib.h> /* for atoi() */ #include <errno.h> -#include <unistd.h> /* for close() */ +#include <signal.h> /* for signal() */ #include <string.h> /* for strncpy() */ #include <time.h> /* for usleep() */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> /* for close() */ +#elif defined(_MSC_VER) +#include <io.h> /* for _close() */ +#define close _close +#endif #ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> #endif @@ -77,6 +88,7 @@ #include "srtp.h" #include "rtp.h" +#include "crypto_kernel.h" #ifdef RTPW_USE_WINSOCK2 # define DICT_FILE "words.txt" @@ -86,8 +98,7 @@ #define USEC_RATE (5e5) #define MAX_WORD_LEN 128 #define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a)) -#define MAX_KEY_LEN 64 -#define MASTER_KEY_LEN 30 +#define MAX_KEY_LEN 96 #ifndef HAVE_USLEEP @@ -116,6 +127,18 @@ leave_group(int sock, struct ip_mreq mreq, char *name); /* + * setup_signal_handler() sets up a signal handler to trigger + * cleanups after an interrupt + */ +int setup_signal_handler(char* name); + +/* + * handle_signal(...) handles interrupt signal to trigger cleanups + */ + +volatile int interrupted = 0; + +/* * program_type distinguishes the [s]rtp sender and receiver cases */ @@ -137,7 +160,11 @@ main (int argc, char *argv[]) { sec_serv_t sec_servs = sec_serv_none; unsigned char ttl = 5; int c; + int key_size = 128; + int tag_size = 8; + int gcm_on = 0; char *input_key = NULL; + int b64_input = 0; char *address = NULL; char key[MAX_KEY_LEN]; unsigned short port = 0; @@ -145,6 +172,7 @@ main (int argc, char *argv[]) { srtp_policy_t policy; err_status_t status; int len; + int expected_len; int do_list_mods = 0; uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ #ifdef RTPW_USE_WINSOCK2 @@ -158,6 +186,12 @@ main (int argc, char *argv[]) { } #endif + printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); + + if (setup_signal_handler(argv[0]) != 0) { + exit(1); + } + /* initialize srtp library */ status = srtp_init(); if (status) { @@ -167,20 +201,39 @@ main (int argc, char *argv[]) { /* check args */ while (1) { - c = getopt_s(argc, argv, "k:rsaeld:"); + c = getopt_s(argc, argv, "b:k:rsgt:ae:ld:"); if (c == -1) { break; } switch (c) { + case 'b': + b64_input = 1; + /* fall thru */ case 'k': input_key = optarg_s; break; case 'e': + key_size = atoi(optarg_s); + if (key_size != 128 && key_size != 256) { + printf("error: encryption key size must be 128 or 256 (%d)\n", key_size); + exit(1); + } sec_servs |= sec_serv_conf; break; + case 't': + tag_size = atoi(optarg_s); + if (tag_size != 8 && tag_size != 16) { + printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size); + exit(1); + } + break; case 'a': sec_servs |= sec_serv_auth; break; + case 'g': + gcm_on = 1; + sec_servs |= sec_serv_auth; + break; case 'r': prog_type = receiver; break; @@ -263,7 +316,7 @@ main (int argc, char *argv[]) { err = errno; #endif fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err); - exit(1); + exit(1); } name.sin_addr = rcvr_addr; @@ -311,16 +364,73 @@ main (int argc, char *argv[]) { */ switch (sec_servs) { case sec_serv_conf_and_auth: - crypto_policy_set_rtp_default(&policy.rtp); - crypto_policy_set_rtcp_default(&policy.rtcp); + if (gcm_on) { +#ifdef OPENSSL + switch (key_size) { + case 128: + crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); + crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); + crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); + break; + } +#else + printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n"); + return 0; +#endif + } else { + switch (key_size) { + case 128: + crypto_policy_set_rtp_default(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + } + } break; case sec_serv_conf: - crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); - crypto_policy_set_rtcp_default(&policy.rtcp); + if (gcm_on) { + printf("error: GCM mode must always be used with auth enabled\n"); + return -1; + } else { + switch (key_size) { + case 128: + crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + break; + } + } break; case sec_serv_auth: - crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); - crypto_policy_set_rtcp_default(&policy.rtcp); + if (gcm_on) { +#ifdef OPENSSL + switch (key_size) { + case 128: + crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); + crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp); + break; + case 256: + crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); + crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp); + break; + } +#else + printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n"); + return 0; +#endif + } else { + crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + } break; default: printf("error: unknown security service requested\n"); @@ -329,28 +439,45 @@ main (int argc, char *argv[]) { policy.ssrc.type = ssrc_specific; policy.ssrc.value = ssrc; policy.key = (uint8_t *) key; + policy.ekt = NULL; policy.next = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; policy.rtp.sec_serv = sec_servs; policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ + if (gcm_on && tag_size != 8) { + policy.rtp.auth_tag_len = tag_size; + } + /* - * read key from hexadecimal on command line into an octet string + * read key from hexadecimal or base64 on command line into an octet string */ - len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2); - + if (b64_input) { + int pad; + expected_len = (policy.rtp.cipher_key_len*4)/3; + len = base64_string_to_octet_string(key, &pad, input_key, expected_len); + if (pad != 0) { + fprintf(stderr, "error: padding in base64 unexpected\n"); + exit(1); + } + } else { + expected_len = policy.rtp.cipher_key_len*2; + len = hex_string_to_octet_string(key, input_key, expected_len); + } /* check that hex string is the right length */ - if (len < MASTER_KEY_LEN*2) { + if (len < expected_len) { fprintf(stderr, "error: too few digits in key/salt " - "(should be %d hexadecimal digits, found %d)\n", - MASTER_KEY_LEN*2, len); + "(should be %d digits, found %d)\n", + expected_len, len); exit(1); } - if (strlen(input_key) > MASTER_KEY_LEN*2) { + if ((int) strlen(input_key) > policy.rtp.cipher_key_len*2) { fprintf(stderr, "error: too many digits in key/salt " "(should be %d hexadecimal digits, found %u)\n", - MASTER_KEY_LEN*2, (unsigned)strlen(input_key)); + policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key)); exit(1); } @@ -382,6 +509,9 @@ main (int argc, char *argv[]) { policy.rtcp.auth_key_len = 0; policy.rtcp.auth_tag_len = 0; policy.rtcp.sec_serv = sec_serv_none; + policy.window_size = 0; + policy.allow_repeat_tx = 0; + policy.ekt = NULL; policy.next = NULL; } @@ -426,7 +556,7 @@ main (int argc, char *argv[]) { } /* read words from dictionary, then send them off */ - while (fgets(word, MAX_WORD_LEN, dict) != NULL) { + while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) { len = strlen(word) + 1; /* plus one for null */ if (len > MAX_WORD_LEN) @@ -437,7 +567,11 @@ main (int argc, char *argv[]) { } usleep(USEC_RATE); } - + + rtp_sender_deinit_srtp(snd); + rtp_sender_dealloc(snd); + + fclose(dict); } else { /* prog_type == receiver */ rtp_receiver_t rcvr; @@ -466,12 +600,14 @@ main (int argc, char *argv[]) { } /* get next word and loop */ - while (1) { + while (!interrupted) { len = MAX_WORD_LEN; if (rtp_recvfrom(rcvr, word, &len) > -1) - printf("\tword: %s", word); + printf("\tword: %s\n", word); } + rtp_receiver_deinit_srtp(rcvr); + rtp_receiver_dealloc(rcvr); } if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) { @@ -479,6 +615,22 @@ main (int argc, char *argv[]) { } #ifdef RTPW_USE_WINSOCK2 + ret = closesocket(sock); +#else + ret = close(sock); +#endif + if (ret < 0) { + fprintf(stderr, "%s: Failed to close socket", argv[0]); + perror(""); + } + + status = srtp_shutdown(); + if (status) { + printf("error: srtp shutdown failed with error code %d\n", status); + exit(1); + } + +#ifdef RTPW_USE_WINSOCK2 WSACleanup(); #endif @@ -493,8 +645,11 @@ usage(char *string) { "[-s | -r] dest_ip dest_port\n" "or %s -l\n" "where -a use message authentication\n" - " -e use encryption\n" - " -k <key> sets the srtp master key\n" + " -e <key size> use encryption (use 128 or 256 for key size)\n" + " -g Use AES-GCM mode (must be used with -e)\n" + " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n" + " -k <key> sets the srtp master key given in hexadecimal\n" + " -b <key> sets the srtp master key given in base64\n" " -s act as rtp sender\n" " -r act as rtp receiver\n" " -l list debug modules\n" @@ -517,3 +672,41 @@ leave_group(int sock, struct ip_mreq mreq, char *name) { } } +void handle_signal(int signum) +{ + interrupted = 1; + /* Reset handler explicitly, in case we don't have sigaction() (and signal() + has BSD semantics), or we don't have SA_RESETHAND */ + signal(signum, SIG_DFL); +} + +int setup_signal_handler(char* name) +{ +#if HAVE_SIGACTION + struct sigaction act; + memset(&act, 0, sizeof(act)); + + act.sa_handler = handle_signal; + sigemptyset(&act.sa_mask); +#if defined(SA_RESETHAND) + act.sa_flags = SA_RESETHAND; +#else + act.sa_flags = 0; +#endif + /* Note that we're not setting SA_RESTART; we want recvfrom to return + * EINTR when we signal the receiver. */ + + if (sigaction(SIGTERM, &act, NULL) != 0) { + fprintf(stderr, "%s: error setting up signal handler", name); + perror(""); + return -1; + } +#else + if (signal(SIGTERM, handle_signal) == SIG_ERR) { + fprintf(stderr, "%s: error setting up signal handler", name); + perror(""); + return -1; + } +#endif + return 0; +} diff --git a/third_party/srtp/test/rtpw_test.sh b/third_party/srtp/test/rtpw_test.sh index f82e9370..d5808aba 100644 --- a/third_party/srtp/test/rtpw_test.sh +++ b/third_party/srtp/test/rtpw_test.sh @@ -3,14 +3,47 @@ # usage: rtpw_test <rtpw_commands> # # tests the rtpw sender and receiver functions - -RTPW=rtpw +# +# Copyright (c) 2001-2006, Cisco Systems, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# Neither the name of the Cisco Systems, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# + +RTPW=./rtpw DEST_PORT=9999 DURATION=3 -key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6 +key=Ky7cUDT2GnI0XKWYbXv9AYmqbcLsqzL9mvdN9t/G -ARGS="-k $key -ae" +ARGS="-b $key -a -e 128" # First, we run "killall" to get rid of all existing rtpw processes. # This step also enables this script to clean up after itself; if this @@ -18,7 +51,7 @@ ARGS="-k $key -ae" # they are killed, those processes will linger. Re-running the script # will get rid of them. -killall rtpw 2&>/dev/null +killall rtpw 2>/dev/null if test -x $RTPW; then @@ -63,6 +96,58 @@ sleep $DURATION kill $receiver_pid kill $sender_pid +wait $receiver_pid +wait $sender_pid + + +key=033490ba9e82994fc21013395739038992b2edc5034f61a72345ca598d7bfd0189aa6dc2ecab32fd9af74df6dfc6 + +ARGS="-k $key -a -e 256" + +echo $0 ": starting rtpw receiver process... " + +$RTPW $* $ARGS -r 0.0.0.0 $DEST_PORT & + +receiver_pid=$! + +echo $0 ": receiver PID = $receiver_pid" + +sleep 1 + +# verify that the background job is running +ps | grep -q $receiver_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 254 +fi + +echo $0 ": starting rtpw sender process..." + +$RTPW $* $ARGS -s 127.0.0.1 $DEST_PORT & + +sender_pid=$! + +echo $0 ": sender PID = $sender_pid" + +# verify that the background job is running +ps | grep -q $sender_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 255 +fi + +sleep $DURATION + +kill $receiver_pid +kill $sender_pid + +wait $receiver_pid +wait $sender_pid + echo $0 ": done (test passed)" else diff --git a/third_party/srtp/test/rtpw_test_gcm.sh b/third_party/srtp/test/rtpw_test_gcm.sh new file mode 100644 index 00000000..6e58b6c8 --- /dev/null +++ b/third_party/srtp/test/rtpw_test_gcm.sh @@ -0,0 +1,237 @@ +#!/bin/sh +# +# usage: rtpw_test <rtpw_commands> +# +# tests the rtpw sender and receiver functions +# +# Copyright (c) 2001-2006, Cisco Systems, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# Neither the name of the Cisco Systems, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# + +RTPW=./rtpw +DEST_PORT=9999 +DURATION=3 + +# First, we run "killall" to get rid of all existing rtpw processes. +# This step also enables this script to clean up after itself; if this +# script is interrupted after the rtpw processes are started but before +# they are killed, those processes will linger. Re-running the script +# will get rid of them. + +killall rtpw 2>/dev/null + +if test -x $RTPW; then + +GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -e 128" +echo $0 ": starting GCM mode 128-bit rtpw receiver process... " + +exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT & + +receiver_pid=$! + +echo $0 ": receiver PID = $receiver_pid" + +sleep 1 + +# verify that the background job is running +ps | grep -q $receiver_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 254 +fi + +echo $0 ": starting GCM 128-bit rtpw sender process..." + +exec $RTPW $* $GCMARGS128 -s 127.0.0.1 $DEST_PORT & + +sender_pid=$! + +echo $0 ": sender PID = $sender_pid" + +# verify that the background job is running +ps | grep -q $sender_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 255 +fi + +sleep $DURATION + +kill $receiver_pid +kill $sender_pid + +GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -t 16 -e 128" +echo $0 ": starting GCM mode 128-bit (16 byte tag) rtpw receiver process... " + +exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT & + +receiver_pid=$! + +echo $0 ": receiver PID = $receiver_pid" + +sleep 1 + +# verify that the background job is running +ps | grep -q $receiver_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 254 +fi + +echo $0 ": starting GCM 128-bit (16 byte tag) rtpw sender process..." + +exec $RTPW $* $GCMARGS128 -s 127.0.0.1 $DEST_PORT & + +sender_pid=$! + +echo $0 ": sender PID = $sender_pid" + +# verify that the background job is running +ps | grep -q $sender_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 255 +fi + +sleep $DURATION + +kill $receiver_pid +kill $sender_pid + + + +GCMARGS256="-k 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -e 256" +echo $0 ": starting GCM mode 256-bit rtpw receiver process... " + +exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT & + +receiver_pid=$! + +echo $0 ": receiver PID = $receiver_pid" + +sleep 1 + +# verify that the background job is running +ps | grep -q $receiver_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 254 +fi + +echo $0 ": starting GCM 256-bit rtpw sender process..." + +exec $RTPW $* $GCMARGS256 -s 127.0.0.1 $DEST_PORT & + +sender_pid=$! + +echo $0 ": sender PID = $sender_pid" + +# verify that the background job is running +ps | grep -q $sender_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 255 +fi + +sleep $DURATION + +kill $receiver_pid +kill $sender_pid + + +GCMARGS256="-k a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -t 16 -e 256" +echo $0 ": starting GCM mode 256-bit (16 byte tag) rtpw receiver process... " + +exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT & + +receiver_pid=$! + +echo $0 ": receiver PID = $receiver_pid" + +sleep 1 + +# verify that the background job is running +ps | grep -q $receiver_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 254 +fi + +echo $0 ": starting GCM 256-bit (16 byte tag) rtpw sender process..." + +exec $RTPW $* $GCMARGS256 -s 127.0.0.1 $DEST_PORT & + +sender_pid=$! + +echo $0 ": sender PID = $sender_pid" + +# verify that the background job is running +ps | grep -q $sender_pid +retval=$? +echo $retval +if [ $retval != 0 ]; then + echo $0 ": error" + exit 255 +fi + +sleep $DURATION + +kill $receiver_pid +kill $sender_pid + + +echo $0 ": done (test passed)" + +else + +echo "error: can't find executable" $RTPW +exit 1 + +fi + +# EOF + + diff --git a/third_party/srtp/test/srtp_driver.c b/third_party/srtp/test/srtp_driver.c index 12d1c8c2..88729717 100644 --- a/third_party/srtp/test/srtp_driver.c +++ b/third_party/srtp/test/srtp_driver.c @@ -63,9 +63,15 @@ err_status_t srtp_validate(void); err_status_t +srtp_validate_aes_256(void); + +err_status_t srtp_create_big_policy(srtp_policy_t **list); err_status_t +srtp_dealloc_big_policy(srtp_policy_t *list); + +err_status_t srtp_test_remove_stream(void); double @@ -98,7 +104,7 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len); double mips_estimate(int num_trials, int *ignore); -extern uint8_t test_key[30]; +extern uint8_t test_key[46]; void usage(char *prog_name) { @@ -138,7 +144,7 @@ debug_module_t mod_driver = { int main (int argc, char *argv[]) { - char q; + int q; unsigned do_timing_test = 0; unsigned do_rejection_test = 0; unsigned do_codec_timing = 0; @@ -153,7 +159,7 @@ main (int argc, char *argv[]) { if (sizeof(srtp_hdr_t) != 12) { printf("error: srtp_hdr_t has incorrect size" "(size is %ld bytes, expected 12)\n", - sizeof(srtp_hdr_t)); + (long)sizeof(srtp_hdr_t)); exit(1); } @@ -253,6 +259,11 @@ main (int argc, char *argv[]) { 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 " @@ -277,6 +288,22 @@ main (int argc, char *argv[]) { exit(1); } +//FIXME: need to get this working with the OpenSSL AES module +#ifndef OPENSSL + /* + * run validation test against the reference packets for + * AES-256 + */ + printf("testing srtp_protect and srtp_unprotect against " + "reference packets (AES-256)\n"); + if (srtp_validate_aes_256() == err_status_ok) + printf("passed\n\n"); + else { + printf("failed\n"); + exit(1); + } +#endif + /* * test the function srtp_remove_stream() */ @@ -321,6 +348,9 @@ main (int argc, char *argv[]) { policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; policy.key = test_key; + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; policy.next = NULL; printf("mips estimate: %e\n", mips); @@ -353,6 +383,12 @@ main (int argc, char *argv[]) { 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; } @@ -492,7 +528,6 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) { timer = clock(); for (i=0; i < num_trials; i++) { - err_status_t status; len = msg_len_octets + 12; /* add in rtp header length */ /* srtp protect message */ @@ -503,12 +538,21 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) { } /* increment message number */ - mesg->seq = htons(ntohs(mesg->seq) + 1); - + { + /* 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; @@ -549,7 +593,13 @@ srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) { 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; } @@ -678,8 +728,11 @@ srtp_test(const srtp_policy_t *policy) { * the compiler would fret about the constness of the policy */ rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t)); - if (rcvr_policy == NULL) + if (rcvr_policy == NULL) { + free(hdr); + free(hdr2); return 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; @@ -701,6 +754,7 @@ srtp_test(const srtp_policy_t *policy) { if (status) { free(hdr); free(hdr2); + free(rcvr_policy); return status; } @@ -721,6 +775,7 @@ srtp_test(const srtp_policy_t *policy) { printf("failed with error code %d\n", status); free(hdr); free(hdr2); + free(rcvr_policy); return status; } else { printf("passed\n"); @@ -746,6 +801,7 @@ srtp_test(const srtp_policy_t *policy) { printf("failed\n"); free(hdr); free(hdr2); + free(rcvr_policy); return status; } else { printf("passed\n"); @@ -758,6 +814,7 @@ srtp_test(const srtp_policy_t *policy) { free(hdr); free(hdr2); + free(rcvr_policy); return err_status_ok; } @@ -900,6 +957,7 @@ srtcp_test(const srtp_policy_t *policy) { if (status) { free(hdr); free(hdr2); + free(rcvr_policy); return status; } @@ -920,6 +978,7 @@ srtcp_test(const srtp_policy_t *policy) { printf("failed with error code %d\n", status); free(hdr); free(hdr2); + free(rcvr_policy); return status; } else { printf("passed\n"); @@ -945,6 +1004,7 @@ srtcp_test(const srtp_policy_t *policy) { printf("failed\n"); free(hdr); free(hdr2); + free(rcvr_policy); return status; } else { printf("passed\n"); @@ -957,6 +1017,7 @@ srtcp_test(const srtp_policy_t *policy) { free(hdr); free(hdr2); + free(rcvr_policy); return err_status_ok; } @@ -989,14 +1050,18 @@ srtp_session_print_policy(srtp_t srtp) { "# rtp services: %s\r\n" "# rtcp cipher: %s\r\n" "# rtcp auth: %s\r\n" - "# rtcp services: %s\r\n", + "# rtcp services: %s\r\n" + "# window size: %lu\r\n" + "# tx rtx allowed:%s\r\n", direction[stream->direction], stream->rtp_cipher->type->description, stream->rtp_auth->type->description, serv_descr[stream->rtp_services], stream->rtcp_cipher->type->description, stream->rtcp_auth->type->description, - serv_descr[stream->rtcp_services]); + serv_descr[stream->rtcp_services], + rdbx_get_window_size(&stream->rtp_rdbx), + stream->allow_repeat_tx ? "true" : "false"); } /* loop over streams in session, printing the policy of each */ @@ -1011,14 +1076,18 @@ srtp_session_print_policy(srtp_t srtp) { "# rtp services: %s\r\n" "# rtcp cipher: %s\r\n" "# rtcp auth: %s\r\n" - "# rtcp services: %s\r\n", + "# rtcp services: %s\r\n" + "# window size: %lu\r\n" + "# tx rtx allowed:%s\r\n", stream->ssrc, stream->rtp_cipher->type->description, stream->rtp_auth->type->description, serv_descr[stream->rtp_services], stream->rtcp_cipher->type->description, stream->rtcp_auth->type->description, - serv_descr[stream->rtcp_services]); + serv_descr[stream->rtcp_services], + rdbx_get_window_size(&stream->rtp_rdbx), + stream->allow_repeat_tx ? "true" : "false"); /* advance to next stream in the list */ stream = stream->next; @@ -1108,7 +1177,7 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) { double mips_estimate(int num_trials, int *ignore) { clock_t t; - int i, sum; + volatile int i, sum; sum = 0; t = clock(); @@ -1132,12 +1201,6 @@ mips_estimate(int num_trials, int *ignore) { err_status_t srtp_validate() { - unsigned char test_key[30] = { - 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, - 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, - 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb, - 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 - }; uint8_t srtp_plaintext_ref[28] = { 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, @@ -1172,6 +1235,9 @@ srtp_validate() { policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key; + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; policy.next = NULL; status = srtp_create(&srtp_snd, &policy); @@ -1213,6 +1279,122 @@ srtp_validate() { if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) return err_status_fail; + status = srtp_dealloc(srtp_snd); + if (status) + return status; + + status = srtp_dealloc(srtp_recv); + if (status) + return status; + + return err_status_ok; +} + + +/* + * 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. + */ + + +err_status_t +srtp_validate_aes_256() { + unsigned char aes_256_test_key[46] = { + 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, + 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, + 0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1, + 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6, + + 0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9, + 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 + }; + uint8_t srtp_plaintext_ref[28] = { + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab + }; + uint8_t srtp_plaintext[38] = { + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, + 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + uint8_t srtp_ciphertext[38] = { + 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, + 0xca, 0xfe, 0xba, 0xbe, 0xf1, 0xd9, 0xde, 0x17, + 0xff, 0x25, 0x1f, 0xf1, 0xaa, 0x00, 0x77, 0x74, + 0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a, + 0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b + }; + srtp_t srtp_snd, srtp_recv; + err_status_t status; + int len; + srtp_policy_t policy; + + /* + * create a session with a single stream using the default srtp + * policy and with the SSRC value 0xcafebabe + */ + crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); + crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp); + policy.ssrc.type = ssrc_specific; + policy.ssrc.value = 0xcafebabe; + policy.key = aes_256_test_key; + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.next = NULL; + + status = srtp_create(&srtp_snd, &policy); + if (status) + return status; + + /* + * protect plaintext, then compare with ciphertext + */ + len = 28; + status = srtp_protect(srtp_snd, srtp_plaintext, &len); + if (status || (len != 38)) + return err_status_fail; + + debug_print(mod_driver, "ciphertext:\n %s", + octet_string_hex_string(srtp_plaintext, len)); + debug_print(mod_driver, "ciphertext reference:\n %s", + octet_string_hex_string(srtp_ciphertext, len)); + + if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) + return err_status_fail; + + /* + * create a receiver session context comparable to the one created + * above - we need to do this so that the replay checking doesn't + * complain + */ + status = srtp_create(&srtp_recv, &policy); + if (status) + return status; + + /* + * unprotect ciphertext, then compare with plaintext + */ + status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len); + if (status || (len != 28)) + return status; + + if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) + return err_status_fail; + + status = srtp_dealloc(srtp_snd); + if (status) + return status; + + status = srtp_dealloc(srtp_recv); + if (status) + return status; + return err_status_ok; } @@ -1250,9 +1432,22 @@ srtp_create_big_policy(srtp_policy_t **list) { } 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 err_status_ok; +} + + +err_status_t srtp_test_remove_stream() { err_status_t status; - srtp_policy_t *policy_list; + srtp_policy_t *policy_list, policy; srtp_t session; srtp_stream_t stream; /* @@ -1293,6 +1488,41 @@ srtp_test_remove_stream() { if (stream == NULL) return err_status_fail; + status = srtp_dealloc(session); + if (status != err_status_ok) + return status; + + status = srtp_dealloc_big_policy(policy_list); + if (status != err_status_ok) + return status; + + /* Now test adding and removing a single stream */ + crypto_policy_set_rtp_default(&policy.rtp); + crypto_policy_set_rtcp_default(&policy.rtcp); + policy.ssrc.type = ssrc_specific; + policy.ssrc.value = 0xcafebabe; + policy.key = test_key; + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.next = NULL; + + status = srtp_create(&session, NULL); + if (status != err_status_ok) + return status; + + status = srtp_add_stream(session, &policy); + if (status != err_status_ok) + return status; + + status = srtp_remove_stream(session, htonl(0xcafebabe)); + if (status != err_status_ok) + return status; + + status = srtp_dealloc(session); + if (status != err_status_ok) + return status; + return err_status_ok; } @@ -1300,10 +1530,12 @@ srtp_test_remove_stream() { * srtp policy definitions - these definitions are used above */ -unsigned char test_key[30] = { +unsigned char test_key[46] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb, + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, 0xc1, 0x73, + 0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, 0x93, 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 }; @@ -1327,6 +1559,9 @@ const srtp_policy_t default_policy = { sec_serv_conf_and_auth /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; @@ -1349,6 +1584,9 @@ const srtp_policy_t aes_tmmh_policy = { sec_serv_conf_and_auth /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; @@ -1371,6 +1609,9 @@ const srtp_policy_t tmmh_only_policy = { sec_serv_auth /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; @@ -1393,6 +1634,9 @@ const srtp_policy_t aes_only_policy = { sec_serv_conf /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; @@ -1415,9 +1659,114 @@ const srtp_policy_t hmac_only_policy = { sec_serv_auth /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; +#ifdef OPENSSL +const srtp_policy_t aes128_gcm_8_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { /* SRTP policy */ + AES_128_GCM, /* cipher type */ + AES_128_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + 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 */ + AES_128_GCM, /* cipher type */ + AES_128_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 8, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ + }, + test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; + +const srtp_policy_t aes128_gcm_8_cauth_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { /* SRTP policy */ + AES_128_GCM, /* cipher type */ + AES_128_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + 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 */ + AES_128_GCM, /* cipher type */ + AES_128_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 8, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ + }, + test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; + +const srtp_policy_t aes256_gcm_8_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { /* SRTP policy */ + AES_256_GCM, /* cipher type */ + AES_256_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + 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 */ + AES_256_GCM, /* cipher type */ + AES_256_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 8, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ + }, + test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; + +const srtp_policy_t aes256_gcm_8_cauth_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { /* SRTP policy */ + AES_256_GCM, /* cipher type */ + AES_256_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + 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 */ + AES_256_GCM, /* cipher type */ + AES_256_GCM_KEYSIZE_WSALT, /* cipher key length in octets */ + NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 8, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ + }, + test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; +#endif + const srtp_policy_t null_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { @@ -1437,6 +1786,83 @@ const srtp_policy_t null_policy = { sec_serv_none /* security services flag */ }, test_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; + +unsigned char test_256_key[46] = { + 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, + 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, + 0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1, + 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6, + + 0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9, + 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 +}; + +const srtp_policy_t aes_256_hmac_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { /* SRTP policy */ + AES_ICM, /* cipher type */ + 46, /* cipher key length in octets */ + 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 */ + AES_ICM, /* cipher type */ + 46, /* cipher key length in octets */ + HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ + }, + test_256_key, + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL +}; + +uint8_t ekt_test_key[16] = { + 0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca, + 0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b +}; + +#include "ekt.h" + +ekt_policy_ctx_t ekt_test_policy = { + 0xa5a5, /* SPI */ + EKT_CIPHER_AES_128_ECB, + ekt_test_key, + NULL +}; + +const srtp_policy_t hmac_only_with_ekt_policy = { + { ssrc_any_outbound, 0 }, /* SSRC */ + { + NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ + }, + { + NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ + }, + test_key, + &ekt_test_policy, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; @@ -1464,7 +1890,15 @@ policy_array[] = { &aes_tmmh_policy, #endif &default_policy, +#ifdef OPENSSL + &aes128_gcm_8_policy, + &aes128_gcm_8_cauth_policy, + &aes256_gcm_8_policy, + &aes256_gcm_8_cauth_policy, +#endif &null_policy, + &aes_256_hmac_policy, + &hmac_only_with_ekt_policy, NULL }; @@ -1487,5 +1921,8 @@ const srtp_policy_t wildcard_policy = { sec_serv_conf_and_auth /* security services flag */ }, test_key, + NULL, + 128, /* replay window size */ + 0, /* retransmission not allowed */ NULL }; |