blob: bfb04dcd4989d5405316085659ca6a32cbc80c75 [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 Sundberg5c40da82005-10-08 18:15:00 +0000555 uint8_t hdr_enc[64];
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000556 uint8_t *pkt_end;
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000557 int msg_len_octets, msg_len_enc;
Cullen Jennings235513a2005-09-21 22:51:36 +0000558 int len;
559 int tag_length = policy->rtp.auth_tag_len;
560 uint32_t ssrc;
561 srtp_policy_t *rcvr_policy;
562
563 err_check(srtp_create(&srtp_sender, policy));
564
565 /* print out policy */
566 err_check(srtp_session_print_policy(srtp_sender));
567
568 /*
569 * initialize data buffer, using the ssrc in the policy unless that
570 * value is a wildcard, in which case we'll just use an arbitrary
571 * one
572 */
573 if (policy->ssrc.type != ssrc_specific)
574 ssrc = 0xdecafbad;
575 else
576 ssrc = policy->ssrc.value;
577 msg_len_octets = 28;
578 hdr = srtp_create_test_packet(msg_len_octets, ssrc);
579
580 if (hdr == NULL)
581 return err_status_alloc_fail;
582 hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
583 if (hdr2 == NULL) {
584 free(hdr);
585 return err_status_alloc_fail;
586 }
587
588 /* set message length */
589 len = msg_len_octets;
590
591 debug_print(mod_driver, "before protection:\n%s",
592 srtp_packet_to_string(hdr, len));
593
594#if PRINT_REFERENCE_PACKET
595 debug_print(mod_driver, "reference packet before protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000596 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000597#endif
598 err_check(srtp_protect(srtp_sender, hdr, &len));
599
600 debug_print(mod_driver, "after protection:\n%s",
601 srtp_packet_to_string(hdr, len));
602#if PRINT_REFERENCE_PACKET
603 debug_print(mod_driver, "after protection:\n%s",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000604 octet_string_hex_string((uint8_t *)hdr, len));
Cullen Jennings235513a2005-09-21 22:51:36 +0000605#endif
606
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000607 /* save protected message and length */
608 memcpy(hdr_enc, hdr, len);
609 msg_len_enc = len;
610
Cullen Jennings235513a2005-09-21 22:51:36 +0000611 /*
612 * check for overrun of the srtp_protect() function
613 *
614 * The packet is followed by a value of 0xfffff; if the value of the
615 * data following the packet is different, then we know that the
616 * protect function is overwriting the end of the packet.
617 */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000618 pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t)
Cullen Jennings235513a2005-09-21 22:51:36 +0000619 + msg_len_octets + tag_length;
620 for (i = 0; i < 4; i++)
621 if (pkt_end[i] != 0xff) {
622 fprintf(stdout, "overwrite in srtp_protect() function "
623 "(expected %x, found %x in trailing octet %d)\n",
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000624 0xff, ((uint8_t *)hdr)[i], i);
Cullen Jennings235513a2005-09-21 22:51:36 +0000625 free(hdr);
626 free(hdr2);
627 return err_status_algo_fail;
628 }
629
630 /*
631 * if the policy includes confidentiality, check that ciphertext is
632 * different than plaintext
633 *
634 * Note that this check will give false negatives, with some small
635 * probability, especially if the packets are short. For that
636 * reason, we skip this check if the plaintext is less than four
637 * octets long.
638 */
639 if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
640 printf("testing that ciphertext is distinct from plaintext...");
641 status = err_status_algo_fail;
642 for (i=12; i < msg_len_octets+12; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000643 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000644 status = err_status_ok;
645 }
646 if (status) {
647 printf("failed\n");
648 free(hdr);
649 free(hdr2);
650 return status;
651 }
652 printf("passed\n");
653 }
654
655 /*
656 * if the policy uses a 'wildcard' ssrc, then we need to make a copy
657 * of the policy that changes the direction to inbound
658 *
659 * we always copy the policy into the rcvr_policy, since otherwise
660 * the compiler would fret about the constness of the policy
661 */
662 rcvr_policy = malloc(sizeof(srtp_policy_t));
663 if (rcvr_policy == NULL)
664 return err_status_alloc_fail;
665 memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
666 if (policy->ssrc.type == ssrc_any_outbound) {
667 rcvr_policy->ssrc.type = ssrc_any_inbound;
668 }
669
670 err_check(srtp_create(&srtp_rcvr, rcvr_policy));
671
672 err_check(srtp_unprotect(srtp_rcvr, hdr, &len));
673
674 debug_print(mod_driver, "after unprotection:\n%s",
675 srtp_packet_to_string(hdr, len));
676
677 /* verify that the unprotected packet matches the origial one */
678 for (i=0; i < msg_len_octets; i++)
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000679 if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000680 fprintf(stdout, "mismatch at octet %d\n", i);
681 status = err_status_algo_fail;
682 }
683 if (status) {
684 free(hdr);
685 free(hdr2);
686 return status;
687 }
688
689 /*
690 * if the policy includes authentication, then test for false positives
691 */
692 if (policy->rtp.sec_serv & sec_serv_auth) {
693 char *data = ((char *)hdr) + 12;
694
695 printf("testing for false positives in replay check...");
696
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000697 /* set message length */
698 len = msg_len_enc;
699
Cullen Jennings235513a2005-09-21 22:51:36 +0000700 /* unprotect a second time - should fail with a replay error */
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000701 status = srtp_unprotect(srtp_rcvr, hdr_enc, &len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000702 if (status != err_status_replay_fail) {
703 printf("failed with error code %d\n", status);
704 free(hdr);
705 free(hdr2);
706 return status;
707 } else {
708 printf("passed\n");
709 }
710
711 printf("testing for false positives in auth check...");
712
713 /* increment sequence number in header */
714 hdr->seq++;
715
Marcus Sundberg5c40da82005-10-08 18:15:00 +0000716 /* set message length */
717 len = msg_len_octets;
718
Cullen Jennings235513a2005-09-21 22:51:36 +0000719 /* apply protection */
720 err_check(srtp_protect(srtp_sender, hdr, &len));
721
722 /* flip bits in packet */
723 data[0] ^= 0xff;
724
725 /* unprotect, and check for authentication failure */
726 status = srtp_unprotect(srtp_rcvr, hdr, &len);
727 if (status != err_status_auth_fail) {
728 printf("failed\n");
729 free(hdr);
730 free(hdr2);
731 return status;
732 } else {
733 printf("passed\n");
734 }
735
736 }
737
738 err_check(srtp_dealloc(srtp_sender));
739 err_check(srtp_dealloc(srtp_rcvr));
740
741 free(hdr);
742 free(hdr2);
743 return err_status_ok;
744}
745
746
747err_status_t
748srtp_session_print_policy(srtp_t srtp) {
749 char *serv_descr[4] = {
750 "none",
751 "confidentiality",
752 "authentication",
753 "confidentiality and authentication"
754 };
755 char *direction[3] = {
756 "unknown",
757 "outbound",
758 "inbound"
759 };
760 srtp_stream_t stream;
761
762 /* sanity checking */
763 if (srtp == NULL)
764 return err_status_fail;
765
766 /* if there's a template stream, print it out */
767 if (srtp->stream_template != NULL) {
768 stream = srtp->stream_template;
769 printf("# SSRC: any %s\r\n"
770 "# rtp cipher: %s\r\n"
771 "# rtp auth: %s\r\n"
772 "# rtp services: %s\r\n"
773 "# rtcp cipher: %s\r\n"
774 "# rtcp auth: %s\r\n"
775 "# rtcp services: %s\r\n",
776 direction[stream->direction],
777 stream->rtp_cipher->type->description,
778 stream->rtp_auth->type->description,
779 serv_descr[stream->rtp_services],
780 stream->rtcp_cipher->type->description,
781 stream->rtcp_auth->type->description,
782 serv_descr[stream->rtcp_services]);
783 }
784
785 /* loop over streams in session, printing the policy of each */
786 stream = srtp->stream_list;
787 while (stream != NULL) {
788 if (stream->rtp_services > sec_serv_conf_and_auth)
789 return err_status_bad_param;
790
791 printf("# SSRC: 0x%08x\r\n"
792 "# rtp cipher: %s\r\n"
793 "# rtp auth: %s\r\n"
794 "# rtp services: %s\r\n"
795 "# rtcp cipher: %s\r\n"
796 "# rtcp auth: %s\r\n"
797 "# rtcp services: %s\r\n",
798 stream->ssrc,
799 stream->rtp_cipher->type->description,
800 stream->rtp_auth->type->description,
801 serv_descr[stream->rtp_services],
802 stream->rtcp_cipher->type->description,
803 stream->rtcp_auth->type->description,
804 serv_descr[stream->rtcp_services]);
805
806 /* advance to next stream in the list */
807 stream = stream->next;
808 }
809 return err_status_ok;
810}
811
812err_status_t
813srtp_print_policy(const srtp_policy_t *policy) {
814 err_status_t status;
815 srtp_t session;
816
817 status = srtp_create(&session, policy);
818 if (status)
819 return status;
820 status = srtp_session_print_policy(session);
821 if (status)
822 return status;
823 status = srtp_dealloc(session);
824 if (status)
825 return status;
826 return err_status_ok;
827}
828
829/*
830 * srtp_print_packet(...) is for debugging only
831 * it prints an RTP packet to the stdout
832 *
833 * note that this function is *not* threadsafe
834 */
835
836#include <stdio.h>
837
838#define MTU 2048
839
840char packet_string[MTU];
841
842char *
843srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
844 int octets_in_rtp_header = 12;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000845 uint8_t *data = ((uint8_t *)hdr)+octets_in_rtp_header;
Cullen Jennings235513a2005-09-21 22:51:36 +0000846 int hex_len = pkt_octet_len-octets_in_rtp_header;
847
848 /* sanity checking */
849 if ((hdr == NULL) || (pkt_octet_len > MTU))
850 return NULL;
851
852 /* write packet into string */
853 sprintf(packet_string,
854 "(s)rtp packet: {\n"
855 " version:\t%d\n"
856 " p:\t\t%d\n"
857 " x:\t\t%d\n"
858 " cc:\t\t%d\n"
859 " m:\t\t%d\n"
860 " pt:\t\t%x\n"
861 " seq:\t\t%x\n"
862 " ts:\t\t%x\n"
863 " ssrc:\t%x\n"
864 " data:\t%s\n"
865 "} (%d octets in total)\n",
866 hdr->version,
867 hdr->p,
868 hdr->x,
869 hdr->cc,
870 hdr->m,
871 hdr->pt,
872 hdr->seq,
873 hdr->ts,
874 hdr->ssrc,
875 octet_string_hex_string(data, hex_len),
876 pkt_octet_len);
877
878 return packet_string;
879}
880
881/*
882 * mips_estimate() is a simple function to estimate the number of
883 * instructions per second that the host can perform. note that this
884 * function can be grossly wrong; you may want to have a manual sanity
885 * check of its output!
886 *
887 * the 'ignore' pointer is there to convince the compiler to not just
888 * optimize away the function
889 */
890
891double
892mips_estimate(int num_trials, int *ignore) {
893 clock_t t;
894 int i, sum;
895
896 sum = 0;
897 t = clock();
898 for (i=0; i<num_trials; i++)
899 sum += i;
900 t = clock() - t;
901
902/* printf("%d\n", sum); */
903 *ignore = sum;
904
905 return (double) num_trials * CLOCKS_PER_SEC / t;
906}
907
908
909/*
910 * srtp_validate() verifies the correctness of libsrtp by comparing
911 * some computed packets against some pre-computed reference values.
912 * These packets were made with the default SRTP policy.
913 */
914
915
916err_status_t
917srtp_validate() {
918 unsigned char test_key[30] = {
919 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
920 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
921 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
922 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
923 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000924 uint8_t srtp_plaintext_ref[28] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000925 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
926 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
927 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
928 0xab, 0xab, 0xab, 0xab
929 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000930 uint8_t srtp_plaintext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000931 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
932 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
933 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
934 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
935 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
936 };
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000937 uint8_t srtp_ciphertext[38] = {
Cullen Jennings235513a2005-09-21 22:51:36 +0000938 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
939 0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
940 0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15,
941 0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
942 0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
943 };
944 srtp_t srtp_snd, srtp_recv;
945 err_status_t status;
946 int len;
947 srtp_policy_t policy;
948
949 /*
950 * create a session with a single stream using the default srtp
951 * policy and with the SSRC value 0xcafebabe
952 */
953 crypto_policy_set_rtp_default(&policy.rtp);
954 crypto_policy_set_rtcp_default(&policy.rtcp);
955 policy.ssrc.type = ssrc_specific;
956 policy.ssrc.value = 0xcafebabe;
957 policy.key = test_key;
958 policy.next = NULL;
959
960 status = srtp_create(&srtp_snd, &policy);
961 if (status)
962 return status;
963
964 /*
965 * protect plaintext, then compare with ciphertext
966 */
967 len = 28;
968 status = srtp_protect(srtp_snd, srtp_plaintext, &len);
969 if (status || (len != 38))
970 return err_status_fail;
971
972 debug_print(mod_driver, "ciphertext:\n %s",
973 octet_string_hex_string(srtp_plaintext, len));
974 debug_print(mod_driver, "ciphertext reference:\n %s",
975 octet_string_hex_string(srtp_ciphertext, len));
976
977 if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
978 return err_status_fail;
979
980 /*
981 * create a receiver session context comparable to the one created
982 * above - we need to do this so that the replay checking doesn't
983 * complain
984 */
985 status = srtp_create(&srtp_recv, &policy);
986 if (status)
987 return status;
988
989 /*
990 * unprotect ciphertext, then compare with plaintext
991 */
992 status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
993 if (status || (len != 28))
994 return status;
995
996 if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
997 return err_status_fail;
998
999 return err_status_ok;
1000}
1001
1002
1003err_status_t
1004srtp_create_big_policy(srtp_policy_t **list) {
1005 extern const srtp_policy_t *policy_array[];
1006 srtp_policy_t *p, *tmp;
1007 int i = 0;
1008 uint32_t ssrc = 0;
1009
1010 /* sanity checking */
1011 if ((list == NULL) || (policy_array[0] == NULL))
1012 return err_status_bad_param;
1013
1014 /*
1015 * loop over policy list, mallocing a new list and copying values
1016 * into it (and incrementing the SSRC value as we go along)
1017 */
1018 tmp = NULL;
1019 while (policy_array[i] != NULL) {
1020 p = malloc(sizeof(srtp_policy_t));
1021 if (p == NULL)
1022 return err_status_bad_param;
1023 memcpy(p, policy_array[i], sizeof(srtp_policy_t));
1024 p->ssrc.type = ssrc_specific;
1025 p->ssrc.value = ssrc++;
1026 p->next = tmp;
1027 tmp = p;
1028 i++;
1029 }
1030 *list = p;
1031
1032 return err_status_ok;
1033}
1034
1035err_status_t
1036srtp_test_remove_stream() {
1037 err_status_t status;
1038 srtp_policy_t *policy_list;
1039 srtp_t session;
1040 srtp_stream_t stream;
1041 /*
1042 * srtp_get_stream() is a libSRTP internal function that we declare
1043 * here so that we can use it to verify the correct operation of the
1044 * library
1045 */
1046 extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
1047
1048
1049 status = srtp_create_big_policy(&policy_list);
1050 if (status)
1051 return status;
1052
1053 status = srtp_create(&session, policy_list);
1054 if (status)
1055 return status;
1056
1057 /*
1058 * check for false positives by trying to remove a stream that's not
1059 * in the session
1060 */
1061 status = srtp_remove_stream(session, htonl(0xaaaaaaaa));
1062 if (status != err_status_no_ctx)
1063 return err_status_fail;
1064
1065 /*
1066 * check for false negatives by removing stream 0x1, then
1067 * searching for streams 0x0 and 0x2
1068 */
1069 status = srtp_remove_stream(session, htonl(0x1));
1070 if (status != err_status_ok)
1071 return err_status_fail;
1072 stream = srtp_get_stream(session, htonl(0x0));
1073 if (stream == NULL)
1074 return err_status_fail;
1075 stream = srtp_get_stream(session, htonl(0x2));
1076 if (stream == NULL)
1077 return err_status_fail;
1078
1079 return err_status_ok;
1080}
1081
1082/*
1083 * srtp policy definitions - these definitions are used above
1084 */
1085
1086unsigned char test_key[30] = {
1087 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
1088 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
1089 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
1090 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
1091};
1092
1093
1094const srtp_policy_t default_policy = {
1095 { ssrc_any_outbound, 0 }, /* SSRC */
1096 { /* SRTP policy */
1097 AES_128_ICM, /* cipher type */
1098 30, /* cipher key length in octets */
1099 HMAC_SHA1, /* authentication func type */
1100 16, /* auth key length in octets */
1101 10, /* auth tag length in octets */
1102 sec_serv_conf_and_auth /* security services flag */
1103 },
1104 { /* SRTCP policy */
1105 AES_128_ICM, /* cipher type */
1106 30, /* cipher key length in octets */
1107 HMAC_SHA1, /* authentication func type */
1108 16, /* auth key length in octets */
1109 10, /* auth tag length in octets */
1110 sec_serv_conf_and_auth /* security services flag */
1111 },
1112 test_key,
1113 NULL
1114};
1115
1116const srtp_policy_t aes_tmmh_policy = {
1117 { ssrc_any_outbound, 0 }, /* SSRC */
1118 {
1119 AES_128_ICM, /* cipher type */
1120 30, /* cipher key length in octets */
1121 UST_TMMHv2, /* authentication func type */
1122 94, /* auth key length in octets */
1123 4, /* auth tag length in octets */
1124 sec_serv_conf_and_auth /* security services flag */
1125 },
1126 {
1127 AES_128_ICM, /* cipher type */
1128 30, /* cipher key length in octets */
1129 UST_TMMHv2, /* authentication func type */
1130 94, /* auth key length in octets */
1131 4, /* auth tag length in octets */
1132 sec_serv_conf_and_auth /* security services flag */
1133 },
1134 test_key,
1135 NULL
1136};
1137
1138const srtp_policy_t tmmh_only_policy = {
1139 { ssrc_any_outbound, 0 }, /* SSRC */
1140 {
1141 AES_128_ICM, /* cipher type */
1142 30, /* cipher key length in octets */
1143 UST_TMMHv2, /* authentication func type */
1144 94, /* auth key length in octets */
1145 4, /* auth tag length in octets */
1146 sec_serv_auth /* security services flag */
1147 },
1148 {
1149 AES_128_ICM, /* cipher type */
1150 30, /* cipher key length in octets */
1151 UST_TMMHv2, /* authentication func type */
1152 94, /* auth key length in octets */
1153 4, /* auth tag length in octets */
1154 sec_serv_auth /* security services flag */
1155 },
1156 test_key,
1157 NULL
1158};
1159
1160const srtp_policy_t aes_only_policy = {
1161 { ssrc_any_outbound, 0 }, /* SSRC */
1162 {
1163 AES_128_ICM, /* cipher type */
1164 30, /* cipher key length in octets */
1165 NULL_AUTH, /* authentication func type */
1166 0, /* auth key length in octets */
1167 0, /* auth tag length in octets */
1168 sec_serv_conf /* security services flag */
1169 },
1170 {
1171 AES_128_ICM, /* cipher type */
1172 30, /* cipher key length in octets */
1173 NULL_AUTH, /* authentication func type */
1174 0, /* auth key length in octets */
1175 0, /* auth tag length in octets */
1176 sec_serv_conf /* security services flag */
1177 },
1178 test_key,
1179 NULL
1180};
1181
1182const srtp_policy_t hmac_only_policy = {
1183 { ssrc_any_outbound, 0 }, /* SSRC */
1184 {
1185 NULL_CIPHER, /* cipher type */
1186 0, /* cipher key length in octets */
1187 HMAC_SHA1, /* authentication func type */
1188 20, /* auth key length in octets */
1189 4, /* auth tag length in octets */
1190 sec_serv_auth /* security services flag */
1191 },
1192 {
1193 NULL_CIPHER, /* cipher type */
1194 0, /* cipher key length in octets */
1195 HMAC_SHA1, /* authentication func type */
1196 20, /* auth key length in octets */
1197 4, /* auth tag length in octets */
1198 sec_serv_auth /* security services flag */
1199 },
1200 test_key,
1201 NULL
1202};
1203
1204const srtp_policy_t null_policy = {
1205 { ssrc_any_outbound, 0 }, /* SSRC */
1206 {
1207 NULL_CIPHER, /* cipher type */
1208 0, /* cipher key length in octets */
1209 NULL_AUTH, /* authentication func type */
1210 0, /* auth key length in octets */
1211 0, /* auth tag length in octets */
1212 sec_serv_none /* security services flag */
1213 },
1214 {
1215 NULL_CIPHER, /* cipher type */
1216 0, /* cipher key length in octets */
1217 NULL_AUTH, /* authentication func type */
1218 0, /* auth key length in octets */
1219 0, /* auth tag length in octets */
1220 sec_serv_none /* security services flag */
1221 },
1222 test_key,
1223 NULL
1224};
1225
1226
1227/*
1228 * an array of pointers to the policies listed above
1229 *
1230 * This array is used to test various aspects of libSRTP for
1231 * different cryptographic policies. The order of the elements
1232 * matters - the timing test generates output that can be used
1233 * in a plot (see the gnuplot script file 'timing'). If you
1234 * add to this list, you should do it at the end.
1235 */
1236
1237#define USE_TMMH 0
1238
1239const srtp_policy_t *
1240policy_array[] = {
1241 &hmac_only_policy,
1242#if USE_TMMH
1243 &tmmh_only_policy,
1244#endif
1245 &aes_only_policy,
1246#if USE_TMMH
1247 &aes_tmmh_policy,
1248#endif
1249 &default_policy,
1250 &null_policy,
1251 NULL
1252};
1253
1254const srtp_policy_t wildcard_policy = {
1255 { ssrc_any_outbound, 0 }, /* SSRC */
1256 { /* SRTP policy */
1257 AES_128_ICM, /* cipher type */
1258 30, /* cipher key length in octets */
1259 HMAC_SHA1, /* authentication func type */
1260 16, /* auth key length in octets */
1261 10, /* auth tag length in octets */
1262 sec_serv_conf_and_auth /* security services flag */
1263 },
1264 { /* SRTCP policy */
1265 AES_128_ICM, /* cipher type */
1266 30, /* cipher key length in octets */
1267 HMAC_SHA1, /* authentication func type */
1268 16, /* auth key length in octets */
1269 10, /* auth tag length in octets */
1270 sec_serv_conf_and_auth /* security services flag */
1271 },
1272 test_key,
1273 NULL
1274};