blob: d9f3faa23ebfe400177eca916cab906742da9ce8 [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 *
11 * Copyright (c) 2001-2005, Cisco Systems, Inc.
12 * 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() */
50#include <unistd.h> /* for getopt() */
51
52#include "srtp.h"
53
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
Marcus Sundberga3f95fe2005-09-29 12:48:41 +000069srtp_test_remove_stream(void);
Cullen Jennings235513a2005-09-21 22:51:36 +000070
71double
72srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy);
73
74double
75srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy);
76
77void
78srtp_do_timing(const srtp_policy_t *policy);
79
80void
81srtp_do_rejection_timing(const srtp_policy_t *policy);
82
83err_status_t
Marcus Sundberga3f95fe2005-09-29 12:48:41 +000084srtp_test(const srtp_policy_t *policy);
Cullen Jennings235513a2005-09-21 22:51:36 +000085
86err_status_t
87srtp_session_print_policy(srtp_t srtp);
88
89err_status_t
90srtp_print_policy(const srtp_policy_t *policy);
91
92char *
93srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
94
95double
96mips_estimate(int num_trials, int *ignore);
97
Marcus Sundberg410faaa2005-09-29 12:36:43 +000098extern uint8_t test_key[30];
Cullen Jennings235513a2005-09-21 22:51:36 +000099
100void
101usage(char *prog_name) {
102 printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
103 " -t run timing test\n"
104 " -r run rejection timing test\n"
105 " -c run codec timing test\n"
106 " -v run validation tests\n"
107 " -d <mod> turn on debugging module <mod>\n"
108 " -l list debugging modules\n", prog_name);
109 exit(1);
110}
111
112/*
113 * The policy_array is a null-terminated array of policy structs. it
114 * is declared at the end of this file
115 */
116
117extern const srtp_policy_t *policy_array[];
118
119
120/* the wildcard_policy is declared below; it has a wildcard ssrc */
121
122extern const srtp_policy_t wildcard_policy;
123
124/*
125 * mod_driver debug module - debugging module for this test driver
126 *
127 * we use the crypto_kernel debugging system in this driver, which
128 * makes the interface uniform and increases portability
129 */
130
131debug_module_t mod_driver = {
132 0, /* debugging is off by default */
133 "driver" /* printable name for module */
134};
135
136int
137main (int argc, char *argv[]) {
138 char q;
139 unsigned do_timing_test = 0;
140 unsigned do_rejection_test = 0;
141 unsigned do_codec_timing = 0;
142 unsigned do_validation = 0;
143 unsigned do_list_mods = 0;
144 err_status_t status;
145
146 /*
147 * verify that the compiler has interpreted the header data
148 * structure srtp_hdr_t correctly
149 */
150 if (sizeof(srtp_hdr_t) != 12) {
151 printf("error: srtp_hdr_t has incorrect size\n");
152 exit(1);
153 }
154
155 /* initialize srtp library */
156 status = srtp_init();
157 if (status) {
158 printf("error: srtp init failed with error code %d\n", status);
159 exit(1);
160 }
161
162 /* load srtp_driver debug module */
163 status = crypto_kernel_load_debug_module(&mod_driver);
164 if (status) {
165 printf("error: load of srtp_driver debug module failed "
166 "with error code %d\n", status);
167 exit(1);
168 }
169
170 /* process input arguments */
171 while (1) {
172 q = getopt(argc, argv, "trcvld:");
173 if (q == -1)
174 break;
175 switch (q) {
176 case 't':
177 do_timing_test = 1;
178 break;
179 case 'r':
180 do_rejection_test = 1;
181 break;
182 case 'c':
183 do_codec_timing = 1;
184 break;
185 case 'v':
186 do_validation = 1;
187 break;
188 case 'l':
189 do_list_mods = 1;
190 break;
191 case 'd':
192 status = crypto_kernel_set_debug_module(optarg, 1);
193 if (status) {
194 printf("error: set debug module (%s) failed\n", optarg);
195 exit(1);
196 }
197 break;
198 default:
199 usage(argv[0]);
200 }
201 }
202
203 if (!do_validation && !do_timing_test && !do_codec_timing
204 && !do_list_mods && !do_rejection_test)
205 usage(argv[0]);
206
207 if (do_list_mods) {
208 status = crypto_kernel_list_debug_modules();
209 if (status) {
210 printf("error: list of debug modules failed\n");
211 exit(1);
212 }
213 }
214
215 if (do_validation) {
216 const srtp_policy_t **policy = policy_array;
217 srtp_policy_t *big_policy;
218
219 /* loop over policy array, testing srtp for each policy */
220 while (*policy != NULL) {
221 printf("testing srtp_protect and srtp_unprotect\n");
222 if (srtp_test(*policy) == err_status_ok)
223 printf("passed\n\n");
224 else {
225 printf("failed\n");
226 exit(1);
227 }
228 policy++;
229 }
230
231 /* create a big policy list and run tests on it */
232 status = srtp_create_big_policy(&big_policy);
233 if (status) {
234 printf("unexpected failure with error code %d\n", status);
235 exit(1);
236 }
237 printf("testing srtp_protect and srtp_unprotect with big policy\n");
238 if (srtp_test(big_policy) == err_status_ok)
239 printf("passed\n\n");
240 else {
241 printf("failed\n");
242 exit(1);
243 }
244
245 /* run test on wildcard policy */
246 printf("testing srtp_protect and srtp_unprotect on "
247 "wildcard ssrc policy\n");
248 if (srtp_test(&wildcard_policy) == err_status_ok)
249 printf("passed\n\n");
250 else {
251 printf("failed\n");
252 exit(1);
253 }
254
255 /*
256 * run validation test against the reference packets - note
257 * that this test only covers the default policy
258 */
259 printf("testing srtp_protect and srtp_unprotect against "
260 "reference packets\n");
261 if (srtp_validate() == err_status_ok)
262 printf("passed\n\n");
263 else {
264 printf("failed\n");
265 exit(1);
266 }
267
268 /*
269 * test the function srtp_remove_stream()
270 */
271 printf("testing srtp_remove_stream()...");
272 if (srtp_test_remove_stream() == err_status_ok)
273 printf("passed\n");
274 else {
275 printf("failed\n");
276 exit(1);
277 }
278 }
279
280 if (do_timing_test) {
281 const srtp_policy_t **policy = policy_array;
282
283 /* loop over policies, run timing test for each */
284 while (*policy != NULL) {
285 srtp_print_policy(*policy);
286 srtp_do_timing(*policy);
287 policy++;
288 }
289 }
290
291 if (do_rejection_test) {
292 const srtp_policy_t **policy = policy_array;
293
294 /* loop over policies, run rejection timing test for each */
295 while (*policy != NULL) {
296 srtp_print_policy(*policy);
297 srtp_do_rejection_timing(*policy);
298 policy++;
299 }
300 }
301
302 if (do_codec_timing) {
303 srtp_policy_t policy;
304 int ignore;
305 double mips = mips_estimate(1000000000, &ignore);
306
307 crypto_policy_set_rtp_default(&policy.rtp);
308 crypto_policy_set_rtcp_default(&policy.rtcp);
309 policy.ssrc.type = ssrc_specific;
310 policy.ssrc.value = 0xdecafbad;
311 policy.key = test_key;
312 policy.next = NULL;
313
314 printf("mips estimate: %e\n", mips);
315
316 printf("testing srtp processing time for voice codecs:\n");
317 printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n");
318 printf("G.711\t\t%d\t\t\t%e\n", 80,
319 (double) mips * (80 * 8) /
320 srtp_bits_per_second(80, &policy) / .01 );
321 printf("G.711\t\t%d\t\t\t%e\n", 160,
322 (double) mips * (160 * 8) /
323 srtp_bits_per_second(160, &policy) / .02);
324 printf("G.726-32\t%d\t\t\t%e\n", 40,
325 (double) mips * (40 * 8) /
326 srtp_bits_per_second(40, &policy) / .01 );
327 printf("G.726-32\t%d\t\t\t%e\n", 80,
328 (double) mips * (80 * 8) /
329 srtp_bits_per_second(80, &policy) / .02);
330 printf("G.729\t\t%d\t\t\t%e\n", 10,
331 (double) mips * (10 * 8) /
332 srtp_bits_per_second(10, &policy) / .01 );
333 printf("G.729\t\t%d\t\t\t%e\n", 20,
334 (double) mips * (20 * 8) /
335 srtp_bits_per_second(20, &policy) / .02 );
336 }
337
338 return 0;
339}
340
341
342
343/*
344 * srtp_create_test_packet(len, ssrc) returns a pointer to a
345 * (malloced) example RTP packet whose data field has the length given
346 * by pkt_octet_len and the SSRC value ssrc. The total length of the
347 * packet is twelve octets longer, since the header is at the
348 * beginning. There is room at the end of the packet for a trailer,
349 * and the four octets following the packet are filled with 0xff
350 * values to enable testing for overwrites.
351 *
352 * note that the location of the test packet can (and should) be
353 * deallocated with the free() call once it is no longer needed.
354 */
355
356srtp_hdr_t *
357srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
358 int i;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000359 uint8_t *buffer;
Cullen Jennings235513a2005-09-21 22:51:36 +0000360 srtp_hdr_t *hdr;
361 int bytes_in_hdr = 12;
362
363 /* allocate memory for test packet */
364 hdr = malloc(pkt_octet_len + bytes_in_hdr
365 + SRTP_MAX_TRAILER_LEN + 4);
366 if (!hdr)
367 return NULL;
368
369 hdr->version = 2; /* RTP version two */
370 hdr->p = 0; /* no padding needed */
371 hdr->x = 0; /* no header extension */
372 hdr->cc = 0; /* no CSRCs */
373 hdr->m = 0; /* marker bit */
374 hdr->pt = 0xf; /* payload type */
375 hdr->seq = htons(0x1234); /* sequence number */
376 hdr->ts = htonl(0xdecafbad); /* timestamp */
377 hdr->ssrc = htonl(ssrc); /* synch. source */
378
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000379 buffer = (uint8_t *)hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +0000380 buffer += bytes_in_hdr;
381
382 /* set RTP data to 0xab */
383 for (i=0; i < pkt_octet_len; i++)
384 *buffer++ = 0xab;
385
386 /* set post-data value to 0xffff to enable overrun checking */
387 for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++)
388 *buffer++ = 0xff;
389
390 return hdr;
391}
392
393void
394srtp_do_timing(const srtp_policy_t *policy) {
395 int len;
396
397 /*
398 * note: the output of this function is formatted so that it
399 * can be used in gnuplot. '#' indicates a comment, and "\r\n"
400 * terminates a record
401 */
402
403 printf("# testing srtp throughput:\r\n");
404 printf("# mesg length (octets)\tthroughput (megabits per second)\r\n");
405
406 for (len=16; len <= 2048; len *= 2)
407 printf("%d\t\t\t%f\r\n", len,
408 srtp_bits_per_second(len, policy) / 1.0E6);
409
410 /* these extra linefeeds let gnuplot know that a dataset is done */
411 printf("\r\n\r\n");
412
413}
414
415void
416srtp_do_rejection_timing(const srtp_policy_t *policy) {
417 int len;
418
419 /*
420 * note: the output of this function is formatted so that it
421 * can be used in gnuplot. '#' indicates a comment, and "\r\n"
422 * terminates a record
423 */
424
425 printf("# testing srtp rejection throughput:\r\n");
426 printf("# mesg length (octets)\trejections per second\r\n");
427
428 for (len=8; len <= 2048; len *= 2)
429 printf("%d\t\t\t%e\r\n", len, srtp_rejections_per_second(len, policy));
430
431 /* these extra linefeeds let gnuplot know that a dataset is done */
432 printf("\r\n\r\n");
433
434}
435
436
437#define MAX_MSG_LEN 1024
438
439double
440srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
441 srtp_t srtp;
442 srtp_hdr_t *mesg;
443 int i;
444 clock_t timer;
445 int num_trials = 100000;
446 int len;
447 uint32_t ssrc;
448 err_status_t status;
449
450 /*
451 * allocate and initialize an srtp session
452 */
453 status = srtp_create(&srtp, policy);
454 if (status) {
455 printf("error: srtp_create() failed with error code %d\n", status);
456 exit(1);
457 }
458
459 /*
460 * if the ssrc is unspecified, use a predetermined one
461 */
462 if (policy->ssrc.type != ssrc_specific) {
463 ssrc = 0xdeadbeef;
464 } else {
465 ssrc = policy->ssrc.value;
466 }
467
468 /*
469 * create a test packet
470 */
471 mesg = srtp_create_test_packet(msg_len_octets, ssrc);
472 if (mesg == NULL)
473 return 0.0; /* indicate failure by returning zero */
474
475 timer = clock();
476 for (i=0; i < num_trials; i++) {
477 err_status_t status;
478 len = msg_len_octets;
479
480 /* srtp protect message */
481 status = srtp_protect(srtp, mesg, &len);
482 if (status) {
483 printf("error: srtp_protect() failed with error code %d\n", status);
484 exit(1);
485 }
486
487 /* increment message number */
488 mesg->seq = htons(ntohs(mesg->seq) + 1);
489
490 }
491 timer = clock() - timer;
492
493 free(mesg);
494
495 return (double) (msg_len_octets) * 8 *
496 num_trials * CLOCKS_PER_SEC / timer;
497}
498
499double
500srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) {
501 srtp_ctx_t *srtp;
502 srtp_hdr_t *mesg;
503 int i;
504 int len;
505 clock_t timer;
506 int num_trials = 1000000;
507 uint32_t ssrc = policy->ssrc.value;
508 err_status_t status;
509
510 /*
511 * allocate and initialize an srtp session
512 */
513 status = srtp_create(&srtp, policy);
514 if (status) {
515 printf("error: srtp_create() failed with error code %d\n", status);
516 exit(1);
517 }
518
519 mesg = srtp_create_test_packet(msg_len_octets, ssrc);
520 if (mesg == NULL)
521 return 0.0; /* indicate failure by returning zero */
522
523 len = msg_len_octets;
524 srtp_protect(srtp, (srtp_hdr_t *)mesg, &len);
525
526 timer = clock();
527 for (i=0; i < num_trials; i++) {
528 len = msg_len_octets;
529 srtp_unprotect(srtp, (srtp_hdr_t *)mesg, &len);
530 }
531 timer = clock() - timer;
532
533 free(mesg);
534
535 return (double) num_trials * CLOCKS_PER_SEC / timer;
536}
537
538
539void
540err_check(err_status_t s) {
541 if (s == err_status_ok)
542 return;
543 else
544 fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s);
545 exit (1);
546}
547
548err_status_t
549srtp_test(const srtp_policy_t *policy) {
550 int i;
551 srtp_t srtp_sender;
552 srtp_t srtp_rcvr;
553 err_status_t status = err_status_ok;
554 srtp_hdr_t *hdr, *hdr2;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000555 uint8_t *pkt_end;
Cullen Jennings235513a2005-09-21 22:51:36 +0000556 int msg_len_octets;
557 int len;
558 int tag_length = policy->rtp.auth_tag_len;
559 uint32_t ssrc;
560 srtp_policy_t *rcvr_policy;
561
562 err_check(srtp_create(&srtp_sender, policy));
563
564 /* print out policy */
565 err_check(srtp_session_print_policy(srtp_sender));
566
567 /*
568 * initialize data buffer, using the ssrc in the policy unless that
569 * value is a wildcard, in which case we'll just use an arbitrary
570 * one
571 */
572 if (policy->ssrc.type != ssrc_specific)
573 ssrc = 0xdecafbad;
574 else
575 ssrc = policy->ssrc.value;
576 msg_len_octets = 28;
577 hdr = srtp_create_test_packet(msg_len_octets, ssrc);
578
579 if (hdr == NULL)
580 return err_status_alloc_fail;
581 hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
582 if (hdr2 == NULL) {
583 free(hdr);
584 return err_status_alloc_fail;
585 }
586
587 /* set message length */
588 len = msg_len_octets;
589
590 debug_print(mod_driver, "before protection:\n%s",
591 srtp_packet_to_string(hdr, len));
592
593#if PRINT_REFERENCE_PACKET
594 debug_print(mod_driver, "reference packet before protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000595 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000596#endif
597 err_check(srtp_protect(srtp_sender, hdr, &len));
598
599 debug_print(mod_driver, "after protection:\n%s",
600 srtp_packet_to_string(hdr, len));
601#if PRINT_REFERENCE_PACKET
602 debug_print(mod_driver, "after protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000603 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000604#endif
605
606 /*
607 * check for overrun of the srtp_protect() function
608 *
609 * The packet is followed by a value of 0xfffff; if the value of the
610 * data following the packet is different, then we know that the
611 * protect function is overwriting the end of the packet.
612 */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000613 pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t)
Cullen Jennings235513a2005-09-21 22:51:36 +0000614 + msg_len_octets + tag_length;
615 for (i = 0; i < 4; i++)
616 if (pkt_end[i] != 0xff) {
617 fprintf(stdout, "overwrite in srtp_protect() function "
618 "(expected %x, found %x in trailing octet %d)\n",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000619 0xff, ((uint8_t *)hdr)[i], i);
Cullen Jennings235513a2005-09-21 22:51:36 +0000620 free(hdr);
621 free(hdr2);
622 return err_status_algo_fail;
623 }
624
625 /*
626 * if the policy includes confidentiality, check that ciphertext is
627 * different than plaintext
628 *
629 * Note that this check will give false negatives, with some small
630 * probability, especially if the packets are short. For that
631 * reason, we skip this check if the plaintext is less than four
632 * octets long.
633 */
634 if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
635 printf("testing that ciphertext is distinct from plaintext...");
636 status = err_status_algo_fail;
637 for (i=12; i < msg_len_octets+12; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000638 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000639 status = err_status_ok;
640 }
641 if (status) {
642 printf("failed\n");
643 free(hdr);
644 free(hdr2);
645 return status;
646 }
647 printf("passed\n");
648 }
649
650 /*
651 * if the policy uses a 'wildcard' ssrc, then we need to make a copy
652 * of the policy that changes the direction to inbound
653 *
654 * we always copy the policy into the rcvr_policy, since otherwise
655 * the compiler would fret about the constness of the policy
656 */
657 rcvr_policy = malloc(sizeof(srtp_policy_t));
658 if (rcvr_policy == NULL)
659 return err_status_alloc_fail;
660 memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
661 if (policy->ssrc.type == ssrc_any_outbound) {
662 rcvr_policy->ssrc.type = ssrc_any_inbound;
663 }
664
665 err_check(srtp_create(&srtp_rcvr, rcvr_policy));
666
667 err_check(srtp_unprotect(srtp_rcvr, hdr, &len));
668
669 debug_print(mod_driver, "after unprotection:\n%s",
670 srtp_packet_to_string(hdr, len));
671
672 /* verify that the unprotected packet matches the origial one */
673 for (i=0; i < msg_len_octets; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000674 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000675 fprintf(stdout, "mismatch at octet %d\n", i);
676 status = err_status_algo_fail;
677 }
678 if (status) {
679 free(hdr);
680 free(hdr2);
681 return status;
682 }
683
684 /*
685 * if the policy includes authentication, then test for false positives
686 */
687 if (policy->rtp.sec_serv & sec_serv_auth) {
688 char *data = ((char *)hdr) + 12;
689
690 printf("testing for false positives in replay check...");
691
692 /* unprotect a second time - should fail with a replay error */
693 status = srtp_unprotect(srtp_rcvr, hdr, &len);
694 if (status != err_status_replay_fail) {
695 printf("failed with error code %d\n", status);
696 free(hdr);
697 free(hdr2);
698 return status;
699 } else {
700 printf("passed\n");
701 }
702
703 printf("testing for false positives in auth check...");
704
705 /* increment sequence number in header */
706 hdr->seq++;
707
708 /* apply protection */
709 err_check(srtp_protect(srtp_sender, hdr, &len));
710
711 /* flip bits in packet */
712 data[0] ^= 0xff;
713
714 /* unprotect, and check for authentication failure */
715 status = srtp_unprotect(srtp_rcvr, hdr, &len);
716 if (status != err_status_auth_fail) {
717 printf("failed\n");
718 free(hdr);
719 free(hdr2);
720 return status;
721 } else {
722 printf("passed\n");
723 }
724
725 }
726
727 err_check(srtp_dealloc(srtp_sender));
728 err_check(srtp_dealloc(srtp_rcvr));
729
730 free(hdr);
731 free(hdr2);
732 return err_status_ok;
733}
734
735
736err_status_t
737srtp_session_print_policy(srtp_t srtp) {
738 char *serv_descr[4] = {
739 "none",
740 "confidentiality",
741 "authentication",
742 "confidentiality and authentication"
743 };
744 char *direction[3] = {
745 "unknown",
746 "outbound",
747 "inbound"
748 };
749 srtp_stream_t stream;
750
751 /* sanity checking */
752 if (srtp == NULL)
753 return err_status_fail;
754
755 /* if there's a template stream, print it out */
756 if (srtp->stream_template != NULL) {
757 stream = srtp->stream_template;
758 printf("# SSRC: any %s\r\n"
759 "# rtp cipher: %s\r\n"
760 "# rtp auth: %s\r\n"
761 "# rtp services: %s\r\n"
762 "# rtcp cipher: %s\r\n"
763 "# rtcp auth: %s\r\n"
764 "# rtcp services: %s\r\n",
765 direction[stream->direction],
766 stream->rtp_cipher->type->description,
767 stream->rtp_auth->type->description,
768 serv_descr[stream->rtp_services],
769 stream->rtcp_cipher->type->description,
770 stream->rtcp_auth->type->description,
771 serv_descr[stream->rtcp_services]);
772 }
773
774 /* loop over streams in session, printing the policy of each */
775 stream = srtp->stream_list;
776 while (stream != NULL) {
777 if (stream->rtp_services > sec_serv_conf_and_auth)
778 return err_status_bad_param;
779
780 printf("# SSRC: 0x%08x\r\n"
781 "# rtp cipher: %s\r\n"
782 "# rtp auth: %s\r\n"
783 "# rtp services: %s\r\n"
784 "# rtcp cipher: %s\r\n"
785 "# rtcp auth: %s\r\n"
786 "# rtcp services: %s\r\n",
787 stream->ssrc,
788 stream->rtp_cipher->type->description,
789 stream->rtp_auth->type->description,
790 serv_descr[stream->rtp_services],
791 stream->rtcp_cipher->type->description,
792 stream->rtcp_auth->type->description,
793 serv_descr[stream->rtcp_services]);
794
795 /* advance to next stream in the list */
796 stream = stream->next;
797 }
798 return err_status_ok;
799}
800
801err_status_t
802srtp_print_policy(const srtp_policy_t *policy) {
803 err_status_t status;
804 srtp_t session;
805
806 status = srtp_create(&session, policy);
807 if (status)
808 return status;
809 status = srtp_session_print_policy(session);
810 if (status)
811 return status;
812 status = srtp_dealloc(session);
813 if (status)
814 return status;
815 return err_status_ok;
816}
817
818/*
819 * srtp_print_packet(...) is for debugging only
820 * it prints an RTP packet to the stdout
821 *
822 * note that this function is *not* threadsafe
823 */
824
825#include <stdio.h>
826
827#define MTU 2048
828
829char packet_string[MTU];
830
831char *
832srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
833 int octets_in_rtp_header = 12;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000834 uint8_t *data = ((uint8_t *)hdr)+octets_in_rtp_header;
Cullen Jennings235513a2005-09-21 22:51:36 +0000835 int hex_len = pkt_octet_len-octets_in_rtp_header;
836
837 /* sanity checking */
838 if ((hdr == NULL) || (pkt_octet_len > MTU))
839 return NULL;
840
841 /* write packet into string */
842 sprintf(packet_string,
843 "(s)rtp packet: {\n"
844 " version:\t%d\n"
845 " p:\t\t%d\n"
846 " x:\t\t%d\n"
847 " cc:\t\t%d\n"
848 " m:\t\t%d\n"
849 " pt:\t\t%x\n"
850 " seq:\t\t%x\n"
851 " ts:\t\t%x\n"
852 " ssrc:\t%x\n"
853 " data:\t%s\n"
854 "} (%d octets in total)\n",
855 hdr->version,
856 hdr->p,
857 hdr->x,
858 hdr->cc,
859 hdr->m,
860 hdr->pt,
861 hdr->seq,
862 hdr->ts,
863 hdr->ssrc,
864 octet_string_hex_string(data, hex_len),
865 pkt_octet_len);
866
867 return packet_string;
868}
869
870/*
871 * mips_estimate() is a simple function to estimate the number of
872 * instructions per second that the host can perform. note that this
873 * function can be grossly wrong; you may want to have a manual sanity
874 * check of its output!
875 *
876 * the 'ignore' pointer is there to convince the compiler to not just
877 * optimize away the function
878 */
879
880double
881mips_estimate(int num_trials, int *ignore) {
882 clock_t t;
883 int i, sum;
884
885 sum = 0;
886 t = clock();
887 for (i=0; i<num_trials; i++)
888 sum += i;
889 t = clock() - t;
890
891/* printf("%d\n", sum); */
892 *ignore = sum;
893
894 return (double) num_trials * CLOCKS_PER_SEC / t;
895}
896
897
898/*
899 * srtp_validate() verifies the correctness of libsrtp by comparing
900 * some computed packets against some pre-computed reference values.
901 * These packets were made with the default SRTP policy.
902 */
903
904
905err_status_t
906srtp_validate() {
907 unsigned char test_key[30] = {
908 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
909 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
910 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
911 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
912 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000913 uint8_t srtp_plaintext_ref[28] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000914 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
915 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
916 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
917 0xab, 0xab, 0xab, 0xab
918 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000919 uint8_t srtp_plaintext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000920 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
921 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
922 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
923 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
924 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
925 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000926 uint8_t srtp_ciphertext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000927 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
928 0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
929 0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15,
930 0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
931 0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
932 };
933 srtp_t srtp_snd, srtp_recv;
934 err_status_t status;
935 int len;
936 srtp_policy_t policy;
937
938 /*
939 * create a session with a single stream using the default srtp
940 * policy and with the SSRC value 0xcafebabe
941 */
942 crypto_policy_set_rtp_default(&policy.rtp);
943 crypto_policy_set_rtcp_default(&policy.rtcp);
944 policy.ssrc.type = ssrc_specific;
945 policy.ssrc.value = 0xcafebabe;
946 policy.key = test_key;
947 policy.next = NULL;
948
949 status = srtp_create(&srtp_snd, &policy);
950 if (status)
951 return status;
952
953 /*
954 * protect plaintext, then compare with ciphertext
955 */
956 len = 28;
957 status = srtp_protect(srtp_snd, srtp_plaintext, &len);
958 if (status || (len != 38))
959 return err_status_fail;
960
961 debug_print(mod_driver, "ciphertext:\n %s",
962 octet_string_hex_string(srtp_plaintext, len));
963 debug_print(mod_driver, "ciphertext reference:\n %s",
964 octet_string_hex_string(srtp_ciphertext, len));
965
966 if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
967 return err_status_fail;
968
969 /*
970 * create a receiver session context comparable to the one created
971 * above - we need to do this so that the replay checking doesn't
972 * complain
973 */
974 status = srtp_create(&srtp_recv, &policy);
975 if (status)
976 return status;
977
978 /*
979 * unprotect ciphertext, then compare with plaintext
980 */
981 status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
982 if (status || (len != 28))
983 return status;
984
985 if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
986 return err_status_fail;
987
988 return err_status_ok;
989}
990
991
992err_status_t
993srtp_create_big_policy(srtp_policy_t **list) {
994 extern const srtp_policy_t *policy_array[];
995 srtp_policy_t *p, *tmp;
996 int i = 0;
997 uint32_t ssrc = 0;
998
999 /* sanity checking */
1000 if ((list == NULL) || (policy_array[0] == NULL))
1001 return err_status_bad_param;
1002
1003 /*
1004 * loop over policy list, mallocing a new list and copying values
1005 * into it (and incrementing the SSRC value as we go along)
1006 */
1007 tmp = NULL;
1008 while (policy_array[i] != NULL) {
1009 p = malloc(sizeof(srtp_policy_t));
1010 if (p == NULL)
1011 return err_status_bad_param;
1012 memcpy(p, policy_array[i], sizeof(srtp_policy_t));
1013 p->ssrc.type = ssrc_specific;
1014 p->ssrc.value = ssrc++;
1015 p->next = tmp;
1016 tmp = p;
1017 i++;
1018 }
1019 *list = p;
1020
1021 return err_status_ok;
1022}
1023
1024err_status_t
1025srtp_test_remove_stream() {
1026 err_status_t status;
1027 srtp_policy_t *policy_list;
1028 srtp_t session;
1029 srtp_stream_t stream;
1030 /*
1031 * srtp_get_stream() is a libSRTP internal function that we declare
1032 * here so that we can use it to verify the correct operation of the
1033 * library
1034 */
1035 extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
1036
1037
1038 status = srtp_create_big_policy(&policy_list);
1039 if (status)
1040 return status;
1041
1042 status = srtp_create(&session, policy_list);
1043 if (status)
1044 return status;
1045
1046 /*
1047 * check for false positives by trying to remove a stream that's not
1048 * in the session
1049 */
1050 status = srtp_remove_stream(session, htonl(0xaaaaaaaa));
1051 if (status != err_status_no_ctx)
1052 return err_status_fail;
1053
1054 /*
1055 * check for false negatives by removing stream 0x1, then
1056 * searching for streams 0x0 and 0x2
1057 */
1058 status = srtp_remove_stream(session, htonl(0x1));
1059 if (status != err_status_ok)
1060 return err_status_fail;
1061 stream = srtp_get_stream(session, htonl(0x0));
1062 if (stream == NULL)
1063 return err_status_fail;
1064 stream = srtp_get_stream(session, htonl(0x2));
1065 if (stream == NULL)
1066 return err_status_fail;
1067
1068 return err_status_ok;
1069}
1070
1071/*
1072 * srtp policy definitions - these definitions are used above
1073 */
1074
1075unsigned char test_key[30] = {
1076 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
1077 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
1078 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
1079 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
1080};
1081
1082
1083const srtp_policy_t default_policy = {
1084 { ssrc_any_outbound, 0 }, /* SSRC */
1085 { /* SRTP policy */
1086 AES_128_ICM, /* cipher type */
1087 30, /* cipher key length in octets */
1088 HMAC_SHA1, /* authentication func type */
1089 16, /* auth key length in octets */
1090 10, /* auth tag length in octets */
1091 sec_serv_conf_and_auth /* security services flag */
1092 },
1093 { /* SRTCP policy */
1094 AES_128_ICM, /* cipher type */
1095 30, /* cipher key length in octets */
1096 HMAC_SHA1, /* authentication func type */
1097 16, /* auth key length in octets */
1098 10, /* auth tag length in octets */
1099 sec_serv_conf_and_auth /* security services flag */
1100 },
1101 test_key,
1102 NULL
1103};
1104
1105const srtp_policy_t aes_tmmh_policy = {
1106 { ssrc_any_outbound, 0 }, /* SSRC */
1107 {
1108 AES_128_ICM, /* cipher type */
1109 30, /* cipher key length in octets */
1110 UST_TMMHv2, /* authentication func type */
1111 94, /* auth key length in octets */
1112 4, /* auth tag length in octets */
1113 sec_serv_conf_and_auth /* security services flag */
1114 },
1115 {
1116 AES_128_ICM, /* cipher type */
1117 30, /* cipher key length in octets */
1118 UST_TMMHv2, /* authentication func type */
1119 94, /* auth key length in octets */
1120 4, /* auth tag length in octets */
1121 sec_serv_conf_and_auth /* security services flag */
1122 },
1123 test_key,
1124 NULL
1125};
1126
1127const srtp_policy_t tmmh_only_policy = {
1128 { ssrc_any_outbound, 0 }, /* SSRC */
1129 {
1130 AES_128_ICM, /* cipher type */
1131 30, /* cipher key length in octets */
1132 UST_TMMHv2, /* authentication func type */
1133 94, /* auth key length in octets */
1134 4, /* auth tag length in octets */
1135 sec_serv_auth /* security services flag */
1136 },
1137 {
1138 AES_128_ICM, /* cipher type */
1139 30, /* cipher key length in octets */
1140 UST_TMMHv2, /* authentication func type */
1141 94, /* auth key length in octets */
1142 4, /* auth tag length in octets */
1143 sec_serv_auth /* security services flag */
1144 },
1145 test_key,
1146 NULL
1147};
1148
1149const srtp_policy_t aes_only_policy = {
1150 { ssrc_any_outbound, 0 }, /* SSRC */
1151 {
1152 AES_128_ICM, /* cipher type */
1153 30, /* cipher key length in octets */
1154 NULL_AUTH, /* authentication func type */
1155 0, /* auth key length in octets */
1156 0, /* auth tag length in octets */
1157 sec_serv_conf /* security services flag */
1158 },
1159 {
1160 AES_128_ICM, /* cipher type */
1161 30, /* cipher key length in octets */
1162 NULL_AUTH, /* authentication func type */
1163 0, /* auth key length in octets */
1164 0, /* auth tag length in octets */
1165 sec_serv_conf /* security services flag */
1166 },
1167 test_key,
1168 NULL
1169};
1170
1171const srtp_policy_t hmac_only_policy = {
1172 { ssrc_any_outbound, 0 }, /* SSRC */
1173 {
1174 NULL_CIPHER, /* cipher type */
1175 0, /* cipher key length in octets */
1176 HMAC_SHA1, /* authentication func type */
1177 20, /* auth key length in octets */
1178 4, /* auth tag length in octets */
1179 sec_serv_auth /* security services flag */
1180 },
1181 {
1182 NULL_CIPHER, /* cipher type */
1183 0, /* cipher key length in octets */
1184 HMAC_SHA1, /* authentication func type */
1185 20, /* auth key length in octets */
1186 4, /* auth tag length in octets */
1187 sec_serv_auth /* security services flag */
1188 },
1189 test_key,
1190 NULL
1191};
1192
1193const srtp_policy_t null_policy = {
1194 { ssrc_any_outbound, 0 }, /* SSRC */
1195 {
1196 NULL_CIPHER, /* cipher type */
1197 0, /* cipher key length in octets */
1198 NULL_AUTH, /* authentication func type */
1199 0, /* auth key length in octets */
1200 0, /* auth tag length in octets */
1201 sec_serv_none /* security services flag */
1202 },
1203 {
1204 NULL_CIPHER, /* cipher type */
1205 0, /* cipher key length in octets */
1206 NULL_AUTH, /* authentication func type */
1207 0, /* auth key length in octets */
1208 0, /* auth tag length in octets */
1209 sec_serv_none /* security services flag */
1210 },
1211 test_key,
1212 NULL
1213};
1214
1215
1216/*
1217 * an array of pointers to the policies listed above
1218 *
1219 * This array is used to test various aspects of libSRTP for
1220 * different cryptographic policies. The order of the elements
1221 * matters - the timing test generates output that can be used
1222 * in a plot (see the gnuplot script file 'timing'). If you
1223 * add to this list, you should do it at the end.
1224 */
1225
1226#define USE_TMMH 0
1227
1228const srtp_policy_t *
1229policy_array[] = {
1230 &hmac_only_policy,
1231#if USE_TMMH
1232 &tmmh_only_policy,
1233#endif
1234 &aes_only_policy,
1235#if USE_TMMH
1236 &aes_tmmh_policy,
1237#endif
1238 &default_policy,
1239 &null_policy,
1240 NULL
1241};
1242
1243const srtp_policy_t wildcard_policy = {
1244 { ssrc_any_outbound, 0 }, /* SSRC */
1245 { /* SRTP policy */
1246 AES_128_ICM, /* cipher type */
1247 30, /* cipher key length in octets */
1248 HMAC_SHA1, /* authentication func type */
1249 16, /* auth key length in octets */
1250 10, /* auth tag length in octets */
1251 sec_serv_conf_and_auth /* security services flag */
1252 },
1253 { /* SRTCP policy */
1254 AES_128_ICM, /* cipher type */
1255 30, /* cipher key length in octets */
1256 HMAC_SHA1, /* authentication func type */
1257 16, /* auth key length in octets */
1258 10, /* auth tag length in octets */
1259 sec_serv_conf_and_auth /* security services flag */
1260 },
1261 test_key,
1262 NULL
1263};