Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: srtp/test/rtp_decoder.c

Issue 2344973002: Update libsrtp to version 2.0 (Closed)
Patch Set: Add '.' back to include_dirs Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « srtp/test/rtp_decoder.h ('k') | srtp/test/rtpw.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * rtp_decoder.c
3 *
4 * decoder structures and functions for SRTP pcap decoder
5 *
6 * Example:
7 * $ wget --no-check-certificate https://raw.githubusercontent.com/gteissier/srt p-decrypt/master/marseillaise-srtp.pcap
8 * $ ./test/rtp_decoder -a -t 0 -e 128 -b aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZX Rz \
9 * < ~/marseillaise-srtp.pcap | text2pcap -t "%M:%S." -u 10000,10000 - - > ./ marseillaise-rtp.pcap
10 *
11 * Bernardo Torres <bernardo@torresautomacao.com.br>
12 *
13 * Some structure and code from https://github.com/gteissier/srtp-decrypt
14 */
15 /*
16 *
17 * Copyright (c) 2001-2006 Cisco Systems, Inc.
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 *
24 * Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 *
27 * Redistributions in binary form must reproduce the above
28 * copyright notice, this list of conditions and the following
29 * disclaimer in the documentation and/or other materials provided
30 * with the distribution.
31 *
32 * Neither the name of the Cisco Systems, Inc. nor the names of its
33 * contributors may be used to endorse or promote products derived
34 * from this software without specific prior written permission.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
40 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 */
50 #include "getopt_s.h" /* for local getopt() */
51 #include <assert.h> /* for assert() */
52
53 #include <pcap.h>
54 #include "rtp_decoder.h"
55
56 #define MAX_KEY_LEN 96
57 #define MAX_FILTER 256
58
59 int
60 main (int argc, char *argv[]) {
61 char errbuf[PCAP_ERRBUF_SIZE];
62 bpf_u_int32 pcap_net = 0;
63 pcap_t *pcap_handle;
64 #if BEW
65 struct sockaddr_in local;
66 #endif
67 sec_serv_t sec_servs = sec_serv_none;
68 int c;
69 int key_size = 128;
70 int tag_size = 8;
71 int gcm_on = 0;
72 char *input_key = NULL;
73 int b64_input = 0;
74 char key[MAX_KEY_LEN];
75 struct bpf_program fp;
76 char filter_exp[MAX_FILTER] = "";
77 rtp_decoder_t dec;
78 srtp_policy_t policy;
79 err_status_t status;
80 int len;
81 int expected_len;
82 int do_list_mods = 0;
83
84 fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_versi on());
85
86 /* initialize srtp library */
87 status = srtp_init();
88 if (status) {
89 fprintf(stderr, "error: srtp initialization failed with error code %d\n", st atus);
90 exit(1);
91 }
92
93 /* check args */
94 while (1) {
95 c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:");
96 if (c == -1) {
97 break;
98 }
99 switch (c) {
100 case 'b':
101 b64_input = 1;
102 /* fall thru */
103 case 'k':
104 input_key = optarg_s;
105 break;
106 case 'e':
107 key_size = atoi(optarg_s);
108 if (key_size != 128 && key_size != 256) {
109 fprintf(stderr, "error: encryption key size must be 128 or 256 (%d)\n", key_size);
110 exit(1);
111 }
112 input_key = malloc(key_size);
113 sec_servs |= sec_serv_conf;
114 break;
115 case 't':
116 tag_size = atoi(optarg_s);
117 if (tag_size != 8 && tag_size != 16) {
118 fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", tag_size);
119 //exit(1);
120 }
121 break;
122 case 'a':
123 sec_servs |= sec_serv_auth;
124 break;
125 case 'g':
126 gcm_on = 1;
127 sec_servs |= sec_serv_auth;
128 break;
129 case 'd':
130 status = crypto_kernel_set_debug_module(optarg_s, 1);
131 if (status) {
132 fprintf(stderr, "error: set debug module (%s) failed\n", optarg_s);
133 exit(1);
134 }
135 break;
136 case 'f':
137 if(strlen(optarg_s) > MAX_FILTER){
138 fprintf(stderr, "error: filter bigger than %d characters\n", MAX_FILTER) ;
139 exit(1);
140 }
141 fprintf(stderr, "Setting filter as %s\n", optarg_s);
142 strcpy(filter_exp, optarg_s);
143 break;
144 case 'l':
145 do_list_mods = 1;
146 break;
147 default:
148 usage(argv[0]);
149 }
150 }
151
152 if (do_list_mods) {
153 status = crypto_kernel_list_debug_modules();
154 if (status) {
155 fprintf(stderr, "error: list of debug modules failed\n");
156 exit(1);
157 }
158 return 0;
159 }
160
161 if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
162 /*
163 * a key must be provided if and only if security services have
164 * been requested
165 */
166 if(input_key == NULL){
167 fprintf(stderr, "key not provided\n");
168 }
169 if(!sec_servs){
170 fprintf(stderr, "no secservs\n");
171 }
172 fprintf(stderr, "provided\n");
173 usage(argv[0]);
174 }
175
176
177
178 /* report security services selected on the command line */
179 fprintf(stderr, "security services: ");
180 if (sec_servs & sec_serv_conf)
181 fprintf(stderr, "confidentiality ");
182 if (sec_servs & sec_serv_auth)
183 fprintf(stderr, "message authentication");
184 if (sec_servs == sec_serv_none)
185 fprintf(stderr, "none");
186 fprintf(stderr, "\n");
187
188 /* set up the srtp policy and master key */
189 memset(&policy, 0, sizeof(policy));
190 if (sec_servs) {
191 /*
192 * create policy structure, using the default mechanisms but
193 * with only the security services requested on the command line,
194 * using the right SSRC value
195 */
196 switch (sec_servs) {
197 case sec_serv_conf_and_auth:
198 if (gcm_on) {
199 #ifdef OPENSSL
200 switch (key_size) {
201 case 128:
202 crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
203 crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
204 break;
205 case 256:
206 crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
207 crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
208 break;
209 }
210 #else
211 fprintf(stderr, "error: GCM mode only supported when using the OpenSSL c rypto engine.\n");
212 return 0;
213 #endif
214 } else {
215 switch (key_size) {
216 case 128:
217 crypto_policy_set_rtp_default(&policy.rtp);
218 crypto_policy_set_rtcp_default(&policy.rtcp);
219 break;
220 case 256:
221 crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
222 crypto_policy_set_rtcp_default(&policy.rtcp);
223 break;
224 }
225 }
226 break;
227 case sec_serv_conf:
228 if (gcm_on) {
229 fprintf(stderr, "error: GCM mode must always be used with auth enabled \n");
230 return -1;
231 } else {
232 switch (key_size) {
233 case 128:
234 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
235 crypto_policy_set_rtcp_default(&policy.rtcp);
236 break;
237 case 256:
238 crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
239 crypto_policy_set_rtcp_default(&policy.rtcp);
240 break;
241 }
242 }
243 break;
244 case sec_serv_auth:
245 if (gcm_on) {
246 #ifdef OPENSSL
247 switch (key_size) {
248 case 128:
249 crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
250 crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp);
251 break;
252 case 256:
253 crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
254 crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp);
255 break;
256 }
257 #else
258 printf("error: GCM mode only supported when using the OpenSSL crypto eng ine.\n");
259 return 0;
260 #endif
261 } else {
262 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
263 crypto_policy_set_rtcp_default(&policy.rtcp);
264 }
265 break;
266 default:
267 fprintf(stderr, "error: unknown security service requested\n");
268 return -1;
269 }
270
271 policy.key = (uint8_t *) key;
272 policy.ekt = NULL;
273 policy.next = NULL;
274 policy.window_size = 128;
275 policy.allow_repeat_tx = 0;
276 policy.rtp.sec_serv = sec_servs;
277 policy.rtcp.sec_serv = sec_servs; //sec_serv_none; /* we don't do RTCP anyw ay */
278 fprintf(stderr, "setting tag len %d\n", tag_size);
279 policy.rtp.auth_tag_len = tag_size;
280
281 if (gcm_on && tag_size != 8) {
282 fprintf(stderr, "setted tag len %d\n", tag_size);
283 policy.rtp.auth_tag_len = tag_size;
284 }
285
286 /*
287 * read key from hexadecimal or base64 on command line into an octet string
288 */
289 if (b64_input) {
290 int pad;
291 expected_len = policy.rtp.cipher_key_len*4/3;
292 len = base64_string_to_octet_string(key, &pad, input_key, expected_len);
293 if (pad != 0) {
294 fprintf(stderr, "error: padding in base64 unexpected\n");
295 exit(1);
296 }
297 } else {
298 expected_len = policy.rtp.cipher_key_len*2;
299 len = hex_string_to_octet_string(key, input_key, expected_len);
300 }
301 /* check that hex string is the right length */
302 if (len < expected_len) {
303 fprintf(stderr,
304 "error: too few digits in key/salt "
305 "(should be %d digits, found %d)\n",
306 expected_len, len);
307 exit(1);
308 }
309 if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
310 fprintf(stderr,
311 "error: too many digits in key/salt "
312 "(should be %d hexadecimal digits, found %u)\n",
313 policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key));
314 exit(1);
315 }
316
317 fprintf(stderr, "set master key/salt to %s/", octet_string_hex_string(key, 1 6));
318 fprintf(stderr, "%s\n", octet_string_hex_string(key+16, 14));
319
320 } else {
321 /*
322 * we're not providing security services, so set the policy to the
323 * null policy
324 *
325 * Note that this policy does not conform to the SRTP
326 * specification, since RTCP authentication is required. However,
327 * the effect of this policy is to turn off SRTP, so that this
328 * application is now a vanilla-flavored RTP application.
329 */
330 policy.key = (uint8_t *)key;
331 policy.ssrc.type = ssrc_specific;
332 policy.rtp.cipher_type = NULL_CIPHER;
333 policy.rtp.cipher_key_len = 0;
334 policy.rtp.auth_type = NULL_AUTH;
335 policy.rtp.auth_key_len = 0;
336 policy.rtp.auth_tag_len = 0;
337 policy.rtp.sec_serv = sec_serv_none;
338 policy.rtcp.cipher_type = NULL_CIPHER;
339 policy.rtcp.cipher_key_len = 0;
340 policy.rtcp.auth_type = NULL_AUTH;
341 policy.rtcp.auth_key_len = 0;
342 policy.rtcp.auth_tag_len = 0;
343 policy.rtcp.sec_serv = sec_serv_none;
344 policy.window_size = 0;
345 policy.allow_repeat_tx = 0;
346 policy.ekt = NULL;
347 policy.next = NULL;
348 }
349
350 pcap_handle = pcap_open_offline("-", errbuf);
351
352 if (!pcap_handle) {
353 fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
354 exit(1);
355 }
356 assert(pcap_handle != NULL);
357 if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1){
358 fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
359 pcap_geterr(pcap_handle));
360 return (2);
361 }
362 if (pcap_setfilter(pcap_handle, &fp) == -1){
363 fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp,
364 pcap_geterr(pcap_handle));
365 return (2);
366 }
367 dec = rtp_decoder_alloc();
368 if (dec == NULL) {
369 fprintf(stderr, "error: malloc() failed\n");
370 exit(1);
371 }
372 fprintf(stderr, "Starting decoder\n");
373 rtp_decoder_init(dec, policy);
374
375 pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec);
376
377 rtp_decoder_deinit_srtp(dec);
378 rtp_decoder_dealloc(dec);
379
380 status = srtp_shutdown();
381 if (status) {
382 fprintf(stderr, "error: srtp shutdown failed with error code %d\n", status);
383 exit(1);
384 }
385
386 return 0;
387 }
388
389
390 void
391 usage(char *string) {
392
393 fprintf(stderr, "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\n"
394 "or %s -l\n"
395 "where -a use message authentication\n"
396 " -e <key size> use encryption (use 128 or 256 for key size)\n"
397 " -g Use AES-GCM mode (must be used with -e)\n"
398 " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
399 " -k <key> sets the srtp master key given in hexadecimal\n"
400 " -b <key> sets the srtp master key given in base64\n"
401 " -l list debug modules\n"
402 " -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
403 " -d <debug> turn on debugging for module <debug>\n",
404 string, string);
405 exit(1);
406
407 }
408
409 rtp_decoder_t
410 rtp_decoder_alloc(void) {
411 return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
412 }
413
414 void
415 rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) {
416 free(rtp_ctx);
417 }
418
419 err_status_t
420 rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc) {
421 decoder->policy.ssrc.value = htonl(ssrc);
422 return srtp_create(&decoder->srtp_ctx, &decoder->policy);
423 }
424
425 int
426 rtp_decoder_deinit_srtp(rtp_decoder_t decoder) {
427 return srtp_dealloc(decoder->srtp_ctx);
428 }
429
430 int
431 rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy){
432 dcdr->rtp_offset = DEFAULT_RTP_OFFSET;
433 dcdr->srtp_ctx = NULL;
434 dcdr->start_tv.tv_usec = 0;
435 dcdr->start_tv.tv_sec = 0;
436 dcdr->frame_nr = -1;
437 dcdr->policy = policy;
438 dcdr->policy.ssrc.type = ssrc_specific;
439 return 0;
440 }
441
442 /*
443 * decodes key as base64
444 */
445
446 void hexdump(const void *ptr, size_t size) {
447 int i, j;
448 const unsigned char *cptr = ptr;
449
450 for (i = 0; i < size; i += 16) {
451 fprintf(stdout, "%04x ", i);
452 for (j = 0; j < 16 && i+j < size; j++) {
453 fprintf(stdout, "%02x ", cptr[i+j]);
454 }
455 fprintf(stdout, "\n");
456 }
457 }
458
459 void
460 rtp_decoder_handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr,
461 const u_char *bytes){
462 rtp_decoder_t dcdr = (rtp_decoder_t)arg;
463 int pktsize;
464 struct timeval delta;
465 int octets_recvd;
466 err_status_t status;
467 dcdr->frame_nr++;
468
469 if (dcdr->start_tv.tv_sec == 0 && dcdr->start_tv.tv_sec == 0) {
470 dcdr->start_tv = hdr->ts;
471 }
472
473 if (hdr->caplen < dcdr->rtp_offset) {
474 return;
475 }
476 const void *rtp_packet = bytes + dcdr->rtp_offset;
477
478 memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
479 pktsize = hdr->caplen - dcdr->rtp_offset;
480 octets_recvd = pktsize;
481
482 if (octets_recvd == -1) {
483 return;
484 }
485
486 /* verify rtp header */
487 if (dcdr->message.header.version != 2) {
488 return; //return -1;
489 }
490 if(dcdr->srtp_ctx == NULL){
491 status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc);
492 if (status) {
493 exit(1);
494 }
495 }
496 if(dcdr->srtp_ctx != NULL){
497 }
498 status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd);
499 if (status){
500 return;
501 }
502 timersub(&hdr->ts, &dcdr->start_tv, &delta);
503 fprintf(stdout, "%02ld:%02ld.%06lu\n", delta.tv_sec/60, delta.tv_sec%60, delta .tv_usec);
504 hexdump(&dcdr->message, pktsize);
505 }
506
507 void rtp_print_error(err_status_t status, char *message){
508 fprintf(stderr,
509 "error: %s %d%s\n", message, status,
510 status == err_status_replay_fail ? " (replay check failed)" :
511 status == err_status_bad_param ? " (bad param)" :
512 status == err_status_no_ctx ? " (no context)" :
513 status == err_status_cipher_fail ? " (cipher failed)" :
514 status == err_status_key_expired ? " (key expired)" :
515 status == err_status_auth_fail ? " (auth check failed)" : "");
516 }
OLDNEW
« no previous file with comments | « srtp/test/rtp_decoder.h ('k') | srtp/test/rtpw.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698