blob: 7b62147720ca6cb29e1ae4ee2e53ed6f3c33cf66 [file] [log] [blame]
Cullen Jennings235513a2005-09-21 22:51:36 +00001/*
2 * srtp_driver.c
3 *
4 * a test driver for libSRTP
5 *
6 * David A. McGrew
7 * Cisco Systems, Inc.
8 */
9/*
10 *
David McGrew7629bf22006-06-08 17:00:25 +000011 * Copyright (c) 2001-2006, Cisco Systems, Inc.
Cullen Jennings235513a2005-09-21 22:51:36 +000012 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * Neither the name of the Cisco Systems, Inc. nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41 * OF THE POSSIBILITY OF SUCH DAMAGE.
42 *
43 */
44
45
46#include <string.h> /* for memcpy() */
47#include <time.h> /* for clock() */
48#include <stdlib.h> /* for malloc(), free() */
49#include <stdio.h> /* for print(), fflush() */
David McGrew79bd3012006-07-17 20:41:21 +000050#include "getopt_s.h" /* for local getopt() */
Cullen Jennings235513a2005-09-21 22:51:36 +000051
David McGrew3c45e0c2006-07-12 00:50:56 +000052#include "srtp_priv.h"
Cullen Jennings235513a2005-09-21 22:51:36 +000053
Marcus Sundberg1cbca882005-10-02 20:50:06 +000054#ifdef HAVE_NETINET_IN_H
55# include <netinet/in.h>
56#elif defined HAVE_WINSOCK2_H
57# include <winsock2.h>
58#endif
59
Cullen Jennings235513a2005-09-21 22:51:36 +000060#define PRINT_REFERENCE_PACKET 1
61
62err_status_t
Marcus Sundberga3f95fe2005-09-29 12:48:41 +000063srtp_validate(void);
Cullen Jennings235513a2005-09-21 22:51:36 +000064
65err_status_t
66srtp_create_big_policy(srtp_policy_t **list);
67
68err_status_t
Jonathan Lennox80c4c832010-05-17 19:30:28 +000069srtp_dealloc_big_policy(srtp_policy_t *list);
70
71err_status_t
Marcus Sundberga3f95fe2005-09-29 12:48:41 +000072srtp_test_remove_stream(void);
Cullen Jennings235513a2005-09-21 22:51:36 +000073
74double
75srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy);
76
77double
78srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy);
79
80void
81srtp_do_timing(const srtp_policy_t *policy);
82
83void
84srtp_do_rejection_timing(const srtp_policy_t *policy);
85
86err_status_t
Marcus Sundberga3f95fe2005-09-29 12:48:41 +000087srtp_test(const srtp_policy_t *policy);
Cullen Jennings235513a2005-09-21 22:51:36 +000088
89err_status_t
David McGrew9c70f292006-05-03 19:38:38 +000090srtcp_test(const srtp_policy_t *policy);
91
92err_status_t
Cullen Jennings235513a2005-09-21 22:51:36 +000093srtp_session_print_policy(srtp_t srtp);
94
95err_status_t
96srtp_print_policy(const srtp_policy_t *policy);
97
98char *
99srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
100
101double
102mips_estimate(int num_trials, int *ignore);
103
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000104extern uint8_t test_key[30];
Cullen Jennings235513a2005-09-21 22:51:36 +0000105
106void
107usage(char *prog_name) {
108 printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
109 " -t run timing test\n"
110 " -r run rejection timing test\n"
111 " -c run codec timing test\n"
112 " -v run validation tests\n"
113 " -d <mod> turn on debugging module <mod>\n"
114 " -l list debugging modules\n", prog_name);
115 exit(1);
116}
117
118/*
119 * The policy_array is a null-terminated array of policy structs. it
120 * is declared at the end of this file
121 */
122
123extern const srtp_policy_t *policy_array[];
124
125
126/* the wildcard_policy is declared below; it has a wildcard ssrc */
127
128extern const srtp_policy_t wildcard_policy;
129
130/*
131 * mod_driver debug module - debugging module for this test driver
132 *
133 * we use the crypto_kernel debugging system in this driver, which
134 * makes the interface uniform and increases portability
135 */
136
137debug_module_t mod_driver = {
138 0, /* debugging is off by default */
139 "driver" /* printable name for module */
140};
141
142int
143main (int argc, char *argv[]) {
Jonathan Lennoxb4842bf2010-05-15 03:55:24 +0000144 int q;
Cullen Jennings235513a2005-09-21 22:51:36 +0000145 unsigned do_timing_test = 0;
146 unsigned do_rejection_test = 0;
147 unsigned do_codec_timing = 0;
148 unsigned do_validation = 0;
149 unsigned do_list_mods = 0;
150 err_status_t status;
151
152 /*
153 * verify that the compiler has interpreted the header data
154 * structure srtp_hdr_t correctly
155 */
156 if (sizeof(srtp_hdr_t) != 12) {
David McGrew1a2ab2c2006-07-12 22:48:44 +0000157 printf("error: srtp_hdr_t has incorrect size"
158 "(size is %ld bytes, expected 12)\n",
Jonathan Lennoxf3132b92010-05-14 22:54:10 +0000159 (long)sizeof(srtp_hdr_t));
Cullen Jennings235513a2005-09-21 22:51:36 +0000160 exit(1);
161 }
162
163 /* initialize srtp library */
164 status = srtp_init();
165 if (status) {
166 printf("error: srtp init failed with error code %d\n", status);
167 exit(1);
168 }
169
170 /* load srtp_driver debug module */
171 status = crypto_kernel_load_debug_module(&mod_driver);
172 if (status) {
173 printf("error: load of srtp_driver debug module failed "
174 "with error code %d\n", status);
175 exit(1);
176 }
177
178 /* process input arguments */
179 while (1) {
David McGrew79bd3012006-07-17 20:41:21 +0000180 q = getopt_s(argc, argv, "trcvld:");
Cullen Jennings235513a2005-09-21 22:51:36 +0000181 if (q == -1)
182 break;
183 switch (q) {
184 case 't':
185 do_timing_test = 1;
186 break;
187 case 'r':
188 do_rejection_test = 1;
189 break;
190 case 'c':
191 do_codec_timing = 1;
192 break;
193 case 'v':
194 do_validation = 1;
195 break;
196 case 'l':
197 do_list_mods = 1;
198 break;
199 case 'd':
David McGrew79bd3012006-07-17 20:41:21 +0000200 status = crypto_kernel_set_debug_module(optarg_s, 1);
Cullen Jennings235513a2005-09-21 22:51:36 +0000201 if (status) {
David McGrew79bd3012006-07-17 20:41:21 +0000202 printf("error: set debug module (%s) failed\n", optarg_s);
Cullen Jennings235513a2005-09-21 22:51:36 +0000203 exit(1);
204 }
205 break;
206 default:
207 usage(argv[0]);
208 }
209 }
210
211 if (!do_validation && !do_timing_test && !do_codec_timing
212 && !do_list_mods && !do_rejection_test)
213 usage(argv[0]);
214
215 if (do_list_mods) {
216 status = crypto_kernel_list_debug_modules();
217 if (status) {
218 printf("error: list of debug modules failed\n");
219 exit(1);
220 }
221 }
222
223 if (do_validation) {
224 const srtp_policy_t **policy = policy_array;
225 srtp_policy_t *big_policy;
226
David McGrew9c70f292006-05-03 19:38:38 +0000227 /* loop over policy array, testing srtp and srtcp for each policy */
Cullen Jennings235513a2005-09-21 22:51:36 +0000228 while (*policy != NULL) {
229 printf("testing srtp_protect and srtp_unprotect\n");
230 if (srtp_test(*policy) == err_status_ok)
231 printf("passed\n\n");
232 else {
233 printf("failed\n");
234 exit(1);
235 }
David McGrew9c70f292006-05-03 19:38:38 +0000236 printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n");
237 if (srtcp_test(*policy) == err_status_ok)
238 printf("passed\n\n");
239 else {
240 printf("failed\n");
241 exit(1);
242 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000243 policy++;
244 }
245
246 /* create a big policy list and run tests on it */
247 status = srtp_create_big_policy(&big_policy);
248 if (status) {
249 printf("unexpected failure with error code %d\n", status);
250 exit(1);
251 }
252 printf("testing srtp_protect and srtp_unprotect with big policy\n");
253 if (srtp_test(big_policy) == err_status_ok)
254 printf("passed\n\n");
255 else {
256 printf("failed\n");
257 exit(1);
258 }
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000259 status = srtp_dealloc_big_policy(big_policy);
260 if (status) {
261 printf("unexpected failure with error code %d\n", status);
262 exit(1);
263 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000264
265 /* run test on wildcard policy */
266 printf("testing srtp_protect and srtp_unprotect on "
267 "wildcard ssrc policy\n");
268 if (srtp_test(&wildcard_policy) == err_status_ok)
269 printf("passed\n\n");
270 else {
271 printf("failed\n");
272 exit(1);
273 }
274
275 /*
276 * run validation test against the reference packets - note
277 * that this test only covers the default policy
278 */
279 printf("testing srtp_protect and srtp_unprotect against "
280 "reference packets\n");
281 if (srtp_validate() == err_status_ok)
282 printf("passed\n\n");
283 else {
284 printf("failed\n");
285 exit(1);
286 }
287
288 /*
289 * test the function srtp_remove_stream()
290 */
291 printf("testing srtp_remove_stream()...");
292 if (srtp_test_remove_stream() == err_status_ok)
293 printf("passed\n");
294 else {
295 printf("failed\n");
296 exit(1);
297 }
298 }
299
300 if (do_timing_test) {
301 const srtp_policy_t **policy = policy_array;
302
303 /* loop over policies, run timing test for each */
304 while (*policy != NULL) {
305 srtp_print_policy(*policy);
306 srtp_do_timing(*policy);
307 policy++;
308 }
309 }
310
311 if (do_rejection_test) {
312 const srtp_policy_t **policy = policy_array;
313
314 /* loop over policies, run rejection timing test for each */
315 while (*policy != NULL) {
316 srtp_print_policy(*policy);
317 srtp_do_rejection_timing(*policy);
318 policy++;
319 }
320 }
321
322 if (do_codec_timing) {
323 srtp_policy_t policy;
324 int ignore;
325 double mips = mips_estimate(1000000000, &ignore);
326
327 crypto_policy_set_rtp_default(&policy.rtp);
328 crypto_policy_set_rtcp_default(&policy.rtcp);
329 policy.ssrc.type = ssrc_specific;
330 policy.ssrc.value = 0xdecafbad;
331 policy.key = test_key;
332 policy.next = NULL;
333
334 printf("mips estimate: %e\n", mips);
335
336 printf("testing srtp processing time for voice codecs:\n");
337 printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n");
338 printf("G.711\t\t%d\t\t\t%e\n", 80,
339 (double) mips * (80 * 8) /
340 srtp_bits_per_second(80, &policy) / .01 );
341 printf("G.711\t\t%d\t\t\t%e\n", 160,
342 (double) mips * (160 * 8) /
343 srtp_bits_per_second(160, &policy) / .02);
344 printf("G.726-32\t%d\t\t\t%e\n", 40,
345 (double) mips * (40 * 8) /
346 srtp_bits_per_second(40, &policy) / .01 );
347 printf("G.726-32\t%d\t\t\t%e\n", 80,
348 (double) mips * (80 * 8) /
349 srtp_bits_per_second(80, &policy) / .02);
350 printf("G.729\t\t%d\t\t\t%e\n", 10,
351 (double) mips * (10 * 8) /
352 srtp_bits_per_second(10, &policy) / .01 );
353 printf("G.729\t\t%d\t\t\t%e\n", 20,
354 (double) mips * (20 * 8) /
355 srtp_bits_per_second(20, &policy) / .02 );
David McGrew93451082006-09-18 13:41:35 +0000356 printf("Wideband\t%d\t\t\t%e\n", 320,
357 (double) mips * (320 * 8) /
358 srtp_bits_per_second(320, &policy) / .01 );
359 printf("Wideband\t%d\t\t\t%e\n", 640,
360 (double) mips * (640 * 8) /
361 srtp_bits_per_second(640, &policy) / .02 );
Cullen Jennings235513a2005-09-21 22:51:36 +0000362 }
363
Jonathan Lennoxdfb30842010-05-15 04:52:01 +0000364 status = srtp_shutdown();
365 if (status) {
366 printf("error: srtp shutdown failed with error code %d\n", status);
367 exit(1);
368 }
369
Cullen Jennings235513a2005-09-21 22:51:36 +0000370 return 0;
371}
372
373
374
375/*
376 * srtp_create_test_packet(len, ssrc) returns a pointer to a
377 * (malloced) example RTP packet whose data field has the length given
378 * by pkt_octet_len and the SSRC value ssrc. The total length of the
379 * packet is twelve octets longer, since the header is at the
380 * beginning. There is room at the end of the packet for a trailer,
381 * and the four octets following the packet are filled with 0xff
382 * values to enable testing for overwrites.
383 *
384 * note that the location of the test packet can (and should) be
385 * deallocated with the free() call once it is no longer needed.
386 */
387
388srtp_hdr_t *
389srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
390 int i;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000391 uint8_t *buffer;
Cullen Jennings235513a2005-09-21 22:51:36 +0000392 srtp_hdr_t *hdr;
393 int bytes_in_hdr = 12;
394
395 /* allocate memory for test packet */
Derek MacDonald17127da2006-07-12 22:22:08 +0000396 hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr
Cullen Jennings235513a2005-09-21 22:51:36 +0000397 + SRTP_MAX_TRAILER_LEN + 4);
398 if (!hdr)
399 return NULL;
400
401 hdr->version = 2; /* RTP version two */
402 hdr->p = 0; /* no padding needed */
403 hdr->x = 0; /* no header extension */
404 hdr->cc = 0; /* no CSRCs */
405 hdr->m = 0; /* marker bit */
406 hdr->pt = 0xf; /* payload type */
407 hdr->seq = htons(0x1234); /* sequence number */
408 hdr->ts = htonl(0xdecafbad); /* timestamp */
409 hdr->ssrc = htonl(ssrc); /* synch. source */
410
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000411 buffer = (uint8_t *)hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +0000412 buffer += bytes_in_hdr;
413
414 /* set RTP data to 0xab */
415 for (i=0; i < pkt_octet_len; i++)
416 *buffer++ = 0xab;
417
418 /* set post-data value to 0xffff to enable overrun checking */
419 for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++)
420 *buffer++ = 0xff;
421
422 return hdr;
423}
424
425void
426srtp_do_timing(const srtp_policy_t *policy) {
427 int len;
428
429 /*
430 * note: the output of this function is formatted so that it
431 * can be used in gnuplot. '#' indicates a comment, and "\r\n"
432 * terminates a record
433 */
434
435 printf("# testing srtp throughput:\r\n");
436 printf("# mesg length (octets)\tthroughput (megabits per second)\r\n");
437
438 for (len=16; len <= 2048; len *= 2)
439 printf("%d\t\t\t%f\r\n", len,
440 srtp_bits_per_second(len, policy) / 1.0E6);
441
442 /* these extra linefeeds let gnuplot know that a dataset is done */
443 printf("\r\n\r\n");
444
445}
446
447void
448srtp_do_rejection_timing(const srtp_policy_t *policy) {
449 int len;
450
451 /*
452 * note: the output of this function is formatted so that it
453 * can be used in gnuplot. '#' indicates a comment, and "\r\n"
454 * terminates a record
455 */
456
457 printf("# testing srtp rejection throughput:\r\n");
458 printf("# mesg length (octets)\trejections per second\r\n");
459
460 for (len=8; len <= 2048; len *= 2)
461 printf("%d\t\t\t%e\r\n", len, srtp_rejections_per_second(len, policy));
462
463 /* these extra linefeeds let gnuplot know that a dataset is done */
464 printf("\r\n\r\n");
465
466}
467
468
469#define MAX_MSG_LEN 1024
470
471double
472srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
473 srtp_t srtp;
474 srtp_hdr_t *mesg;
475 int i;
476 clock_t timer;
477 int num_trials = 100000;
478 int len;
479 uint32_t ssrc;
480 err_status_t status;
481
482 /*
483 * allocate and initialize an srtp session
484 */
485 status = srtp_create(&srtp, policy);
486 if (status) {
487 printf("error: srtp_create() failed with error code %d\n", status);
488 exit(1);
489 }
490
491 /*
492 * if the ssrc is unspecified, use a predetermined one
493 */
494 if (policy->ssrc.type != ssrc_specific) {
495 ssrc = 0xdeadbeef;
496 } else {
497 ssrc = policy->ssrc.value;
498 }
499
500 /*
501 * create a test packet
502 */
503 mesg = srtp_create_test_packet(msg_len_octets, ssrc);
504 if (mesg == NULL)
505 return 0.0; /* indicate failure by returning zero */
506
507 timer = clock();
508 for (i=0; i < num_trials; i++) {
509 err_status_t status;
David McGrewd2f8de42006-02-03 19:43:59 +0000510 len = msg_len_octets + 12; /* add in rtp header length */
Cullen Jennings235513a2005-09-21 22:51:36 +0000511
512 /* srtp protect message */
513 status = srtp_protect(srtp, mesg, &len);
514 if (status) {
515 printf("error: srtp_protect() failed with error code %d\n", status);
516 exit(1);
517 }
518
519 /* increment message number */
520 mesg->seq = htons(ntohs(mesg->seq) + 1);
521
522 }
523 timer = clock() - timer;
524
525 free(mesg);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000526
527 status = srtp_dealloc(srtp);
528 if (status) {
529 printf("error: srtp_dealloc() failed with error code %d\n", status);
530 exit(1);
531 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000532
533 return (double) (msg_len_octets) * 8 *
534 num_trials * CLOCKS_PER_SEC / timer;
535}
536
537double
538srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) {
539 srtp_ctx_t *srtp;
540 srtp_hdr_t *mesg;
541 int i;
542 int len;
543 clock_t timer;
544 int num_trials = 1000000;
545 uint32_t ssrc = policy->ssrc.value;
546 err_status_t status;
547
548 /*
549 * allocate and initialize an srtp session
550 */
551 status = srtp_create(&srtp, policy);
552 if (status) {
553 printf("error: srtp_create() failed with error code %d\n", status);
554 exit(1);
555 }
556
557 mesg = srtp_create_test_packet(msg_len_octets, ssrc);
558 if (mesg == NULL)
559 return 0.0; /* indicate failure by returning zero */
560
561 len = msg_len_octets;
562 srtp_protect(srtp, (srtp_hdr_t *)mesg, &len);
563
564 timer = clock();
565 for (i=0; i < num_trials; i++) {
566 len = msg_len_octets;
567 srtp_unprotect(srtp, (srtp_hdr_t *)mesg, &len);
568 }
569 timer = clock() - timer;
570
571 free(mesg);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000572
573 status = srtp_dealloc(srtp);
574 if (status) {
575 printf("error: srtp_dealloc() failed with error code %d\n", status);
576 exit(1);
577 }
578
Cullen Jennings235513a2005-09-21 22:51:36 +0000579 return (double) num_trials * CLOCKS_PER_SEC / timer;
580}
581
582
583void
584err_check(err_status_t s) {
585 if (s == err_status_ok)
586 return;
587 else
588 fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s);
589 exit (1);
590}
591
592err_status_t
593srtp_test(const srtp_policy_t *policy) {
594 int i;
595 srtp_t srtp_sender;
596 srtp_t srtp_rcvr;
597 err_status_t status = err_status_ok;
598 srtp_hdr_t *hdr, *hdr2;
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000599 uint8_t hdr_enc[64];
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000600 uint8_t *pkt_end;
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000601 int msg_len_octets, msg_len_enc;
Cullen Jennings235513a2005-09-21 22:51:36 +0000602 int len;
603 int tag_length = policy->rtp.auth_tag_len;
604 uint32_t ssrc;
605 srtp_policy_t *rcvr_policy;
606
607 err_check(srtp_create(&srtp_sender, policy));
608
609 /* print out policy */
610 err_check(srtp_session_print_policy(srtp_sender));
611
612 /*
613 * initialize data buffer, using the ssrc in the policy unless that
614 * value is a wildcard, in which case we'll just use an arbitrary
615 * one
616 */
617 if (policy->ssrc.type != ssrc_specific)
618 ssrc = 0xdecafbad;
619 else
620 ssrc = policy->ssrc.value;
621 msg_len_octets = 28;
622 hdr = srtp_create_test_packet(msg_len_octets, ssrc);
623
624 if (hdr == NULL)
625 return err_status_alloc_fail;
626 hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
627 if (hdr2 == NULL) {
628 free(hdr);
629 return err_status_alloc_fail;
630 }
631
632 /* set message length */
633 len = msg_len_octets;
634
635 debug_print(mod_driver, "before protection:\n%s",
636 srtp_packet_to_string(hdr, len));
637
638#if PRINT_REFERENCE_PACKET
639 debug_print(mod_driver, "reference packet before protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000640 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000641#endif
642 err_check(srtp_protect(srtp_sender, hdr, &len));
643
644 debug_print(mod_driver, "after protection:\n%s",
645 srtp_packet_to_string(hdr, len));
646#if PRINT_REFERENCE_PACKET
647 debug_print(mod_driver, "after protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000648 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000649#endif
650
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000651 /* save protected message and length */
652 memcpy(hdr_enc, hdr, len);
653 msg_len_enc = len;
654
Cullen Jennings235513a2005-09-21 22:51:36 +0000655 /*
656 * check for overrun of the srtp_protect() function
657 *
658 * The packet is followed by a value of 0xfffff; if the value of the
659 * data following the packet is different, then we know that the
660 * protect function is overwriting the end of the packet.
661 */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000662 pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t)
Cullen Jennings235513a2005-09-21 22:51:36 +0000663 + msg_len_octets + tag_length;
664 for (i = 0; i < 4; i++)
665 if (pkt_end[i] != 0xff) {
666 fprintf(stdout, "overwrite in srtp_protect() function "
667 "(expected %x, found %x in trailing octet %d)\n",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000668 0xff, ((uint8_t *)hdr)[i], i);
Cullen Jennings235513a2005-09-21 22:51:36 +0000669 free(hdr);
670 free(hdr2);
671 return err_status_algo_fail;
672 }
673
674 /*
675 * if the policy includes confidentiality, check that ciphertext is
676 * different than plaintext
677 *
678 * Note that this check will give false negatives, with some small
679 * probability, especially if the packets are short. For that
680 * reason, we skip this check if the plaintext is less than four
681 * octets long.
682 */
683 if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
684 printf("testing that ciphertext is distinct from plaintext...");
685 status = err_status_algo_fail;
686 for (i=12; i < msg_len_octets+12; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000687 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000688 status = err_status_ok;
689 }
690 if (status) {
691 printf("failed\n");
692 free(hdr);
693 free(hdr2);
694 return status;
695 }
696 printf("passed\n");
697 }
698
699 /*
700 * if the policy uses a 'wildcard' ssrc, then we need to make a copy
701 * of the policy that changes the direction to inbound
702 *
703 * we always copy the policy into the rcvr_policy, since otherwise
704 * the compiler would fret about the constness of the policy
705 */
Derek MacDonald17127da2006-07-12 22:22:08 +0000706 rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000707 if (rcvr_policy == NULL) {
708 free(hdr);
709 free(hdr2);
Cullen Jennings235513a2005-09-21 22:51:36 +0000710 return err_status_alloc_fail;
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000711 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000712 memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
713 if (policy->ssrc.type == ssrc_any_outbound) {
714 rcvr_policy->ssrc.type = ssrc_any_inbound;
715 }
716
717 err_check(srtp_create(&srtp_rcvr, rcvr_policy));
718
719 err_check(srtp_unprotect(srtp_rcvr, hdr, &len));
720
721 debug_print(mod_driver, "after unprotection:\n%s",
722 srtp_packet_to_string(hdr, len));
723
724 /* verify that the unprotected packet matches the origial one */
725 for (i=0; i < msg_len_octets; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000726 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000727 fprintf(stdout, "mismatch at octet %d\n", i);
728 status = err_status_algo_fail;
729 }
730 if (status) {
731 free(hdr);
732 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000733 free(rcvr_policy);
Cullen Jennings235513a2005-09-21 22:51:36 +0000734 return status;
735 }
736
737 /*
738 * if the policy includes authentication, then test for false positives
739 */
740 if (policy->rtp.sec_serv & sec_serv_auth) {
741 char *data = ((char *)hdr) + 12;
742
743 printf("testing for false positives in replay check...");
744
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000745 /* set message length */
746 len = msg_len_enc;
747
Cullen Jennings235513a2005-09-21 22:51:36 +0000748 /* unprotect a second time - should fail with a replay error */
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000749 status = srtp_unprotect(srtp_rcvr, hdr_enc, &len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000750 if (status != err_status_replay_fail) {
751 printf("failed with error code %d\n", status);
752 free(hdr);
753 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000754 free(rcvr_policy);
Cullen Jennings235513a2005-09-21 22:51:36 +0000755 return status;
756 } else {
757 printf("passed\n");
758 }
759
760 printf("testing for false positives in auth check...");
761
762 /* increment sequence number in header */
763 hdr->seq++;
764
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000765 /* set message length */
766 len = msg_len_octets;
767
Cullen Jennings235513a2005-09-21 22:51:36 +0000768 /* apply protection */
769 err_check(srtp_protect(srtp_sender, hdr, &len));
770
771 /* flip bits in packet */
772 data[0] ^= 0xff;
773
774 /* unprotect, and check for authentication failure */
775 status = srtp_unprotect(srtp_rcvr, hdr, &len);
776 if (status != err_status_auth_fail) {
777 printf("failed\n");
778 free(hdr);
779 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000780 free(rcvr_policy);
Cullen Jennings235513a2005-09-21 22:51:36 +0000781 return status;
782 } else {
783 printf("passed\n");
784 }
785
786 }
787
788 err_check(srtp_dealloc(srtp_sender));
789 err_check(srtp_dealloc(srtp_rcvr));
790
791 free(hdr);
792 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000793 free(rcvr_policy);
Cullen Jennings235513a2005-09-21 22:51:36 +0000794 return err_status_ok;
795}
796
797
798err_status_t
David McGrew9c70f292006-05-03 19:38:38 +0000799srtcp_test(const srtp_policy_t *policy) {
800 int i;
801 srtp_t srtcp_sender;
802 srtp_t srtcp_rcvr;
803 err_status_t status = err_status_ok;
804 srtp_hdr_t *hdr, *hdr2;
805 uint8_t hdr_enc[64];
806 uint8_t *pkt_end;
807 int msg_len_octets, msg_len_enc;
808 int len;
809 int tag_length = policy->rtp.auth_tag_len;
810 uint32_t ssrc;
811 srtp_policy_t *rcvr_policy;
812
813 err_check(srtp_create(&srtcp_sender, policy));
814
815 /* print out policy */
816 err_check(srtp_session_print_policy(srtcp_sender));
817
818 /*
819 * initialize data buffer, using the ssrc in the policy unless that
820 * value is a wildcard, in which case we'll just use an arbitrary
821 * one
822 */
823 if (policy->ssrc.type != ssrc_specific)
824 ssrc = 0xdecafbad;
825 else
826 ssrc = policy->ssrc.value;
827 msg_len_octets = 28;
828 hdr = srtp_create_test_packet(msg_len_octets, ssrc);
829
830 if (hdr == NULL)
831 return err_status_alloc_fail;
832 hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
833 if (hdr2 == NULL) {
834 free(hdr);
835 return err_status_alloc_fail;
836 }
837
838 /* set message length */
839 len = msg_len_octets;
840
841 debug_print(mod_driver, "before protection:\n%s",
842 srtp_packet_to_string(hdr, len));
843
844#if PRINT_REFERENCE_PACKET
845 debug_print(mod_driver, "reference packet before protection:\n%s",
846 octet_string_hex_string((uint8_t *)hdr, len));
847#endif
848 err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
849
850 debug_print(mod_driver, "after protection:\n%s",
851 srtp_packet_to_string(hdr, len));
852#if PRINT_REFERENCE_PACKET
853 debug_print(mod_driver, "after protection:\n%s",
854 octet_string_hex_string((uint8_t *)hdr, len));
855#endif
856
857 /* save protected message and length */
858 memcpy(hdr_enc, hdr, len);
859 msg_len_enc = len;
860
861 /*
862 * check for overrun of the srtp_protect() function
863 *
864 * The packet is followed by a value of 0xfffff; if the value of the
865 * data following the packet is different, then we know that the
866 * protect function is overwriting the end of the packet.
867 */
868 pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t)
869 + msg_len_octets + tag_length;
870 for (i = 0; i < 4; i++)
871 if (pkt_end[i] != 0xff) {
872 fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
873 "(expected %x, found %x in trailing octet %d)\n",
874 0xff, ((uint8_t *)hdr)[i], i);
875 free(hdr);
876 free(hdr2);
877 return err_status_algo_fail;
878 }
879
880 /*
881 * if the policy includes confidentiality, check that ciphertext is
882 * different than plaintext
883 *
884 * Note that this check will give false negatives, with some small
885 * probability, especially if the packets are short. For that
886 * reason, we skip this check if the plaintext is less than four
887 * octets long.
888 */
889 if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
890 printf("testing that ciphertext is distinct from plaintext...");
891 status = err_status_algo_fail;
892 for (i=12; i < msg_len_octets+12; i++)
893 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
894 status = err_status_ok;
895 }
896 if (status) {
897 printf("failed\n");
898 free(hdr);
899 free(hdr2);
900 return status;
901 }
902 printf("passed\n");
903 }
904
905 /*
906 * if the policy uses a 'wildcard' ssrc, then we need to make a copy
907 * of the policy that changes the direction to inbound
908 *
909 * we always copy the policy into the rcvr_policy, since otherwise
910 * the compiler would fret about the constness of the policy
911 */
Derek MacDonald17127da2006-07-12 22:22:08 +0000912 rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
David McGrew9c70f292006-05-03 19:38:38 +0000913 if (rcvr_policy == NULL)
914 return err_status_alloc_fail;
915 memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
916 if (policy->ssrc.type == ssrc_any_outbound) {
917 rcvr_policy->ssrc.type = ssrc_any_inbound;
918 }
919
920 err_check(srtp_create(&srtcp_rcvr, rcvr_policy));
921
922 err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len));
923
924 debug_print(mod_driver, "after unprotection:\n%s",
925 srtp_packet_to_string(hdr, len));
926
927 /* verify that the unprotected packet matches the origial one */
928 for (i=0; i < msg_len_octets; i++)
929 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
930 fprintf(stdout, "mismatch at octet %d\n", i);
931 status = err_status_algo_fail;
932 }
933 if (status) {
934 free(hdr);
935 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000936 free(rcvr_policy);
David McGrew9c70f292006-05-03 19:38:38 +0000937 return status;
938 }
939
940 /*
941 * if the policy includes authentication, then test for false positives
942 */
943 if (policy->rtp.sec_serv & sec_serv_auth) {
944 char *data = ((char *)hdr) + 12;
945
946 printf("testing for false positives in replay check...");
947
948 /* set message length */
949 len = msg_len_enc;
950
951 /* unprotect a second time - should fail with a replay error */
952 status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len);
953 if (status != err_status_replay_fail) {
954 printf("failed with error code %d\n", status);
955 free(hdr);
956 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000957 free(rcvr_policy);
David McGrew9c70f292006-05-03 19:38:38 +0000958 return status;
959 } else {
960 printf("passed\n");
961 }
962
963 printf("testing for false positives in auth check...");
964
965 /* increment sequence number in header */
966 hdr->seq++;
967
968 /* set message length */
969 len = msg_len_octets;
970
971 /* apply protection */
972 err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
973
974 /* flip bits in packet */
975 data[0] ^= 0xff;
976
977 /* unprotect, and check for authentication failure */
978 status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len);
979 if (status != err_status_auth_fail) {
980 printf("failed\n");
981 free(hdr);
982 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000983 free(rcvr_policy);
David McGrew9c70f292006-05-03 19:38:38 +0000984 return status;
985 } else {
986 printf("passed\n");
987 }
988
989 }
990
991 err_check(srtp_dealloc(srtcp_sender));
992 err_check(srtp_dealloc(srtcp_rcvr));
993
994 free(hdr);
995 free(hdr2);
Jonathan Lennox80c4c832010-05-17 19:30:28 +0000996 free(rcvr_policy);
David McGrew9c70f292006-05-03 19:38:38 +0000997 return err_status_ok;
998}
999
1000
1001err_status_t
Cullen Jennings235513a2005-09-21 22:51:36 +00001002srtp_session_print_policy(srtp_t srtp) {
1003 char *serv_descr[4] = {
1004 "none",
1005 "confidentiality",
1006 "authentication",
1007 "confidentiality and authentication"
1008 };
1009 char *direction[3] = {
1010 "unknown",
1011 "outbound",
1012 "inbound"
1013 };
1014 srtp_stream_t stream;
1015
1016 /* sanity checking */
1017 if (srtp == NULL)
1018 return err_status_fail;
1019
1020 /* if there's a template stream, print it out */
1021 if (srtp->stream_template != NULL) {
1022 stream = srtp->stream_template;
1023 printf("# SSRC: any %s\r\n"
1024 "# rtp cipher: %s\r\n"
1025 "# rtp auth: %s\r\n"
1026 "# rtp services: %s\r\n"
1027 "# rtcp cipher: %s\r\n"
1028 "# rtcp auth: %s\r\n"
1029 "# rtcp services: %s\r\n",
1030 direction[stream->direction],
1031 stream->rtp_cipher->type->description,
1032 stream->rtp_auth->type->description,
1033 serv_descr[stream->rtp_services],
1034 stream->rtcp_cipher->type->description,
1035 stream->rtcp_auth->type->description,
1036 serv_descr[stream->rtcp_services]);
1037 }
1038
1039 /* loop over streams in session, printing the policy of each */
1040 stream = srtp->stream_list;
1041 while (stream != NULL) {
1042 if (stream->rtp_services > sec_serv_conf_and_auth)
1043 return err_status_bad_param;
1044
1045 printf("# SSRC: 0x%08x\r\n"
1046 "# rtp cipher: %s\r\n"
1047 "# rtp auth: %s\r\n"
1048 "# rtp services: %s\r\n"
1049 "# rtcp cipher: %s\r\n"
1050 "# rtcp auth: %s\r\n"
1051 "# rtcp services: %s\r\n",
1052 stream->ssrc,
1053 stream->rtp_cipher->type->description,
1054 stream->rtp_auth->type->description,
1055 serv_descr[stream->rtp_services],
1056 stream->rtcp_cipher->type->description,
1057 stream->rtcp_auth->type->description,
1058 serv_descr[stream->rtcp_services]);
1059
1060 /* advance to next stream in the list */
1061 stream = stream->next;
1062 }
1063 return err_status_ok;
1064}
1065
1066err_status_t
1067srtp_print_policy(const srtp_policy_t *policy) {
1068 err_status_t status;
1069 srtp_t session;
1070
1071 status = srtp_create(&session, policy);
1072 if (status)
1073 return status;
1074 status = srtp_session_print_policy(session);
1075 if (status)
1076 return status;
1077 status = srtp_dealloc(session);
1078 if (status)
1079 return status;
1080 return err_status_ok;
1081}
1082
1083/*
1084 * srtp_print_packet(...) is for debugging only
1085 * it prints an RTP packet to the stdout
1086 *
1087 * note that this function is *not* threadsafe
1088 */
1089
1090#include <stdio.h>
1091
1092#define MTU 2048
1093
1094char packet_string[MTU];
1095
1096char *
1097srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
1098 int octets_in_rtp_header = 12;
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001099 uint8_t *data = ((uint8_t *)hdr)+octets_in_rtp_header;
Cullen Jennings235513a2005-09-21 22:51:36 +00001100 int hex_len = pkt_octet_len-octets_in_rtp_header;
1101
1102 /* sanity checking */
1103 if ((hdr == NULL) || (pkt_octet_len > MTU))
1104 return NULL;
1105
1106 /* write packet into string */
1107 sprintf(packet_string,
1108 "(s)rtp packet: {\n"
1109 " version:\t%d\n"
1110 " p:\t\t%d\n"
1111 " x:\t\t%d\n"
1112 " cc:\t\t%d\n"
1113 " m:\t\t%d\n"
1114 " pt:\t\t%x\n"
1115 " seq:\t\t%x\n"
1116 " ts:\t\t%x\n"
1117 " ssrc:\t%x\n"
1118 " data:\t%s\n"
1119 "} (%d octets in total)\n",
1120 hdr->version,
1121 hdr->p,
1122 hdr->x,
1123 hdr->cc,
1124 hdr->m,
1125 hdr->pt,
1126 hdr->seq,
1127 hdr->ts,
1128 hdr->ssrc,
1129 octet_string_hex_string(data, hex_len),
1130 pkt_octet_len);
1131
1132 return packet_string;
1133}
1134
1135/*
1136 * mips_estimate() is a simple function to estimate the number of
1137 * instructions per second that the host can perform. note that this
1138 * function can be grossly wrong; you may want to have a manual sanity
1139 * check of its output!
1140 *
1141 * the 'ignore' pointer is there to convince the compiler to not just
1142 * optimize away the function
1143 */
1144
1145double
1146mips_estimate(int num_trials, int *ignore) {
1147 clock_t t;
Jonathan Lennox33554932010-05-15 04:53:10 +00001148 volatile int i, sum;
Cullen Jennings235513a2005-09-21 22:51:36 +00001149
1150 sum = 0;
1151 t = clock();
1152 for (i=0; i<num_trials; i++)
1153 sum += i;
1154 t = clock() - t;
1155
1156/* printf("%d\n", sum); */
1157 *ignore = sum;
1158
1159 return (double) num_trials * CLOCKS_PER_SEC / t;
1160}
1161
1162
1163/*
1164 * srtp_validate() verifies the correctness of libsrtp by comparing
1165 * some computed packets against some pre-computed reference values.
1166 * These packets were made with the default SRTP policy.
1167 */
1168
1169
1170err_status_t
1171srtp_validate() {
1172 unsigned char test_key[30] = {
1173 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
1174 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
1175 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
1176 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
1177 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001178 uint8_t srtp_plaintext_ref[28] = {
Cullen Jennings235513a2005-09-21 22:51:36 +00001179 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
1180 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
1181 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
1182 0xab, 0xab, 0xab, 0xab
1183 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001184 uint8_t srtp_plaintext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +00001185 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
1186 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
1187 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
1188 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1190 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001191 uint8_t srtp_ciphertext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +00001192 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
1193 0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
1194 0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15,
1195 0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
1196 0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
1197 };
1198 srtp_t srtp_snd, srtp_recv;
1199 err_status_t status;
1200 int len;
1201 srtp_policy_t policy;
1202
1203 /*
1204 * create a session with a single stream using the default srtp
1205 * policy and with the SSRC value 0xcafebabe
1206 */
1207 crypto_policy_set_rtp_default(&policy.rtp);
1208 crypto_policy_set_rtcp_default(&policy.rtcp);
1209 policy.ssrc.type = ssrc_specific;
1210 policy.ssrc.value = 0xcafebabe;
1211 policy.key = test_key;
1212 policy.next = NULL;
1213
1214 status = srtp_create(&srtp_snd, &policy);
1215 if (status)
1216 return status;
1217
1218 /*
1219 * protect plaintext, then compare with ciphertext
1220 */
1221 len = 28;
1222 status = srtp_protect(srtp_snd, srtp_plaintext, &len);
1223 if (status || (len != 38))
1224 return err_status_fail;
1225
1226 debug_print(mod_driver, "ciphertext:\n %s",
1227 octet_string_hex_string(srtp_plaintext, len));
1228 debug_print(mod_driver, "ciphertext reference:\n %s",
1229 octet_string_hex_string(srtp_ciphertext, len));
1230
1231 if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
1232 return err_status_fail;
1233
1234 /*
1235 * create a receiver session context comparable to the one created
1236 * above - we need to do this so that the replay checking doesn't
1237 * complain
1238 */
1239 status = srtp_create(&srtp_recv, &policy);
1240 if (status)
1241 return status;
1242
1243 /*
1244 * unprotect ciphertext, then compare with plaintext
1245 */
1246 status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
1247 if (status || (len != 28))
1248 return status;
1249
1250 if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
1251 return err_status_fail;
1252
Jonathan Lennox80c4c832010-05-17 19:30:28 +00001253 status = srtp_dealloc(srtp_snd);
1254 if (status)
1255 return status;
1256
1257 status = srtp_dealloc(srtp_recv);
1258 if (status)
1259 return status;
1260
Cullen Jennings235513a2005-09-21 22:51:36 +00001261 return err_status_ok;
1262}
1263
1264
1265err_status_t
1266srtp_create_big_policy(srtp_policy_t **list) {
1267 extern const srtp_policy_t *policy_array[];
1268 srtp_policy_t *p, *tmp;
1269 int i = 0;
1270 uint32_t ssrc = 0;
1271
1272 /* sanity checking */
1273 if ((list == NULL) || (policy_array[0] == NULL))
1274 return err_status_bad_param;
1275
1276 /*
1277 * loop over policy list, mallocing a new list and copying values
1278 * into it (and incrementing the SSRC value as we go along)
1279 */
1280 tmp = NULL;
1281 while (policy_array[i] != NULL) {
Derek MacDonald17127da2006-07-12 22:22:08 +00001282 p = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
Cullen Jennings235513a2005-09-21 22:51:36 +00001283 if (p == NULL)
1284 return err_status_bad_param;
1285 memcpy(p, policy_array[i], sizeof(srtp_policy_t));
1286 p->ssrc.type = ssrc_specific;
1287 p->ssrc.value = ssrc++;
1288 p->next = tmp;
1289 tmp = p;
1290 i++;
1291 }
1292 *list = p;
1293
1294 return err_status_ok;
1295}
1296
1297err_status_t
Jonathan Lennox80c4c832010-05-17 19:30:28 +00001298srtp_dealloc_big_policy(srtp_policy_t *list) {
1299 srtp_policy_t *p, *next;
1300
1301 for (p = list; p != NULL; p = next) {
1302 next = p->next;
1303 free(p);
1304 }
1305
1306 return err_status_ok;
1307}
1308
1309
1310err_status_t
Cullen Jennings235513a2005-09-21 22:51:36 +00001311srtp_test_remove_stream() {
1312 err_status_t status;
1313 srtp_policy_t *policy_list;
1314 srtp_t session;
1315 srtp_stream_t stream;
1316 /*
1317 * srtp_get_stream() is a libSRTP internal function that we declare
1318 * here so that we can use it to verify the correct operation of the
1319 * library
1320 */
1321 extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
1322
1323
1324 status = srtp_create_big_policy(&policy_list);
1325 if (status)
1326 return status;
1327
1328 status = srtp_create(&session, policy_list);
1329 if (status)
1330 return status;
1331
1332 /*
1333 * check for false positives by trying to remove a stream that's not
1334 * in the session
1335 */
1336 status = srtp_remove_stream(session, htonl(0xaaaaaaaa));
1337 if (status != err_status_no_ctx)
1338 return err_status_fail;
1339
1340 /*
1341 * check for false negatives by removing stream 0x1, then
1342 * searching for streams 0x0 and 0x2
1343 */
1344 status = srtp_remove_stream(session, htonl(0x1));
1345 if (status != err_status_ok)
1346 return err_status_fail;
1347 stream = srtp_get_stream(session, htonl(0x0));
1348 if (stream == NULL)
1349 return err_status_fail;
1350 stream = srtp_get_stream(session, htonl(0x2));
1351 if (stream == NULL)
1352 return err_status_fail;
1353
Jonathan Lennox80c4c832010-05-17 19:30:28 +00001354 status = srtp_dealloc(session);
1355 if (status != err_status_ok)
1356 return status;
1357
1358 status = srtp_dealloc_big_policy(policy_list);
1359 if (status != err_status_ok)
1360 return status;
1361
Cullen Jennings235513a2005-09-21 22:51:36 +00001362 return err_status_ok;
1363}
1364
1365/*
1366 * srtp policy definitions - these definitions are used above
1367 */
1368
1369unsigned char test_key[30] = {
1370 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
1371 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
1372 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
1373 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
1374};
1375
1376
1377const srtp_policy_t default_policy = {
1378 { ssrc_any_outbound, 0 }, /* SSRC */
1379 { /* SRTP policy */
1380 AES_128_ICM, /* cipher type */
1381 30, /* cipher key length in octets */
1382 HMAC_SHA1, /* authentication func type */
1383 16, /* auth key length in octets */
1384 10, /* auth tag length in octets */
1385 sec_serv_conf_and_auth /* security services flag */
1386 },
1387 { /* SRTCP policy */
1388 AES_128_ICM, /* cipher type */
1389 30, /* cipher key length in octets */
1390 HMAC_SHA1, /* authentication func type */
1391 16, /* auth key length in octets */
1392 10, /* auth tag length in octets */
1393 sec_serv_conf_and_auth /* security services flag */
1394 },
1395 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001396 NULL, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001397 NULL
1398};
1399
1400const srtp_policy_t aes_tmmh_policy = {
1401 { ssrc_any_outbound, 0 }, /* SSRC */
1402 {
1403 AES_128_ICM, /* cipher type */
1404 30, /* cipher key length in octets */
1405 UST_TMMHv2, /* authentication func type */
1406 94, /* auth key length in octets */
1407 4, /* auth tag length in octets */
1408 sec_serv_conf_and_auth /* security services flag */
1409 },
1410 {
1411 AES_128_ICM, /* cipher type */
1412 30, /* cipher key length in octets */
1413 UST_TMMHv2, /* authentication func type */
1414 94, /* auth key length in octets */
1415 4, /* auth tag length in octets */
1416 sec_serv_conf_and_auth /* security services flag */
1417 },
1418 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001419 NULL, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001420 NULL
1421};
1422
1423const srtp_policy_t tmmh_only_policy = {
1424 { ssrc_any_outbound, 0 }, /* SSRC */
1425 {
1426 AES_128_ICM, /* cipher type */
1427 30, /* cipher key length in octets */
1428 UST_TMMHv2, /* authentication func type */
1429 94, /* auth key length in octets */
1430 4, /* auth tag length in octets */
1431 sec_serv_auth /* security services flag */
1432 },
1433 {
1434 AES_128_ICM, /* cipher type */
1435 30, /* cipher key length in octets */
1436 UST_TMMHv2, /* authentication func type */
1437 94, /* auth key length in octets */
1438 4, /* auth tag length in octets */
1439 sec_serv_auth /* security services flag */
1440 },
1441 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001442 NULL, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001443 NULL
1444};
1445
1446const srtp_policy_t aes_only_policy = {
1447 { ssrc_any_outbound, 0 }, /* SSRC */
1448 {
1449 AES_128_ICM, /* cipher type */
1450 30, /* cipher key length in octets */
1451 NULL_AUTH, /* authentication func type */
1452 0, /* auth key length in octets */
1453 0, /* auth tag length in octets */
1454 sec_serv_conf /* security services flag */
1455 },
1456 {
1457 AES_128_ICM, /* cipher type */
1458 30, /* cipher key length in octets */
1459 NULL_AUTH, /* authentication func type */
1460 0, /* auth key length in octets */
1461 0, /* auth tag length in octets */
1462 sec_serv_conf /* security services flag */
1463 },
1464 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001465 NULL, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001466 NULL
1467};
1468
1469const srtp_policy_t hmac_only_policy = {
1470 { ssrc_any_outbound, 0 }, /* SSRC */
1471 {
1472 NULL_CIPHER, /* cipher type */
1473 0, /* cipher key length in octets */
1474 HMAC_SHA1, /* authentication func type */
1475 20, /* auth key length in octets */
1476 4, /* auth tag length in octets */
1477 sec_serv_auth /* security services flag */
1478 },
1479 {
1480 NULL_CIPHER, /* cipher type */
1481 0, /* cipher key length in octets */
1482 HMAC_SHA1, /* authentication func type */
1483 20, /* auth key length in octets */
1484 4, /* auth tag length in octets */
1485 sec_serv_auth /* security services flag */
1486 },
1487 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001488 NULL, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001489 NULL
1490};
1491
1492const srtp_policy_t null_policy = {
1493 { ssrc_any_outbound, 0 }, /* SSRC */
1494 {
1495 NULL_CIPHER, /* cipher type */
1496 0, /* cipher key length in octets */
1497 NULL_AUTH, /* authentication func type */
1498 0, /* auth key length in octets */
1499 0, /* auth tag length in octets */
1500 sec_serv_none /* security services flag */
1501 },
1502 {
1503 NULL_CIPHER, /* cipher type */
1504 0, /* cipher key length in octets */
1505 NULL_AUTH, /* authentication func type */
1506 0, /* auth key length in octets */
1507 0, /* auth tag length in octets */
1508 sec_serv_none /* security services flag */
1509 },
1510 test_key,
David McGrew79870d62007-06-15 18:17:39 +00001511 NULL, /* indicates that EKT is not in use */
1512 NULL
1513};
1514
1515uint8_t ekt_test_key[16] = {
1516 0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca,
1517 0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
1518};
1519
1520#include "ekt.h"
1521
1522ekt_policy_ctx_t ekt_test_policy = {
1523 0xa5a5, /* SPI */
1524 EKT_CIPHER_AES_128_ECB,
1525 ekt_test_key,
1526 NULL
1527};
1528
1529const srtp_policy_t hmac_only_with_ekt_policy = {
1530 { ssrc_any_outbound, 0 }, /* SSRC */
1531 {
1532 NULL_CIPHER, /* cipher type */
1533 0, /* cipher key length in octets */
1534 HMAC_SHA1, /* authentication func type */
1535 20, /* auth key length in octets */
1536 4, /* auth tag length in octets */
1537 sec_serv_auth /* security services flag */
1538 },
1539 {
1540 NULL_CIPHER, /* cipher type */
1541 0, /* cipher key length in octets */
1542 HMAC_SHA1, /* authentication func type */
1543 20, /* auth key length in octets */
1544 4, /* auth tag length in octets */
1545 sec_serv_auth /* security services flag */
1546 },
1547 test_key,
1548 &ekt_test_policy, /* indicates that EKT is not in use */
Cullen Jennings235513a2005-09-21 22:51:36 +00001549 NULL
1550};
1551
1552
1553/*
1554 * an array of pointers to the policies listed above
1555 *
1556 * This array is used to test various aspects of libSRTP for
1557 * different cryptographic policies. The order of the elements
1558 * matters - the timing test generates output that can be used
1559 * in a plot (see the gnuplot script file 'timing'). If you
1560 * add to this list, you should do it at the end.
1561 */
1562
1563#define USE_TMMH 0
1564
1565const srtp_policy_t *
1566policy_array[] = {
1567 &hmac_only_policy,
1568#if USE_TMMH
1569 &tmmh_only_policy,
1570#endif
1571 &aes_only_policy,
1572#if USE_TMMH
1573 &aes_tmmh_policy,
1574#endif
1575 &default_policy,
1576 &null_policy,
David McGrew79870d62007-06-15 18:17:39 +00001577 &hmac_only_with_ekt_policy,
Cullen Jennings235513a2005-09-21 22:51:36 +00001578 NULL
1579};
1580
1581const srtp_policy_t wildcard_policy = {
1582 { ssrc_any_outbound, 0 }, /* SSRC */
1583 { /* SRTP policy */
1584 AES_128_ICM, /* cipher type */
1585 30, /* cipher key length in octets */
1586 HMAC_SHA1, /* authentication func type */
1587 16, /* auth key length in octets */
1588 10, /* auth tag length in octets */
1589 sec_serv_conf_and_auth /* security services flag */
1590 },
1591 { /* SRTCP policy */
1592 AES_128_ICM, /* cipher type */
1593 30, /* cipher key length in octets */
1594 HMAC_SHA1, /* authentication func type */
1595 16, /* auth key length in octets */
1596 10, /* auth tag length in octets */
1597 sec_serv_conf_and_auth /* security services flag */
1598 },
1599 test_key,
Jonathan Lennox28bd7c12010-05-15 00:23:19 +00001600 NULL,
Cullen Jennings235513a2005-09-21 22:51:36 +00001601 NULL
1602};