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

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

Issue 889083003: Update libsrtp to upstream 1.5.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libsrtp@master
Patch Set: Updated to libsrtp 1.5.1 Created 5 years, 10 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 if (sec_servs) {
190 /*
191 * create policy structure, using the default mechanisms but
192 * with only the security services requested on the command line,
193 * using the right SSRC value
194 */
195 switch (sec_servs) {
196 case sec_serv_conf_and_auth:
197 if (gcm_on) {
198 #ifdef OPENSSL
199 switch (key_size) {
200 case 128:
201 crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
202 crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
203 break;
204 case 256:
205 crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
206 crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
207 break;
208 }
209 #else
210 fprintf(stderr, "error: GCM mode only supported when using the OpenSSL c rypto engine.\n");
211 return 0;
212 #endif
213 } else {
214 switch (key_size) {
215 case 128:
216 crypto_policy_set_rtp_default(&policy.rtp);
217 crypto_policy_set_rtcp_default(&policy.rtcp);
218 break;
219 case 256:
220 crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
221 crypto_policy_set_rtcp_default(&policy.rtcp);
222 break;
223 }
224 }
225 break;
226 case sec_serv_conf:
227 if (gcm_on) {
228 fprintf(stderr, "error: GCM mode must always be used with auth enabled \n");
229 return -1;
230 } else {
231 switch (key_size) {
232 case 128:
233 crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
234 crypto_policy_set_rtcp_default(&policy.rtcp);
235 break;
236 case 256:
237 crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
238 crypto_policy_set_rtcp_default(&policy.rtcp);
239 break;
240 }
241 }
242 break;
243 case sec_serv_auth:
244 if (gcm_on) {
245 #ifdef OPENSSL
246 switch (key_size) {
247 case 128:
248 crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
249 crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp);
250 break;
251 case 256:
252 crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
253 crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp);
254 break;
255 }
256 #else
257 printf("error: GCM mode only supported when using the OpenSSL crypto eng ine.\n");
258 return 0;
259 #endif
260 } else {
261 crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
262 crypto_policy_set_rtcp_default(&policy.rtcp);
263 }
264 break;
265 default:
266 fprintf(stderr, "error: unknown security service requested\n");
267 return -1;
268 }
269
270 policy.key = (uint8_t *) key;
271 policy.ekt = NULL;
272 policy.next = NULL;
273 policy.window_size = 128;
274 policy.allow_repeat_tx = 0;
275 policy.rtp.sec_serv = sec_servs;
276 policy.rtcp.sec_serv = sec_servs; //sec_serv_none; /* we don't do RTCP anyw ay */
277 fprintf(stderr, "setting tag len %d\n", tag_size);
278 policy.rtp.auth_tag_len = tag_size;
279
280 if (gcm_on && tag_size != 8) {
281 fprintf(stderr, "setted tag len %d\n", tag_size);
282 policy.rtp.auth_tag_len = tag_size;
283 }
284
285 /*
286 * read key from hexadecimal or base64 on command line into an octet string
287 */
288 if (b64_input) {
289 int pad;
290 expected_len = policy.rtp.cipher_key_len*4/3;
291 len = base64_string_to_octet_string(key, &pad, input_key, expected_len);
292 if (pad != 0) {
293 fprintf(stderr, "error: padding in base64 unexpected\n");
294 exit(1);
295 }
296 } else {
297 expected_len = policy.rtp.cipher_key_len*2;
298 len = hex_string_to_octet_string(key, input_key, expected_len);
299 }
300 /* check that hex string is the right length */
301 if (len < expected_len) {
302 fprintf(stderr,
303 "error: too few digits in key/salt "
304 "(should be %d digits, found %d)\n",
305 expected_len, len);
306 exit(1);
307 }
308 if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
309 fprintf(stderr,
310 "error: too many digits in key/salt "
311 "(should be %d hexadecimal digits, found %u)\n",
312 policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key));
313 exit(1);
314 }
315
316 fprintf(stderr, "set master key/salt to %s/", octet_string_hex_string(key, 1 6));
317 fprintf(stderr, "%s\n", octet_string_hex_string(key+16, 14));
318
319 } else {
320 /*
321 * we're not providing security services, so set the policy to the
322 * null policy
323 *
324 * Note that this policy does not conform to the SRTP
325 * specification, since RTCP authentication is required. However,
326 * the effect of this policy is to turn off SRTP, so that this
327 * application is now a vanilla-flavored RTP application.
328 */
329 policy.key = (uint8_t *)key;
330 policy.ssrc.type = ssrc_specific;
331 policy.rtp.cipher_type = NULL_CIPHER;
332 policy.rtp.cipher_key_len = 0;
333 policy.rtp.auth_type = NULL_AUTH;
334 policy.rtp.auth_key_len = 0;
335 policy.rtp.auth_tag_len = 0;
336 policy.rtp.sec_serv = sec_serv_none;
337 policy.rtcp.cipher_type = NULL_CIPHER;
338 policy.rtcp.cipher_key_len = 0;
339 policy.rtcp.auth_type = NULL_AUTH;
340 policy.rtcp.auth_key_len = 0;
341 policy.rtcp.auth_tag_len = 0;
342 policy.rtcp.sec_serv = sec_serv_none;
343 policy.window_size = 0;
344 policy.allow_repeat_tx = 0;
345 policy.ekt = NULL;
346 policy.next = NULL;
347 }
348
349 pcap_handle = pcap_open_offline("-", errbuf);
350
351 if (!pcap_handle) {
352 fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
353 exit(1);
354 }
355 assert(pcap_handle != NULL);
356 if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1){
357 fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
358 pcap_geterr(pcap_handle));
359 return (2);
360 }
361 if (pcap_setfilter(pcap_handle, &fp) == -1){
362 fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp,
363 pcap_geterr(pcap_handle));
364 return (2);
365 }
366 dec = rtp_decoder_alloc();
367 if (dec == NULL) {
368 fprintf(stderr, "error: malloc() failed\n");
369 exit(1);
370 }
371 fprintf(stderr, "Starting decoder\n");
372 rtp_decoder_init(dec, policy);
373
374 pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec);
375
376 rtp_decoder_deinit_srtp(dec);
377 rtp_decoder_dealloc(dec);
378
379 status = srtp_shutdown();
380 if (status) {
381 fprintf(stderr, "error: srtp shutdown failed with error code %d\n", status);
382 exit(1);
383 }
384
385 return 0;
386 }
387
388
389 void
390 usage(char *string) {
391
392 fprintf(stderr, "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\n"
393 "or %s -l\n"
394 "where -a use message authentication\n"
395 " -e <key size> use encryption (use 128 or 256 for key size)\n"
396 " -g Use AES-GCM mode (must be used with -e)\n"
397 " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
398 " -k <key> sets the srtp master key given in hexadecimal\n"
399 " -b <key> sets the srtp master key given in base64\n"
400 " -l list debug modules\n"
401 " -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
402 " -d <debug> turn on debugging for module <debug>\n",
403 string, string);
404 exit(1);
405
406 }
407
408 rtp_decoder_t
409 rtp_decoder_alloc(void) {
410 return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
411 }
412
413 void
414 rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) {
415 free(rtp_ctx);
416 }
417
418 err_status_t
419 rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc) {
420 decoder->policy.ssrc.value = htonl(ssrc);
421 return srtp_create(&decoder->srtp_ctx, &decoder->policy);
422 }
423
424 int
425 rtp_decoder_deinit_srtp(rtp_decoder_t decoder) {
426 return srtp_dealloc(decoder->srtp_ctx);
427 }
428
429 int
430 rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy){
431 dcdr->rtp_offset = DEFAULT_RTP_OFFSET;
432 dcdr->srtp_ctx = NULL;
433 dcdr->start_tv.tv_usec = 0;
434 dcdr->start_tv.tv_sec = 0;
435 dcdr->frame_nr = -1;
436 dcdr->policy = policy;
437 dcdr->policy.ssrc.type = ssrc_specific;
438 return 0;
439 }
440
441 /*
442 * decodes key as base64
443 */
444
445 void hexdump(const void *ptr, size_t size) {
446 int i, j;
447 const unsigned char *cptr = ptr;
448
449 for (i = 0; i < size; i += 16) {
450 fprintf(stdout, "%04x ", i);
451 for (j = 0; j < 16 && i+j < size; j++) {
452 fprintf(stdout, "%02x ", cptr[i+j]);
453 }
454 fprintf(stdout, "\n");
455 }
456 }
457
458 void
459 rtp_decoder_handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr,
460 const u_char *bytes){
461 rtp_decoder_t dcdr = (rtp_decoder_t)arg;
462 int pktsize;
463 struct timeval delta;
464 int octets_recvd;
465 err_status_t status;
466 dcdr->frame_nr++;
467
468 if (dcdr->start_tv.tv_sec == 0 && dcdr->start_tv.tv_sec == 0) {
469 dcdr->start_tv = hdr->ts;
470 }
471
472 if (hdr->caplen < dcdr->rtp_offset) {
473 return;
474 }
475 const void *rtp_packet = bytes + dcdr->rtp_offset;
476
477 memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
478 pktsize = hdr->caplen - dcdr->rtp_offset;
479 octets_recvd = pktsize;
480
481 if (octets_recvd == -1) {
482 return;
483 }
484
485 /* verify rtp header */
486 if (dcdr->message.header.version != 2) {
487 return; //return -1;
488 }
489 if(dcdr->srtp_ctx == NULL){
490 status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc);
491 if (status) {
492 exit(1);
493 }
494 }
495 if(dcdr->srtp_ctx != NULL){
496 }
497 status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd);
498 if (status){
499 return;
500 }
501 timersub(&hdr->ts, &dcdr->start_tv, &delta);
502 fprintf(stdout, "%02ld:%02ld.%06lu\n", delta.tv_sec/60, delta.tv_sec%60, delta .tv_usec);
503 hexdump(&dcdr->message, pktsize);
504 }
505
506 void rtp_print_error(err_status_t status, char *message){
507 fprintf(stderr,
508 "error: %s %d%s\n", message, status,
509 status == err_status_replay_fail ? " (replay check failed)" :
510 status == err_status_bad_param ? " (bad param)" :
511 status == err_status_no_ctx ? " (no context)" :
512 status == err_status_cipher_fail ? " (cipher failed)" :
513 status == err_status_key_expired ? " (key expired)" :
514 status == err_status_auth_fail ? " (auth check failed)" : "");
515 }
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