From 26d978a556ae9099f6610ace9834991636e4a71b Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 15 Mar 2016 03:57:39 +0000 Subject: Close #1847: Upgraded libsrtp version to 1.5.4 and added support for AES-CM-256 crypto. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5261 74dad513-b988-da41-8d7b-12977e46ad98 --- third_party/srtp/test/rtpw.c | 243 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 218 insertions(+), 25 deletions(-) (limited to 'third_party/srtp/test/rtpw.c') 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 +#endif + #include "datatypes.h" #include "getopt_s.h" /* for local getopt() */ #include /* for printf, fprintf */ #include /* for atoi() */ #include -#include /* for close() */ +#include /* for signal() */ #include /* for strncpy() */ #include /* for usleep() */ + +#ifdef HAVE_UNISTD_H +#include /* for close() */ +#elif defined(_MSC_VER) +#include /* for _close() */ +#define close _close +#endif #ifdef HAVE_SYS_SOCKET_H # include #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 @@ -115,6 +126,18 @@ void 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,18 +600,36 @@ 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)) { leave_group(sock, mreq, argv[0]); } +#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 sets the srtp master key\n" + " -e use encryption (use 128 or 256 for key size)\n" + " -g Use AES-GCM mode (must be used with -e)\n" + " -t Tag size to use in GCM mode (use 8 or 16)\n" + " -k sets the srtp master key given in hexadecimal\n" + " -b sets the srtp master key given in base64\n" " -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; +} -- cgit v1.2.3