rtp_decoder.c (26470B)
1 /* 2 * rtp_decoder.c 3 * 4 * decoder structures and functions for SRTP pcap decoder 5 * 6 * Example: 7 * $ wget --no-check-certificate \ 8 * https://raw.githubusercontent.com/gteissier/srtp-decrypt/master/marseillaise-srtp.pcap 9 * $ ./test/rtp_decoder -a -t 10 -e 128 -b \ 10 * aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz \ 11 * < ~/marseillaise-srtp.pcap \ 12 * | text2pcap -t "%M:%S." -u 10000,10000 - - \ 13 * > ./marseillaise-rtp.pcap 14 * 15 * There is also a different way of setting up key size and tag size 16 * based upon RFC 4568 crypto suite specification, i.e.: 17 * 18 * $ ./test/rtp_decoder -s AES_CM_128_HMAC_SHA1_80 -b \ 19 * aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz ... 20 * 21 * Audio can be extracted using extractaudio utility from the RTPproxy 22 * package: 23 * 24 * $ extractaudio -A ./marseillaise-rtp.pcap ./marseillaise-out.wav 25 * 26 * Bernardo Torres <bernardo@torresautomacao.com.br> 27 * 28 * Some structure and code from https://github.com/gteissier/srtp-decrypt 29 */ 30 /* 31 * 32 * Copyright (c) 2001-2017 Cisco Systems, Inc. 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 39 * Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 42 * Redistributions in binary form must reproduce the above 43 * copyright notice, this list of conditions and the following 44 * disclaimer in the documentation and/or other materials provided 45 * with the distribution. 46 * 47 * Neither the name of the Cisco Systems, Inc. nor the names of its 48 * contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 54 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 55 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 56 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 57 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 58 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 60 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 62 * OF THE POSSIBILITY OF SUCH DAMAGE. 63 * 64 */ 65 #include "getopt_s.h" /* for local getopt() */ 66 #include <assert.h> /* for assert() */ 67 68 #include <pcap.h> 69 #include "rtp_decoder.h" 70 #include "util.h" 71 72 #ifndef timersub 73 #define timersub(a, b, result) \ 74 do { \ 75 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 76 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 77 if ((result)->tv_usec < 0) { \ 78 --(result)->tv_sec; \ 79 (result)->tv_usec += 1000000; \ 80 } \ 81 } while (0) 82 #endif 83 84 #define MAX_KEY_LEN 96 85 #define MAX_FILTER 256 86 #define MAX_FILE 255 87 88 struct srtp_crypto_suite { 89 const char *can_name; 90 int gcm_on; 91 int key_size; 92 int tag_size; 93 }; 94 95 static struct srtp_crypto_suite srtp_crypto_suites[] = { 96 #if 0 97 {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4}, 98 #endif 99 { .can_name = "AES_CM_128_HMAC_SHA1_32", 100 .gcm_on = 0, 101 .key_size = 128, 102 .tag_size = 4 }, 103 { .can_name = "AES_CM_128_HMAC_SHA1_80", 104 .gcm_on = 0, 105 .key_size = 128, 106 .tag_size = 10 }, 107 { .can_name = "AES_192_CM_HMAC_SHA1_32", 108 .gcm_on = 0, 109 .key_size = 192, 110 .tag_size = 4 }, 111 { .can_name = "AES_192_CM_HMAC_SHA1_80", 112 .gcm_on = 0, 113 .key_size = 192, 114 .tag_size = 10 }, 115 { .can_name = "AES_256_CM_HMAC_SHA1_32", 116 .gcm_on = 0, 117 .key_size = 256, 118 .tag_size = 4 }, 119 { .can_name = "AES_256_CM_HMAC_SHA1_80", 120 .gcm_on = 0, 121 .key_size = 256, 122 .tag_size = 10 }, 123 { .can_name = "AEAD_AES_128_GCM", 124 .gcm_on = 1, 125 .key_size = 128, 126 .tag_size = 16 }, 127 { .can_name = "AEAD_AES_256_GCM", 128 .gcm_on = 1, 129 .key_size = 256, 130 .tag_size = 16 }, 131 { .can_name = NULL } 132 }; 133 134 void rtp_decoder_srtp_log_handler(srtp_log_level_t level, 135 const char *msg, 136 void *data) 137 { 138 (void)data; 139 char level_char = '?'; 140 switch (level) { 141 case srtp_log_level_error: 142 level_char = 'e'; 143 break; 144 case srtp_log_level_warning: 145 level_char = 'w'; 146 break; 147 case srtp_log_level_info: 148 level_char = 'i'; 149 break; 150 case srtp_log_level_debug: 151 level_char = 'd'; 152 break; 153 } 154 fprintf(stderr, "SRTP-LOG [%c]: %s\n", level_char, msg); 155 } 156 157 int main(int argc, char *argv[]) 158 { 159 char errbuf[PCAP_ERRBUF_SIZE]; 160 bpf_u_int32 pcap_net = 0; 161 pcap_t *pcap_handle; 162 #if BEW 163 struct sockaddr_in local; 164 #endif 165 srtp_sec_serv_t sec_servs = sec_serv_none; 166 int c; 167 struct srtp_crypto_suite scs, *i_scsp; 168 scs.key_size = 128; 169 scs.tag_size = 0; 170 int gcm_on = 0; 171 char *input_key = NULL; 172 int b64_input = 0; 173 char key[MAX_KEY_LEN]; 174 struct bpf_program fp; 175 char filter_exp[MAX_FILTER] = ""; 176 char pcap_file[MAX_FILE] = "-"; 177 size_t rtp_packet_offset = DEFAULT_RTP_OFFSET; 178 rtp_decoder_t dec; 179 srtp_policy_t policy = { 0 }; 180 rtp_decoder_mode_t mode = mode_rtp; 181 srtp_ssrc_t ssrc = { ssrc_any_inbound, 0 }; 182 uint32_t roc = 0; 183 srtp_err_status_t status; 184 int len; 185 int expected_len; 186 int do_list_mods = 0; 187 188 fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(), 189 srtp_get_version()); 190 191 /* initialize srtp library */ 192 status = srtp_init(); 193 if (status) { 194 fprintf(stderr, 195 "error: srtp initialization failed with error code %d\n", 196 status); 197 exit(1); 198 } 199 200 status = srtp_install_log_handler(rtp_decoder_srtp_log_handler, NULL); 201 if (status) { 202 fprintf(stderr, "error: install log handler failed\n"); 203 exit(1); 204 } 205 206 /* check args */ 207 while (1) { 208 c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:c:m:p:o:s:r:"); 209 if (c == -1) { 210 break; 211 } 212 switch (c) { 213 case 'b': 214 b64_input = 1; 215 /* fall thru */ 216 case 'k': 217 input_key = optarg_s; 218 break; 219 case 'e': 220 scs.key_size = atoi(optarg_s); 221 if (scs.key_size != 128 && scs.key_size != 192 && 222 scs.key_size != 256) { 223 fprintf( 224 stderr, 225 "error: encryption key size must be 128, 192 or 256 (%d)\n", 226 scs.key_size); 227 exit(1); 228 } 229 input_key = malloc(scs.key_size); 230 sec_servs |= sec_serv_conf; 231 break; 232 case 't': 233 scs.tag_size = atoi(optarg_s); 234 break; 235 case 'a': 236 sec_servs |= sec_serv_auth; 237 break; 238 case 'g': 239 gcm_on = 1; 240 sec_servs |= sec_serv_auth; 241 break; 242 case 'd': 243 status = srtp_set_debug_module(optarg_s, 1); 244 if (status) { 245 fprintf(stderr, "error: set debug module (%s) failed\n", 246 optarg_s); 247 exit(1); 248 } 249 break; 250 case 'f': 251 if (strlen(optarg_s) > MAX_FILTER) { 252 fprintf(stderr, "error: filter bigger than %d characters\n", 253 MAX_FILTER); 254 exit(1); 255 } 256 fprintf(stderr, "Setting filter as %s\n", optarg_s); 257 strcpy(filter_exp, optarg_s); 258 break; 259 case 'l': 260 do_list_mods = 1; 261 break; 262 case 'c': 263 for (i_scsp = &srtp_crypto_suites[0]; i_scsp->can_name != NULL; 264 i_scsp++) { 265 if (strcasecmp(i_scsp->can_name, optarg_s) == 0) { 266 break; 267 } 268 } 269 if (i_scsp->can_name == NULL) { 270 fprintf(stderr, "Unknown/unsupported crypto suite name %s\n", 271 optarg_s); 272 exit(1); 273 } 274 scs = *i_scsp; 275 input_key = malloc(scs.key_size); 276 sec_servs |= sec_serv_conf | sec_serv_auth; 277 gcm_on = scs.gcm_on; 278 break; 279 case 'm': 280 if (strcasecmp("rtp", optarg_s) == 0) { 281 mode = mode_rtp; 282 } else if (strcasecmp("rtcp", optarg_s) == 0) { 283 mode = mode_rtcp; 284 } else if (strcasecmp("rtcp-mux", optarg_s) == 0) { 285 mode = mode_rtcp_mux; 286 } else { 287 fprintf(stderr, "Unknown/unsupported mode %s\n", optarg_s); 288 exit(1); 289 } 290 break; 291 case 'p': 292 if (strlen(optarg_s) > MAX_FILE) { 293 fprintf(stderr, 294 "error: pcap file path bigger than %d characters\n", 295 MAX_FILE); 296 exit(1); 297 } 298 strcpy(pcap_file, optarg_s); 299 break; 300 case 'o': 301 rtp_packet_offset = atoi(optarg_s); 302 break; 303 case 's': 304 ssrc.type = ssrc_specific; 305 ssrc.value = strtol(optarg_s, NULL, 0); 306 break; 307 case 'r': 308 roc = atoi(optarg_s); 309 break; 310 default: 311 usage(argv[0]); 312 } 313 } 314 315 if (scs.tag_size == 0) { 316 if (gcm_on) { 317 scs.tag_size = 16; 318 } else { 319 scs.tag_size = 10; 320 } 321 } 322 323 if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) { 324 fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", 325 scs.tag_size); 326 exit(1); 327 } 328 329 if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) { 330 fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%d)\n", 331 scs.tag_size); 332 exit(1); 333 } 334 335 if (do_list_mods) { 336 status = srtp_list_debug_modules(); 337 if (status) { 338 fprintf(stderr, "error: list of debug modules failed\n"); 339 exit(1); 340 } 341 return 0; 342 } 343 344 if ((sec_servs && !input_key) || (!sec_servs && input_key)) { 345 /* 346 * a key must be provided if and only if security services have 347 * been requested 348 */ 349 if (input_key == NULL) { 350 fprintf(stderr, "key not provided\n"); 351 } 352 if (!sec_servs) { 353 fprintf(stderr, "no secservs\n"); 354 } 355 fprintf(stderr, "provided\n"); 356 usage(argv[0]); 357 } 358 359 /* report security services selected on the command line */ 360 fprintf(stderr, "security services: "); 361 if (sec_servs & sec_serv_conf) 362 fprintf(stderr, "confidentiality "); 363 if (sec_servs & sec_serv_auth) 364 fprintf(stderr, "message authentication"); 365 if (sec_servs == sec_serv_none) 366 fprintf(stderr, "none"); 367 fprintf(stderr, "\n"); 368 369 /* set up the srtp policy and master key */ 370 if (sec_servs) { 371 /* 372 * create policy structure, using the default mechanisms but 373 * with only the security services requested on the command line, 374 * using the right SSRC value 375 */ 376 switch (sec_servs) { 377 case sec_serv_conf_and_auth: 378 if (gcm_on) { 379 #ifdef OPENSSL 380 switch (scs.key_size) { 381 case 128: 382 if (scs.tag_size == 16) { 383 srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); 384 srtp_crypto_policy_set_aes_gcm_128_16_auth( 385 &policy.rtcp); 386 } else { 387 srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); 388 srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); 389 } 390 break; 391 case 256: 392 if (scs.tag_size == 16) { 393 srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); 394 srtp_crypto_policy_set_aes_gcm_256_16_auth( 395 &policy.rtcp); 396 } else { 397 srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); 398 srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); 399 } 400 break; 401 } 402 #else 403 fprintf(stderr, "error: GCM mode only supported when using the " 404 "OpenSSL crypto engine.\n"); 405 return 0; 406 #endif 407 } else { 408 switch (scs.key_size) { 409 case 128: 410 if (scs.tag_size == 4) { 411 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32( 412 &policy.rtp); 413 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( 414 &policy.rtcp); 415 } else { 416 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( 417 &policy.rtp); 418 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( 419 &policy.rtcp); 420 } 421 break; 422 case 192: 423 #ifdef OPENSSL 424 if (scs.tag_size == 4) { 425 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32( 426 &policy.rtp); 427 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( 428 &policy.rtcp); 429 } else { 430 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( 431 &policy.rtp); 432 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( 433 &policy.rtcp); 434 } 435 #else 436 fprintf(stderr, 437 "error: AES 192 mode only supported when using the " 438 "OpenSSL crypto engine.\n"); 439 return 0; 440 441 #endif 442 break; 443 case 256: 444 if (scs.tag_size == 4) { 445 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32( 446 &policy.rtp); 447 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( 448 &policy.rtcp); 449 } else { 450 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( 451 &policy.rtp); 452 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( 453 &policy.rtcp); 454 } 455 break; 456 } 457 } 458 break; 459 case sec_serv_conf: 460 if (gcm_on) { 461 fprintf( 462 stderr, 463 "error: GCM mode must always be used with auth enabled\n"); 464 return -1; 465 } else { 466 switch (scs.key_size) { 467 case 128: 468 srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); 469 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( 470 &policy.rtcp); 471 break; 472 case 192: 473 #ifdef OPENSSL 474 srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp); 475 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( 476 &policy.rtcp); 477 #else 478 fprintf(stderr, 479 "error: AES 192 mode only supported when using the " 480 "OpenSSL crypto engine.\n"); 481 return 0; 482 483 #endif 484 break; 485 case 256: 486 srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); 487 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( 488 &policy.rtcp); 489 break; 490 } 491 } 492 break; 493 case sec_serv_auth: 494 if (gcm_on) { 495 #ifdef OPENSSL 496 switch (scs.key_size) { 497 case 128: 498 srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); 499 srtp_crypto_policy_set_aes_gcm_128_8_only_auth( 500 &policy.rtcp); 501 break; 502 case 256: 503 srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); 504 srtp_crypto_policy_set_aes_gcm_256_8_only_auth( 505 &policy.rtcp); 506 break; 507 } 508 #else 509 printf("error: GCM mode only supported when using the OpenSSL " 510 "crypto engine.\n"); 511 return 0; 512 #endif 513 } else { 514 srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); 515 srtp_crypto_policy_set_rtcp_default(&policy.rtcp); 516 } 517 break; 518 default: 519 fprintf(stderr, "error: unknown security service requested\n"); 520 return -1; 521 } 522 523 policy.key = (uint8_t *)key; 524 policy.next = NULL; 525 policy.window_size = 128; 526 policy.allow_repeat_tx = 0; 527 policy.rtp.sec_serv = sec_servs; 528 policy.rtcp.sec_serv = 529 sec_servs; // sec_serv_none; /* we don't do RTCP anyway */ 530 fprintf(stderr, "setting tag len %d\n", scs.tag_size); 531 policy.rtp.auth_tag_len = scs.tag_size; 532 533 if (gcm_on && scs.tag_size != 8) { 534 fprintf(stderr, "set tag len %d\n", scs.tag_size); 535 policy.rtp.auth_tag_len = scs.tag_size; 536 } 537 538 /* 539 * read key from hexadecimal or base64 on command line into an octet 540 * string 541 */ 542 if (b64_input) { 543 int pad; 544 expected_len = policy.rtp.cipher_key_len * 4 / 3; 545 len = base64_string_to_octet_string(key, &pad, input_key, 546 strlen(input_key)); 547 } else { 548 expected_len = policy.rtp.cipher_key_len * 2; 549 len = hex_string_to_octet_string(key, input_key, expected_len); 550 } 551 /* check that hex string is the right length */ 552 if (len < expected_len) { 553 fprintf(stderr, 554 "error: too few digits in key/salt " 555 "(should be %d digits, found %d)\n", 556 expected_len, len); 557 exit(1); 558 } 559 if (strlen(input_key) > (size_t)policy.rtp.cipher_key_len * 2) { 560 fprintf(stderr, 561 "error: too many digits in key/salt " 562 "(should be %d hexadecimal digits, found %u)\n", 563 policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key)); 564 exit(1); 565 } 566 567 int key_octets = (scs.key_size / 8); 568 int salt_octets = policy.rtp.cipher_key_len - key_octets; 569 fprintf(stderr, "set master key/salt to %s/", 570 octet_string_hex_string(key, key_octets)); 571 fprintf(stderr, "%s\n", 572 octet_string_hex_string(key + key_octets, salt_octets)); 573 574 } else { 575 fprintf(stderr, 576 "error: neither encryption or authentication were selected\n"); 577 exit(1); 578 } 579 580 policy.ssrc = ssrc; 581 582 if (roc != 0 && policy.ssrc.type != ssrc_specific) { 583 fprintf(stderr, "error: setting ROC (-r) requires -s <ssrc>\n"); 584 exit(1); 585 } 586 587 pcap_handle = pcap_open_offline(pcap_file, errbuf); 588 589 if (!pcap_handle) { 590 fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); 591 exit(1); 592 } 593 assert(pcap_handle != NULL); 594 if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1) { 595 fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, 596 pcap_geterr(pcap_handle)); 597 return (2); 598 } 599 if (pcap_setfilter(pcap_handle, &fp) == -1) { 600 fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp, 601 pcap_geterr(pcap_handle)); 602 return (2); 603 } 604 dec = rtp_decoder_alloc(); 605 if (dec == NULL) { 606 fprintf(stderr, "error: malloc() failed\n"); 607 exit(1); 608 } 609 fprintf(stderr, "Starting decoder\n"); 610 if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset, roc)) { 611 fprintf(stderr, "error: init failed\n"); 612 exit(1); 613 } 614 615 pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); 616 617 if (dec->mode == mode_rtp || dec->mode == mode_rtcp_mux) { 618 fprintf(stderr, "RTP packets decoded: %d\n", dec->rtp_cnt); 619 } 620 if (dec->mode == mode_rtcp || dec->mode == mode_rtcp_mux) { 621 fprintf(stderr, "RTCP packets decoded: %d\n", dec->rtcp_cnt); 622 } 623 fprintf(stderr, "Packet decode errors: %d\n", dec->error_cnt); 624 625 rtp_decoder_deinit(dec); 626 rtp_decoder_dealloc(dec); 627 628 status = srtp_shutdown(); 629 if (status) { 630 fprintf(stderr, "error: srtp shutdown failed with error code %d\n", 631 status); 632 exit(1); 633 } 634 635 return 0; 636 } 637 638 void usage(char *string) 639 { 640 fprintf( 641 stderr, 642 "usage: %s [-d <debug>]* [[-k][-b] <key>] [-a][-t][-e] [-c " 643 "<srtp-crypto-suite>] [-m <mode>] [-s <ssrc> [-r <roc>]]\n" 644 "or %s -l\n" 645 "where -a use message authentication\n" 646 " -e <key size> use encryption (use 128 or 256 for key size)\n" 647 " -g Use AES-GCM mode (must be used with -e)\n" 648 " -t <tag size> Tag size to use (in GCM mode use 8 or 16)\n" 649 " -k <key> sets the srtp master key given in hexadecimal\n" 650 " -b <key> sets the srtp master key given in base64\n" 651 " -l list debug modules\n" 652 " -f \"<pcap filter>\" to filter only the desired SRTP packets\n" 653 " -d <debug> turn on debugging for module <debug>\n" 654 " -c \"<srtp-crypto-suite>\" to set both key and tag size based\n" 655 " on RFC4568-style crypto suite specification\n" 656 " -m <mode> set the mode to be one of [rtp]|rtcp|rtcp-mux\n" 657 " -p <pcap file> path to pcap file (defaults to stdin)\n" 658 " -o byte offset of RTP packet in capture (defaults to 42)\n" 659 " -s <ssrc> restrict decrypting to the given SSRC (in host byte " 660 "order)\n" 661 " -r <roc> initial rollover counter, requires -s <ssrc> " 662 "(defaults to 0)\n", 663 string, string); 664 exit(1); 665 } 666 667 rtp_decoder_t rtp_decoder_alloc(void) 668 { 669 return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t)); 670 } 671 672 void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) 673 { 674 free(rtp_ctx); 675 } 676 677 int rtp_decoder_deinit(rtp_decoder_t decoder) 678 { 679 if (decoder->srtp_ctx) { 680 return srtp_dealloc(decoder->srtp_ctx); 681 } 682 return 0; 683 } 684 685 int rtp_decoder_init(rtp_decoder_t dcdr, 686 srtp_policy_t policy, 687 rtp_decoder_mode_t mode, 688 size_t rtp_packet_offset, 689 uint32_t roc) 690 { 691 dcdr->rtp_offset = rtp_packet_offset; 692 dcdr->srtp_ctx = NULL; 693 dcdr->start_tv.tv_usec = 0; 694 dcdr->start_tv.tv_sec = 0; 695 dcdr->frame_nr = -1; 696 dcdr->error_cnt = 0; 697 dcdr->rtp_cnt = 0; 698 dcdr->rtcp_cnt = 0; 699 dcdr->mode = mode; 700 dcdr->policy = policy; 701 702 if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) { 703 return 1; 704 } 705 706 if (policy.ssrc.type == ssrc_specific && roc != 0) { 707 if (srtp_set_stream_roc(dcdr->srtp_ctx, policy.ssrc.value, roc)) { 708 return 1; 709 } 710 } 711 return 0; 712 } 713 714 /* 715 * decodes key as base64 716 */ 717 718 void hexdump(const void *ptr, size_t size) 719 { 720 size_t i, j; 721 const unsigned char *cptr = ptr; 722 723 for (i = 0; i < size; i += 16) { 724 fprintf(stdout, "%04x ", (unsigned int)i); 725 for (j = 0; j < 16 && i + j < size; j++) { 726 fprintf(stdout, "%02x ", cptr[i + j]); 727 } 728 fprintf(stdout, "\n"); 729 } 730 } 731 732 void rtp_decoder_handle_pkt(u_char *arg, 733 const struct pcap_pkthdr *hdr, 734 const u_char *bytes) 735 { 736 rtp_decoder_t dcdr = (rtp_decoder_t)arg; 737 rtp_msg_t message; 738 int rtp; 739 int pktsize; 740 struct timeval delta; 741 int octets_recvd; 742 srtp_err_status_t status; 743 dcdr->frame_nr++; 744 745 if ((dcdr->start_tv.tv_sec == 0) && (dcdr->start_tv.tv_usec == 0)) { 746 dcdr->start_tv = hdr->ts; 747 } 748 749 if (hdr->caplen < dcdr->rtp_offset) { 750 return; 751 } 752 const void *rtp_packet = bytes + dcdr->rtp_offset; 753 754 memcpy((void *)&message, rtp_packet, hdr->caplen - dcdr->rtp_offset); 755 pktsize = hdr->caplen - dcdr->rtp_offset; 756 octets_recvd = pktsize; 757 758 if (octets_recvd == -1) { 759 return; 760 } 761 762 if (dcdr->mode == mode_rtp) { 763 rtp = 1; 764 } else if (dcdr->mode == mode_rtcp) { 765 rtp = 0; 766 } else { 767 rtp = 1; 768 if (octets_recvd >= 2) { 769 /* rfc5761 */ 770 u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f; 771 rtp = payload_type < 64 || payload_type > 95; 772 } 773 } 774 775 if (rtp) { 776 /* verify rtp header */ 777 if (message.header.version != 2) { 778 return; 779 } 780 781 status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd); 782 if (status) { 783 dcdr->error_cnt++; 784 return; 785 } 786 dcdr->rtp_cnt++; 787 } else { 788 status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd); 789 if (status) { 790 dcdr->error_cnt++; 791 return; 792 } 793 dcdr->rtcp_cnt++; 794 } 795 timersub(&hdr->ts, &dcdr->start_tv, &delta); 796 fprintf(stdout, "%02ld:%02d.%06ld\n", (long)(delta.tv_sec / 60), 797 (int)(delta.tv_sec % 60), (long)delta.tv_usec); 798 hexdump(&message, octets_recvd); 799 }