Index: srtp/test/rtpw.c |
diff --git a/srtp/test/rtpw.c b/srtp/test/rtpw.c |
index f18d42045e0e4eac7c1d17afb6acbb773b9d80fc..17f27f278136bfb72c451b182878f75a6f8c9421 100644 |
--- a/srtp/test/rtpw.c |
+++ b/srtp/test/rtpw.c |
@@ -51,6 +51,10 @@ |
*/ |
+#ifdef HAVE_CONFIG_H |
+ #include <config.h> |
+#endif |
+ |
#include "datatypes.h" |
#include "getopt_s.h" /* for local getopt() */ |
@@ -81,6 +85,7 @@ |
#include "srtp.h" |
#include "rtp.h" |
+#include "crypto_kernel.h" |
#ifdef RTPW_USE_WINSOCK2 |
# define DICT_FILE "words.txt" |
@@ -90,8 +95,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 |
@@ -153,7 +157,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; |
@@ -161,6 +169,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 |
@@ -174,6 +183,8 @@ 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); |
} |
@@ -187,20 +198,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; |
@@ -331,16 +361,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"); |
@@ -356,24 +443,38 @@ main (int argc, char *argv[]) { |
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 (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); |
} |
@@ -541,8 +642,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" |