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
87 struct srtp_crypto_suite {
88 const char *can_name;
89 int gcm_on;
90 int key_size;
91 int tag_size;
92 };
93
94 static struct srtp_crypto_suite srtp_crypto_suites[] = {
95 #if 0
96 {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4},
97 #endif
98 {.can_name = "AES_CM_128_HMAC_SHA1_32",
99 .gcm_on = 0,
100 .key_size = 128,
101 .tag_size = 4 },
102 {.can_name = "AES_CM_128_HMAC_SHA1_80",
103 .gcm_on = 0,
104 .key_size = 128,
105 .tag_size = 10 },
106 {.can_name = "AES_192_CM_HMAC_SHA1_32",
107 .gcm_on = 0,
108 .key_size = 192,
109 .tag_size = 4 },
110 {.can_name = "AES_192_CM_HMAC_SHA1_80",
111 .gcm_on = 0,
112 .key_size = 192,
113 .tag_size = 10 },
114 {.can_name = "AES_256_CM_HMAC_SHA1_32",
115 .gcm_on = 0,
116 .key_size = 256,
117 .tag_size = 4 },
118 {.can_name = "AES_256_CM_HMAC_SHA1_80",
119 .gcm_on = 0,
120 .key_size = 256,
121 .tag_size = 10 },
122 {.can_name = "AEAD_AES_128_GCM",
123 .gcm_on = 1,
124 .key_size = 128,
125 .tag_size = 16 },
126 {.can_name = "AEAD_AES_256_GCM",
127 .gcm_on = 1,
128 .key_size = 256,
129 .tag_size = 16 },
130 {.can_name = NULL }
131 };
132
rtp_decoder_srtp_log_handler(srtp_log_level_t level,const char * msg,void * data)133 void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
134 const char *msg,
135 void *data)
136 {
137 char level_char = '?';
138 switch (level) {
139 case srtp_log_level_error:
140 level_char = 'e';
141 break;
142 case srtp_log_level_warning:
143 level_char = 'w';
144 break;
145 case srtp_log_level_info:
146 level_char = 'i';
147 break;
148 case srtp_log_level_debug:
149 level_char = 'd';
150 break;
151 }
152 fprintf(stderr, "SRTP-LOG [%c]: %s\n", level_char, msg);
153 }
154
main(int argc,char * argv[])155 int main(int argc, char *argv[])
156 {
157 char errbuf[PCAP_ERRBUF_SIZE];
158 bpf_u_int32 pcap_net = 0;
159 pcap_t *pcap_handle;
160 #if BEW
161 struct sockaddr_in local;
162 #endif
163 srtp_sec_serv_t sec_servs = sec_serv_none;
164 int c;
165 struct srtp_crypto_suite scs, *i_scsp;
166 scs.key_size = 128;
167 scs.tag_size = 0;
168 int gcm_on = 0;
169 char *input_key = NULL;
170 int b64_input = 0;
171 char key[MAX_KEY_LEN];
172 struct bpf_program fp;
173 char filter_exp[MAX_FILTER] = "";
174 rtp_decoder_t dec;
175 srtp_policy_t policy = { { 0 } };
176 rtp_decoder_mode_t mode = mode_rtp;
177 srtp_err_status_t status;
178 int len;
179 int expected_len;
180 int do_list_mods = 0;
181
182 fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(),
183 srtp_get_version());
184
185 /* initialize srtp library */
186 status = srtp_init();
187 if (status) {
188 fprintf(stderr,
189 "error: srtp initialization failed with error code %d\n",
190 status);
191 exit(1);
192 }
193
194 status = srtp_install_log_handler(rtp_decoder_srtp_log_handler, NULL);
195 if (status) {
196 fprintf(stderr, "error: install log handler failed\n");
197 exit(1);
198 }
199
200 /* check args */
201 while (1) {
202 c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:m:");
203 if (c == -1) {
204 break;
205 }
206 switch (c) {
207 case 'b':
208 b64_input = 1;
209 /* fall thru */
210 case 'k':
211 input_key = optarg_s;
212 break;
213 case 'e':
214 scs.key_size = atoi(optarg_s);
215 if (scs.key_size != 128 && scs.key_size != 192 &&
216 scs.key_size != 256) {
217 fprintf(
218 stderr,
219 "error: encryption key size must be 128, 192 or 256 (%d)\n",
220 scs.key_size);
221 exit(1);
222 }
223 input_key = malloc(scs.key_size);
224 sec_servs |= sec_serv_conf;
225 break;
226 case 't':
227 scs.tag_size = atoi(optarg_s);
228 break;
229 case 'a':
230 sec_servs |= sec_serv_auth;
231 break;
232 case 'g':
233 gcm_on = 1;
234 sec_servs |= sec_serv_auth;
235 break;
236 case 'd':
237 status = srtp_set_debug_module(optarg_s, 1);
238 if (status) {
239 fprintf(stderr, "error: set debug module (%s) failed\n",
240 optarg_s);
241 exit(1);
242 }
243 break;
244 case 'f':
245 if (strlen(optarg_s) > MAX_FILTER) {
246 fprintf(stderr, "error: filter bigger than %d characters\n",
247 MAX_FILTER);
248 exit(1);
249 }
250 fprintf(stderr, "Setting filter as %s\n", optarg_s);
251 strcpy(filter_exp, optarg_s);
252 break;
253 case 'l':
254 do_list_mods = 1;
255 break;
256 case 's':
257 for (i_scsp = &srtp_crypto_suites[0]; i_scsp->can_name != NULL;
258 i_scsp++) {
259 if (strcasecmp(i_scsp->can_name, optarg_s) == 0) {
260 break;
261 }
262 }
263 if (i_scsp->can_name == NULL) {
264 fprintf(stderr, "Unknown/unsupported crypto suite name %s\n",
265 optarg_s);
266 exit(1);
267 }
268 scs = *i_scsp;
269 input_key = malloc(scs.key_size);
270 sec_servs |= sec_serv_conf | sec_serv_auth;
271 gcm_on = scs.gcm_on;
272 break;
273 case 'm':
274 if (strcasecmp("rtp", optarg_s) == 0) {
275 mode = mode_rtp;
276 } else if (strcasecmp("rtcp", optarg_s) == 0) {
277 mode = mode_rtcp;
278 } else if (strcasecmp("rtcp-mux", optarg_s) == 0) {
279 mode = mode_rtcp_mux;
280 } else {
281 fprintf(stderr, "Unknown/unsupported mode %s\n", optarg_s);
282 exit(1);
283 }
284 break;
285 default:
286 usage(argv[0]);
287 }
288 }
289
290 if (scs.tag_size == 0) {
291 if (gcm_on) {
292 scs.tag_size = 16;
293 } else {
294 scs.tag_size = 10;
295 }
296 }
297
298 if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) {
299 fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n",
300 scs.tag_size);
301 exit(1);
302 }
303
304 if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) {
305 fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%d)\n",
306 scs.tag_size);
307 exit(1);
308 }
309
310 if (do_list_mods) {
311 status = srtp_list_debug_modules();
312 if (status) {
313 fprintf(stderr, "error: list of debug modules failed\n");
314 exit(1);
315 }
316 return 0;
317 }
318
319 if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
320 /*
321 * a key must be provided if and only if security services have
322 * been requested
323 */
324 if (input_key == NULL) {
325 fprintf(stderr, "key not provided\n");
326 }
327 if (!sec_servs) {
328 fprintf(stderr, "no secservs\n");
329 }
330 fprintf(stderr, "provided\n");
331 usage(argv[0]);
332 }
333
334 /* report security services selected on the command line */
335 fprintf(stderr, "security services: ");
336 if (sec_servs & sec_serv_conf)
337 fprintf(stderr, "confidentiality ");
338 if (sec_servs & sec_serv_auth)
339 fprintf(stderr, "message authentication");
340 if (sec_servs == sec_serv_none)
341 fprintf(stderr, "none");
342 fprintf(stderr, "\n");
343
344 /* set up the srtp policy and master key */
345 if (sec_servs) {
346 /*
347 * create policy structure, using the default mechanisms but
348 * with only the security services requested on the command line,
349 * using the right SSRC value
350 */
351 switch (sec_servs) {
352 case sec_serv_conf_and_auth:
353 if (gcm_on) {
354 #ifdef OPENSSL
355 switch (scs.key_size) {
356 case 128:
357 if (scs.tag_size == 16) {
358 srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
359 srtp_crypto_policy_set_aes_gcm_128_16_auth(
360 &policy.rtcp);
361 } else {
362 srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
363 srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
364 }
365 break;
366 case 256:
367 if (scs.tag_size == 16) {
368 srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
369 srtp_crypto_policy_set_aes_gcm_256_16_auth(
370 &policy.rtcp);
371 } else {
372 srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
373 srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
374 }
375 break;
376 }
377 #else
378 fprintf(stderr, "error: GCM mode only supported when using the "
379 "OpenSSL crypto engine.\n");
380 return 0;
381 #endif
382 } else {
383 switch (scs.key_size) {
384 case 128:
385 if (scs.tag_size == 4) {
386 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(
387 &policy.rtp);
388 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
389 &policy.rtcp);
390 } else {
391 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
392 &policy.rtp);
393 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
394 &policy.rtcp);
395 }
396 break;
397 case 192:
398 #ifdef OPENSSL
399 if (scs.tag_size == 4) {
400 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(
401 &policy.rtp);
402 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
403 &policy.rtcp);
404 } else {
405 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
406 &policy.rtp);
407 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
408 &policy.rtcp);
409 }
410 #else
411 fprintf(stderr,
412 "error: AES 192 mode only supported when using the "
413 "OpenSSL crypto engine.\n");
414 return 0;
415
416 #endif
417 break;
418 case 256:
419 if (scs.tag_size == 4) {
420 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(
421 &policy.rtp);
422 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
423 &policy.rtcp);
424 } else {
425 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
426 &policy.rtp);
427 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
428 &policy.rtcp);
429 }
430 break;
431 }
432 }
433 break;
434 case sec_serv_conf:
435 if (gcm_on) {
436 fprintf(
437 stderr,
438 "error: GCM mode must always be used with auth enabled\n");
439 return -1;
440 } else {
441 switch (scs.key_size) {
442 case 128:
443 srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
444 srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
445 &policy.rtcp);
446 break;
447 case 192:
448 #ifdef OPENSSL
449 srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp);
450 srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
451 &policy.rtcp);
452 #else
453 fprintf(stderr,
454 "error: AES 192 mode only supported when using the "
455 "OpenSSL crypto engine.\n");
456 return 0;
457
458 #endif
459 break;
460 case 256:
461 srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
462 srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
463 &policy.rtcp);
464 break;
465 }
466 }
467 break;
468 case sec_serv_auth:
469 if (gcm_on) {
470 #ifdef OPENSSL
471 switch (scs.key_size) {
472 case 128:
473 srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
474 srtp_crypto_policy_set_aes_gcm_128_8_only_auth(
475 &policy.rtcp);
476 break;
477 case 256:
478 srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
479 srtp_crypto_policy_set_aes_gcm_256_8_only_auth(
480 &policy.rtcp);
481 break;
482 }
483 #else
484 printf("error: GCM mode only supported when using the OpenSSL "
485 "crypto engine.\n");
486 return 0;
487 #endif
488 } else {
489 srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
490 srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
491 }
492 break;
493 default:
494 fprintf(stderr, "error: unknown security service requested\n");
495 return -1;
496 }
497
498 policy.key = (uint8_t *)key;
499 policy.ekt = NULL;
500 policy.next = NULL;
501 policy.window_size = 128;
502 policy.allow_repeat_tx = 0;
503 policy.rtp.sec_serv = sec_servs;
504 policy.rtcp.sec_serv =
505 sec_servs; // sec_serv_none; /* we don't do RTCP anyway */
506 fprintf(stderr, "setting tag len %d\n", scs.tag_size);
507 policy.rtp.auth_tag_len = scs.tag_size;
508
509 if (gcm_on && scs.tag_size != 8) {
510 fprintf(stderr, "setted tag len %d\n", scs.tag_size);
511 policy.rtp.auth_tag_len = scs.tag_size;
512 }
513
514 /*
515 * read key from hexadecimal or base64 on command line into an octet
516 * string
517 */
518 if (b64_input) {
519 int pad;
520 expected_len = policy.rtp.cipher_key_len * 4 / 3;
521 len = base64_string_to_octet_string(key, &pad, input_key,
522 strlen(input_key));
523 } else {
524 expected_len = policy.rtp.cipher_key_len * 2;
525 len = hex_string_to_octet_string(key, input_key, expected_len);
526 }
527 /* check that hex string is the right length */
528 if (len < expected_len) {
529 fprintf(stderr, "error: too few digits in key/salt "
530 "(should be %d digits, found %d)\n",
531 expected_len, len);
532 exit(1);
533 }
534 if (strlen(input_key) > policy.rtp.cipher_key_len * 2) {
535 fprintf(stderr, "error: too many digits in key/salt "
536 "(should be %d hexadecimal digits, found %u)\n",
537 policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
538 exit(1);
539 }
540
541 fprintf(stderr, "set master key/salt to %s/",
542 octet_string_hex_string(key, 16));
543 fprintf(stderr, "%s\n", octet_string_hex_string(key + 16, 14));
544
545 } else {
546 fprintf(stderr,
547 "error: neither encryption or authentication were selected\n");
548 exit(1);
549 }
550
551 pcap_handle = pcap_open_offline("-", errbuf);
552
553 if (!pcap_handle) {
554 fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
555 exit(1);
556 }
557 assert(pcap_handle != NULL);
558 if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1) {
559 fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
560 pcap_geterr(pcap_handle));
561 return (2);
562 }
563 if (pcap_setfilter(pcap_handle, &fp) == -1) {
564 fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp,
565 pcap_geterr(pcap_handle));
566 return (2);
567 }
568 dec = rtp_decoder_alloc();
569 if (dec == NULL) {
570 fprintf(stderr, "error: malloc() failed\n");
571 exit(1);
572 }
573 fprintf(stderr, "Starting decoder\n");
574 if (rtp_decoder_init(dec, policy, mode)) {
575 fprintf(stderr, "error: init failed\n");
576 exit(1);
577 }
578
579 pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec);
580
581 if (dec->mode == mode_rtp || dec->mode == mode_rtcp_mux) {
582 fprintf(stderr, "RTP packets decoded: %d\n", dec->rtp_cnt);
583 }
584 if (dec->mode == mode_rtcp || dec->mode == mode_rtcp_mux) {
585 fprintf(stderr, "RTCP packets decoded: %d\n", dec->rtcp_cnt);
586 }
587 fprintf(stderr, "Packet decode errors: %d\n", dec->error_cnt);
588
589 rtp_decoder_deinit(dec);
590 rtp_decoder_dealloc(dec);
591
592 status = srtp_shutdown();
593 if (status) {
594 fprintf(stderr, "error: srtp shutdown failed with error code %d\n",
595 status);
596 exit(1);
597 }
598
599 return 0;
600 }
601
usage(char * string)602 void usage(char *string)
603 {
604 fprintf(
605 stderr,
606 "usage: %s [-d <debug>]* [[-k][-b] <key>] [-a][-t][-e] [-s "
607 "<srtp-crypto-suite>] [-m <mode>]\n"
608 "or %s -l\n"
609 "where -a use message authentication\n"
610 " -e <key size> use encryption (use 128 or 256 for key size)\n"
611 " -g Use AES-GCM mode (must be used with -e)\n"
612 " -t <tag size> Tag size to use (in GCM mode use 8 or 16)\n"
613 " -k <key> sets the srtp master key given in hexadecimal\n"
614 " -b <key> sets the srtp master key given in base64\n"
615 " -l list debug modules\n"
616 " -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
617 " -d <debug> turn on debugging for module <debug>\n"
618 " -s \"<srtp-crypto-suite>\" to set both key and tag size based\n"
619 " on RFC4568-style crypto suite specification\n"
620 " -m <mode> set the mode to be one of [rtp]|rtcp|rtcp-mux\n",
621 string, string);
622 exit(1);
623 }
624
rtp_decoder_alloc(void)625 rtp_decoder_t rtp_decoder_alloc(void)
626 {
627 return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
628 }
629
rtp_decoder_dealloc(rtp_decoder_t rtp_ctx)630 void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx)
631 {
632 free(rtp_ctx);
633 }
634
rtp_decoder_deinit(rtp_decoder_t decoder)635 int rtp_decoder_deinit(rtp_decoder_t decoder)
636 {
637 if (decoder->srtp_ctx) {
638 return srtp_dealloc(decoder->srtp_ctx);
639 }
640 return 0;
641 }
642
rtp_decoder_init(rtp_decoder_t dcdr,srtp_policy_t policy,rtp_decoder_mode_t mode)643 int rtp_decoder_init(rtp_decoder_t dcdr,
644 srtp_policy_t policy,
645 rtp_decoder_mode_t mode)
646 {
647 dcdr->rtp_offset = DEFAULT_RTP_OFFSET;
648 dcdr->srtp_ctx = NULL;
649 dcdr->start_tv.tv_usec = 0;
650 dcdr->start_tv.tv_sec = 0;
651 dcdr->frame_nr = -1;
652 dcdr->error_cnt = 0;
653 dcdr->rtp_cnt = 0;
654 dcdr->rtcp_cnt = 0;
655 dcdr->mode = mode;
656 dcdr->policy = policy;
657 dcdr->policy.ssrc.type = ssrc_any_inbound;
658
659 if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) {
660 return 1;
661 }
662 return 0;
663 }
664
665 /*
666 * decodes key as base64
667 */
668
hexdump(const void * ptr,size_t size)669 void hexdump(const void *ptr, size_t size)
670 {
671 int i, j;
672 const unsigned char *cptr = ptr;
673
674 for (i = 0; i < size; i += 16) {
675 fprintf(stdout, "%04x ", i);
676 for (j = 0; j < 16 && i + j < size; j++) {
677 fprintf(stdout, "%02x ", cptr[i + j]);
678 }
679 fprintf(stdout, "\n");
680 }
681 }
682
rtp_decoder_handle_pkt(u_char * arg,const struct pcap_pkthdr * hdr,const u_char * bytes)683 void rtp_decoder_handle_pkt(u_char *arg,
684 const struct pcap_pkthdr *hdr,
685 const u_char *bytes)
686 {
687 rtp_decoder_t dcdr = (rtp_decoder_t)arg;
688 rtp_msg_t message;
689 int rtp;
690 int pktsize;
691 struct timeval delta;
692 int octets_recvd;
693 srtp_err_status_t status;
694 dcdr->frame_nr++;
695
696 if ((dcdr->start_tv.tv_sec == 0) && (dcdr->start_tv.tv_usec == 0)) {
697 dcdr->start_tv = hdr->ts;
698 }
699
700 if (hdr->caplen < dcdr->rtp_offset) {
701 return;
702 }
703 const void *rtp_packet = bytes + dcdr->rtp_offset;
704
705 memcpy((void *)&message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
706 pktsize = hdr->caplen - dcdr->rtp_offset;
707 octets_recvd = pktsize;
708
709 if (octets_recvd == -1) {
710 return;
711 }
712
713 if (dcdr->mode == mode_rtp) {
714 rtp = 1;
715 } else if (dcdr->mode == mode_rtcp) {
716 rtp = 0;
717 } else {
718 rtp = 1;
719 if (octets_recvd >= 2) {
720 /* rfc5761 */
721 u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f;
722 rtp = payload_type < 64 || payload_type > 95;
723 }
724 }
725
726 if (rtp) {
727 /* verify rtp header */
728 if (message.header.version != 2) {
729 return;
730 }
731
732 status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd);
733 if (status) {
734 dcdr->error_cnt++;
735 return;
736 }
737 dcdr->rtp_cnt++;
738 } else {
739 status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd);
740 if (status) {
741 dcdr->error_cnt++;
742 return;
743 }
744 dcdr->rtcp_cnt++;
745 }
746 timersub(&hdr->ts, &dcdr->start_tv, &delta);
747 fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60,
748 (long)delta.tv_usec);
749 hexdump(&message, octets_recvd);
750 }
751
rtp_print_error(srtp_err_status_t status,char * message)752 void rtp_print_error(srtp_err_status_t status, char *message)
753 {
754 // clang-format off
755 fprintf(stderr,
756 "error: %s %d%s\n", message, status,
757 status == srtp_err_status_replay_fail ? " (replay check failed)" :
758 status == srtp_err_status_bad_param ? " (bad param)" :
759 status == srtp_err_status_no_ctx ? " (no context)" :
760 status == srtp_err_status_cipher_fail ? " (cipher failed)" :
761 status == srtp_err_status_key_expired ? " (key expired)" :
762 status == srtp_err_status_auth_fail ? " (auth check failed)" : "");
763 // clang-format on
764 }
765