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