summaryrefslogtreecommitdiff
path: root/third_party/srtp/test/rtpw.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/srtp/test/rtpw.c')
-rw-r--r--third_party/srtp/test/rtpw.c243
1 files changed, 218 insertions, 25 deletions
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;
+}