blob: 7c044a1c7cbcb0b313635ecaf643bbf8647041d7 [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 *
David McGrew7629bf22006-06-08 17:00:25 +000011 * Copyright (c) 2001-2006, Cisco Systems, Inc.
Cullen Jennings235513a2005-09-21 22:51:36 +000012 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * Neither the name of the Cisco Systems, Inc. nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41 * OF THE POSSIBILITY OF SUCH DAMAGE.
42 *
43 */
44
45
David McGrew3c45e0c2006-07-12 00:50:56 +000046#include "srtp_priv.h"
Cullen Jennings235513a2005-09-21 22:51:36 +000047#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
Cullen Jennings235513a2005-09-21 22:51:36 +000075
76err_status_t
77srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
78 const srtp_policy_t *p) {
79 srtp_stream_ctx_t *str;
80 err_status_t stat;
81
82 /*
83 * This function allocates the stream context, rtp and rtcp ciphers
84 * and auth functions, and key limit structure. If there is a
85 * failure during allocation, we free all previously allocated
86 * memory and return a failure code. The code could probably
87 * be improved, but it works and should be clear.
88 */
89
90 /* allocate srtp stream and set str_ptr */
91 str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
92 if (str == NULL)
93 return err_status_alloc_fail;
94 *str_ptr = str;
95
96 /* allocate cipher */
97 stat = crypto_kernel_alloc_cipher(p->rtp.cipher_type,
98 &str->rtp_cipher,
99 p->rtp.cipher_key_len);
100 if (stat) {
101 crypto_free(str);
102 return stat;
103 }
104
105 /* allocate auth function */
106 stat = crypto_kernel_alloc_auth(p->rtp.auth_type,
107 &str->rtp_auth,
108 p->rtp.auth_key_len,
109 p->rtp.auth_tag_len);
110 if (stat) {
111 cipher_dealloc(str->rtp_cipher);
112 crypto_free(str);
113 return stat;
114 }
115
116 /* allocate key limit structure */
Derek MacDonald17127da2006-07-12 22:22:08 +0000117 str->limit = (key_limit_ctx_t*) crypto_alloc(sizeof(key_limit_ctx_t));
Cullen Jennings235513a2005-09-21 22:51:36 +0000118 if (str->limit == NULL) {
119 auth_dealloc(str->rtp_auth);
120 cipher_dealloc(str->rtp_cipher);
121 crypto_free(str);
122 return err_status_alloc_fail;
123 }
124
125 /*
126 * ...and now the RTCP-specific initialization - first, allocate
127 * the cipher
128 */
129 stat = crypto_kernel_alloc_cipher(p->rtcp.cipher_type,
130 &str->rtcp_cipher,
131 p->rtcp.cipher_key_len);
132 if (stat) {
133 auth_dealloc(str->rtp_auth);
134 cipher_dealloc(str->rtp_cipher);
135 crypto_free(str->limit);
136 crypto_free(str);
137 return stat;
138 }
139
140 /* allocate auth function */
141 stat = crypto_kernel_alloc_auth(p->rtcp.auth_type,
142 &str->rtcp_auth,
143 p->rtcp.auth_key_len,
144 p->rtcp.auth_tag_len);
145 if (stat) {
146 cipher_dealloc(str->rtcp_cipher);
147 auth_dealloc(str->rtp_auth);
148 cipher_dealloc(str->rtp_cipher);
149 crypto_free(str->limit);
150 crypto_free(str);
151 return stat;
152 }
153
154 return err_status_ok;
155}
156
157err_status_t
158srtp_stream_dealloc(srtp_t session, srtp_stream_ctx_t *stream) {
159 err_status_t status;
160
161 /*
162 * we use a conservative deallocation strategy - if any deallocation
163 * fails, then we report that fact without trying to deallocate
164 * anything else
165 */
166
167 /* deallocate cipher, if it is not the same as that in template */
David McGrewfec49dd2005-09-23 19:34:11 +0000168 if (session->stream_template
Cullen Jennings235513a2005-09-21 22:51:36 +0000169 && stream->rtp_cipher == session->stream_template->rtp_cipher) {
170 /* do nothing */
171 } else {
172 status = cipher_dealloc(stream->rtp_cipher);
173 if (status)
David McGrewfec49dd2005-09-23 19:34:11 +0000174 return status;
Cullen Jennings235513a2005-09-21 22:51:36 +0000175 }
176
177 /* deallocate auth function, if it is not the same as that in template */
178 if (session->stream_template
179 && stream->rtp_auth == session->stream_template->rtp_auth) {
180 /* do nothing */
181 } else {
182 status = auth_dealloc(stream->rtp_auth);
183 if (status)
184 return status;
185 }
186
David McGrewfec49dd2005-09-23 19:34:11 +0000187 /* deallocate key usage limit, if it is not the same as that in template */
188 if (session->stream_template
189 && stream->limit == session->stream_template->limit) {
190 /* do nothing */
191 } else {
Cullen Jennings235513a2005-09-21 22:51:36 +0000192 crypto_free(stream->limit);
David McGrewfec49dd2005-09-23 19:34:11 +0000193 }
Cullen Jennings235513a2005-09-21 22:51:36 +0000194
195 /*
196 * deallocate rtcp cipher, if it is not the same as that in
197 * template
198 */
199 if (session->stream_template
200 && stream->rtcp_cipher == session->stream_template->rtcp_cipher) {
201 /* do nothing */
202 } else {
203 status = cipher_dealloc(stream->rtcp_cipher);
204 if (status)
205 return status;
206 }
207
208 /*
209 * deallocate rtcp auth function, if it is not the same as that in
210 * template
211 */
212 if (session->stream_template
213 && stream->rtcp_auth == session->stream_template->rtcp_auth) {
214 /* do nothing */
215 } else {
216 status = auth_dealloc(stream->rtcp_auth);
217 if (status)
218 return status;
219 }
220
221 /* deallocate srtp stream context */
222 crypto_free(stream);
223
224 return err_status_ok;
225}
226
227
228/*
229 * srtp_stream_clone(stream_template, new) allocates a new stream and
230 * initializes it using the cipher and auth of the stream_template
231 *
232 * the only unique data in a cloned stream is the replay database and
233 * the SSRC
234 */
235
236err_status_t
237srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
238 uint32_t ssrc,
239 srtp_stream_ctx_t **str_ptr) {
240 err_status_t status;
241 srtp_stream_ctx_t *str;
242
243 debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ssrc);
244
245 /* allocate srtp stream and set str_ptr */
246 str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
247 if (str == NULL)
248 return err_status_alloc_fail;
249 *str_ptr = str;
250
251 /* set cipher and auth pointers to those of the template */
252 str->rtp_cipher = stream_template->rtp_cipher;
253 str->rtp_auth = stream_template->rtp_auth;
254 str->rtcp_cipher = stream_template->rtcp_cipher;
255 str->rtcp_auth = stream_template->rtcp_auth;
256
257 /* set key limit to point to that of the template */
258 status = key_limit_clone(stream_template->limit, &str->limit);
259 if (status)
260 return status;
261
262 /* initialize replay databases */
263 rdbx_init(&str->rtp_rdbx);
264 rdb_init(&str->rtcp_rdb);
265
266 /* set ssrc to that provided */
267 str->ssrc = ssrc;
268
269 /* set direction and security services */
270 str->direction = stream_template->direction;
271 str->rtp_services = stream_template->rtp_services;
272 str->rtcp_services = stream_template->rtcp_services;
273
274 /* defensive coding */
275 str->next = NULL;
276
277 return err_status_ok;
278}
279
280
281/*
282 * key derivation functions, internal to libSRTP
283 *
284 * srtp_kdf_t is a key derivation context
285 *
286 * srtp_kdf_init(&kdf, k) initializes kdf with the key k
287 *
288 * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key
289 * corresponding to label l and puts it into kl; the length
290 * of the key in octets is provided as keylen. this function
291 * should be called once for each subkey that is derived.
292 *
293 * srtp_kdf_clear(&kdf) zeroizes the kdf state
294 */
295
296typedef enum {
297 label_rtp_encryption = 0x00,
298 label_rtp_msg_auth = 0x01,
299 label_rtp_salt = 0x02,
300 label_rtcp_encryption = 0x03,
301 label_rtcp_msg_auth = 0x04,
302 label_rtcp_salt = 0x05
303} srtp_prf_label;
304
305
306/*
307 * srtp_kdf_t represents a key derivation function. The SRTP
308 * default KDF is the only one implemented at present.
309 */
310
311typedef struct {
312 aes_icm_ctx_t c; /* cipher used for key derivation */
313} srtp_kdf_t;
314
315err_status_t
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000316srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t key[30]) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000317
318 aes_icm_context_init(&kdf->c, key);
319
320 return err_status_ok;
321}
322
323err_status_t
324srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000325 uint8_t *key, int length) {
Cullen Jennings235513a2005-09-21 22:51:36 +0000326
327 v128_t nonce;
328
329 /* set eigth octet of nonce to <label>, set the rest of it to zero */
330 v128_set_to_zero(&nonce);
Marcus Sundberg7627bc52005-10-08 16:38:06 +0000331 nonce.v8[7] = label;
Cullen Jennings235513a2005-09-21 22:51:36 +0000332
333 aes_icm_set_iv(&kdf->c, &nonce);
334
335 /* generate keystream output */
336 aes_icm_output(&kdf->c, key, length);
337
338 return err_status_ok;
339}
340
341err_status_t
342srtp_kdf_clear(srtp_kdf_t *kdf) {
343
344 /* zeroize aes context */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000345 octet_string_set_to_zero((uint8_t *)kdf, sizeof(srtp_kdf_t));
Cullen Jennings235513a2005-09-21 22:51:36 +0000346
347 return err_status_ok;
348}
349
350/*
351 * end of key derivation functions
352 */
353
354#define MAX_SRTP_KEY_LEN 256
355
356
David McGrew576e1482006-06-09 21:47:44 +0000357err_status_t
358srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
359 err_status_t stat;
360 srtp_kdf_t kdf;
361 uint8_t tmp_key[MAX_SRTP_KEY_LEN];
362
363 /* initialize KDF state */
Derek MacDonald17127da2006-07-12 22:22:08 +0000364 srtp_kdf_init(&kdf, (const uint8_t *)key);
David McGrew576e1482006-06-09 21:47:44 +0000365
366 /* generate encryption key */
367 srtp_kdf_generate(&kdf, label_rtp_encryption,
368 tmp_key, cipher_get_key_length(srtp->rtp_cipher));
369 /*
370 * if the cipher in the srtp context is aes_icm, then we need
371 * to generate the salt value
372 */
373 if (srtp->rtp_cipher->type == &aes_icm) {
374 /* FIX!!! this is really the cipher key length; rest is salt */
375 int base_key_len = 16;
376 int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;
377
378 debug_print(mod_srtp, "found aes_icm, generating salt", NULL);
379
380 /* generate encryption salt, put after encryption key */
381 srtp_kdf_generate(&kdf, label_rtp_salt,
382 tmp_key + base_key_len, salt_len);
383 }
384 debug_print(mod_srtp, "cipher key: %s",
385 octet_string_hex_string(tmp_key,
386 cipher_get_key_length(srtp->rtp_cipher)));
387
388 /* initialize cipher */
389 stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
390 if (stat) {
391 /* zeroize temp buffer */
392 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
393 return err_status_init_fail;
394 }
395
396 /* generate authentication key */
397 srtp_kdf_generate(&kdf, label_rtp_msg_auth,
398 tmp_key, auth_get_key_length(srtp->rtp_auth));
399 debug_print(mod_srtp, "auth key: %s",
400 octet_string_hex_string(tmp_key,
401 auth_get_key_length(srtp->rtp_auth)));
402
403 /* initialize auth function */
404 stat = auth_init(srtp->rtp_auth, tmp_key);
405 if (stat) {
406 /* zeroize temp buffer */
407 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
408 return err_status_init_fail;
409 }
410
411 /*
412 * ...now initialize SRTCP keys
413 */
414
415 /* generate encryption key */
416 srtp_kdf_generate(&kdf, label_rtcp_encryption,
417 tmp_key, cipher_get_key_length(srtp->rtcp_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->rtcp_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->rtcp_cipher) - base_key_len;
426
427 debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);
428
429 /* generate encryption salt, put after encryption key */
430 srtp_kdf_generate(&kdf, label_rtcp_salt,
431 tmp_key + base_key_len, salt_len);
432 }
433 debug_print(mod_srtp, "rtcp cipher key: %s",
434 octet_string_hex_string(tmp_key,
435 cipher_get_key_length(srtp->rtcp_cipher)));
436
437 /* initialize cipher */
438 stat = cipher_init(srtp->rtcp_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_rtcp_msg_auth,
447 tmp_key, auth_get_key_length(srtp->rtcp_auth));
448 debug_print(mod_srtp, "rtcp auth key: %s",
449 octet_string_hex_string(tmp_key,
450 auth_get_key_length(srtp->rtcp_auth)));
451
452 /* initialize auth function */
453 stat = auth_init(srtp->rtcp_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 /* clear memory then return */
461 srtp_kdf_clear(&kdf);
462 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
463
464 return err_status_ok;
465}
Cullen Jennings235513a2005-09-21 22:51:36 +0000466
467err_status_t
468srtp_stream_init(srtp_stream_ctx_t *srtp,
469 const srtp_policy_t *p) {
David McGrew576e1482006-06-09 21:47:44 +0000470 err_status_t err;
Cullen Jennings235513a2005-09-21 22:51:36 +0000471
472 debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)",
473 p->ssrc.value);
474
475 /* initialize replay database */
476 rdbx_init(&srtp->rtp_rdbx);
477
478 /* initialize key limit to maximum value */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000479#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000480{
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000481 uint64_t temp;
482 temp = make64(UINT_MAX,UINT_MAX);
483 key_limit_set(srtp->limit, temp);
Cullen Jennings235513a2005-09-21 22:51:36 +0000484}
485#else
486 key_limit_set(srtp->limit, 0xffffffffffffLL);
487#endif
488
489 /* set the SSRC value */
490 srtp->ssrc = htonl(p->ssrc.value);
491
492 /* set the security service flags */
493 srtp->rtp_services = p->rtp.sec_serv;
494 srtp->rtcp_services = p->rtcp.sec_serv;
495
496 /*
497 * set direction to unknown - this flag gets checked in srtp_protect(),
498 * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and
499 * gets set appropriately if it is set to unknown.
500 */
501 srtp->direction = dir_unknown;
502
David McGrew576e1482006-06-09 21:47:44 +0000503 /* initialize SRTCP replay database */
Cullen Jennings235513a2005-09-21 22:51:36 +0000504 rdb_init(&srtp->rtcp_rdb);
505
506 /* DAM - no RTCP key limit at present */
507
David McGrew576e1482006-06-09 21:47:44 +0000508 /* initialize keys */
509 err = srtp_stream_init_keys(srtp, p->key);
510 if (err) return err;
Cullen Jennings235513a2005-09-21 22:51:36 +0000511
Cullen Jennings235513a2005-09-21 22:51:36 +0000512 return err_status_ok;
513 }
514
515
516 /*
517 * srtp_event_reporter is an event handler function that merely
518 * reports the events that are reported by the callbacks
519 */
520
521 void
522 srtp_event_reporter(srtp_event_data_t *data) {
523
524 err_report(err_level_warning, "srtp: in stream 0x%x: ",
525 data->stream->ssrc);
526
527 switch(data->event) {
528 case event_ssrc_collision:
529 err_report(err_level_warning, "\tSSRC collision\n");
530 break;
531 case event_key_soft_limit:
532 err_report(err_level_warning, "\tkey usage soft limit reached\n");
533 break;
534 case event_key_hard_limit:
535 err_report(err_level_warning, "\tkey usage hard limit reached\n");
536 break;
537 case event_packet_index_limit:
538 err_report(err_level_warning, "\tpacket index limit reached\n");
539 break;
540 default:
541 err_report(err_level_warning, "\tunknown event reported to handler\n");
542 }
543 }
544
545 /*
546 * srtp_event_handler is a global variable holding a pointer to the
547 * event handler function; this function is called for any unexpected
548 * event that needs to be handled out of the SRTP data path. see
549 * srtp_event_t in srtp.h for more info
550 *
551 * it is okay to set srtp_event_handler to NULL, but we set
552 * it to the srtp_event_reporter.
553 */
554
555 static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter;
556
557 err_status_t
558 srtp_install_event_handler(srtp_event_handler_func_t func) {
559
560 /*
561 * note that we accept NULL arguments intentionally - calling this
562 * function with a NULL arguments removes an event handler that's
563 * been previously installed
564 */
565
566 /* set global event handling function */
567 srtp_event_handler = func;
568 return err_status_ok;
569 }
570
571 err_status_t
572 srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) {
Derek MacDonald17127da2006-07-12 22:22:08 +0000573 srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +0000574 uint32_t *enc_start; /* pointer to start of encrypted portion */
575 uint32_t *auth_start; /* pointer to start of auth. portion */
576 unsigned enc_octet_len = 0; /* number of octets in encrypted portion */
577 xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
578 int delta; /* delta of local pkt idx and that in hdr */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000579 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +0000580 err_status_t status;
581 int tag_len;
582 srtp_stream_ctx_t *stream;
583 int prefix_len;
584
585 debug_print(mod_srtp, "function srtp_protect", NULL);
586
587 /* we assume the hdr is 32-bit aligned to start */
588
589 /* check the packet length - it must at least contain a full header */
590 if (*pkt_octet_len < octets_in_rtp_header)
591 return err_status_bad_param;
592
593 /*
594 * look up ssrc in srtp_stream list, and process the packet with
595 * the appropriate stream. if we haven't seen this stream before,
596 * there's a template key for this srtp_session, and the cipher
597 * supports key-sharing, then we assume that a new stream using
598 * that key has just started up
599 */
600 stream = srtp_get_stream(ctx, hdr->ssrc);
601 if (stream == NULL) {
602 if (ctx->stream_template != NULL) {
603 srtp_stream_ctx_t *new_stream;
604
605 /* allocate and initialize a new stream */
606 status = srtp_stream_clone(ctx->stream_template,
David McGrewfec49dd2005-09-23 19:34:11 +0000607 hdr->ssrc, &new_stream);
Cullen Jennings235513a2005-09-21 22:51:36 +0000608 if (status)
609 return status;
610
611 /* add new stream to the head of the stream_list */
612 new_stream->next = ctx->stream_list;
613 ctx->stream_list = new_stream;
614
615 /* set direction to outbound */
616 new_stream->direction = dir_srtp_sender;
617
618 /* set stream (the pointer used in this function) */
619 stream = new_stream;
620 } else {
621 /* no template stream, so we return an error */
622 return err_status_no_ctx;
623 }
624 }
625
626 /*
627 * verify that stream is for sending traffic - this check will
628 * detect SSRC collisions, since a stream that appears in both
629 * srtp_protect() and srtp_unprotect() will fail this test in one of
630 * those functions.
631 */
632 if (stream->direction != dir_srtp_sender) {
633 if (stream->direction == dir_unknown) {
634 stream->direction = dir_srtp_sender;
635 } else {
636 srtp_handle_event(ctx, stream, event_ssrc_collision);
637 }
638 }
639
640 /*
641 * update the key usage limit, and check it to make sure that we
642 * didn't just hit either the soft limit or the hard limit, and call
643 * the event handler if we hit either.
644 */
645 switch(key_limit_update(stream->limit)) {
646 case key_event_normal:
647 break;
648 case key_event_soft_limit:
649 srtp_handle_event(ctx, stream, event_key_soft_limit);
650 break;
651 case key_event_hard_limit:
652 srtp_handle_event(ctx, stream, event_key_hard_limit);
David McGrewfec49dd2005-09-23 19:34:11 +0000653 return err_status_key_expired;
Cullen Jennings235513a2005-09-21 22:51:36 +0000654 default:
655 break;
656 }
657
658 /* get tag length from stream */
659 tag_len = auth_get_tag_length(stream->rtp_auth);
660
661 /*
662 * find starting point for encryption and length of data to be
663 * encrypted - the encrypted portion starts after the rtp header
664 * extension, if present; otherwise, it starts after the last csrc,
665 * if any are present
666 *
667 * if we're not providing confidentiality, set enc_start to NULL
668 */
669 if (stream->rtp_services & sec_serv_conf) {
670 enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
David McGrew14829302005-10-10 18:53:19 +0000671 if (hdr->x == 1) {
672 srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
673 enc_start += (ntohs(xtn_hdr->length) + 1);
674 }
David McGrewc4fc00b2006-06-08 18:51:27 +0000675 enc_octet_len = (unsigned int)(*pkt_octet_len
676 - ((enc_start - (uint32_t *)hdr) << 2));
Cullen Jennings235513a2005-09-21 22:51:36 +0000677 } else {
678 enc_start = NULL;
679 }
680
681 /*
682 * if we're providing authentication, set the auth_start and auth_tag
683 * pointers to the proper locations; otherwise, set auth_start to NULL
684 * to indicate that no authentication is needed
685 */
686 if (stream->rtp_services & sec_serv_auth) {
687 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000688 auth_tag = (uint8_t *)hdr + *pkt_octet_len;
Cullen Jennings235513a2005-09-21 22:51:36 +0000689 } else {
690 auth_start = NULL;
691 auth_tag = NULL;
692 }
693
694 /*
695 * estimate the packet index using the start of the replay window
696 * and the sequence number from the header
697 */
698 delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
699 status = rdbx_check(&stream->rtp_rdbx, delta);
700 if (status)
701 return status; /* we've been asked to reuse an index */
702 rdbx_add_index(&stream->rtp_rdbx, delta);
703
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000704#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000705 debug_print2(mod_srtp, "estimated packet index: %08x%08x",
706 high32(est),low32(est));
707#else
708 debug_print(mod_srtp, "estimated packet index: %016llx", est);
709#endif
710
711 /*
712 * if we're using rindael counter mode, set nonce and seq
713 */
714 if (stream->rtp_cipher->type == &aes_icm) {
715 v128_t iv;
716
717 iv.v32[0] = 0;
718 iv.v32[1] = hdr->ssrc;
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000719#ifdef NO_64BIT_MATH
720 iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
David McGrewfec49dd2005-09-23 19:34:11 +0000721 low32(est) << 16));
Cullen Jennings235513a2005-09-21 22:51:36 +0000722#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000723 iv.v64[1] = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000724#endif
725 status = cipher_set_iv(stream->rtp_cipher, &iv);
726
727 } else {
728 v128_t iv;
729
730 /* otherwise, set the index to est */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000731#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000732 iv.v32[0] = 0;
733 iv.v32[1] = 0;
734#else
735 iv.v64[0] = 0;
736#endif
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000737 iv.v64[1] = be64_to_cpu(est);
Cullen Jennings235513a2005-09-21 22:51:36 +0000738 status = cipher_set_iv(stream->rtp_cipher, &iv);
739 }
740 if (status)
741 return err_status_cipher_fail;
742
743 /* shift est, put into network byte order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000744#ifdef NO_64BIT_MATH
745 est = be64_to_cpu(make64((high32(est) << 16) |
Cullen Jennings235513a2005-09-21 22:51:36 +0000746 (low32(est) >> 16),
Randell Jesup811e1442005-09-28 22:43:41 +0000747 low32(est) << 16));
Cullen Jennings235513a2005-09-21 22:51:36 +0000748#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000749 est = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000750#endif
751
752 /*
753 * if we're authenticating using a universal hash, put the keystream
754 * prefix into the authentication tag
755 */
756 if (auth_start) {
757
758 prefix_len = auth_get_prefix_length(stream->rtp_auth);
759 if (prefix_len) {
760 status = cipher_output(stream->rtp_cipher, auth_tag, prefix_len);
761 if (status)
762 return err_status_cipher_fail;
763 debug_print(mod_srtp, "keystream prefix: %s",
764 octet_string_hex_string(auth_tag, prefix_len));
765 }
766 }
767
768 /* if we're encrypting, exor keystream into the message */
769 if (enc_start) {
770 status = cipher_encrypt(stream->rtp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000771 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000772 if (status)
773 return err_status_cipher_fail;
774 }
775
776 /*
777 * if we're authenticating, run authentication function and put result
778 * into the auth_tag
779 */
780 if (auth_start) {
781
782 /* initialize auth func context */
783 status = auth_start(stream->rtp_auth);
784 if (status) return status;
785
786 /* run auth func over packet */
787 status = auth_update(stream->rtp_auth,
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000788 (uint8_t *)auth_start, *pkt_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +0000789 if (status) return status;
790
791 /* run auth func over ROC, put result into auth_tag */
David McGrew89fb7ea2005-09-26 19:33:44 +0000792 debug_print(mod_srtp, "estimated packet index: %016llx", est);
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000793 status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, auth_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +0000794 debug_print(mod_srtp, "srtp auth tag: %s",
795 octet_string_hex_string(auth_tag, tag_len));
796 if (status)
797 return err_status_auth_fail;
798
799 }
800
801 if (auth_tag) {
802
803 /* increase the packet length by the length of the auth tag */
804 *pkt_octet_len += tag_len;
805 }
806
807 return err_status_ok;
808}
809
810
811err_status_t
812srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
Derek MacDonald17127da2006-07-12 22:22:08 +0000813 srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +0000814 uint32_t *enc_start; /* pointer to start of encrypted portion */
815 uint32_t *auth_start; /* pointer to start of auth. portion */
816 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000817 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +0000818 xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
819 int delta; /* delta of local pkt idx and that in hdr */
820 v128_t iv;
821 err_status_t status;
822 srtp_stream_ctx_t *stream;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000823 uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
Cullen Jennings235513a2005-09-21 22:51:36 +0000824 int tag_len, prefix_len;
825
826 debug_print(mod_srtp, "function srtp_unprotect", NULL);
827
828 /* we assume the hdr is 32-bit aligned to start */
829
830 /* check the packet length - it must at least contain a full header */
831 if (*pkt_octet_len < octets_in_rtp_header)
832 return err_status_bad_param;
833
834 /*
835 * look up ssrc in srtp_stream list, and process the packet with
836 * the appropriate stream. if we haven't seen this stream before,
837 * there's only one key for this srtp_session, and the cipher
838 * supports key-sharing, then we assume that a new stream using
839 * that key has just started up
840 */
841 stream = srtp_get_stream(ctx, hdr->ssrc);
842 if (stream == NULL) {
843 if (ctx->stream_template != NULL) {
844 stream = ctx->stream_template;
845 debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)",
846 hdr->ssrc);
847
848 /*
849 * set estimated packet index to sequence number from header,
850 * and set delta equal to the same value
851 */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000852#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000853 est = (xtd_seq_num_t) make64(0,ntohs(hdr->seq));
854 delta = low32(est);
855#else
856 est = (xtd_seq_num_t) ntohs(hdr->seq);
David McGrewc4fc00b2006-06-08 18:51:27 +0000857 delta = (int)est;
Cullen Jennings235513a2005-09-21 22:51:36 +0000858#endif
859 } else {
860
861 /*
862 * no stream corresponding to SSRC found, and we don't do
863 * key-sharing, so return an error
864 */
865 return err_status_no_ctx;
866 }
867 } else {
868
869 /* estimate packet index from seq. num. in header */
870 delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
Marcus Sundberg0c324cb2005-10-10 17:23:47 +0000871
872 /* check replay database */
873 status = rdbx_check(&stream->rtp_rdbx, delta);
874 if (status)
875 return status;
Cullen Jennings235513a2005-09-21 22:51:36 +0000876 }
877
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000878#ifdef NO_64BIT_MATH
David McGrewfec49dd2005-09-23 19:34:11 +0000879 debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),low32(est));
880#else
881 debug_print(mod_srtp, "estimated u_packet index: %016llx", est);
882#endif
Cullen Jennings235513a2005-09-21 22:51:36 +0000883
Cullen Jennings235513a2005-09-21 22:51:36 +0000884 /* get tag length from stream */
885 tag_len = auth_get_tag_length(stream->rtp_auth);
886
887 /*
888 * set the cipher's IV properly, depending on whatever cipher we
889 * happen to be using
890 */
891 if (stream->rtp_cipher->type == &aes_icm) {
892
893 /* aes counter mode */
894 iv.v32[0] = 0;
895 iv.v32[1] = hdr->ssrc; /* still in network order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000896#ifdef NO_64BIT_MATH
897 iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
Cullen Jennings235513a2005-09-21 22:51:36 +0000898 low32(est) << 16));
899#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000900 iv.v64[1] = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000901#endif
Derek MacDonald17127da2006-07-12 22:22:08 +0000902 status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtp_cipher->state, &iv);
Cullen Jennings235513a2005-09-21 22:51:36 +0000903 } else {
904
905 /* no particular format - set the iv to the pakcet index */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000906#ifdef NO_64BIT_MATH
Cullen Jennings235513a2005-09-21 22:51:36 +0000907 iv.v32[0] = 0;
908 iv.v32[1] = 0;
909#else
910 iv.v64[0] = 0;
911#endif
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000912 iv.v64[1] = be64_to_cpu(est);
Cullen Jennings235513a2005-09-21 22:51:36 +0000913 status = cipher_set_iv(stream->rtp_cipher, &iv);
914 }
915 if (status)
916 return err_status_cipher_fail;
917
918 /* shift est, put into network byte order */
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000919#ifdef NO_64BIT_MATH
920 est = be64_to_cpu(make64((high32(est) << 16) |
Cullen Jennings235513a2005-09-21 22:51:36 +0000921 (low32(est) >> 16),
922 low32(est) << 16));
923#else
Marcus Sundberge4e34f92005-10-02 20:19:35 +0000924 est = be64_to_cpu(est << 16);
Cullen Jennings235513a2005-09-21 22:51:36 +0000925#endif
926
Marcus Sundberg0c324cb2005-10-10 17:23:47 +0000927 /*
928 * find starting point for decryption and length of data to be
929 * decrypted - the encrypted portion starts after the rtp header
930 * extension, if present; otherwise, it starts after the last csrc,
931 * if any are present
932 *
933 * if we're not providing confidentiality, set enc_start to NULL
934 */
935 if (stream->rtp_services & sec_serv_conf) {
936 enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
David McGrew14829302005-10-10 18:53:19 +0000937 if (hdr->x == 1) {
938 srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
939 enc_start += (ntohs(xtn_hdr->length) + 1);
940 }
David McGrewc4fc00b2006-06-08 18:51:27 +0000941 enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len
942 - ((enc_start - (uint32_t *)hdr) << 2));
Marcus Sundberg0c324cb2005-10-10 17:23:47 +0000943 } else {
944 enc_start = NULL;
945 }
946
Cullen Jennings235513a2005-09-21 22:51:36 +0000947 /*
948 * if we're providing authentication, set the auth_start and auth_tag
949 * pointers to the proper locations; otherwise, set auth_start to NULL
950 * to indicate that no authentication is needed
951 */
952 if (stream->rtp_services & sec_serv_auth) {
953 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000954 auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
Cullen Jennings235513a2005-09-21 22:51:36 +0000955 } else {
956 auth_start = NULL;
957 auth_tag = NULL;
958 }
959
960 /*
961 * if we expect message authentication, run the authentication
962 * function and compare the result with the value of the auth_tag
963 */
964 if (auth_start) {
965
966 /*
967 * if we're using a universal hash, then we need to compute the
968 * keystream prefix for encrypting the universal hash output
969 *
970 * if the keystream prefix length is zero, then we know that
971 * the authenticator isn't using a universal hash function
972 */
973 if (stream->rtp_auth->prefix_len != 0) {
974
975 prefix_len = auth_get_prefix_length(stream->rtp_auth);
976 status = cipher_output(stream->rtp_cipher, tmp_tag, prefix_len);
977 debug_print(mod_srtp, "keystream prefix: %s",
978 octet_string_hex_string(tmp_tag, prefix_len));
979 if (status)
980 return err_status_cipher_fail;
981 }
982
983 /* initialize auth func context */
984 status = auth_start(stream->rtp_auth);
985 if (status) return status;
David McGrewfec49dd2005-09-23 19:34:11 +0000986
Cullen Jennings235513a2005-09-21 22:51:36 +0000987 /* now compute auth function over packet */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000988 status = auth_update(stream->rtp_auth, (uint8_t *)auth_start,
Cullen Jennings235513a2005-09-21 22:51:36 +0000989 *pkt_octet_len - tag_len);
990
991 /* run auth func over ROC, then write tmp tag */
Marcus Sundberg410faaa2005-09-29 12:36:43 +0000992 status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +0000993
994 debug_print(mod_srtp, "computed auth tag: %s",
995 octet_string_hex_string(tmp_tag, tag_len));
996 debug_print(mod_srtp, "packet auth tag: %s",
997 octet_string_hex_string(auth_tag, tag_len));
998 if (status)
999 return err_status_auth_fail;
1000
1001 if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1002 return err_status_auth_fail;
1003 }
1004
Marcus Sundbergfc4d1382005-10-08 18:28:16 +00001005 /*
1006 * update the key usage limit, and check it to make sure that we
1007 * didn't just hit either the soft limit or the hard limit, and call
1008 * the event handler if we hit either.
1009 */
1010 switch(key_limit_update(stream->limit)) {
1011 case key_event_normal:
1012 break;
1013 case key_event_soft_limit:
1014 srtp_handle_event(ctx, stream, event_key_soft_limit);
1015 break;
1016 case key_event_hard_limit:
1017 srtp_handle_event(ctx, stream, event_key_hard_limit);
1018 return err_status_key_expired;
1019 default:
1020 break;
1021 }
1022
Cullen Jennings235513a2005-09-21 22:51:36 +00001023 /* 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
David McGrewa8546882006-01-12 17:56:02 +00001360void
1361crypto_policy_set_aes_cm_128_hmac_sha1_32(crypto_policy_t *p) {
1362
1363 /*
1364 * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1365 *
1366 * note that this crypto policy is intended for SRTP, but not SRTCP
1367 */
1368
1369 p->cipher_type = AES_128_ICM;
1370 p->cipher_key_len = 30; /* 128 bit key, 112 bit salt */
1371 p->auth_type = HMAC_SHA1;
1372 p->auth_key_len = 20; /* 160 bit key */
1373 p->auth_tag_len = 4; /* 32 bit tag */
1374 p->sec_serv = sec_serv_conf_and_auth;
1375
1376}
1377
1378
1379void
1380crypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p) {
1381
1382 /*
1383 * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1384 *
1385 * note that this crypto policy is intended for SRTP, but not SRTCP
1386 */
1387
1388 p->cipher_type = AES_128_ICM;
1389 p->cipher_key_len = 30; /* 128 bit key, 112 bit salt */
1390 p->auth_type = NULL_AUTH;
1391 p->auth_key_len = 0;
1392 p->auth_tag_len = 0;
1393 p->sec_serv = sec_serv_conf;
1394
1395}
1396
1397
1398void
1399crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p) {
1400
1401 /*
1402 * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1403 */
1404
1405 p->cipher_type = NULL_CIPHER;
1406 p->cipher_key_len = 0;
1407 p->auth_type = HMAC_SHA1;
1408 p->auth_key_len = 20;
1409 p->auth_tag_len = 10;
1410 p->sec_serv = sec_serv_auth;
1411
1412}
1413
1414
Cullen Jennings235513a2005-09-21 22:51:36 +00001415/*
1416 * secure rtcp functions
1417 */
1418
1419err_status_t
1420srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
Derek MacDonald17127da2006-07-12 22:22:08 +00001421 srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +00001422 uint32_t *enc_start; /* pointer to start of encrypted portion */
1423 uint32_t *auth_start; /* pointer to start of auth. portion */
1424 uint32_t *trailer; /* pointer to start of trailer */
1425 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001426 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
Cullen Jennings235513a2005-09-21 22:51:36 +00001427 err_status_t status;
1428 int tag_len;
1429 srtp_stream_ctx_t *stream;
1430 int prefix_len;
1431 uint32_t seq_num;
1432
1433 /* we assume the hdr is 32-bit aligned to start */
1434 /*
1435 * look up ssrc in srtp_stream list, and process the packet with
1436 * the appropriate stream. if we haven't seen this stream before,
1437 * there's only one key for this srtp_session, and the cipher
1438 * supports key-sharing, then we assume that a new stream using
1439 * that key has just started up
1440 */
1441 stream = srtp_get_stream(ctx, hdr->ssrc);
1442 if (stream == NULL) {
1443 if (ctx->stream_template != NULL) {
1444 srtp_stream_ctx_t *new_stream;
1445
1446 /* allocate and initialize a new stream */
1447 status = srtp_stream_clone(ctx->stream_template,
1448 hdr->ssrc, &new_stream);
1449 if (status)
1450 return status;
1451
1452 /* add new stream to the head of the stream_list */
1453 new_stream->next = ctx->stream_list;
1454 ctx->stream_list = new_stream;
1455
1456 /* set stream (the pointer used in this function) */
1457 stream = new_stream;
1458 } else {
1459 /* no template stream, so we return an error */
1460 return err_status_no_ctx;
1461 }
1462 }
1463
1464 /*
1465 * verify that stream is for sending traffic - this check will
1466 * detect SSRC collisions, since a stream that appears in both
1467 * srtp_protect() and srtp_unprotect() will fail this test in one of
1468 * those functions.
1469 */
1470 if (stream->direction != dir_srtp_sender) {
1471 if (stream->direction == dir_unknown) {
David McGrewc34f7402006-03-09 21:17:00 +00001472 stream->direction = dir_srtp_sender;
Cullen Jennings235513a2005-09-21 22:51:36 +00001473 } else {
1474 srtp_handle_event(ctx, stream, event_ssrc_collision);
1475 }
1476 }
1477
1478 /* get tag length from stream context */
1479 tag_len = auth_get_tag_length(stream->rtcp_auth);
1480
1481 /*
1482 * set encryption start and encryption length - if we're not
1483 * providing confidentiality, set enc_start to NULL
1484 */
1485 enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1486 enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
1487
1488 /* all of the packet, except the header, gets encrypted */
1489 /* NOTE: hdr->length is not usable - it refers to only the first
1490 RTCP report in the compound packet! */
1491 /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1492 multiples of 32-bits (RFC 3550 6.1) */
1493 trailer = (uint32_t *) ((char *)enc_start + enc_octet_len);
1494
1495 if (stream->rtcp_services & sec_serv_conf) {
1496 *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
1497 } else {
1498 enc_start = NULL;
1499 enc_octet_len = 0;
1500 /* 0 is network-order independant */
1501 *trailer = 0x00000000; /* set encrypt bit */
1502 }
1503
1504 /*
1505 * set the auth_start and auth_tag pointers to the proper locations
1506 * (note that srtpc *always* provides authentication, unlike srtp)
1507 */
1508 /* Note: This would need to change for optional mikey data */
1509 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001510 auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t);
Cullen Jennings235513a2005-09-21 22:51:36 +00001511
1512 /*
1513 * check sequence number for overruns, and copy it into the packet
1514 * if its value isn't too big
1515 */
1516 status = rdb_increment(&stream->rtcp_rdb);
1517 if (status)
1518 return status;
1519 seq_num = rdb_get_value(&stream->rtcp_rdb);
1520 *trailer |= htonl(seq_num);
1521 debug_print(mod_srtp, "srtcp index: %x", seq_num);
1522
1523 /*
1524 * if we're using rindael counter mode, set nonce and seq
1525 */
1526 if (stream->rtcp_cipher->type == &aes_icm) {
1527 v128_t iv;
1528
1529 iv.v32[0] = 0;
1530 iv.v32[1] = hdr->ssrc; /* still in network order! */
1531 iv.v32[2] = htonl(seq_num >> 16);
1532 iv.v32[3] = htonl(seq_num << 16);
Derek MacDonald17127da2006-07-12 22:22:08 +00001533 status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtcp_cipher->state, &iv);
Cullen Jennings235513a2005-09-21 22:51:36 +00001534
1535 } else {
1536 v128_t iv;
1537
1538 /* otherwise, just set the index to seq_num */
1539 iv.v32[0] = 0;
1540 iv.v32[1] = 0;
1541 iv.v32[2] = 0;
1542 iv.v32[3] = htonl(seq_num);
1543 status = cipher_set_iv(stream->rtcp_cipher, &iv);
1544 }
1545 if (status)
1546 return err_status_cipher_fail;
1547
1548 /*
1549 * if we're authenticating using a universal hash, put the keystream
1550 * prefix into the authentication tag
1551 */
1552
1553 /* if auth_start is non-null, then put keystream into tag */
1554 if (auth_start) {
1555
1556 /* put keystream prefix into auth_tag */
1557 prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1558 status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1559
1560 debug_print(mod_srtp, "keystream prefix: %s",
1561 octet_string_hex_string(auth_tag, prefix_len));
1562
1563 if (status)
1564 return err_status_cipher_fail;
1565 }
1566
1567 /* if we're encrypting, exor keystream into the message */
1568 if (enc_start) {
1569 status = cipher_encrypt(stream->rtcp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001570 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +00001571 if (status)
1572 return err_status_cipher_fail;
1573 }
1574
1575 /* initialize auth func context */
1576 auth_start(stream->rtcp_auth);
1577
David McGrew9c70f292006-05-03 19:38:38 +00001578 /*
1579 * run auth func over packet (including trailer), and write the
1580 * result at auth_tag
1581 */
Cullen Jennings235513a2005-09-21 22:51:36 +00001582 status = auth_compute(stream->rtcp_auth,
David McGrew9c70f292006-05-03 19:38:38 +00001583 (uint8_t *)auth_start,
1584 (*pkt_octet_len) + sizeof(srtcp_trailer_t),
1585 auth_tag);
Cullen Jennings235513a2005-09-21 22:51:36 +00001586 debug_print(mod_srtp, "srtcp auth tag: %s",
1587 octet_string_hex_string(auth_tag, tag_len));
1588 if (status)
1589 return err_status_auth_fail;
1590
1591 /* increase the packet length by the length of the auth tag and seq_num*/
1592 *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
1593
1594 return err_status_ok;
1595}
1596
1597
1598err_status_t
1599srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
Derek MacDonald17127da2006-07-12 22:22:08 +00001600 srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
Cullen Jennings235513a2005-09-21 22:51:36 +00001601 uint32_t *enc_start; /* pointer to start of encrypted portion */
1602 uint32_t *auth_start; /* pointer to start of auth. portion */
1603 uint32_t *trailer; /* pointer to start of trailer */
1604 uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001605 uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
1606 uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
Cullen Jennings235513a2005-09-21 22:51:36 +00001607 err_status_t status;
1608 int tag_len;
1609 srtp_stream_ctx_t *stream;
1610 int prefix_len;
1611 uint32_t seq_num;
1612
1613 /* we assume the hdr is 32-bit aligned to start */
1614 /*
1615 * look up ssrc in srtp_stream list, and process the packet with
1616 * the appropriate stream. if we haven't seen this stream before,
1617 * there's only one key for this srtp_session, and the cipher
1618 * supports key-sharing, then we assume that a new stream using
1619 * that key has just started up
1620 */
1621 stream = srtp_get_stream(ctx, hdr->ssrc);
1622 if (stream == NULL) {
1623 if (ctx->stream_template != NULL) {
1624 stream = ctx->stream_template;
1625 debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)",
1626 hdr->ssrc);
1627 } else {
1628 /* no template stream, so we return an error */
1629 return err_status_no_ctx;
1630 }
1631 }
1632
1633 /* get tag length from stream context */
1634 tag_len = auth_get_tag_length(stream->rtcp_auth);
1635
1636 /*
1637 * set encryption start, encryption length, and trailer
1638 */
1639 enc_octet_len = *pkt_octet_len -
1640 (octets_in_rtcp_header + tag_len + sizeof(srtcp_trailer_t));
1641 /* index & E (encryption) bit follow normal data. hdr->len
1642 is the number of words (32-bit) in the normal packet minus 1 */
1643 /* This should point trailer to the word past the end of the
1644 normal data. */
1645 /* This would need to be modified for optional mikey data */
1646 /*
1647 * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1648 * multiples of 32-bits (RFC 3550 6.1)
1649 */
1650 trailer = (uint32_t *) ((char *) hdr +
1651 *pkt_octet_len -(tag_len + sizeof(srtcp_trailer_t)));
1652 if (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) {
1653 enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1654 } else {
1655 enc_octet_len = 0;
1656 enc_start = NULL; /* this indicates that there's no encryption */
1657 }
1658
1659 /*
1660 * set the auth_start and auth_tag pointers to the proper locations
1661 * (note that srtcp *always* uses authentication, unlike srtp)
1662 */
1663 auth_start = (uint32_t *)hdr;
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001664 auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
Cullen Jennings235513a2005-09-21 22:51:36 +00001665
1666 /*
1667 * check the sequence number for replays
1668 */
1669 /* this is easier than dealing with bitfield access */
1670 seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK;
David McGrew9c70f292006-05-03 19:38:38 +00001671 debug_print(mod_srtp, "srtcp index: %x", seq_num);
Cullen Jennings235513a2005-09-21 22:51:36 +00001672 status = rdb_check(&stream->rtcp_rdb, seq_num);
1673 if (status)
1674 return status;
Cullen Jennings235513a2005-09-21 22:51:36 +00001675
1676 /*
1677 * if we're using aes counter mode, set nonce and seq
1678 */
1679 if (stream->rtcp_cipher->type == &aes_icm) {
1680 v128_t iv;
1681
1682 iv.v32[0] = 0;
1683 iv.v32[1] = hdr->ssrc; /* still in network order! */
1684 iv.v32[2] = htonl(seq_num >> 16);
1685 iv.v32[3] = htonl(seq_num << 16);
Derek MacDonald17127da2006-07-12 22:22:08 +00001686 status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtcp_cipher->state, &iv);
Cullen Jennings235513a2005-09-21 22:51:36 +00001687
1688 } else {
1689 v128_t iv;
1690
1691 /* otherwise, just set the index to seq_num */
1692 iv.v32[0] = 0;
1693 iv.v32[1] = 0;
1694 iv.v32[2] = 0;
1695 iv.v32[3] = htonl(seq_num);
1696 status = cipher_set_iv(stream->rtcp_cipher, &iv);
1697
1698 }
1699 if (status)
1700 return err_status_cipher_fail;
1701
1702 /* initialize auth func context */
1703 auth_start(stream->rtcp_auth);
1704
1705 /* run auth func over packet, put result into tmp_tag */
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001706 status = auth_compute(stream->rtcp_auth, (uint8_t *)auth_start,
David McGrew9c70f292006-05-03 19:38:38 +00001707 *pkt_octet_len - tag_len,
Cullen Jennings235513a2005-09-21 22:51:36 +00001708 tmp_tag);
1709 debug_print(mod_srtp, "srtcp computed tag: %s",
1710 octet_string_hex_string(tmp_tag, tag_len));
1711 if (status)
1712 return err_status_auth_fail;
1713
1714 /* compare the tag just computed with the one in the packet */
1715 debug_print(mod_srtp, "srtcp tag from packet: %s",
1716 octet_string_hex_string(auth_tag, tag_len));
1717 if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1718 return err_status_auth_fail;
1719
1720 /*
1721 * if we're authenticating using a universal hash, put the keystream
1722 * prefix into the authentication tag
1723 */
1724 prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1725 if (prefix_len) {
1726 status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1727 debug_print(mod_srtp, "keystream prefix: %s",
1728 octet_string_hex_string(auth_tag, prefix_len));
1729 if (status)
1730 return err_status_cipher_fail;
1731 }
1732
1733 /* if we're decrypting, exor keystream into the message */
1734 if (enc_start) {
1735 status = cipher_encrypt(stream->rtcp_cipher,
Marcus Sundberg410faaa2005-09-29 12:36:43 +00001736 (uint8_t *)enc_start, &enc_octet_len);
Cullen Jennings235513a2005-09-21 22:51:36 +00001737 if (status)
1738 return err_status_cipher_fail;
1739 }
1740
1741 /* decrease the packet length by the length of the auth tag and seq_num*/
1742 *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));
1743
1744 /*
1745 * verify that stream is for received traffic - this check will
1746 * detect SSRC collisions, since a stream that appears in both
1747 * srtp_protect() and srtp_unprotect() will fail this test in one of
1748 * those functions.
1749 *
1750 * we do this check *after* the authentication check, so that the
1751 * latter check will catch any attempts to fool us into thinking
1752 * that we've got a collision
1753 */
1754 if (stream->direction != dir_srtp_receiver) {
1755 if (stream->direction == dir_unknown) {
1756 stream->direction = dir_srtp_receiver;
1757 } else {
1758 srtp_handle_event(ctx, stream, event_ssrc_collision);
1759 }
1760 }
1761
1762 /*
1763 * if the stream is a 'provisional' one, in which the template context
1764 * is used, then we need to allocate a new stream at this point, since
1765 * the authentication passed
1766 */
1767 if (stream == ctx->stream_template) {
1768 srtp_stream_ctx_t *new_stream;
1769
1770 /*
1771 * allocate and initialize a new stream
1772 *
1773 * note that we indicate failure if we can't allocate the new
1774 * stream, and some implementations will want to not return
1775 * failure here
1776 */
1777 status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
1778 if (status)
1779 return status;
1780
1781 /* add new stream to the head of the stream_list */
1782 new_stream->next = ctx->stream_list;
1783 ctx->stream_list = new_stream;
1784
1785 /* set stream (the pointer used in this function) */
1786 stream = new_stream;
1787 }
1788
1789 /* we've passed the authentication check, so add seq_num to the rdb */
1790 rdb_add_index(&stream->rtcp_rdb, seq_num);
1791
1792
1793 return err_status_ok;
1794}
David McGrew0cb86ee2006-07-07 15:46:57 +00001795
1796
1797
1798/*
1799 * dtls keying for srtp
1800 */
1801
1802err_status_t
1803crypto_policy_set_from_profile_for_rtp(crypto_policy_t *policy,
1804 srtp_profile_t profile) {
1805
1806 /* set SRTP policy from the SRTP profile in the key set */
1807 switch(profile) {
1808 case srtp_profile_aes128_cm_sha1_80:
1809 crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1810 crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1811 break;
1812 case srtp_profile_aes128_cm_sha1_32:
1813 crypto_policy_set_aes_cm_128_hmac_sha1_32(policy);
1814 crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1815 break;
1816 case srtp_profile_null_sha1_80:
1817 crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1818 crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1819 break;
1820 /* the following profiles are not (yet) supported */
1821 case srtp_profile_null_sha1_32:
1822 case srtp_profile_aes256_cm_sha1_80:
1823 case srtp_profile_aes256_cm_sha1_32:
1824 default:
1825 return err_status_bad_param;
1826 }
1827
1828 return err_status_ok;
1829}
1830
1831err_status_t
1832crypto_policy_set_from_profile_for_rtcp(crypto_policy_t *policy,
1833 srtp_profile_t profile) {
1834
1835 /* set SRTP policy from the SRTP profile in the key set */
1836 switch(profile) {
1837 case srtp_profile_aes128_cm_sha1_80:
1838 crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1839 break;
1840 case srtp_profile_aes128_cm_sha1_32:
1841 crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1842 break;
1843 case srtp_profile_null_sha1_80:
1844 crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1845 break;
1846 /* the following profiles are not (yet) supported */
1847 case srtp_profile_null_sha1_32:
1848 case srtp_profile_aes256_cm_sha1_80:
1849 case srtp_profile_aes256_cm_sha1_32:
1850 default:
1851 return err_status_bad_param;
1852 }
1853
1854 return err_status_ok;
1855}
1856
1857void
1858append_salt_to_key(uint8_t *key, unsigned int bytes_in_key,
1859 uint8_t *salt, unsigned int bytes_in_salt) {
1860
1861 memcpy(key + bytes_in_key, salt, bytes_in_salt);
1862
1863}
1864
1865unsigned int
1866srtp_profile_get_master_key_length(srtp_profile_t profile) {
1867
1868 switch(profile) {
1869 case srtp_profile_aes128_cm_sha1_80:
1870 return 16;
1871 break;
1872 case srtp_profile_aes128_cm_sha1_32:
1873 return 16;
1874 break;
1875 case srtp_profile_null_sha1_80:
1876 return 16;
1877 break;
1878 /* the following profiles are not (yet) supported */
1879 case srtp_profile_null_sha1_32:
1880 case srtp_profile_aes256_cm_sha1_80:
1881 case srtp_profile_aes256_cm_sha1_32:
1882 default:
1883 return 0; /* indicate error by returning a zero */
1884 }
1885}
1886
1887unsigned int
1888srtp_profile_get_master_salt_length(srtp_profile_t profile) {
1889
1890 switch(profile) {
1891 case srtp_profile_aes128_cm_sha1_80:
1892 return 14;
1893 break;
1894 case srtp_profile_aes128_cm_sha1_32:
1895 return 14;
1896 break;
1897 case srtp_profile_null_sha1_80:
1898 return 14;
1899 break;
1900 /* the following profiles are not (yet) supported */
1901 case srtp_profile_null_sha1_32:
1902 case srtp_profile_aes256_cm_sha1_80:
1903 case srtp_profile_aes256_cm_sha1_32:
1904 default:
1905 return 0; /* indicate error by returning a zero */
1906 }
1907}