OLD | NEW |
1 /* | 1 /* |
2 * rtpw.c | 2 * rtpw.c |
3 * | 3 * |
4 * rtp word sender/receiver | 4 * rtp word sender/receiver |
5 * | 5 * |
6 * David A. McGrew | 6 * David A. McGrew |
7 * Cisco Systems, Inc. | 7 * Cisco Systems, Inc. |
8 * | 8 * |
9 * This app is a simple RTP application intended only for testing | 9 * This app is a simple RTP application intended only for testing |
10 * libsrtp. It reads one word at a time from /usr/dict/words (or | 10 * libsrtp. It reads one word at a time from /usr/dict/words (or |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 44 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
45 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 45 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
49 * OF THE POSSIBILITY OF SUCH DAMAGE. | 49 * OF THE POSSIBILITY OF SUCH DAMAGE. |
50 * | 50 * |
51 */ | 51 */ |
52 | 52 |
53 | 53 |
| 54 #ifdef HAVE_CONFIG_H |
| 55 #include <config.h> |
| 56 #endif |
| 57 |
54 #include "datatypes.h" | 58 #include "datatypes.h" |
55 #include "getopt_s.h" /* for local getopt() */ | 59 #include "getopt_s.h" /* for local getopt() */ |
56 | 60 |
57 #include <stdio.h> /* for printf, fprintf */ | 61 #include <stdio.h> /* for printf, fprintf */ |
58 #include <stdlib.h> /* for atoi() */ | 62 #include <stdlib.h> /* for atoi() */ |
59 #include <errno.h> | 63 #include <errno.h> |
60 #include <signal.h> /* for signal() */ | 64 #include <signal.h> /* for signal() */ |
61 | 65 |
62 #include <string.h> /* for strncpy() */ | 66 #include <string.h> /* for strncpy() */ |
63 #include <time.h> /* for usleep() */ | 67 #include <time.h> /* for usleep() */ |
(...skipping 10 matching lines...) Expand all Loading... |
74 # include <winsock2.h> | 78 # include <winsock2.h> |
75 # include <ws2tcpip.h> | 79 # include <ws2tcpip.h> |
76 # define RTPW_USE_WINSOCK2 1 | 80 # define RTPW_USE_WINSOCK2 1 |
77 #endif | 81 #endif |
78 #ifdef HAVE_ARPA_INET_H | 82 #ifdef HAVE_ARPA_INET_H |
79 # include <arpa/inet.h> | 83 # include <arpa/inet.h> |
80 #endif | 84 #endif |
81 | 85 |
82 #include "srtp.h" | 86 #include "srtp.h" |
83 #include "rtp.h" | 87 #include "rtp.h" |
| 88 #include "crypto_kernel.h" |
84 | 89 |
85 #ifdef RTPW_USE_WINSOCK2 | 90 #ifdef RTPW_USE_WINSOCK2 |
86 # define DICT_FILE "words.txt" | 91 # define DICT_FILE "words.txt" |
87 #else | 92 #else |
88 # define DICT_FILE "/usr/share/dict/words" | 93 # define DICT_FILE "/usr/share/dict/words" |
89 #endif | 94 #endif |
90 #define USEC_RATE (5e5) | 95 #define USEC_RATE (5e5) |
91 #define MAX_WORD_LEN 128 | 96 #define MAX_WORD_LEN 128 |
92 #define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a)) | 97 #define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a)) |
93 #define MAX_KEY_LEN 64 | 98 #define MAX_KEY_LEN 96 |
94 #define MASTER_KEY_LEN 30 | |
95 | 99 |
96 | 100 |
97 #ifndef HAVE_USLEEP | 101 #ifndef HAVE_USLEEP |
98 # ifdef HAVE_WINDOWS_H | 102 # ifdef HAVE_WINDOWS_H |
99 # define usleep(us) Sleep((us)/1000) | 103 # define usleep(us) Sleep((us)/1000) |
100 # else | 104 # else |
101 # define usleep(us) sleep((us)/1000000) | 105 # define usleep(us) sleep((us)/1000000) |
102 # endif | 106 # endif |
103 #endif | 107 #endif |
104 | 108 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 struct in_addr rcvr_addr; | 150 struct in_addr rcvr_addr; |
147 struct sockaddr_in name; | 151 struct sockaddr_in name; |
148 struct ip_mreq mreq; | 152 struct ip_mreq mreq; |
149 #if BEW | 153 #if BEW |
150 struct sockaddr_in local; | 154 struct sockaddr_in local; |
151 #endif | 155 #endif |
152 program_type prog_type = unknown; | 156 program_type prog_type = unknown; |
153 sec_serv_t sec_servs = sec_serv_none; | 157 sec_serv_t sec_servs = sec_serv_none; |
154 unsigned char ttl = 5; | 158 unsigned char ttl = 5; |
155 int c; | 159 int c; |
| 160 int key_size = 128; |
| 161 int tag_size = 8; |
| 162 int gcm_on = 0; |
156 char *input_key = NULL; | 163 char *input_key = NULL; |
| 164 int b64_input = 0; |
157 char *address = NULL; | 165 char *address = NULL; |
158 char key[MAX_KEY_LEN]; | 166 char key[MAX_KEY_LEN]; |
159 unsigned short port = 0; | 167 unsigned short port = 0; |
160 rtp_sender_t snd; | 168 rtp_sender_t snd; |
161 srtp_policy_t policy; | 169 srtp_policy_t policy; |
162 err_status_t status; | 170 err_status_t status; |
163 int len; | 171 int len; |
| 172 int expected_len; |
164 int do_list_mods = 0; | 173 int do_list_mods = 0; |
165 uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ | 174 uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ |
166 #ifdef RTPW_USE_WINSOCK2 | 175 #ifdef RTPW_USE_WINSOCK2 |
167 WORD wVersionRequested = MAKEWORD(2, 0); | 176 WORD wVersionRequested = MAKEWORD(2, 0); |
168 WSADATA wsaData; | 177 WSADATA wsaData; |
169 | 178 |
170 ret = WSAStartup(wVersionRequested, &wsaData); | 179 ret = WSAStartup(wVersionRequested, &wsaData); |
171 if (ret != 0) { | 180 if (ret != 0) { |
172 fprintf(stderr, "error: WSAStartup() failed: %d\n", ret); | 181 fprintf(stderr, "error: WSAStartup() failed: %d\n", ret); |
173 exit(1); | 182 exit(1); |
174 } | 183 } |
175 #endif | 184 #endif |
176 | 185 |
| 186 printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); |
| 187 |
177 if (setup_signal_handler(argv[0]) != 0) { | 188 if (setup_signal_handler(argv[0]) != 0) { |
178 exit(1); | 189 exit(1); |
179 } | 190 } |
180 | 191 |
181 /* initialize srtp library */ | 192 /* initialize srtp library */ |
182 status = srtp_init(); | 193 status = srtp_init(); |
183 if (status) { | 194 if (status) { |
184 printf("error: srtp initialization failed with error code %d\n", status); | 195 printf("error: srtp initialization failed with error code %d\n", status); |
185 exit(1); | 196 exit(1); |
186 } | 197 } |
187 | 198 |
188 /* check args */ | 199 /* check args */ |
189 while (1) { | 200 while (1) { |
190 c = getopt_s(argc, argv, "k:rsaeld:"); | 201 c = getopt_s(argc, argv, "b:k:rsgt:ae:ld:"); |
191 if (c == -1) { | 202 if (c == -1) { |
192 break; | 203 break; |
193 } | 204 } |
194 switch (c) { | 205 switch (c) { |
| 206 case 'b': |
| 207 b64_input = 1; |
| 208 /* fall thru */ |
195 case 'k': | 209 case 'k': |
196 input_key = optarg_s; | 210 input_key = optarg_s; |
197 break; | 211 break; |
198 case 'e': | 212 case 'e': |
| 213 key_size = atoi(optarg_s); |
| 214 if (key_size != 128 && key_size != 256) { |
| 215 printf("error: encryption key size must be 128 or 256 (%d)\n", key_size)
; |
| 216 exit(1); |
| 217 } |
199 sec_servs |= sec_serv_conf; | 218 sec_servs |= sec_serv_conf; |
200 break; | 219 break; |
| 220 case 't': |
| 221 tag_size = atoi(optarg_s); |
| 222 if (tag_size != 8 && tag_size != 16) { |
| 223 printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size); |
| 224 exit(1); |
| 225 } |
| 226 break; |
201 case 'a': | 227 case 'a': |
202 sec_servs |= sec_serv_auth; | 228 sec_servs |= sec_serv_auth; |
203 break; | 229 break; |
| 230 case 'g': |
| 231 gcm_on = 1; |
| 232 sec_servs |= sec_serv_auth; |
| 233 break; |
204 case 'r': | 234 case 'r': |
205 prog_type = receiver; | 235 prog_type = receiver; |
206 break; | 236 break; |
207 case 's': | 237 case 's': |
208 prog_type = sender; | 238 prog_type = sender; |
209 break; | 239 break; |
210 case 'd': | 240 case 'd': |
211 status = crypto_kernel_set_debug_module(optarg_s, 1); | 241 status = crypto_kernel_set_debug_module(optarg_s, 1); |
212 if (status) { | 242 if (status) { |
213 printf("error: set debug module (%s) failed\n", optarg_s); | 243 printf("error: set debug module (%s) failed\n", optarg_s); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 | 354 |
325 /* set up the srtp policy and master key */ | 355 /* set up the srtp policy and master key */ |
326 if (sec_servs) { | 356 if (sec_servs) { |
327 /* | 357 /* |
328 * create policy structure, using the default mechanisms but | 358 * create policy structure, using the default mechanisms but |
329 * with only the security services requested on the command line, | 359 * with only the security services requested on the command line, |
330 * using the right SSRC value | 360 * using the right SSRC value |
331 */ | 361 */ |
332 switch (sec_servs) { | 362 switch (sec_servs) { |
333 case sec_serv_conf_and_auth: | 363 case sec_serv_conf_and_auth: |
334 crypto_policy_set_rtp_default(&policy.rtp); | 364 if (gcm_on) { |
335 crypto_policy_set_rtcp_default(&policy.rtcp); | 365 #ifdef OPENSSL |
| 366 » switch (key_size) { |
| 367 » case 128: |
| 368 » crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); |
| 369 » crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); |
| 370 » break; |
| 371 » case 256: |
| 372 » crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); |
| 373 » crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); |
| 374 » break; |
| 375 » } |
| 376 #else |
| 377 » printf("error: GCM mode only supported when using the OpenSSL crypto eng
ine.\n"); |
| 378 » return 0; |
| 379 #endif |
| 380 } else { |
| 381 » switch (key_size) { |
| 382 » case 128: |
| 383 crypto_policy_set_rtp_default(&policy.rtp); |
| 384 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 385 » break; |
| 386 » case 256: |
| 387 crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); |
| 388 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 389 » break; |
| 390 » } |
| 391 } |
336 break; | 392 break; |
337 case sec_serv_conf: | 393 case sec_serv_conf: |
338 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); | 394 if (gcm_on) { |
339 crypto_policy_set_rtcp_default(&policy.rtcp); | 395 » printf("error: GCM mode must always be used with auth enabled\n"); |
| 396 » return -1; |
| 397 } else { |
| 398 » switch (key_size) { |
| 399 » case 128: |
| 400 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); |
| 401 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 402 » break; |
| 403 » case 256: |
| 404 crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); |
| 405 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 406 » break; |
| 407 » } |
| 408 } |
340 break; | 409 break; |
341 case sec_serv_auth: | 410 case sec_serv_auth: |
342 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); | 411 if (gcm_on) { |
343 crypto_policy_set_rtcp_default(&policy.rtcp); | 412 #ifdef OPENSSL |
| 413 » switch (key_size) { |
| 414 » case 128: |
| 415 » crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); |
| 416 » crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp); |
| 417 » break; |
| 418 » case 256: |
| 419 » crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); |
| 420 » crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp); |
| 421 » break; |
| 422 » } |
| 423 #else |
| 424 » printf("error: GCM mode only supported when using the OpenSSL crypto eng
ine.\n"); |
| 425 » return 0; |
| 426 #endif |
| 427 } else { |
| 428 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); |
| 429 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 430 } |
344 break; | 431 break; |
345 default: | 432 default: |
346 printf("error: unknown security service requested\n"); | 433 printf("error: unknown security service requested\n"); |
347 return -1; | 434 return -1; |
348 } | 435 } |
349 policy.ssrc.type = ssrc_specific; | 436 policy.ssrc.type = ssrc_specific; |
350 policy.ssrc.value = ssrc; | 437 policy.ssrc.value = ssrc; |
351 policy.key = (uint8_t *) key; | 438 policy.key = (uint8_t *) key; |
352 policy.ekt = NULL; | 439 policy.ekt = NULL; |
353 policy.next = NULL; | 440 policy.next = NULL; |
354 policy.window_size = 128; | 441 policy.window_size = 128; |
355 policy.allow_repeat_tx = 0; | 442 policy.allow_repeat_tx = 0; |
356 policy.rtp.sec_serv = sec_servs; | 443 policy.rtp.sec_serv = sec_servs; |
357 policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ | 444 policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ |
358 | 445 |
| 446 if (gcm_on && tag_size != 8) { |
| 447 policy.rtp.auth_tag_len = tag_size; |
| 448 } |
| 449 |
359 /* | 450 /* |
360 * read key from hexadecimal on command line into an octet string | 451 * read key from hexadecimal or base64 on command line into an octet string |
361 */ | 452 */ |
362 len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2); | 453 if (b64_input) { |
363 | 454 int pad; |
| 455 expected_len = (policy.rtp.cipher_key_len*4)/3; |
| 456 len = base64_string_to_octet_string(key, &pad, input_key, expected_len); |
| 457 if (pad != 0) { |
| 458 fprintf(stderr, "error: padding in base64 unexpected\n"); |
| 459 exit(1); |
| 460 } |
| 461 } else { |
| 462 expected_len = policy.rtp.cipher_key_len*2; |
| 463 len = hex_string_to_octet_string(key, input_key, expected_len); |
| 464 } |
364 /* check that hex string is the right length */ | 465 /* check that hex string is the right length */ |
365 if (len < MASTER_KEY_LEN*2) { | 466 if (len < expected_len) { |
366 fprintf(stderr, | 467 fprintf(stderr, |
367 "error: too few digits in key/salt " | 468 "error: too few digits in key/salt " |
368 » "(should be %d hexadecimal digits, found %d)\n", | 469 » "(should be %d digits, found %d)\n", |
369 » MASTER_KEY_LEN*2, len); | 470 » expected_len, len); |
370 exit(1); | 471 exit(1); |
371 } | 472 } |
372 if (strlen(input_key) > MASTER_KEY_LEN*2) { | 473 if (strlen(input_key) > policy.rtp.cipher_key_len*2) { |
373 fprintf(stderr, | 474 fprintf(stderr, |
374 "error: too many digits in key/salt " | 475 "error: too many digits in key/salt " |
375 "(should be %d hexadecimal digits, found %u)\n", | 476 "(should be %d hexadecimal digits, found %u)\n", |
376 » MASTER_KEY_LEN*2, (unsigned)strlen(input_key)); | 477 » policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key)); |
377 exit(1); | 478 exit(1); |
378 } | 479 } |
379 | 480 |
380 printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); | 481 printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); |
381 printf("%s\n", octet_string_hex_string(key+16, 14)); | 482 printf("%s\n", octet_string_hex_string(key+16, 14)); |
382 | 483 |
383 } else { | 484 } else { |
384 /* | 485 /* |
385 * we're not providing security services, so set the policy to the | 486 * we're not providing security services, so set the policy to the |
386 * null policy | 487 * null policy |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 } | 635 } |
535 | 636 |
536 | 637 |
537 void | 638 void |
538 usage(char *string) { | 639 usage(char *string) { |
539 | 640 |
540 printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] " | 641 printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] " |
541 "[-s | -r] dest_ip dest_port\n" | 642 "[-s | -r] dest_ip dest_port\n" |
542 "or %s -l\n" | 643 "or %s -l\n" |
543 "where -a use message authentication\n" | 644 "where -a use message authentication\n" |
544 » " -e use encryption\n" | 645 » " -e <key size> use encryption (use 128 or 256 for key size)\n" |
545 » " -k <key> sets the srtp master key\n" | 646 » " -g Use AES-GCM mode (must be used with -e)\n" |
| 647 » " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n" |
| 648 » " -k <key> sets the srtp master key given in hexadecimal\n" |
| 649 » " -b <key> sets the srtp master key given in base64\n" |
546 " -s act as rtp sender\n" | 650 " -s act as rtp sender\n" |
547 " -r act as rtp receiver\n" | 651 " -r act as rtp receiver\n" |
548 " -l list debug modules\n" | 652 " -l list debug modules\n" |
549 " -d <debug> turn on debugging for module <debug>\n", | 653 " -d <debug> turn on debugging for module <debug>\n", |
550 string, string); | 654 string, string); |
551 exit(1); | 655 exit(1); |
552 | 656 |
553 } | 657 } |
554 | 658 |
555 | 659 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 } | 700 } |
597 #else | 701 #else |
598 if (signal(SIGTERM, handle_signal) == SIG_ERR) { | 702 if (signal(SIGTERM, handle_signal) == SIG_ERR) { |
599 fprintf(stderr, "%s: error setting up signal handler", name); | 703 fprintf(stderr, "%s: error setting up signal handler", name); |
600 perror(""); | 704 perror(""); |
601 return -1; | 705 return -1; |
602 } | 706 } |
603 #endif | 707 #endif |
604 return 0; | 708 return 0; |
605 } | 709 } |
OLD | NEW |