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; |
157 char *address = NULL; | 164 char *address = NULL; |
158 char key[MAX_KEY_LEN]; | 165 char key[MAX_KEY_LEN]; |
159 unsigned short port = 0; | 166 unsigned short port = 0; |
160 rtp_sender_t snd; | 167 rtp_sender_t snd; |
161 srtp_policy_t policy; | 168 srtp_policy_t policy; |
162 err_status_t status; | 169 err_status_t status; |
163 int len; | 170 int len; |
164 int do_list_mods = 0; | 171 int do_list_mods = 0; |
165 uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ | 172 uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */ |
166 #ifdef RTPW_USE_WINSOCK2 | 173 #ifdef RTPW_USE_WINSOCK2 |
167 WORD wVersionRequested = MAKEWORD(2, 0); | 174 WORD wVersionRequested = MAKEWORD(2, 0); |
168 WSADATA wsaData; | 175 WSADATA wsaData; |
169 | 176 |
170 ret = WSAStartup(wVersionRequested, &wsaData); | 177 ret = WSAStartup(wVersionRequested, &wsaData); |
171 if (ret != 0) { | 178 if (ret != 0) { |
172 fprintf(stderr, "error: WSAStartup() failed: %d\n", ret); | 179 fprintf(stderr, "error: WSAStartup() failed: %d\n", ret); |
173 exit(1); | 180 exit(1); |
174 } | 181 } |
175 #endif | 182 #endif |
176 | 183 |
| 184 printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); |
| 185 |
177 if (setup_signal_handler(argv[0]) != 0) { | 186 if (setup_signal_handler(argv[0]) != 0) { |
178 exit(1); | 187 exit(1); |
179 } | 188 } |
180 | 189 |
181 /* initialize srtp library */ | 190 /* initialize srtp library */ |
182 status = srtp_init(); | 191 status = srtp_init(); |
183 if (status) { | 192 if (status) { |
184 printf("error: srtp initialization failed with error code %d\n", status); | 193 printf("error: srtp initialization failed with error code %d\n", status); |
185 exit(1); | 194 exit(1); |
186 } | 195 } |
187 | 196 |
188 /* check args */ | 197 /* check args */ |
189 while (1) { | 198 while (1) { |
190 c = getopt_s(argc, argv, "k:rsaeld:"); | 199 c = getopt_s(argc, argv, "k:rsgt:ae:ld:"); |
191 if (c == -1) { | 200 if (c == -1) { |
192 break; | 201 break; |
193 } | 202 } |
194 switch (c) { | 203 switch (c) { |
195 case 'k': | 204 case 'k': |
196 input_key = optarg_s; | 205 input_key = optarg_s; |
197 break; | 206 break; |
198 case 'e': | 207 case 'e': |
| 208 key_size = atoi(optarg_s); |
| 209 if (key_size != 128 && key_size != 256) { |
| 210 printf("error: encryption key size must be 128 or 256 (%d)\n", key_size)
; |
| 211 exit(1); |
| 212 } |
199 sec_servs |= sec_serv_conf; | 213 sec_servs |= sec_serv_conf; |
200 break; | 214 break; |
| 215 case 't': |
| 216 tag_size = atoi(optarg_s); |
| 217 if (tag_size != 8 && tag_size != 16) { |
| 218 printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size); |
| 219 exit(1); |
| 220 } |
| 221 break; |
201 case 'a': | 222 case 'a': |
202 sec_servs |= sec_serv_auth; | 223 sec_servs |= sec_serv_auth; |
203 break; | 224 break; |
| 225 case 'g': |
| 226 gcm_on = 1; |
| 227 sec_servs |= sec_serv_auth; |
| 228 break; |
204 case 'r': | 229 case 'r': |
205 prog_type = receiver; | 230 prog_type = receiver; |
206 break; | 231 break; |
207 case 's': | 232 case 's': |
208 prog_type = sender; | 233 prog_type = sender; |
209 break; | 234 break; |
210 case 'd': | 235 case 'd': |
211 status = crypto_kernel_set_debug_module(optarg_s, 1); | 236 status = crypto_kernel_set_debug_module(optarg_s, 1); |
212 if (status) { | 237 if (status) { |
213 printf("error: set debug module (%s) failed\n", optarg_s); | 238 printf("error: set debug module (%s) failed\n", optarg_s); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 | 349 |
325 /* set up the srtp policy and master key */ | 350 /* set up the srtp policy and master key */ |
326 if (sec_servs) { | 351 if (sec_servs) { |
327 /* | 352 /* |
328 * create policy structure, using the default mechanisms but | 353 * create policy structure, using the default mechanisms but |
329 * with only the security services requested on the command line, | 354 * with only the security services requested on the command line, |
330 * using the right SSRC value | 355 * using the right SSRC value |
331 */ | 356 */ |
332 switch (sec_servs) { | 357 switch (sec_servs) { |
333 case sec_serv_conf_and_auth: | 358 case sec_serv_conf_and_auth: |
334 crypto_policy_set_rtp_default(&policy.rtp); | 359 if (gcm_on) { |
335 crypto_policy_set_rtcp_default(&policy.rtcp); | 360 #ifdef OPENSSL |
| 361 » switch (key_size) { |
| 362 » case 128: |
| 363 » crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); |
| 364 » crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); |
| 365 » break; |
| 366 » case 256: |
| 367 » crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); |
| 368 » crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); |
| 369 » break; |
| 370 » } |
| 371 #else |
| 372 » printf("error: GCM mode only supported when using the OpenSSL crypto eng
ine.\n"); |
| 373 » return 0; |
| 374 #endif |
| 375 } else { |
| 376 » switch (key_size) { |
| 377 » case 128: |
| 378 crypto_policy_set_rtp_default(&policy.rtp); |
| 379 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 380 » break; |
| 381 » case 256: |
| 382 crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); |
| 383 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 384 » break; |
| 385 » } |
| 386 } |
336 break; | 387 break; |
337 case sec_serv_conf: | 388 case sec_serv_conf: |
338 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); | 389 if (gcm_on) { |
339 crypto_policy_set_rtcp_default(&policy.rtcp); | 390 » printf("error: GCM mode must always be used with auth enabled\n"); |
| 391 » return -1; |
| 392 } else { |
| 393 » switch (key_size) { |
| 394 » case 128: |
| 395 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); |
| 396 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 397 » break; |
| 398 » case 256: |
| 399 crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); |
| 400 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 401 » break; |
| 402 » } |
| 403 } |
340 break; | 404 break; |
341 case sec_serv_auth: | 405 case sec_serv_auth: |
342 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); | 406 if (gcm_on) { |
343 crypto_policy_set_rtcp_default(&policy.rtcp); | 407 #ifdef OPENSSL |
| 408 » switch (key_size) { |
| 409 » case 128: |
| 410 » crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); |
| 411 » crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp); |
| 412 » break; |
| 413 » case 256: |
| 414 » crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); |
| 415 » crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp); |
| 416 » break; |
| 417 » } |
| 418 #else |
| 419 » printf("error: GCM mode only supported when using the OpenSSL crypto eng
ine.\n"); |
| 420 » return 0; |
| 421 #endif |
| 422 } else { |
| 423 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); |
| 424 crypto_policy_set_rtcp_default(&policy.rtcp); |
| 425 } |
344 break; | 426 break; |
345 default: | 427 default: |
346 printf("error: unknown security service requested\n"); | 428 printf("error: unknown security service requested\n"); |
347 return -1; | 429 return -1; |
348 } | 430 } |
349 policy.ssrc.type = ssrc_specific; | 431 policy.ssrc.type = ssrc_specific; |
350 policy.ssrc.value = ssrc; | 432 policy.ssrc.value = ssrc; |
351 policy.key = (uint8_t *) key; | 433 policy.key = (uint8_t *) key; |
352 policy.ekt = NULL; | 434 policy.ekt = NULL; |
353 policy.next = NULL; | 435 policy.next = NULL; |
354 policy.window_size = 128; | 436 policy.window_size = 128; |
355 policy.allow_repeat_tx = 0; | 437 policy.allow_repeat_tx = 0; |
356 policy.rtp.sec_serv = sec_servs; | 438 policy.rtp.sec_serv = sec_servs; |
357 policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ | 439 policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ |
358 | 440 |
| 441 if (gcm_on && tag_size != 8) { |
| 442 policy.rtp.auth_tag_len = tag_size; |
| 443 } |
| 444 |
359 /* | 445 /* |
360 * read key from hexadecimal on command line into an octet string | 446 * read key from hexadecimal on command line into an octet string |
361 */ | 447 */ |
362 len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2); | 448 len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2
); |
363 | 449 |
364 /* check that hex string is the right length */ | 450 /* check that hex string is the right length */ |
365 if (len < MASTER_KEY_LEN*2) { | 451 if (len < policy.rtp.cipher_key_len*2) { |
366 fprintf(stderr, | 452 fprintf(stderr, |
367 "error: too few digits in key/salt " | 453 "error: too few digits in key/salt " |
368 "(should be %d hexadecimal digits, found %d)\n", | 454 "(should be %d hexadecimal digits, found %d)\n", |
369 » MASTER_KEY_LEN*2, len); | 455 » policy.rtp.cipher_key_len*2, len); |
370 exit(1); | 456 exit(1); |
371 } | 457 } |
372 if (strlen(input_key) > MASTER_KEY_LEN*2) { | 458 if (strlen(input_key) > policy.rtp.cipher_key_len*2) { |
373 fprintf(stderr, | 459 fprintf(stderr, |
374 "error: too many digits in key/salt " | 460 "error: too many digits in key/salt " |
375 "(should be %d hexadecimal digits, found %u)\n", | 461 "(should be %d hexadecimal digits, found %u)\n", |
376 » MASTER_KEY_LEN*2, (unsigned)strlen(input_key)); | 462 » policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key)); |
377 exit(1); | 463 exit(1); |
378 } | 464 } |
379 | 465 |
380 printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); | 466 printf("set master key/salt to %s/", octet_string_hex_string(key, 16)); |
381 printf("%s\n", octet_string_hex_string(key+16, 14)); | 467 printf("%s\n", octet_string_hex_string(key+16, 14)); |
382 | 468 |
383 } else { | 469 } else { |
384 /* | 470 /* |
385 * we're not providing security services, so set the policy to the | 471 * we're not providing security services, so set the policy to the |
386 * null policy | 472 * null policy |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 } | 620 } |
535 | 621 |
536 | 622 |
537 void | 623 void |
538 usage(char *string) { | 624 usage(char *string) { |
539 | 625 |
540 printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] " | 626 printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] " |
541 "[-s | -r] dest_ip dest_port\n" | 627 "[-s | -r] dest_ip dest_port\n" |
542 "or %s -l\n" | 628 "or %s -l\n" |
543 "where -a use message authentication\n" | 629 "where -a use message authentication\n" |
544 » " -e use encryption\n" | 630 » " -e <key size> use encryption (use 128 or 256 for key size)\n" |
| 631 » " -g Use AES-GCM mode (must be used with -e)\n" |
| 632 » " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n" |
545 " -k <key> sets the srtp master key\n" | 633 " -k <key> sets the srtp master key\n" |
546 " -s act as rtp sender\n" | 634 " -s act as rtp sender\n" |
547 " -r act as rtp receiver\n" | 635 " -r act as rtp receiver\n" |
548 " -l list debug modules\n" | 636 " -l list debug modules\n" |
549 " -d <debug> turn on debugging for module <debug>\n", | 637 " -d <debug> turn on debugging for module <debug>\n", |
550 string, string); | 638 string, string); |
551 exit(1); | 639 exit(1); |
552 | 640 |
553 } | 641 } |
554 | 642 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 } | 684 } |
597 #else | 685 #else |
598 if (signal(SIGTERM, handle_signal) == SIG_ERR) { | 686 if (signal(SIGTERM, handle_signal) == SIG_ERR) { |
599 fprintf(stderr, "%s: error setting up signal handler", name); | 687 fprintf(stderr, "%s: error setting up signal handler", name); |
600 perror(""); | 688 perror(""); |
601 return -1; | 689 return -1; |
602 } | 690 } |
603 #endif | 691 #endif |
604 return 0; | 692 return 0; |
605 } | 693 } |
OLD | NEW |