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