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