blob: 51d44a75e61342fb59ad0762327b079d0240b9ce [file] [log] [blame]
Cullen Jennings235513a2005-09-21 22:51:36 +00001/*
2 * srtp.c
3 *
4 * the secure real-time transport protocol
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 "srtp.h"
47#include "aes_icm.h" /* aes_icm is used in the KDF */
48#include "alloc.h" /* for crypto_alloc() */
Cullen Jennings235513a2005-09-21 22:51:36 +000049
Marcus Sundberg735eb4f2005-10-03 15:31:07 +000050#ifndef SRTP_KERNEL
51# include <limits.h>
52# ifdef HAVE_NETINET_IN_H
53# include <netinet/in.h>
54# elif defined(HAVE_WINSOCK2_H)
55# include <winsock2.h>
56# endif
57#endif /* ! SRTP_KERNEL */
Marcus Sundberge4e34f92005-10-02 20:19:35 +000058
59
Cullen Jennings235513a2005-09-21 22:51:36 +000060extern cipher_type_t aes_icm;
61extern auth_type_t tmmhv2;
62
63/* the debug module for srtp */
64
65debug_module_t mod_srtp = {
66 0, /* debugging is off by default */
67 "srtp" /* printable name for module */
68};
69
70#define octets_in_rtp_header 12
71#define uint32s_in_rtp_header 3
72#define octets_in_rtcp_header 8
73#define uint32s_in_rtcp_header 2
74
75/*
76 * the following declarations are libSRTP internal functions
77 */
78
79/*
80 * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
81 * to ssrc, or NULL if no stream exists for that ssrc
82 */
83
84srtp_stream_t
85srtp_get_stream(srtp_t srtp, uint32_t ssrc);
86
87err_status_t
88srtp_session_alloc(srtp_t *ctx_ptr, const crypto_policy_t *p);
89
90
91err_status_t
92srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
93 const srtp_policy_t *p) {
94 srtp_stream_ctx_t *str;
95 err_status_t stat;
96
97 /*
98 * This function allocates the stream context, rtp and rtcp ciphers
99 * and auth functions, and key limit structure. If there is a
100 * failure during allocation, we free all previously allocated
101 * memory and return a failure code. The code could probably
102 * be improved, but it works and should be clear.
103 */
104
105 /* allocate srtp stream and set str_ptr */
106 str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
107 if (str == NULL)
108 return err_status_alloc_fail;
109 *str_ptr = str;
110
111 /* allocate cipher */
112 stat = crypto_kernel_alloc_cipher(p->rtp.cipher_type,
113 &str->rtp_cipher,
114 p->rtp.cipher_key_len);
115 if (stat) {
116 crypto_free(str);
117 return stat;
118 }
119
120 /* allocate auth function */
121 stat = crypto_kernel_alloc_auth(p->rtp.auth_type,
122 &str->rtp_auth,
123 p->rtp.auth_key_len,
124 p->rtp.auth_tag_len);
125 if (stat) {
126 cipher_dealloc(str->rtp_cipher);
127 crypto_free(str);
128 return stat;
129 }
130
131 /* allocate key limit structure */
132 str->limit = crypto_alloc(sizeof(key_limit_ctx_t));
133 if (str->limit == NULL) {
134 auth_dealloc(str->rtp_auth);
135 cipher_dealloc(str->rtp_cipher);
136 crypto_free(str);
137 return err_status_alloc_fail;
138 }
139
140 /*
141 * ...and now the RTCP-specific initialization - first, allocate
142 * the cipher
143 */
144 stat = crypto_kernel_alloc_cipher(p->rtcp.cipher_type,
145 &str->rtcp_cipher,
146 p->rtcp.cipher_key_len);
147 if (stat) {
148 auth_dealloc(str->rtp_auth);
149 cipher_dealloc(str->rtp_cipher);
150 crypto_free(str->limit);
151 crypto_free(str);
152 return stat;
153 }
154
155 /* allocate auth function */
156 stat = crypto_kernel_alloc_auth(p->rtcp.auth_type,
157 &str->rtcp_auth,
158 p->rtcp.auth_key_len,
159 p->rtcp.auth_tag_len);
160 if (stat) {
161 cipher_dealloc(str->rtcp_cipher);
162 auth_dealloc(str->rtp_auth);
163 cipher_dealloc(str->rtp_cipher);
164 crypto_free(str->limit);
165 crypto_free(str);
166 return stat;
167 }
168
169 return err_status_ok;
170}
171
172err_status_t
173srtp_stream_dealloc(srtp_t session, srtp_stream_ctx_t *stream) {
174 err_status_t status;
175
176 /*
177 * we use a conservative deallocation strategy - if any deallocation
178 * fails, then we report that fact without trying to deallocate
179 * anything else
180 */
181
182 /* deallocate cipher, if it is not the same as that in template */
David McGrewfec49dd2005-09-23 19:34:11 +0000183 if (session->stream_template
Cullen Jennings235513a2005-09-21 22:51:36 +0000184 && stream->rtp_cipher == session->stream_template->rtp_cipher) {
185 /* do nothing */
186 } else {
187 status = cipher_dealloc(stream->rtp_cipher);
188 if (status)
David McGrewfec49dd2005-09-23 19:34:11 +0000189 return status;
Cullen Jennings235513a2005-09-21 22:51:36 +0000190 }
191
192 /* deallocate auth function, if it is not the same as that in template */
193 if (session->stream_template
194 && stream->rtp_auth == session->stream_template->rtp_auth) {
195 /* do nothing */
196 } else {
197 status = auth_dealloc(stream->rtp_auth);
198 if (status)
199 return status;
200 }
201
David McGrewfec49dd2005-09-23 19:34:11 +0000202 /* deallocate key usage limit, if it is not the same as that in template */
203 if (session->stream_template
204 && stream->limit == session->stream_template->limit) {
205 /* do nothing */
206 } else {
Cullen Jennings235513a2005-09-21 22:51:36 +0000207 crypto_free(stream->limit);
David McGrewfec49dd2005-09-23 19:34:11 +0000208 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000209
210 /*
211 * deallocate rtcp cipher, if it is not the same as that in
212 * template
213 */
214 if (session->stream_template
215 && stream->rtcp_cipher == session->stream_template->rtcp_cipher) {
216 /* do nothing */
217 } else {
218 status = cipher_dealloc(stream->rtcp_cipher);
219 if (status)
220 return status;
221 }
222
223 /*
224 * deallocate rtcp auth function, if it is not the same as that in
225 * template
226 */
227 if (session->stream_template
228 && stream->rtcp_auth == session->stream_template->rtcp_auth) {
229 /* do nothing */
230 } else {
231 status = auth_dealloc(stream->rtcp_auth);
232 if (status)
233 return status;
234 }
235
236 /* deallocate srtp stream context */
237 crypto_free(stream);
238
239 return err_status_ok;
240}
241
242
243/*
244 * srtp_stream_clone(stream_template, new) allocates a new stream and
245 * initializes it using the cipher and auth of the stream_template
246 *
247 * the only unique data in a cloned stream is the replay database and
248 * the SSRC
249 */
250
251err_status_t
252srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
253 uint32_t ssrc,
254 srtp_stream_ctx_t **str_ptr) {
255 err_status_t status;
256 srtp_stream_ctx_t *str;
257
258 debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ssrc);
259
260 /* allocate srtp stream and set str_ptr */
261 str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
262 if (str == NULL)
263 return err_status_alloc_fail;
264 *str_ptr = str;
265
266 /* set cipher and auth pointers to those of the template */
267 str->rtp_cipher = stream_template->rtp_cipher;
268 str->rtp_auth = stream_template->rtp_auth;
269 str->rtcp_cipher = stream_template->rtcp_cipher;
270 str->rtcp_auth = stream_template->rtcp_auth;
271
272 /* set key limit to point to that of the template */
273 status = key_limit_clone(stream_template->limit, &str->limit);
274 if (status)
275 return status;
276
277 /* initialize replay databases */
278 rdbx_init(&str->rtp_rdbx);
279 rdb_init(&str->rtcp_rdb);
280
281 /* set ssrc to that provided */
282 str->ssrc = ssrc;
283
284 /* set direction and security services */
285 str->direction = stream_template->direction;
286 str->rtp_services = stream_template->rtp_services;
287 str->rtcp_services = stream_template->rtcp_services;
288
289 /* defensive coding */
290 str->next = NULL;
291
292 return err_status_ok;
293}
294
295
296/*
297 * key derivation functions, internal to libSRTP
298 *
299 * srtp_kdf_t is a key derivation context
300 *
301 * srtp_kdf_init(&kdf, k) initializes kdf with the key k
302 *
303 * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key
304 * corresponding to label l and puts it into kl; the length
305 * of the key in octets is provided as keylen. this function
306 * should be called once for each subkey that is derived.
307 *
308 * srtp_kdf_clear(&kdf) zeroizes the kdf state
309 */
310
311typedef enum {
312 label_rtp_encryption = 0x00,
313 label_rtp_msg_auth = 0x01,
314 label_rtp_salt = 0x02,
315 label_rtcp_encryption = 0x03,
316 label_rtcp_msg_auth = 0x04,
317 label_rtcp_salt = 0x05
318} srtp_prf_label;
319
320
321/*
322 * srtp_kdf_t represents a key derivation function. The SRTP
323 * default KDF is the only one implemented at present.
324 */
325
326typedef struct {
327 aes_icm_ctx_t c; /* cipher used for key derivation */
328} srtp_kdf_t;
329
330err_status_t
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000331srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t key[30]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000332
333 aes_icm_context_init(&kdf->c, key);
334
335 return err_status_ok;
336}
337
338err_status_t
339srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000340 uint8_t *key, int length) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000341
342 v128_t nonce;
343
344 /* set eigth octet of nonce to <label>, set the rest of it to zero */
345 v128_set_to_zero(&nonce);
Marcus Sundberg7627bc52005-10-08 16:38:06 +0000346 nonce.v8[7] = label;
Cullen Jennings235513a2005-09-21 22:51:36 +0000347
348 aes_icm_set_iv(&kdf->c, &nonce);
349
350 /* generate keystream output */
351 aes_icm_output(&kdf->c, key, length);
352
353 return err_status_ok;
354}
355
356err_status_t
357srtp_kdf_clear(srtp_kdf_t *kdf) {
358
359 /* zeroize aes context */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000360 octet_string_set_to_zero((uint8_t *)kdf, sizeof(srtp_kdf_t));
Cullen Jennings235513a2005-09-21 22:51:36 +0000361
362 return err_status_ok;
363}
364
365/*
366 * end of key derivation functions
367 */
368
369#define MAX_SRTP_KEY_LEN 256
370
371
372
373err_status_t
374srtp_stream_init(srtp_stream_ctx_t *srtp,
375 const srtp_policy_t *p) {
376 err_status_t stat;
377 srtp_kdf_t kdf;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000378 uint8_t tmp_key[MAX_SRTP_KEY_LEN];
379 uint8_t *key = p->key;
Cullen Jennings235513a2005-09-21 22:51:36 +0000380
381 debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)",
382 p->ssrc.value);
383
384 /* initialize replay database */
385 rdbx_init(&srtp->rtp_rdbx);
386
387 /* initialize key limit to maximum value */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000388#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000389{
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000390 uint64_t temp;
391 temp = make64(UINT_MAX,UINT_MAX);
392 key_limit_set(srtp->limit, temp);
Cullen Jennings235513a2005-09-21 22:51:36 +0000393}
394#else
395 key_limit_set(srtp->limit, 0xffffffffffffLL);
396#endif
397
398 /* set the SSRC value */
399 srtp->ssrc = htonl(p->ssrc.value);
400
401 /* set the security service flags */
402 srtp->rtp_services = p->rtp.sec_serv;
403 srtp->rtcp_services = p->rtcp.sec_serv;
404
405 /*
406 * set direction to unknown - this flag gets checked in srtp_protect(),
407 * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and
408 * gets set appropriately if it is set to unknown.
409 */
410 srtp->direction = dir_unknown;
411
412 /* initialize KDF state */
413 srtp_kdf_init(&kdf, key);
414
415 /* generate encryption key */
416 srtp_kdf_generate(&kdf, label_rtp_encryption,
417 tmp_key, cipher_get_key_length(srtp->rtp_cipher));
418 /*
419 * if the cipher in the srtp context is aes_icm, then we need
420 * to generate the salt value
421 */
422 if (srtp->rtp_cipher->type == &aes_icm) {
423 /* FIX!!! this is really the cipher key length; rest is salt */
424 int base_key_len = 16;
425 int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;
426
427 debug_print(mod_srtp, "found aes_icm, generating salt", NULL);
428
429 /* generate encryption salt, put after encryption key */
430 srtp_kdf_generate(&kdf, label_rtp_salt,
431 tmp_key + base_key_len, salt_len);
432 }
433 debug_print(mod_srtp, "cipher key: %s",
434 octet_string_hex_string(tmp_key,
435 cipher_get_key_length(srtp->rtp_cipher)));
436
437 /* initialize cipher */
438 stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
439 if (stat) {
440 /* zeroize temp buffer */
441 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
442 return err_status_init_fail;
443 }
444
445 /* generate authentication key */
446 srtp_kdf_generate(&kdf, label_rtp_msg_auth,
447 tmp_key, auth_get_key_length(srtp->rtp_auth));
448 debug_print(mod_srtp, "auth key: %s",
449 octet_string_hex_string(tmp_key,
450 auth_get_key_length(srtp->rtp_auth)));
451
452 /* initialize auth function */
453 stat = auth_init(srtp->rtp_auth, tmp_key);
454 if (stat) {
455 /* zeroize temp buffer */
456 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
457 return err_status_init_fail;
458 }
459
460 /*
461 * ...now initialize RTCP-specific structures
462 */
463
464 /* initialize replay database */
465 rdb_init(&srtp->rtcp_rdb);
466
467 /* DAM - no RTCP key limit at present */
468
469 /* generate encryption key */
470 srtp_kdf_generate(&kdf, label_rtcp_encryption,
471 tmp_key, cipher_get_key_length(srtp->rtcp_cipher));
472 /*
473 * if the cipher in the srtp context is aes_icm, then we need
474 * to generate the salt value
475 */
476 if (srtp->rtcp_cipher->type == &aes_icm) {
477 /* FIX!!! this is really the cipher key length; rest is salt */
478 int base_key_len = 16;
479 int salt_len = cipher_get_key_length(srtp->rtcp_cipher) - base_key_len;
480
481 debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);
482
483 /* generate encryption salt, put after encryption key */
484 srtp_kdf_generate(&kdf, label_rtcp_salt,
485 tmp_key + base_key_len, salt_len);
486 }
487 debug_print(mod_srtp, "rtcp cipher key: %s",
488 octet_string_hex_string(tmp_key,
489 cipher_get_key_length(srtp->rtcp_cipher)));
490
491 /* initialize cipher */
492 stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);
493 if (stat) {
494 /* zeroize temp buffer */
495 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
496 return err_status_init_fail;
497 }
498
499 /* generate authentication key */
500 srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
501 tmp_key, auth_get_key_length(srtp->rtcp_auth));
502 debug_print(mod_srtp, "rtcp auth key: %s",
503 octet_string_hex_string(tmp_key,
504 auth_get_key_length(srtp->rtcp_auth)));
505
506 /* initialize auth function */
507 stat = auth_init(srtp->rtcp_auth, tmp_key);
508 if (stat) {
509 /* zeroize temp buffer */
510 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
511 return err_status_init_fail;
512 }
513
514 /* clear memory then return */
515 srtp_kdf_clear(&kdf);
516 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
517 return err_status_ok;
518 }
519
520
521 /*
522 * srtp_event_reporter is an event handler function that merely
523 * reports the events that are reported by the callbacks
524 */
525
526 void
527 srtp_event_reporter(srtp_event_data_t *data) {
528
529 err_report(err_level_warning, "srtp: in stream 0x%x: ",
530 data->stream->ssrc);
531
532 switch(data->event) {
533 case event_ssrc_collision:
534 err_report(err_level_warning, "\tSSRC collision\n");
535 break;
536 case event_key_soft_limit:
537 err_report(err_level_warning, "\tkey usage soft limit reached\n");
538 break;
539 case event_key_hard_limit:
540 err_report(err_level_warning, "\tkey usage hard limit reached\n");
541 break;
542 case event_packet_index_limit:
543 err_report(err_level_warning, "\tpacket index limit reached\n");
544 break;
545 default:
546 err_report(err_level_warning, "\tunknown event reported to handler\n");
547 }
548 }
549
550 /*
551 * srtp_event_handler is a global variable holding a pointer to the
552 * event handler function; this function is called for any unexpected
553 * event that needs to be handled out of the SRTP data path. see
554 * srtp_event_t in srtp.h for more info
555 *
556 * it is okay to set srtp_event_handler to NULL, but we set
557 * it to the srtp_event_reporter.
558 */
559
560 static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter;
561
562 err_status_t
563 srtp_install_event_handler(srtp_event_handler_func_t func) {
564
565 /*
566 * note that we accept NULL arguments intentionally - calling this
567 * function with a NULL arguments removes an event handler that's
568 * been previously installed
569 */
570
571 /* set global event handling function */
572 srtp_event_handler = func;
573 return err_status_ok;
574 }
575
576 err_status_t
577 srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) {
578 srtp_hdr_t *hdr = rtp_hdr;
579 uint32_t *enc_start; /* pointer to start of encrypted portion */
580 uint32_t *auth_start; /* pointer to start of auth. portion */
581 unsigned enc_octet_len = 0; /* number of octets in encrypted portion */
582 xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
583 int delta; /* delta of local pkt idx and that in hdr */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000584 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +0000585 err_status_t status;
586 int tag_len;
587 srtp_stream_ctx_t *stream;
588 int prefix_len;
589
590 debug_print(mod_srtp, "function srtp_protect", NULL);
591
592 /* we assume the hdr is 32-bit aligned to start */
593
594 /* check the packet length - it must at least contain a full header */
595 if (*pkt_octet_len < octets_in_rtp_header)
596 return err_status_bad_param;
597
598 /*
599 * look up ssrc in srtp_stream list, and process the packet with
600 * the appropriate stream. if we haven't seen this stream before,
601 * there's a template key for this srtp_session, and the cipher
602 * supports key-sharing, then we assume that a new stream using
603 * that key has just started up
604 */
605 stream = srtp_get_stream(ctx, hdr->ssrc);
606 if (stream == NULL) {
607 if (ctx->stream_template != NULL) {
608 srtp_stream_ctx_t *new_stream;
609
610 /* allocate and initialize a new stream */
611 status = srtp_stream_clone(ctx->stream_template,
David McGrewfec49dd2005-09-23 19:34:11 +0000612 hdr->ssrc, &new_stream);
Cullen Jennings235513a2005-09-21 22:51:36 +0000613 if (status)
614 return status;
615
616 /* add new stream to the head of the stream_list */
617 new_stream->next = ctx->stream_list;
618 ctx->stream_list = new_stream;
619
620 /* set direction to outbound */
621 new_stream->direction = dir_srtp_sender;
622
623 /* set stream (the pointer used in this function) */
624 stream = new_stream;
625 } else {
626 /* no template stream, so we return an error */
627 return err_status_no_ctx;
628 }
629 }
630
631 /*
632 * verify that stream is for sending traffic - this check will
633 * detect SSRC collisions, since a stream that appears in both
634 * srtp_protect() and srtp_unprotect() will fail this test in one of
635 * those functions.
636 */
637 if (stream->direction != dir_srtp_sender) {
638 if (stream->direction == dir_unknown) {
639 stream->direction = dir_srtp_sender;
640 } else {
641 srtp_handle_event(ctx, stream, event_ssrc_collision);
642 }
643 }
644
645 /*
646 * update the key usage limit, and check it to make sure that we
647 * didn't just hit either the soft limit or the hard limit, and call
648 * the event handler if we hit either.
649 */
650 switch(key_limit_update(stream->limit)) {
651 case key_event_normal:
652 break;
653 case key_event_soft_limit:
654 srtp_handle_event(ctx, stream, event_key_soft_limit);
655 break;
656 case key_event_hard_limit:
657 srtp_handle_event(ctx, stream, event_key_hard_limit);
David McGrewfec49dd2005-09-23 19:34:11 +0000658 return err_status_key_expired;
Cullen Jennings235513a2005-09-21 22:51:36 +0000659 default:
660 break;
661 }
662
663 /* get tag length from stream */
664 tag_len = auth_get_tag_length(stream->rtp_auth);
665
666 /*
667 * find starting point for encryption and length of data to be
668 * encrypted - the encrypted portion starts after the rtp header
669 * extension, if present; otherwise, it starts after the last csrc,
670 * if any are present
671 *
672 * if we're not providing confidentiality, set enc_start to NULL
673 */
674 if (stream->rtp_services & sec_serv_conf) {
675 enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
676 if (hdr->x == 1)
677 enc_start += ((srtp_hdr_xtnd_t *)enc_start)->length;
678 enc_octet_len = *pkt_octet_len - ((enc_start - (uint32_t *)hdr) << 2);
679 } else {
680 enc_start = NULL;
681 }
682
683 /*
684 * if we're providing authentication, set the auth_start and auth_tag
685 * pointers to the proper locations; otherwise, set auth_start to NULL
686 * to indicate that no authentication is needed
687 */
688 if (stream->rtp_services & sec_serv_auth) {
689 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000690 auth_tag = (uint8_t *)hdr + *pkt_octet_len;
Cullen Jennings235513a2005-09-21 22:51:36 +0000691 } else {
692 auth_start = NULL;
693 auth_tag = NULL;
694 }
695
696 /*
697 * estimate the packet index using the start of the replay window
698 * and the sequence number from the header
699 */
700 delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
701 status = rdbx_check(&stream->rtp_rdbx, delta);
702 if (status)
703 return status; /* we've been asked to reuse an index */
704 rdbx_add_index(&stream->rtp_rdbx, delta);
705
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000706#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000707 debug_print2(mod_srtp, "estimated packet index: %08x%08x",
708 high32(est),low32(est));
709#else
710 debug_print(mod_srtp, "estimated packet index: %016llx", est);
711#endif
712
713 /*
714 * if we're using rindael counter mode, set nonce and seq
715 */
716 if (stream->rtp_cipher->type == &aes_icm) {
717 v128_t iv;
718
719 iv.v32[0] = 0;
720 iv.v32[1] = hdr->ssrc;
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000721#ifdef NO_64BIT_MATH
722 iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
David McGrewfec49dd2005-09-23 19:34:11 +0000723 low32(est) << 16));
Cullen Jennings235513a2005-09-21 22:51:36 +0000724#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000725 iv.v64[1] = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000726#endif
727 status = cipher_set_iv(stream->rtp_cipher, &iv);
728
729 } else {
730 v128_t iv;
731
732 /* otherwise, set the index to est */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000733#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000734 iv.v32[0] = 0;
735 iv.v32[1] = 0;
736#else
737 iv.v64[0] = 0;
738#endif
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000739 iv.v64[1] = be64_to_cpu(est);
Cullen Jennings235513a2005-09-21 22:51:36 +0000740 status = cipher_set_iv(stream->rtp_cipher, &iv);
741 }
742 if (status)
743 return err_status_cipher_fail;
744
745 /* shift est, put into network byte order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000746#ifdef NO_64BIT_MATH
747 est = be64_to_cpu(make64((high32(est) << 16) |
Cullen Jennings235513a2005-09-21 22:51:36 +0000748 (low32(est) >> 16),
Randell Jesup811e1442005-09-28 22:43:41 +0000749 low32(est) << 16));
Cullen Jennings235513a2005-09-21 22:51:36 +0000750#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000751 est = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000752#endif
753
754 /*
755 * if we're authenticating using a universal hash, put the keystream
756 * prefix into the authentication tag
757 */
758 if (auth_start) {
759
760 prefix_len = auth_get_prefix_length(stream->rtp_auth);
761 if (prefix_len) {
762 status = cipher_output(stream->rtp_cipher, auth_tag, prefix_len);
763 if (status)
764 return err_status_cipher_fail;
765 debug_print(mod_srtp, "keystream prefix: %s",
766 octet_string_hex_string(auth_tag, prefix_len));
767 }
768 }
769
770 /* if we're encrypting, exor keystream into the message */
771 if (enc_start) {
772 status = cipher_encrypt(stream->rtp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000773 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000774 if (status)
775 return err_status_cipher_fail;
776 }
777
778 /*
779 * if we're authenticating, run authentication function and put result
780 * into the auth_tag
781 */
782 if (auth_start) {
783
784 /* initialize auth func context */
785 status = auth_start(stream->rtp_auth);
786 if (status) return status;
787
788 /* run auth func over packet */
789 status = auth_update(stream->rtp_auth,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000790 (uint8_t *)auth_start, *pkt_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000791 if (status) return status;
792
793 /* run auth func over ROC, put result into auth_tag */
David McGrew89fb7ea2005-09-26 19:33:44 +0000794 debug_print(mod_srtp, "estimated packet index: %016llx", est);
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000795 status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, auth_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +0000796 debug_print(mod_srtp, "srtp auth tag: %s",
797 octet_string_hex_string(auth_tag, tag_len));
798 if (status)
799 return err_status_auth_fail;
800
801 }
802
803 if (auth_tag) {
804
805 /* increase the packet length by the length of the auth tag */
806 *pkt_octet_len += tag_len;
807 }
808
809 return err_status_ok;
810}
811
812
813err_status_t
814srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
815 srtp_hdr_t *hdr = srtp_hdr;
816 uint32_t *enc_start; /* pointer to start of encrypted portion */
817 uint32_t *auth_start; /* pointer to start of auth. portion */
818 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000819 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +0000820 xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
821 int delta; /* delta of local pkt idx and that in hdr */
822 v128_t iv;
823 err_status_t status;
824 srtp_stream_ctx_t *stream;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000825 uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
Cullen Jennings235513a2005-09-21 22:51:36 +0000826 int tag_len, prefix_len;
827
828 debug_print(mod_srtp, "function srtp_unprotect", NULL);
829
830 /* we assume the hdr is 32-bit aligned to start */
831
832 /* check the packet length - it must at least contain a full header */
833 if (*pkt_octet_len < octets_in_rtp_header)
834 return err_status_bad_param;
835
836 /*
837 * look up ssrc in srtp_stream list, and process the packet with
838 * the appropriate stream. if we haven't seen this stream before,
839 * there's only one key for this srtp_session, and the cipher
840 * supports key-sharing, then we assume that a new stream using
841 * that key has just started up
842 */
843 stream = srtp_get_stream(ctx, hdr->ssrc);
844 if (stream == NULL) {
845 if (ctx->stream_template != NULL) {
846 stream = ctx->stream_template;
847 debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)",
848 hdr->ssrc);
849
850 /*
851 * set estimated packet index to sequence number from header,
852 * and set delta equal to the same value
853 */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000854#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000855 est = (xtd_seq_num_t) make64(0,ntohs(hdr->seq));
856 delta = low32(est);
857#else
858 est = (xtd_seq_num_t) ntohs(hdr->seq);
859 delta = est;
860#endif
861 } else {
862
863 /*
864 * no stream corresponding to SSRC found, and we don't do
865 * key-sharing, so return an error
866 */
867 return err_status_no_ctx;
868 }
869 } else {
870
871 /* estimate packet index from seq. num. in header */
872 delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
873
874 /* check replay database */
875 status = rdbx_check(&stream->rtp_rdbx, delta);
876 if (status)
877 return status;
878 }
879
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000880#ifdef NO_64BIT_MATH
David McGrewfec49dd2005-09-23 19:34:11 +0000881 debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),low32(est));
882#else
883 debug_print(mod_srtp, "estimated u_packet index: %016llx", est);
884#endif
Cullen Jennings235513a2005-09-21 22:51:36 +0000885
886 /*
887 * update the key usage limit, and check it to make sure that we
888 * didn't just hit either the soft limit or the hard limit, and call
889 * the event handler if we hit either.
890 */
891 switch(key_limit_update(stream->limit)) {
892 case key_event_normal:
893 break;
894 case key_event_soft_limit:
895 srtp_handle_event(ctx, stream, event_key_soft_limit);
896 break;
897 case key_event_hard_limit:
898 srtp_handle_event(ctx, stream, event_key_hard_limit);
899 return err_status_key_expired;
900 default:
901 break;
902 }
903
904 /* get tag length from stream */
905 tag_len = auth_get_tag_length(stream->rtp_auth);
906
907 /*
908 * set the cipher's IV properly, depending on whatever cipher we
909 * happen to be using
910 */
911 if (stream->rtp_cipher->type == &aes_icm) {
912
913 /* aes counter mode */
914 iv.v32[0] = 0;
915 iv.v32[1] = hdr->ssrc; /* still in network order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000916#ifdef NO_64BIT_MATH
917 iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
Cullen Jennings235513a2005-09-21 22:51:36 +0000918 low32(est) << 16));
919#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000920 iv.v64[1] = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000921#endif
922 status = aes_icm_set_iv(stream->rtp_cipher->state, &iv);
923 } else {
924
925 /* no particular format - set the iv to the pakcet index */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000926#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000927 iv.v32[0] = 0;
928 iv.v32[1] = 0;
929#else
930 iv.v64[0] = 0;
931#endif
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000932 iv.v64[1] = be64_to_cpu(est);
Cullen Jennings235513a2005-09-21 22:51:36 +0000933 status = cipher_set_iv(stream->rtp_cipher, &iv);
934 }
935 if (status)
936 return err_status_cipher_fail;
937
938 /* shift est, put into network byte order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000939#ifdef NO_64BIT_MATH
940 est = be64_to_cpu(make64((high32(est) << 16) |
Cullen Jennings235513a2005-09-21 22:51:36 +0000941 (low32(est) >> 16),
942 low32(est) << 16));
943#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000944 est = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000945#endif
946
947 /*
948 * find starting point for decryption and length of data to be
949 * decrypted - the encrypted portion starts after the rtp header
950 * extension, if present; otherwise, it starts after the last csrc,
951 * if any are present
952 *
953 * if we're not providing confidentiality, set enc_start to NULL
954 */
955 if (stream->rtp_services & sec_serv_conf) {
956 enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
957 if (hdr->x == 1)
958 enc_start += ((srtp_hdr_xtnd_t *)enc_start)->length;
959 enc_octet_len = *pkt_octet_len - tag_len
960 - ((enc_start - (uint32_t *)hdr) << 2);
961 } else {
962 enc_start = NULL;
963 }
964
965 /*
966 * if we're providing authentication, set the auth_start and auth_tag
967 * pointers to the proper locations; otherwise, set auth_start to NULL
968 * to indicate that no authentication is needed
969 */
970 if (stream->rtp_services & sec_serv_auth) {
971 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000972 auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
Cullen Jennings235513a2005-09-21 22:51:36 +0000973 } else {
974 auth_start = NULL;
975 auth_tag = NULL;
976 }
977
978 /*
979 * if we expect message authentication, run the authentication
980 * function and compare the result with the value of the auth_tag
981 */
982 if (auth_start) {
983
984 /*
985 * if we're using a universal hash, then we need to compute the
986 * keystream prefix for encrypting the universal hash output
987 *
988 * if the keystream prefix length is zero, then we know that
989 * the authenticator isn't using a universal hash function
990 */
991 if (stream->rtp_auth->prefix_len != 0) {
992
993 prefix_len = auth_get_prefix_length(stream->rtp_auth);
994 status = cipher_output(stream->rtp_cipher, tmp_tag, prefix_len);
995 debug_print(mod_srtp, "keystream prefix: %s",
996 octet_string_hex_string(tmp_tag, prefix_len));
997 if (status)
998 return err_status_cipher_fail;
999 }
1000
1001 /* initialize auth func context */
1002 status = auth_start(stream->rtp_auth);
1003 if (status) return status;
David McGrewfec49dd2005-09-23 19:34:11 +00001004
Cullen Jennings235513a2005-09-21 22:51:36 +00001005 /* now compute auth function over packet */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001006 status = auth_update(stream->rtp_auth, (uint8_t *)auth_start,
Cullen Jennings235513a2005-09-21 22:51:36 +00001007 *pkt_octet_len - tag_len);
1008
1009 /* run auth func over ROC, then write tmp tag */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001010 status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +00001011
1012 debug_print(mod_srtp, "computed auth tag: %s",
1013 octet_string_hex_string(tmp_tag, tag_len));
1014 debug_print(mod_srtp, "packet auth tag: %s",
1015 octet_string_hex_string(auth_tag, tag_len));
1016 if (status)
1017 return err_status_auth_fail;
1018
1019 if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1020 return err_status_auth_fail;
1021 }
1022
1023 /* if we're encrypting, add keystream into ciphertext */
1024 if (enc_start) {
1025 status = cipher_encrypt(stream->rtp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001026 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +00001027 if (status)
1028 return err_status_cipher_fail;
1029 }
1030
1031 /*
1032 * verify that stream is for received traffic - this check will
1033 * detect SSRC collisions, since a stream that appears in both
1034 * srtp_protect() and srtp_unprotect() will fail this test in one of
1035 * those functions.
1036 *
1037 * we do this check *after* the authentication check, so that the
1038 * latter check will catch any attempts to fool us into thinking
1039 * that we've got a collision
1040 */
1041 if (stream->direction != dir_srtp_receiver) {
1042 if (stream->direction == dir_unknown) {
1043 stream->direction = dir_srtp_receiver;
1044 } else {
1045 srtp_handle_event(ctx, stream, event_ssrc_collision);
1046 }
1047 }
1048
1049 /*
1050 * if the stream is a 'provisional' one, in which the template context
1051 * is used, then we need to allocate a new stream at this point, since
1052 * the authentication passed
1053 */
1054 if (stream == ctx->stream_template) {
1055 srtp_stream_ctx_t *new_stream;
1056
1057 /*
1058 * allocate and initialize a new stream
1059 *
1060 * note that we indicate failure if we can't allocate the new
1061 * stream, and some implementations will want to not return
1062 * failure here
1063 */
1064 status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
1065 if (status)
1066 return status;
1067
1068 /* add new stream to the head of the stream_list */
1069 new_stream->next = ctx->stream_list;
1070 ctx->stream_list = new_stream;
1071
1072 /* set stream (the pointer used in this function) */
1073 stream = new_stream;
1074 }
1075
1076 /*
1077 * the message authentication function passed, so add the packet
1078 * index into the replay database
1079 */
1080 rdbx_add_index(&stream->rtp_rdbx, delta);
1081
1082 /* decrease the packet length by the length of the auth tag */
1083 *pkt_octet_len -= tag_len;
1084
1085 return err_status_ok;
1086}
1087
1088err_status_t
1089srtp_init() {
1090 err_status_t status;
1091
1092 /* initialize crypto kernel */
1093 status = crypto_kernel_init();
1094 if (status)
1095 return status;
1096
1097 /* load srtp debug module into the kernel */
1098 status = crypto_kernel_load_debug_module(&mod_srtp);
1099 if (status)
1100 return status;
1101
1102 return err_status_ok;
1103}
1104
1105/*
1106 * The following code is under consideration for removal. See
1107 * SRTP_MAX_TRAILER_LEN
1108 */
1109#if 0
1110
1111/*
1112 * srtp_get_trailer_length(&a) returns the number of octets that will
1113 * be added to an RTP packet by the SRTP processing. This value
1114 * is constant for a given srtp_stream_t (i.e. between initializations).
1115 */
1116
1117int
1118srtp_get_trailer_length(const srtp_stream_t s) {
1119 return auth_get_tag_length(s->rtp_auth);
1120}
1121
1122#endif
1123
1124/*
1125 * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
1126 * to ssrc, or NULL if no stream exists for that ssrc
1127 *
1128 * this is an internal function
1129 */
1130
1131srtp_stream_ctx_t *
1132srtp_get_stream(srtp_t srtp, uint32_t ssrc) {
1133 srtp_stream_ctx_t *stream;
1134
1135 /* walk down list until ssrc is found */
1136 stream = srtp->stream_list;
1137 while (stream != NULL) {
1138 if (stream->ssrc == ssrc)
1139 return stream;
1140 stream = stream->next;
1141 }
1142
1143 /* we haven't found our ssrc, so return a null */
1144 return NULL;
1145}
1146
1147err_status_t
1148srtp_dealloc(srtp_t session) {
1149 srtp_stream_ctx_t *stream;
1150 err_status_t status;
1151
1152 /*
1153 * we take a conservative deallocation strategy - if we encounter an
1154 * error deallocating a stream, then we stop trying to deallocate
1155 * memory and just return an error
1156 */
1157
1158 /* walk list of streams, deallocating as we go */
1159 stream = session->stream_list;
1160 while (stream != NULL) {
1161 srtp_stream_t next = stream->next;
1162 status = srtp_stream_dealloc(session, stream);
1163 if (status)
1164 return status;
1165 stream = next;
1166 }
1167
1168 /* deallocate stream template, if there is one */
1169 if (session->stream_template != NULL) {
David McGrewfec49dd2005-09-23 19:34:11 +00001170 status = auth_dealloc(session->stream_template->rtcp_auth);
1171 if (status)
1172 return status;
1173 status = cipher_dealloc(session->stream_template->rtcp_cipher);
1174 if (status)
1175 return status;
1176 crypto_free(session->stream_template->limit);
Cullen Jennings235513a2005-09-21 22:51:36 +00001177 status = cipher_dealloc(session->stream_template->rtp_cipher);
1178 if (status)
1179 return status;
1180 status = auth_dealloc(session->stream_template->rtp_auth);
1181 if (status)
1182 return status;
1183 crypto_free(session->stream_template);
1184 }
1185
1186 /* deallocate session context */
1187 crypto_free(session);
1188
1189 return err_status_ok;
1190}
1191
1192
1193err_status_t
1194srtp_add_stream(srtp_t session,
1195 const srtp_policy_t *policy) {
1196 err_status_t status;
1197 srtp_stream_t tmp;
1198
Marcus Sundberg67398e62005-10-05 12:39:51 +00001199 /* sanity check arguments */
1200 if ((session == NULL) || (policy == NULL) || (policy->key == NULL))
1201 return err_status_bad_param;
1202
Cullen Jennings235513a2005-09-21 22:51:36 +00001203 /* allocate stream */
1204 status = srtp_stream_alloc(&tmp, policy);
1205 if (status) {
1206 return status;
1207 }
1208
1209 /* initialize stream */
1210 status = srtp_stream_init(tmp, policy);
1211 if (status) {
1212 crypto_free(tmp);
1213 return status;
1214 }
1215
1216 /*
1217 * set the head of the stream list or the template to point to the
1218 * stream that we've just alloced and init'ed, depending on whether
1219 * or not it has a wildcard SSRC value or not
1220 *
1221 * if the template stream has already been set, then the policy is
1222 * inconsistent, so we return a bad_param error code
1223 */
1224 switch (policy->ssrc.type) {
1225 case (ssrc_any_outbound):
1226 if (session->stream_template) {
1227 return err_status_bad_param;
1228 }
1229 session->stream_template = tmp;
1230 session->stream_template->direction = dir_srtp_sender;
1231 break;
1232 case (ssrc_any_inbound):
1233 if (session->stream_template) {
1234 return err_status_bad_param;
1235 }
1236 session->stream_template = tmp;
1237 session->stream_template->direction = dir_srtp_receiver;
1238 break;
1239 case (ssrc_specific):
1240 tmp->next = session->stream_list;
1241 session->stream_list = tmp;
1242 break;
1243 case (ssrc_undefined):
1244 default:
1245 crypto_free(tmp);
1246 return err_status_bad_param;
1247 }
1248
1249 return err_status_ok;
1250}
1251
1252
1253err_status_t
1254srtp_create(srtp_t *session, /* handle for session */
1255 const srtp_policy_t *policy) { /* SRTP policy (list) */
1256 err_status_t stat;
1257 srtp_ctx_t *ctx;
1258
1259 /* sanity check arguments */
Marcus Sundberg67398e62005-10-05 12:39:51 +00001260 if (session == NULL)
Cullen Jennings235513a2005-09-21 22:51:36 +00001261 return err_status_bad_param;
1262
1263 /* allocate srtp context and set ctx_ptr */
1264 ctx = (srtp_ctx_t *) crypto_alloc(sizeof(srtp_ctx_t));
1265 if (ctx == NULL)
1266 return err_status_alloc_fail;
1267 *session = ctx;
1268
1269 /*
1270 * loop over elements in the policy list, allocating and
1271 * initializing a stream for each element
1272 */
1273 ctx->stream_template = NULL;
1274 ctx->stream_list = NULL;
1275 while (policy != NULL) {
1276
1277 stat = srtp_add_stream(ctx, policy);
1278 if (stat) {
Marcus Sundberg67398e62005-10-05 12:39:51 +00001279 /* clean up everything */
1280 srtp_dealloc(*session);
Cullen Jennings235513a2005-09-21 22:51:36 +00001281 return stat;
1282 }
1283
1284 /* set policy to next item in list */
1285 policy = policy->next;
1286 }
1287
1288 return err_status_ok;
1289}
1290
1291
1292err_status_t
1293srtp_remove_stream(srtp_t session, uint32_t ssrc) {
1294 srtp_stream_ctx_t *stream, *last_stream;
1295 err_status_t status;
1296
1297 /* sanity check arguments */
1298 if (session == NULL)
1299 return err_status_bad_param;
1300
1301 /* find stream in list; complain if not found */
1302 last_stream = stream = session->stream_list;
1303 while ((stream != NULL) && (ssrc != stream->ssrc)) {
1304 last_stream = stream;
1305 stream = stream->next;
1306 }
1307 if (stream == NULL)
1308 return err_status_no_ctx;
1309
1310 /* remove stream from the list */
1311 last_stream->next = stream->next;
1312
1313 /* deallocate the stream */
1314 status = srtp_stream_dealloc(session, stream);
1315 if (status)
1316 return status;
1317
1318 return err_status_ok;
1319}
1320
1321
1322/*
1323 * the default policy - provides a convenient way for callers to use
1324 * the default security policy
1325 *
1326 * this policy is that defined in the current SRTP internet draft.
1327 *
1328 */
1329
1330/*
1331 * NOTE: cipher_key_len is really key len (128 bits) plus salt len
1332 * (112 bits)
1333 */
1334/* There are hard-coded 16's for base_key_len in the key generation code */
1335
1336void
1337crypto_policy_set_rtp_default(crypto_policy_t *p) {
1338
1339 p->cipher_type = AES_128_ICM;
1340 p->cipher_key_len = 30; /* default 128 bits per RFC 3711 */
1341 p->auth_type = HMAC_SHA1;
1342 p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
1343 p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
1344 p->sec_serv = sec_serv_conf_and_auth;
1345
1346}
1347
1348void
1349crypto_policy_set_rtcp_default(crypto_policy_t *p) {
1350
1351 p->cipher_type = AES_128_ICM;
1352 p->cipher_key_len = 30; /* default 128 bits per RFC 3711 */
1353 p->auth_type = HMAC_SHA1;
1354 p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
1355 p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
1356 p->sec_serv = sec_serv_conf_and_auth;
1357
1358}
1359
1360/*
1361 * secure rtcp functions
1362 */
1363
1364err_status_t
1365srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
1366 srtcp_hdr_t *hdr = rtcp_hdr;
1367 uint32_t *enc_start; /* pointer to start of encrypted portion */
1368 uint32_t *auth_start; /* pointer to start of auth. portion */
1369 uint32_t *trailer; /* pointer to start of trailer */
1370 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001371 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +00001372 err_status_t status;
1373 int tag_len;
1374 srtp_stream_ctx_t *stream;
1375 int prefix_len;
1376 uint32_t seq_num;
1377
1378 /* we assume the hdr is 32-bit aligned to start */
1379 /*
1380 * look up ssrc in srtp_stream list, and process the packet with
1381 * the appropriate stream. if we haven't seen this stream before,
1382 * there's only one key for this srtp_session, and the cipher
1383 * supports key-sharing, then we assume that a new stream using
1384 * that key has just started up
1385 */
1386 stream = srtp_get_stream(ctx, hdr->ssrc);
1387 if (stream == NULL) {
1388 if (ctx->stream_template != NULL) {
1389 srtp_stream_ctx_t *new_stream;
1390
1391 /* allocate and initialize a new stream */
1392 status = srtp_stream_clone(ctx->stream_template,
1393 hdr->ssrc, &new_stream);
1394 if (status)
1395 return status;
1396
1397 /* add new stream to the head of the stream_list */
1398 new_stream->next = ctx->stream_list;
1399 ctx->stream_list = new_stream;
1400
1401 /* set stream (the pointer used in this function) */
1402 stream = new_stream;
1403 } else {
1404 /* no template stream, so we return an error */
1405 return err_status_no_ctx;
1406 }
1407 }
1408
1409 /*
1410 * verify that stream is for sending traffic - this check will
1411 * detect SSRC collisions, since a stream that appears in both
1412 * srtp_protect() and srtp_unprotect() will fail this test in one of
1413 * those functions.
1414 */
1415 if (stream->direction != dir_srtp_sender) {
1416 if (stream->direction == dir_unknown) {
1417 stream->direction = dir_srtp_receiver;
1418 } else {
1419 srtp_handle_event(ctx, stream, event_ssrc_collision);
1420 }
1421 }
1422
1423 /* get tag length from stream context */
1424 tag_len = auth_get_tag_length(stream->rtcp_auth);
1425
1426 /*
1427 * set encryption start and encryption length - if we're not
1428 * providing confidentiality, set enc_start to NULL
1429 */
1430 enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1431 enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
1432
1433 /* all of the packet, except the header, gets encrypted */
1434 /* NOTE: hdr->length is not usable - it refers to only the first
1435 RTCP report in the compound packet! */
1436 /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1437 multiples of 32-bits (RFC 3550 6.1) */
1438 trailer = (uint32_t *) ((char *)enc_start + enc_octet_len);
1439
1440 if (stream->rtcp_services & sec_serv_conf) {
1441 *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
1442 } else {
1443 enc_start = NULL;
1444 enc_octet_len = 0;
1445 /* 0 is network-order independant */
1446 *trailer = 0x00000000; /* set encrypt bit */
1447 }
1448
1449 /*
1450 * set the auth_start and auth_tag pointers to the proper locations
1451 * (note that srtpc *always* provides authentication, unlike srtp)
1452 */
1453 /* Note: This would need to change for optional mikey data */
1454 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001455 auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t);
Cullen Jennings235513a2005-09-21 22:51:36 +00001456
1457 /*
1458 * check sequence number for overruns, and copy it into the packet
1459 * if its value isn't too big
1460 */
1461 status = rdb_increment(&stream->rtcp_rdb);
1462 if (status)
1463 return status;
1464 seq_num = rdb_get_value(&stream->rtcp_rdb);
1465 *trailer |= htonl(seq_num);
1466 debug_print(mod_srtp, "srtcp index: %x", seq_num);
1467
1468 /*
1469 * if we're using rindael counter mode, set nonce and seq
1470 */
1471 if (stream->rtcp_cipher->type == &aes_icm) {
1472 v128_t iv;
1473
1474 iv.v32[0] = 0;
1475 iv.v32[1] = hdr->ssrc; /* still in network order! */
1476 iv.v32[2] = htonl(seq_num >> 16);
1477 iv.v32[3] = htonl(seq_num << 16);
1478 status = aes_icm_set_iv(stream->rtcp_cipher->state, &iv);
1479
1480 } else {
1481 v128_t iv;
1482
1483 /* otherwise, just set the index to seq_num */
1484 iv.v32[0] = 0;
1485 iv.v32[1] = 0;
1486 iv.v32[2] = 0;
1487 iv.v32[3] = htonl(seq_num);
1488 status = cipher_set_iv(stream->rtcp_cipher, &iv);
1489 }
1490 if (status)
1491 return err_status_cipher_fail;
1492
1493 /*
1494 * if we're authenticating using a universal hash, put the keystream
1495 * prefix into the authentication tag
1496 */
1497
1498 /* if auth_start is non-null, then put keystream into tag */
1499 if (auth_start) {
1500
1501 /* put keystream prefix into auth_tag */
1502 prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1503 status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1504
1505 debug_print(mod_srtp, "keystream prefix: %s",
1506 octet_string_hex_string(auth_tag, prefix_len));
1507
1508 if (status)
1509 return err_status_cipher_fail;
1510 }
1511
1512 /* if we're encrypting, exor keystream into the message */
1513 if (enc_start) {
1514 status = cipher_encrypt(stream->rtcp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001515 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +00001516 if (status)
1517 return err_status_cipher_fail;
1518 }
1519
1520 /* initialize auth func context */
1521 auth_start(stream->rtcp_auth);
1522
1523 /* per spec, do auth after encryption */
1524 /* run auth func over packet, put result into auth_tag */
1525 status = auth_compute(stream->rtcp_auth,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001526 (uint8_t *)auth_start, *pkt_octet_len, auth_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +00001527 debug_print(mod_srtp, "srtcp auth tag: %s",
1528 octet_string_hex_string(auth_tag, tag_len));
1529 if (status)
1530 return err_status_auth_fail;
1531
1532 /* increase the packet length by the length of the auth tag and seq_num*/
1533 *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
1534
1535 return err_status_ok;
1536}
1537
1538
1539err_status_t
1540srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
1541 srtcp_hdr_t *hdr = srtcp_hdr;
1542 uint32_t *enc_start; /* pointer to start of encrypted portion */
1543 uint32_t *auth_start; /* pointer to start of auth. portion */
1544 uint32_t *trailer; /* pointer to start of trailer */
1545 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001546 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
1547 uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
Cullen Jennings235513a2005-09-21 22:51:36 +00001548 err_status_t status;
1549 int tag_len;
1550 srtp_stream_ctx_t *stream;
1551 int prefix_len;
1552 uint32_t seq_num;
1553
1554 /* we assume the hdr is 32-bit aligned to start */
1555 /*
1556 * look up ssrc in srtp_stream list, and process the packet with
1557 * the appropriate stream. if we haven't seen this stream before,
1558 * there's only one key for this srtp_session, and the cipher
1559 * supports key-sharing, then we assume that a new stream using
1560 * that key has just started up
1561 */
1562 stream = srtp_get_stream(ctx, hdr->ssrc);
1563 if (stream == NULL) {
1564 if (ctx->stream_template != NULL) {
1565 stream = ctx->stream_template;
1566 debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)",
1567 hdr->ssrc);
1568 } else {
1569 /* no template stream, so we return an error */
1570 return err_status_no_ctx;
1571 }
1572 }
1573
1574 /* get tag length from stream context */
1575 tag_len = auth_get_tag_length(stream->rtcp_auth);
1576
1577 /*
1578 * set encryption start, encryption length, and trailer
1579 */
1580 enc_octet_len = *pkt_octet_len -
1581 (octets_in_rtcp_header + tag_len + sizeof(srtcp_trailer_t));
1582 /* index & E (encryption) bit follow normal data. hdr->len
1583 is the number of words (32-bit) in the normal packet minus 1 */
1584 /* This should point trailer to the word past the end of the
1585 normal data. */
1586 /* This would need to be modified for optional mikey data */
1587 /*
1588 * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1589 * multiples of 32-bits (RFC 3550 6.1)
1590 */
1591 trailer = (uint32_t *) ((char *) hdr +
1592 *pkt_octet_len -(tag_len + sizeof(srtcp_trailer_t)));
1593 if (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) {
1594 enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1595 } else {
1596 enc_octet_len = 0;
1597 enc_start = NULL; /* this indicates that there's no encryption */
1598 }
1599
1600 /*
1601 * set the auth_start and auth_tag pointers to the proper locations
1602 * (note that srtcp *always* uses authentication, unlike srtp)
1603 */
1604 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001605 auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
Cullen Jennings235513a2005-09-21 22:51:36 +00001606
1607 /*
1608 * check the sequence number for replays
1609 */
1610 /* this is easier than dealing with bitfield access */
1611 seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK;
1612 status = rdb_check(&stream->rtcp_rdb, seq_num);
1613 if (status)
1614 return status;
1615 debug_print(mod_srtp, "srtcp index: %x", seq_num);
1616
1617 /*
1618 * if we're using aes counter mode, set nonce and seq
1619 */
1620 if (stream->rtcp_cipher->type == &aes_icm) {
1621 v128_t iv;
1622
1623 iv.v32[0] = 0;
1624 iv.v32[1] = hdr->ssrc; /* still in network order! */
1625 iv.v32[2] = htonl(seq_num >> 16);
1626 iv.v32[3] = htonl(seq_num << 16);
1627 status = aes_icm_set_iv(stream->rtcp_cipher->state, &iv);
1628
1629 } else {
1630 v128_t iv;
1631
1632 /* otherwise, just set the index to seq_num */
1633 iv.v32[0] = 0;
1634 iv.v32[1] = 0;
1635 iv.v32[2] = 0;
1636 iv.v32[3] = htonl(seq_num);
1637 status = cipher_set_iv(stream->rtcp_cipher, &iv);
1638
1639 }
1640 if (status)
1641 return err_status_cipher_fail;
1642
1643 /* initialize auth func context */
1644 auth_start(stream->rtcp_auth);
1645
1646 /* run auth func over packet, put result into tmp_tag */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001647 status = auth_compute(stream->rtcp_auth, (uint8_t *)auth_start,
Cullen Jennings235513a2005-09-21 22:51:36 +00001648 *pkt_octet_len - (tag_len + sizeof(srtcp_trailer_t)),
1649 tmp_tag);
1650 debug_print(mod_srtp, "srtcp computed tag: %s",
1651 octet_string_hex_string(tmp_tag, tag_len));
1652 if (status)
1653 return err_status_auth_fail;
1654
1655 /* compare the tag just computed with the one in the packet */
1656 debug_print(mod_srtp, "srtcp tag from packet: %s",
1657 octet_string_hex_string(auth_tag, tag_len));
1658 if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1659 return err_status_auth_fail;
1660
1661 /*
1662 * if we're authenticating using a universal hash, put the keystream
1663 * prefix into the authentication tag
1664 */
1665 prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1666 if (prefix_len) {
1667 status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1668 debug_print(mod_srtp, "keystream prefix: %s",
1669 octet_string_hex_string(auth_tag, prefix_len));
1670 if (status)
1671 return err_status_cipher_fail;
1672 }
1673
1674 /* if we're decrypting, exor keystream into the message */
1675 if (enc_start) {
1676 status = cipher_encrypt(stream->rtcp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001677 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +00001678 if (status)
1679 return err_status_cipher_fail;
1680 }
1681
1682 /* decrease the packet length by the length of the auth tag and seq_num*/
1683 *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));
1684
1685 /*
1686 * verify that stream is for received traffic - this check will
1687 * detect SSRC collisions, since a stream that appears in both
1688 * srtp_protect() and srtp_unprotect() will fail this test in one of
1689 * those functions.
1690 *
1691 * we do this check *after* the authentication check, so that the
1692 * latter check will catch any attempts to fool us into thinking
1693 * that we've got a collision
1694 */
1695 if (stream->direction != dir_srtp_receiver) {
1696 if (stream->direction == dir_unknown) {
1697 stream->direction = dir_srtp_receiver;
1698 } else {
1699 srtp_handle_event(ctx, stream, event_ssrc_collision);
1700 }
1701 }
1702
1703 /*
1704 * if the stream is a 'provisional' one, in which the template context
1705 * is used, then we need to allocate a new stream at this point, since
1706 * the authentication passed
1707 */
1708 if (stream == ctx->stream_template) {
1709 srtp_stream_ctx_t *new_stream;
1710
1711 /*
1712 * allocate and initialize a new stream
1713 *
1714 * note that we indicate failure if we can't allocate the new
1715 * stream, and some implementations will want to not return
1716 * failure here
1717 */
1718 status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
1719 if (status)
1720 return status;
1721
1722 /* add new stream to the head of the stream_list */
1723 new_stream->next = ctx->stream_list;
1724 ctx->stream_list = new_stream;
1725
1726 /* set stream (the pointer used in this function) */
1727 stream = new_stream;
1728 }
1729
1730 /* we've passed the authentication check, so add seq_num to the rdb */
1731 rdb_add_index(&stream->rtcp_rdb, seq_num);
1732
1733
1734 return err_status_ok;
1735}