1386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
2386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp.c
3386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
4386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the secure real-time transport protocol
5386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
6386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * David A. McGrew
7386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Cisco Systems, Inc.
8386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
9386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
10386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
11386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Copyright (c) 2001-2006, Cisco Systems, Inc.
12386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * All rights reserved.
13386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
14386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Redistribution and use in source and binary forms, with or without
15386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * modification, are permitted provided that the following conditions
16386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * are met:
17386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
18386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Redistributions of source code must retain the above copyright
19386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   notice, this list of conditions and the following disclaimer.
20386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
21386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Redistributions in binary form must reproduce the above
22386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   copyright notice, this list of conditions and the following
23386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   disclaimer in the documentation and/or other materials provided
24386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   with the distribution.
25386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
26386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   Neither the name of the Cisco Systems, Inc. nor the names of its
27386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   contributors may be used to endorse or promote products derived
28386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *   from this software without specific prior written permission.
29386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
30386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * OF THE POSSIBILITY OF SUCH DAMAGE.
42386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
43386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
44386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
45386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
46386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "srtp.h"
47386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "ekt.h"             /* for SRTP Encrypted Key Transport */
48386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "aes_icm.h"         /* aes_icm is used in the KDF  */
49386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "alloc.h"           /* for crypto_alloc()          */
50386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
51386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifndef SRTP_KERNEL
52386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari# include <limits.h>
53386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari# ifdef HAVE_NETINET_IN_H
54386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#  include <netinet/in.h>
55386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari# elif defined(HAVE_WINSOCK2_H)
56386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#  include <winsock2.h>
57386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari# endif
58386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif /* ! SRTP_KERNEL */
59386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
60386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
61386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariextern cipher_type_t aes_icm;
62386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariextern auth_type_t   tmmhv2;
63386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
64386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* the debug module for srtp */
65386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
66386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaridebug_module_t mod_srtp = {
67386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  0,                  /* debugging is off by default */
68386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  "srtp"              /* printable name for module   */
69386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari};
70386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
71386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define octets_in_rtp_header   12
72386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define uint32s_in_rtp_header  3
73386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define octets_in_rtcp_header  8
74386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define uint32s_in_rtcp_header 2
75386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
76386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
77386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
78386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
79386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  const srtp_policy_t *p) {
80386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *str;
81386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t stat;
82386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
83386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
84386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * This function allocates the stream context, rtp and rtcp ciphers
85386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * and auth functions, and key limit structure.  If there is a
86386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * failure during allocation, we free all previously allocated
87386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * memory and return a failure code.  The code could probably
88386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * be improved, but it works and should be clear.
89386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
90386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
91386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate srtp stream and set str_ptr */
92386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
93386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (str == NULL)
94386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_alloc_fail;
95386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *str_ptr = str;
96386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
97386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate cipher */
98386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = crypto_kernel_alloc_cipher(p->rtp.cipher_type,
99386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    &str->rtp_cipher,
100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    p->rtp.cipher_key_len);
101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_rtp_cipher_alloc;
103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate auth function */
106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = crypto_kernel_alloc_auth(p->rtp.auth_type,
107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  &str->rtp_auth,
108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  p->rtp.auth_key_len,
109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  p->rtp.auth_tag_len);
110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_rtp_auth_alloc;
113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate key limit structure */
116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->limit = (key_limit_ctx_t*) crypto_alloc(sizeof(key_limit_ctx_t));
117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (str->limit == NULL) {
118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stat = err_status_alloc_fail;
119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_limit_alloc;
120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * ...and now the RTCP-specific initialization - first, allocate
124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the cipher
125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = crypto_kernel_alloc_cipher(p->rtcp.cipher_type,
127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    &str->rtcp_cipher,
128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    p->rtcp.cipher_key_len);
129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_rtcp_cipher_alloc;
131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate auth function */
134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = crypto_kernel_alloc_auth(p->rtcp.auth_type,
135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  &str->rtcp_auth,
136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  p->rtcp.auth_key_len,
137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  p->rtcp.auth_tag_len);
138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_rtcp_auth_alloc;
140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate ekt data associated with stream */
143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = ekt_alloc(&str->ekt, p->ekt);
144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    goto err_ekt_alloc;
146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_ekt_alloc:
151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_dealloc(str->rtcp_auth);
152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_rtcp_auth_alloc:
153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_dealloc(str->rtcp_cipher);
154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_rtcp_cipher_alloc:
155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  crypto_free(str->limit);
156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_limit_alloc:
157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_dealloc(str->rtp_auth);
158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_rtp_auth_alloc:
159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  cipher_dealloc(str->rtp_cipher);
160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_rtp_cipher_alloc:
161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  crypto_free(str);
162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return stat;
163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_dealloc(srtp_stream_ctx_t *stream,
167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari                    srtp_stream_ctx_t *stream_template) {
168386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
169386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
170386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
171386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * we use a conservative deallocation strategy - if any deallocation
172386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * fails, then we report that fact without trying to deallocate
173386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * anything else
174386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
175386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
176386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate cipher, if it is not the same as that in template */
177386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!stream_template || stream->rtp_cipher != stream_template->rtp_cipher) {
178386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_dealloc(stream->rtp_cipher);
179386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
180386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
181386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
182386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
183386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate auth function, if it is not the same as that in template */
184386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!stream_template || stream->rtp_auth != stream_template->rtp_auth) {
185386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_dealloc(stream->rtp_auth);
186386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
187386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
188386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
189386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
190386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate key usage limit, if it is not the same as that in template */
191386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!stream_template || stream->limit != stream_template->limit) {
192386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_free(stream->limit);
193386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
194386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
195386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
196386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * deallocate rtcp cipher, if it is not the same as that in
197386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * template
198386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
199386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!stream_template || stream->rtcp_cipher != stream_template->rtcp_cipher) {
200386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_dealloc(stream->rtcp_cipher);
201386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
202386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
203386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
204386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
205386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
206386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * deallocate rtcp auth function, if it is not the same as that in
207386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * template
208386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
209386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (!stream_template || stream->rtcp_auth != stream_template->rtcp_auth) {
210386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_dealloc(stream->rtcp_auth);
211386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
212386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
213386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
214386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
215386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* DAM - need to deallocate EKT here */
216386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
217386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate srtp stream context */
218386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  crypto_free(stream);
219386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
220386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
221386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
222386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
223386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
224386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
225386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_stream_clone(stream_template, new) allocates a new stream and
226386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * initializes it using the cipher and auth of the stream_template
227386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
228386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the only unique data in a cloned stream is the replay database and
229386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the SSRC
230386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
231386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
232386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
233386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_clone(const srtp_stream_ctx_t *stream_template,
234386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  uint32_t ssrc,
235386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  srtp_stream_ctx_t **str_ptr) {
236386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
237386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *str;
238386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
239386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ssrc);
240386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
241386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate srtp stream and set str_ptr */
242386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));
243386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (str == NULL)
244386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_alloc_fail;
245386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *str_ptr = str;
246386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
247386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set cipher and auth pointers to those of the template */
248386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtp_cipher  = stream_template->rtp_cipher;
249386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtp_auth    = stream_template->rtp_auth;
250386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtcp_cipher = stream_template->rtcp_cipher;
251386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtcp_auth   = stream_template->rtcp_auth;
252386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
253386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set key limit to point to that of the template */
254386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = key_limit_clone(stream_template->limit, &str->limit);
255386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
256386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
257386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
258386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize replay databases */
259386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = rdbx_init(&str->rtp_rdbx,
260386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		     rdbx_get_window_size(&stream_template->rtp_rdbx));
261386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
262386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
263386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rdb_init(&str->rtcp_rdb);
264386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->allow_repeat_tx = stream_template->allow_repeat_tx;
265386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
266386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set ssrc to that provided */
267386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->ssrc = ssrc;
268386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
269386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set direction and security services */
270386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->direction     = stream_template->direction;
271386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtp_services  = stream_template->rtp_services;
272386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->rtcp_services = stream_template->rtcp_services;
273386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
274386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set pointer to EKT data associated with stream */
275386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->ekt = stream_template->ekt;
276386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
277386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* defensive coding */
278386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  str->next = NULL;
279386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
280386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
281386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
282386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
283386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
284386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
285386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * key derivation functions, internal to libSRTP
286386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
287386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_kdf_t is a key derivation context
288386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
289386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_kdf_init(&kdf, k) initializes kdf with the key k
290386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
291386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key
292386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * corresponding to label l and puts it into kl; the length
293386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * of the key in octets is provided as keylen.  this function
294386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * should be called once for each subkey that is derived.
295386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
296386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_kdf_clear(&kdf) zeroizes the kdf state
297386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
298386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
299386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaritypedef enum {
300386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtp_encryption  = 0x00,
301386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtp_msg_auth    = 0x01,
302386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtp_salt        = 0x02,
303386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtcp_encryption = 0x03,
304386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtcp_msg_auth   = 0x04,
305386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  label_rtcp_salt       = 0x05
306386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} srtp_prf_label;
307386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
308386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
309386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
310386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_kdf_t represents a key derivation function.  The SRTP
311386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * default KDF is the only one implemented at present.
312386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
313386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
314386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaritypedef struct {
315386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  aes_icm_ctx_t c;    /* cipher used for key derivation  */
316386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} srtp_kdf_t;
317386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
318386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
319386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_kdf_init(srtp_kdf_t *kdf, const uint8_t key[30]) {
320386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
321386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  aes_icm_context_init(&kdf->c, key);
322386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
323386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
324386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
325386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
326386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
327386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label,
328386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  uint8_t *key, int length) {
329386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
330386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  v128_t nonce;
331386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
332386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set eigth octet of nonce to <label>, set the rest of it to zero */
333386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  v128_set_to_zero(&nonce);
334386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  nonce.v8[7] = label;
335386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
336386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  aes_icm_set_iv(&kdf->c, &nonce);
337386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
338386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* generate keystream output */
339386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  aes_icm_output(&kdf->c, key, length);
340386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
341386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
342386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
343386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
344386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
345386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_kdf_clear(srtp_kdf_t *kdf) {
346386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
347386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* zeroize aes context */
348386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  octet_string_set_to_zero((uint8_t *)kdf, sizeof(srtp_kdf_t));
349386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
350386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
351386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
352386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
353386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
354386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *  end of key derivation functions
355386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
356386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
357386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define MAX_SRTP_KEY_LEN 256
358386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
359386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
360386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
361386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
362386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t stat;
363386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_t kdf;
364386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t tmp_key[MAX_SRTP_KEY_LEN];
365386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
366386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize KDF state     */
367386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_init(&kdf, (const uint8_t *)key);
368386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
369386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* generate encryption key  */
370386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_generate(&kdf, label_rtp_encryption,
371386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		    tmp_key, cipher_get_key_length(srtp->rtp_cipher));
372386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
373386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if the cipher in the srtp context is aes_icm, then we need
374386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * to generate the salt value
375386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
376386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (srtp->rtp_cipher->type == &aes_icm) {
377386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* FIX!!! this is really the cipher key length; rest is salt */
378386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int base_key_len = 16;
379386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;
380386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
381386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "found aes_icm, generating salt", NULL);
382386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
383386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* generate encryption salt, put after encryption key */
384386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_kdf_generate(&kdf, label_rtp_salt,
385386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		      tmp_key + base_key_len, salt_len);
386386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
387386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "cipher key: %s",
388386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(tmp_key,
389386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		      cipher_get_key_length(srtp->rtp_cipher)));
390386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
391386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize cipher */
392386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
393386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
394386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* zeroize temp buffer */
395386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
396386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_init_fail;
397386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
398386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
399386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* generate authentication key */
400386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_generate(&kdf, label_rtp_msg_auth,
401386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		    tmp_key, auth_get_key_length(srtp->rtp_auth));
402386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "auth key:   %s",
403386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(tmp_key,
404386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				      auth_get_key_length(srtp->rtp_auth)));
405386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
406386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize auth function */
407386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = auth_init(srtp->rtp_auth, tmp_key);
408386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
409386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* zeroize temp buffer */
410386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
411386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_init_fail;
412386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
413386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
414386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
415386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * ...now initialize SRTCP keys
416386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
417386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
418386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* generate encryption key  */
419386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_generate(&kdf, label_rtcp_encryption,
420386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		    tmp_key, cipher_get_key_length(srtp->rtcp_cipher));
421386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
422386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if the cipher in the srtp context is aes_icm, then we need
423386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * to generate the salt value
424386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
425386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (srtp->rtcp_cipher->type == &aes_icm) {
426386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* FIX!!! this is really the cipher key length; rest is salt */
427386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int base_key_len = 16;
428386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    int salt_len = cipher_get_key_length(srtp->rtcp_cipher) - base_key_len;
429386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
430386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);
431386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
432386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* generate encryption salt, put after encryption key */
433386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_kdf_generate(&kdf, label_rtcp_salt,
434386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		      tmp_key + base_key_len, salt_len);
435386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
436386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "rtcp cipher key: %s",
437386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(tmp_key,
438386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		   cipher_get_key_length(srtp->rtcp_cipher)));
439386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
440386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize cipher */
441386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);
442386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
443386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* zeroize temp buffer */
444386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
445386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_init_fail;
446386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
447386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
448386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* generate authentication key */
449386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
450386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		    tmp_key, auth_get_key_length(srtp->rtcp_auth));
451386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "rtcp auth key:   %s",
452386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(tmp_key,
453386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		     auth_get_key_length(srtp->rtcp_auth)));
454386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
455386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize auth function */
456386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stat = auth_init(srtp->rtcp_auth, tmp_key);
457386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stat) {
458386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* zeroize temp buffer */
459386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
460386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_init_fail;
461386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
462386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
463386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* clear memory then return */
464386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_kdf_clear(&kdf);
465386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
466386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
467386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
468386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
469386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
470386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
471386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_init(srtp_stream_ctx_t *srtp,
472386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  const srtp_policy_t *p) {
473386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t err;
474386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
475386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)",
476386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	       p->ssrc.value);
477386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
478386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* initialize replay database */
479386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   err = rdbx_init(&srtp->rtp_rdbx, p->window_size);
480386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (err) return err;
481386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
482386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* initialize key limit to maximum value */
483386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
484386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari{
485386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   uint64_t temp;
486386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   temp = make64(UINT_MAX,UINT_MAX);
487386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   key_limit_set(srtp->limit, temp);
488386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
489386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
490386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   key_limit_set(srtp->limit, 0xffffffffffffLL);
491386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
492386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
493386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* set the SSRC value */
494386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp->ssrc = htonl(p->ssrc.value);
495386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
496386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* set the security service flags */
497386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp->rtp_services  = p->rtp.sec_serv;
498386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp->rtcp_services = p->rtcp.sec_serv;
499386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
500386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
501386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * set direction to unknown - this flag gets checked in srtp_protect(),
502386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and
503386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * gets set appropriately if it is set to unknown.
504386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
505386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp->direction = dir_unknown;
506386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
507386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* initialize SRTCP replay database */
508386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   rdb_init(&srtp->rtcp_rdb);
509386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
510386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* initialize allow_repeat_tx */
511386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp->allow_repeat_tx = p->allow_repeat_tx;
512386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
513386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* DAM - no RTCP key limit at present */
514386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
515386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* initialize keys */
516386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   err = srtp_stream_init_keys(srtp, p->key);
517386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (err) {
518386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     rdbx_uninit(&srtp->rtp_rdbx);
519386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     return err;
520386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
521386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
522386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
523386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if EKT is in use, then initialize the EKT data associated with
524386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * the stream
525386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
526386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   err = ekt_stream_init_from_policy(srtp->ekt, p->ekt);
527386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (err) {
528386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     rdbx_uninit(&srtp->rtp_rdbx);
529386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     return err;
530386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
531386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
532386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   return err_status_ok;
533386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
534386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
535386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
536386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_uninit(srtp_stream_ctx_t *srtp) {
537386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return rdbx_uninit(&srtp->rtp_rdbx);
538386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
539386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
540386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
541386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /*
542386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * srtp_event_reporter is an event handler function that merely
543386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * reports the events that are reported by the callbacks
544386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  */
545386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
546386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari void
547386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari srtp_event_reporter(srtp_event_data_t *data) {
548386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
549386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   err_report(err_level_warning, "srtp: in stream 0x%x: ",
550386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      data->stream->ssrc);
551386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
552386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   switch(data->event) {
553386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   case event_ssrc_collision:
554386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     err_report(err_level_warning, "\tSSRC collision\n");
555386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     break;
556386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   case event_key_soft_limit:
557386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     err_report(err_level_warning, "\tkey usage soft limit reached\n");
558386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     break;
559386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   case event_key_hard_limit:
560386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     err_report(err_level_warning, "\tkey usage hard limit reached\n");
561386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     break;
562386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   case event_packet_index_limit:
563386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     err_report(err_level_warning, "\tpacket index limit reached\n");
564386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     break;
565386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   default:
566386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     err_report(err_level_warning, "\tunknown event reported to handler\n");
567386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
568386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari }
569386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
570386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /*
571386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * srtp_event_handler is a global variable holding a pointer to the
572386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * event handler function; this function is called for any unexpected
573386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * event that needs to be handled out of the SRTP data path.  see
574386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * srtp_event_t in srtp.h for more info
575386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *
576386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * it is okay to set srtp_event_handler to NULL, but we set
577386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  * it to the srtp_event_reporter.
578386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  */
579386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
580386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter;
581386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
582386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err_status_t
583386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari srtp_install_event_handler(srtp_event_handler_func_t func) {
584386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
585386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
586386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * note that we accept NULL arguments intentionally - calling this
587386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * function with a NULL arguments removes an event handler that's
588386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * been previously installed
589386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
590386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
591386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* set global event handling function */
592386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp_event_handler = func;
593386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   return err_status_ok;
594386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari }
595386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
596386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err_status_t
597386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) {
598386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
599386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   uint32_t *enc_start;        /* pointer to start of encrypted portion  */
600386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   uint32_t *auth_start;       /* pointer to start of auth. portion      */
601386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   unsigned enc_octet_len = 0; /* number of octets in encrypted portion  */
602386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   xtd_seq_num_t est;          /* estimated xtd_seq_num_t of *hdr        */
603386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   int delta;                  /* delta of local pkt idx and that in hdr */
604386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   uint8_t *auth_tag = NULL;   /* location of auth_tag within packet     */
605386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   err_status_t status;
606386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   int tag_len;
607386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   srtp_stream_ctx_t *stream;
608386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   int prefix_len;
609386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
610386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   debug_print(mod_srtp, "function srtp_protect", NULL);
611386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
612386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we assume the hdr is 32-bit aligned to start */
613386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
614386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* check the packet length - it must at least contain a full header */
615386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (*pkt_octet_len < octets_in_rtp_header)
616386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     return err_status_bad_param;
617386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
618386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
619386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * look up ssrc in srtp_stream list, and process the packet with
620386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * the appropriate stream.  if we haven't seen this stream before,
621386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * there's a template key for this srtp_session, and the cipher
622386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * supports key-sharing, then we assume that a new stream using
623386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * that key has just started up
624386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
625386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   stream = srtp_get_stream(ctx, hdr->ssrc);
626386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (stream == NULL) {
627386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     if (ctx->stream_template != NULL) {
628386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       srtp_stream_ctx_t *new_stream;
629386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
630386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       /* allocate and initialize a new stream */
631386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       status = srtp_stream_clone(ctx->stream_template,
632386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				  hdr->ssrc, &new_stream);
633386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       if (status)
634386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 return status;
635386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
636386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       /* add new stream to the head of the stream_list */
637386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       new_stream->next = ctx->stream_list;
638386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       ctx->stream_list = new_stream;
639386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
640386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       /* set direction to outbound */
641386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       new_stream->direction = dir_srtp_sender;
642386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
643386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       /* set stream (the pointer used in this function) */
644386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       stream = new_stream;
645386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     } else {
646386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       /* no template stream, so we return an error */
647386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       return err_status_no_ctx;
648386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     }
649386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
650386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
651386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
652386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * verify that stream is for sending traffic - this check will
653386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * detect SSRC collisions, since a stream that appears in both
654386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * srtp_protect() and srtp_unprotect() will fail this test in one of
655386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * those functions.
656386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
657386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (stream->direction != dir_srtp_sender) {
658386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     if (stream->direction == dir_unknown) {
659386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       stream->direction = dir_srtp_sender;
660386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     } else {
661386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       srtp_handle_event(ctx, stream, event_ssrc_collision);
662386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     }
663386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
664386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
665386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
666386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * update the key usage limit, and check it to make sure that we
667386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * didn't just hit either the soft limit or the hard limit, and call
668386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the event handler if we hit either.
669386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
670386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(key_limit_update(stream->limit)) {
671386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_normal:
672386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
673386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_soft_limit:
674386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_handle_event(ctx, stream, event_key_soft_limit);
675386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
676386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_hard_limit:
677386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_handle_event(ctx, stream, event_key_hard_limit);
678386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return err_status_key_expired;
679386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
680386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
681386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
682386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
683386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* get tag length from stream */
684386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   tag_len = auth_get_tag_length(stream->rtp_auth);
685386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
686386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
687386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * find starting point for encryption and length of data to be
688386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * encrypted - the encrypted portion starts after the rtp header
689386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * extension, if present; otherwise, it starts after the last csrc,
690386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if any are present
691386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    *
692386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if we're not providing confidentiality, set enc_start to NULL
693386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
694386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (stream->rtp_services & sec_serv_conf) {
695386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
696386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     if (hdr->x == 1) {
697386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
698386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       enc_start += (ntohs(xtn_hdr->length) + 1);
699386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     }
700386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     enc_octet_len = (unsigned int)(*pkt_octet_len
701386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				    - ((enc_start - (uint32_t *)hdr) << 2));
702386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   } else {
703386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     enc_start = NULL;
704386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
705386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
706386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
707386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if we're providing authentication, set the auth_start and auth_tag
708386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * pointers to the proper locations; otherwise, set auth_start to NULL
709386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * to indicate that no authentication is needed
710386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
711386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (stream->rtp_services & sec_serv_auth) {
712386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     auth_start = (uint32_t *)hdr;
713386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     auth_tag = (uint8_t *)hdr + *pkt_octet_len;
714386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   } else {
715386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     auth_start = NULL;
716386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     auth_tag = NULL;
717386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
718386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
719386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
720386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * estimate the packet index using the start of the replay window
721386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * and the sequence number from the header
722386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
723386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
724386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   status = rdbx_check(&stream->rtp_rdbx, delta);
725386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (status) {
726386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     if (status != err_status_replay_fail || !stream->allow_repeat_tx)
727386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       return status;  /* we've been asked to reuse an index */
728386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
729386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   else
730386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     rdbx_add_index(&stream->rtp_rdbx, delta);
731386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
732386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
733386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   debug_print2(mod_srtp, "estimated packet index: %08x%08x",
734386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		high32(est),low32(est));
735386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
736386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   debug_print(mod_srtp, "estimated packet index: %016llx", est);
737386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
738386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
739386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
740386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if we're using rindael counter mode, set nonce and seq
741386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
742386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (stream->rtp_cipher->type == &aes_icm) {
743386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     v128_t iv;
744386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
745386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v32[0] = 0;
746386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v32[1] = hdr->ssrc;
747386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
748386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
749386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari								 low32(est) << 16));
750386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
751386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v64[1] = be64_to_cpu(est << 16);
752386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
753386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     status = cipher_set_iv(stream->rtp_cipher, &iv);
754386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
755386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   } else {
756386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     v128_t iv;
757386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
758386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     /* otherwise, set the index to est */
759386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
760386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v32[0] = 0;
761386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v32[1] = 0;
762386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
763386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v64[0] = 0;
764386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
765386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     iv.v64[1] = be64_to_cpu(est);
766386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     status = cipher_set_iv(stream->rtp_cipher, &iv);
767386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   }
768386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (status)
769386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     return err_status_cipher_fail;
770386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
771386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /* shift est, put into network byte order */
772386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
773386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   est = be64_to_cpu(make64((high32(est) << 16) |
774386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari						 (low32(est) >> 16),
775386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari						 low32(est) << 16));
776386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
777386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   est = be64_to_cpu(est << 16);
778386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
779386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
780386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   /*
781386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * if we're authenticating using a universal hash, put the keystream
782386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    * prefix into the authentication tag
783386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    */
784386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   if (auth_start) {
785386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
786386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    prefix_len = auth_get_prefix_length(stream->rtp_auth);
787386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (prefix_len) {
788386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      status = cipher_output(stream->rtp_cipher, auth_tag, prefix_len);
789386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (status)
790386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return err_status_cipher_fail;
791386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      debug_print(mod_srtp, "keystream prefix: %s",
792386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  octet_string_hex_string(auth_tag, prefix_len));
793386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
794386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
795386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
796386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* if we're encrypting, exor keystream into the message */
797386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (enc_start) {
798386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_encrypt(stream->rtp_cipher,
799386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			    (uint8_t *)enc_start, &enc_octet_len);
800386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
801386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
802386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
803386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
804386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
805386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *  if we're authenticating, run authentication function and put result
806386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *  into the auth_tag
807386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
808386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (auth_start) {
809386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
810386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* initialize auth func context */
811386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_start(stream->rtp_auth);
812386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status) return status;
813386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
814386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* run auth func over packet */
815386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_update(stream->rtp_auth,
816386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			 (uint8_t *)auth_start, *pkt_octet_len);
817386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status) return status;
818386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
819386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* run auth func over ROC, put result into auth_tag */
820386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "estimated packet index: %016llx", est);
821386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, auth_tag);
822386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "srtp auth tag:    %s",
823386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		octet_string_hex_string(auth_tag, tag_len));
824386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
825386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_auth_fail;
826386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
827386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
828386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
829386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (auth_tag) {
830386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
831386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* increase the packet length by the length of the auth tag */
832386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    *pkt_octet_len += tag_len;
833386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
834386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
835386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
836386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
837386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
838386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
839386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
840386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
841386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
842386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *enc_start;      /* pointer to start of encrypted portion  */
843386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *auth_start;     /* pointer to start of auth. portion      */
844386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
845386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
846386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  xtd_seq_num_t est;        /* estimated xtd_seq_num_t of *hdr        */
847386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int delta;                /* delta of local pkt idx and that in hdr */
848386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  v128_t iv;
849386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
850386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream;
851386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
852386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int tag_len, prefix_len;
853386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
854386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "function srtp_unprotect", NULL);
855386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
856386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we assume the hdr is 32-bit aligned to start */
857386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
858386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* check the packet length - it must at least contain a full header */
859386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (*pkt_octet_len < octets_in_rtp_header)
860386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
861386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
862386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
863386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * look up ssrc in srtp_stream list, and process the packet with
864386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the appropriate stream.  if we haven't seen this stream before,
865386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * there's only one key for this srtp_session, and the cipher
866386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * supports key-sharing, then we assume that a new stream using
867386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * that key has just started up
868386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
869386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stream = srtp_get_stream(ctx, hdr->ssrc);
870386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == NULL) {
871386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (ctx->stream_template != NULL) {
872386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream = ctx->stream_template;
873386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)",
874386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  hdr->ssrc);
875386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
876386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /*
877386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * set estimated packet index to sequence number from header,
878386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * and set delta equal to the same value
879386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       */
880386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
881386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      est = (xtd_seq_num_t) make64(0,ntohs(hdr->seq));
882386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      delta = low32(est);
883386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
884386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      est = (xtd_seq_num_t) ntohs(hdr->seq);
885386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      delta = (int)est;
886386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
887386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
888386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
889386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /*
890386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * no stream corresponding to SSRC found, and we don't do
891386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * key-sharing, so return an error
892386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       */
893386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_no_ctx;
894386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
895386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
896386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
897386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* estimate packet index from seq. num. in header */
898386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
899386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
900386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* check replay database */
901386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = rdbx_check(&stream->rtp_rdbx, delta);
902386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
903386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
904386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
905386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
906386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
907386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),low32(est));
908386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
909386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "estimated u_packet index: %016llx", est);
910386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
911386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
912386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* get tag length from stream */
913386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  tag_len = auth_get_tag_length(stream->rtp_auth);
914386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
915386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
916386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set the cipher's IV properly, depending on whatever cipher we
917386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * happen to be using
918386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
919386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtp_cipher->type == &aes_icm) {
920386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
921386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* aes counter mode */
922386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
923386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = hdr->ssrc;  /* still in network order */
924386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
925386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),
926386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			         low32(est) << 16));
927386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
928386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v64[1] = be64_to_cpu(est << 16);
929386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
930386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtp_cipher->state, &iv);
931386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
932386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
933386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* no particular format - set the iv to the pakcet index */
934386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
935386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
936386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = 0;
937386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
938386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v64[0] = 0;
939386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
940386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v64[1] = be64_to_cpu(est);
941386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_set_iv(stream->rtp_cipher, &iv);
942386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
943386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
944386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_cipher_fail;
945386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
946386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* shift est, put into network byte order */
947386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#ifdef NO_64BIT_MATH
948386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  est = be64_to_cpu(make64((high32(est) << 16) |
949386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari					    (low32(est) >> 16),
950386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari					    low32(est) << 16));
951386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#else
952386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  est = be64_to_cpu(est << 16);
953386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
954386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
955386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
956386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * find starting point for decryption and length of data to be
957386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * decrypted - the encrypted portion starts after the rtp header
958386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * extension, if present; otherwise, it starts after the last csrc,
959386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if any are present
960386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
961386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're not providing confidentiality, set enc_start to NULL
962386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
963386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtp_services & sec_serv_conf) {
964386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
965386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (hdr->x == 1) {
966386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
967386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      enc_start += (ntohs(xtn_hdr->length) + 1);
968386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
969386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len
970386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			       - ((enc_start - (uint32_t *)hdr) << 2));
971386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
972386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_start = NULL;
973386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
974386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
975386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
976386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're providing authentication, set the auth_start and auth_tag
977386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * pointers to the proper locations; otherwise, set auth_start to NULL
978386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * to indicate that no authentication is needed
979386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
980386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtp_services & sec_serv_auth) {
981386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_start = (uint32_t *)hdr;
982386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
983386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
984386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_start = NULL;
985386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_tag = NULL;
986386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
987386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
988386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
989386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we expect message authentication, run the authentication
990386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * function and compare the result with the value of the auth_tag
991386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
992386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (auth_start) {
993386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
994386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /*
995386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * if we're using a universal hash, then we need to compute the
996386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * keystream prefix for encrypting the universal hash output
997386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     *
998386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * if the keystream prefix length is zero, then we know that
999386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * the authenticator isn't using a universal hash function
1000386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     */
1001386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stream->rtp_auth->prefix_len != 0) {
1002386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1003386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      prefix_len = auth_get_prefix_length(stream->rtp_auth);
1004386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      status = cipher_output(stream->rtp_cipher, tmp_tag, prefix_len);
1005386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      debug_print(mod_srtp, "keystream prefix: %s",
1006386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  octet_string_hex_string(tmp_tag, prefix_len));
1007386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (status)
1008386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return err_status_cipher_fail;
1009386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1010386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1011386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* initialize auth func context */
1012386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_start(stream->rtp_auth);
1013386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status) return status;
1014386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1015386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* now compute auth function over packet */
1016386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_update(stream->rtp_auth, (uint8_t *)auth_start,
1017386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			 *pkt_octet_len - tag_len);
1018386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1019386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* run auth func over ROC, then write tmp tag */
1020386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag);
1021386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1022386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "computed auth tag:    %s",
1023386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		octet_string_hex_string(tmp_tag, tag_len));
1024386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "packet auth tag:      %s",
1025386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		octet_string_hex_string(auth_tag, tag_len));
1026386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1027386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_auth_fail;
1028386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1029386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1030386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_auth_fail;
1031386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1032386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1033386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1034386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * update the key usage limit, and check it to make sure that we
1035386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * didn't just hit either the soft limit or the hard limit, and call
1036386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the event handler if we hit either.
1037386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1038386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(key_limit_update(stream->limit)) {
1039386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_normal:
1040386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1041386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_soft_limit:
1042386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_handle_event(ctx, stream, event_key_soft_limit);
1043386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1044386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case key_event_hard_limit:
1045386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_handle_event(ctx, stream, event_key_hard_limit);
1046386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_key_expired;
1047386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1048386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1049386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1050386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1051386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* if we're encrypting, add keystream into ciphertext */
1052386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (enc_start) {
1053386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_encrypt(stream->rtp_cipher,
1054386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			    (uint8_t *)enc_start, &enc_octet_len);
1055386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1056386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
1057386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1058386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1059386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1060386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * verify that stream is for received traffic - this check will
1061386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * detect SSRC collisions, since a stream that appears in both
1062386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * srtp_protect() and srtp_unprotect() will fail this test in one of
1063386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * those functions.
1064386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1065386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * we do this check *after* the authentication check, so that the
1066386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * latter check will catch any attempts to fool us into thinking
1067386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * that we've got a collision
1068386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1069386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->direction != dir_srtp_receiver) {
1070386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stream->direction == dir_unknown) {
1071386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream->direction = dir_srtp_receiver;
1072386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
1073386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_handle_event(ctx, stream, event_ssrc_collision);
1074386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1075386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1076386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1077386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1078386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if the stream is a 'provisional' one, in which the template context
1079386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * is used, then we need to allocate a new stream at this point, since
1080386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the authentication passed
1081386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1082386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == ctx->stream_template) {
1083386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_stream_ctx_t *new_stream;
1084386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1085386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /*
1086386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * allocate and initialize a new stream
1087386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     *
1088386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * note that we indicate failure if we can't allocate the new
1089386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * stream, and some implementations will want to not return
1090386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * failure here
1091386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     */
1092386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
1093386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1094386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
1095386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1096386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* add new stream to the head of the stream_list */
1097386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    new_stream->next = ctx->stream_list;
1098386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    ctx->stream_list = new_stream;
1099386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* set stream (the pointer used in this function) */
1101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stream = new_stream;
1102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the message authentication function passed, so add the packet
1106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * index into the replay database
1107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rdbx_add_index(&stream->rtp_rdbx, delta);
1109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* decrease the packet length by the length of the auth tag */
1111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *pkt_octet_len -= tag_len;
1112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_init() {
1118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize crypto kernel */
1121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = crypto_kernel_init();
1122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* load srtp debug module into the kernel */
1126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = crypto_kernel_load_debug_module(&mod_srtp);
1127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * The following code is under consideration for removal.  See
1135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * SRTP_MAX_TRAILER_LEN
1136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if 0
1138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_get_trailer_length(&a) returns the number of octets that will
1141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * be added to an RTP packet by the SRTP processing.  This value
1142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * is constant for a given srtp_stream_t (i.e. between initializations).
1143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariint
1146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_get_trailer_length(const srtp_stream_t s) {
1147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return auth_get_tag_length(s->rtp_auth);
1148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif
1151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
1154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * to ssrc, or NULL if no stream exists for that ssrc
1155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
1156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * this is an internal function
1157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_ctx_t *
1160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_get_stream(srtp_t srtp, uint32_t ssrc) {
1161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream;
1162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* walk down list until ssrc is found */
1164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stream = srtp->stream_list;
1165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  while (stream != NULL) {
1166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stream->ssrc == ssrc)
1167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return stream;
1168386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stream = stream->next;
1169386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1170386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1171386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we haven't found our ssrc, so return a null */
1172386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return NULL;
1173386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1174386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1175386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1176386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_dealloc(srtp_t session) {
1177386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream;
1178386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1179386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1180386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1181386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * we take a conservative deallocation strategy - if we encounter an
1182386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * error deallocating a stream, then we stop trying to deallocate
1183386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * memory and just return an error
1184386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1185386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1186386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* walk list of streams, deallocating as we go */
1187386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stream = session->stream_list;
1188386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  while (stream != NULL) {
1189386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_stream_t next = stream->next;
1190386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = srtp_stream_uninit_and_dealloc(stream, session->stream_template);
1191386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status) {
1192386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
1193386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1194386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stream = next;
1195386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1196386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1197386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate stream template, if there is one */
1198386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (session->stream_template != NULL) {
1199386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = srtp_stream_uninit_and_dealloc(session->stream_template, NULL);
1200386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1201386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1202386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate session context */
1203386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  crypto_free(session);
1204386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1205386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1206386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1207386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1208386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1209386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1210386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_add_stream(srtp_t session,
1211386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		const srtp_policy_t *policy)  {
1212386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1213386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_t tmp;
1214386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1215386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* sanity check arguments */
1216386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if ((session == NULL) || (policy == NULL) || (policy->key == NULL))
1217386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1218386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1219386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate stream  */
1220386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = srtp_stream_alloc(&tmp, policy);
1221386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status) {
1222386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1223386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1224386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1225386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize stream  */
1226386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = srtp_stream_init(tmp, policy);
1227386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status) {
1228386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_free(tmp);
1229386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1230386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1231386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1232386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1233386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set the head of the stream list or the template to point to the
1234386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * stream that we've just alloced and init'ed, depending on whether
1235386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * or not it has a wildcard SSRC value or not
1236386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1237386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if the template stream has already been set, then the policy is
1238386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * inconsistent, so we return a bad_param error code
1239386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1240386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch (policy->ssrc.type) {
1241386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case (ssrc_any_outbound):
1242386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (session->stream_template) {
1243386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_bad_param;
1244386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1245386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    session->stream_template = tmp;
1246386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    session->stream_template->direction = dir_srtp_sender;
1247386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1248386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case (ssrc_any_inbound):
1249386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (session->stream_template) {
1250386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_bad_param;
1251386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1252386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    session->stream_template = tmp;
1253386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    session->stream_template->direction = dir_srtp_receiver;
1254386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1255386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case (ssrc_specific):
1256386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    tmp->next = session->stream_list;
1257386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    session->stream_list = tmp;
1258386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1259386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case (ssrc_undefined):
1260386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1261386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_free(tmp);
1262386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1263386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1264386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1265386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1266386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1267386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1268386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1269386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_create(srtp_t *session,               /* handle for session     */
1270386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	    const srtp_policy_t *policy) { /* SRTP policy (list)     */
1271386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t stat;
1272386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_ctx_t *ctx;
1273386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1274386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* sanity check arguments */
1275386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (session == NULL)
1276386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1277386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1278386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* allocate srtp context and set ctx_ptr */
1279386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  ctx = (srtp_ctx_t *) crypto_alloc(sizeof(srtp_ctx_t));
1280386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (ctx == NULL)
1281386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_alloc_fail;
1282386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *session = ctx;
1283386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1284386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1285386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * loop over elements in the policy list, allocating and
1286386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * initializing a stream for each element
1287386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1288386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  ctx->stream_template = NULL;
1289386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  ctx->stream_list = NULL;
1290386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  while (policy != NULL) {
1291386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1292386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stat = srtp_add_stream(ctx, policy);
1293386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stat) {
1294386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* clean up everything */
1295386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_dealloc(*session);
1296386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return stat;
1297386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1298386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1299386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* set policy to next item in list  */
1300386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    policy = policy->next;
1301386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1302386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1303386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1304386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1305386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1306386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1307386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1308386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_remove_stream(srtp_t session, uint32_t ssrc) {
1309386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream, *last_stream;
1310386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1311386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* sanity check arguments */
1312386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (session == NULL)
1313386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1314386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1315386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* find stream in list; complain if not found */
1316386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  last_stream = stream = session->stream_list;
1317386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  while ((stream != NULL) && (ssrc != stream->ssrc)) {
1318386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    last_stream = stream;
1319386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stream = stream->next;
1320386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1321386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == NULL)
1322386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_no_ctx;
1323386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1324386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* remove stream from the list */
1325386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  last_stream->next = stream->next;
1326386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1327386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return srtp_stream_uninit_and_dealloc(stream, session->stream_template);
1328386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1329386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1330386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1331386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_stream_uninit_and_dealloc(srtp_stream_ctx_t *stream,
1332386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari                               srtp_stream_ctx_t *stream_template) {
1333386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1334386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate rdbx data */
1335386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = srtp_stream_uninit(stream);
1336386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1337386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1338386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1339386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* deallocate the stream */
1340386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = srtp_stream_dealloc(stream, stream_template);
1341386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1342386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1343386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1344386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1345386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1346386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1347386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1348386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1349386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the default policy - provides a convenient way for callers to use
1350386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the default security policy
1351386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
1352386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * this policy is that defined in the current SRTP internet draft.
1353386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *
1354386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1355386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1356386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1357386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * NOTE: cipher_key_len is really key len (128 bits) plus salt len
1358386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari *  (112 bits)
1359386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1360386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* There are hard-coded 16's for base_key_len in the key generation code */
1361386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1362386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1363386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_rtp_default(crypto_policy_t *p) {
1364386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1365386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_type     = AES_128_ICM;
1366386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_key_len  = 30;                /* default 128 bits per RFC 3711 */
1367386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_type       = HMAC_SHA1;
1368386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
1369386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_tag_len    = 10;                /* default 80 bits per RFC 3711 */
1370386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->sec_serv        = sec_serv_conf_and_auth;
1371386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1372386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1373386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1374386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1375386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_rtcp_default(crypto_policy_t *p) {
1376386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1377386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_type     = AES_128_ICM;
1378386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_key_len  = 30;                 /* default 128 bits per RFC 3711 */
1379386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_type       = HMAC_SHA1;
1380386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_key_len    = 20;                 /* default 160 bits per RFC 3711 */
1381386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_tag_len    = 10;                 /* default 80 bits per RFC 3711 */
1382386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->sec_serv        = sec_serv_conf_and_auth;
1383386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1384386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1385386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1386386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1387386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_aes_cm_128_hmac_sha1_32(crypto_policy_t *p) {
1388386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1389386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1390386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1391386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1392386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * note that this crypto policy is intended for SRTP, but not SRTCP
1393386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1394386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1395386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_type     = AES_128_ICM;
1396386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
1397386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_type       = HMAC_SHA1;
1398386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_key_len    = 20;                /* 160 bit key               */
1399386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_tag_len    = 4;                 /* 32 bit tag                */
1400386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->sec_serv        = sec_serv_conf_and_auth;
1401386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1402386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1403386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1404386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1405386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1406386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p) {
1407386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1408386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1409386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1410386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1411386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * note that this crypto policy is intended for SRTP, but not SRTCP
1412386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1413386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1414386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_type     = AES_128_ICM;
1415386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
1416386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_type       = NULL_AUTH;
1417386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_key_len    = 0;
1418386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_tag_len    = 0;
1419386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->sec_serv        = sec_serv_conf;
1420386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1421386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1422386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1423386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1424386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1425386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p) {
1426386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1427386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1428386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
1429386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1430386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1431386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_type     = NULL_CIPHER;
1432386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->cipher_key_len  = 0;
1433386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_type       = HMAC_SHA1;
1434386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_key_len    = 20;
1435386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->auth_tag_len    = 10;
1436386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  p->sec_serv        = sec_serv_auth;
1437386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1438386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1439386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1440386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1441386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1442386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * secure rtcp functions
1443386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1444386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1445386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1446386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
1447386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
1448386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *enc_start;      /* pointer to start of encrypted portion  */
1449386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *auth_start;     /* pointer to start of auth. portion      */
1450386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *trailer;        /* pointer to start of trailer            */
1451386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
1452386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
1453386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1454386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int tag_len;
1455386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream;
1456386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int prefix_len;
1457386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t seq_num;
1458386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1459386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we assume the hdr is 32-bit aligned to start */
1460386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1461386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * look up ssrc in srtp_stream list, and process the packet with
1462386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the appropriate stream.  if we haven't seen this stream before,
1463386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * there's only one key for this srtp_session, and the cipher
1464386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * supports key-sharing, then we assume that a new stream using
1465386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * that key has just started up
1466386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1467386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stream = srtp_get_stream(ctx, hdr->ssrc);
1468386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == NULL) {
1469386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (ctx->stream_template != NULL) {
1470386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_stream_ctx_t *new_stream;
1471386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1472386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* allocate and initialize a new stream */
1473386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      status = srtp_stream_clone(ctx->stream_template,
1474386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				 hdr->ssrc, &new_stream);
1475386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (status)
1476386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	return status;
1477386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1478386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* add new stream to the head of the stream_list */
1479386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      new_stream->next = ctx->stream_list;
1480386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      ctx->stream_list = new_stream;
1481386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1482386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* set stream (the pointer used in this function) */
1483386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream = new_stream;
1484386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
1485386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* no template stream, so we return an error */
1486386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_no_ctx;
1487386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1488386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1489386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1490386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1491386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * verify that stream is for sending traffic - this check will
1492386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * detect SSRC collisions, since a stream that appears in both
1493386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * srtp_protect() and srtp_unprotect() will fail this test in one of
1494386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * those functions.
1495386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1496386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->direction != dir_srtp_sender) {
1497386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stream->direction == dir_unknown) {
1498386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream->direction = dir_srtp_sender;
1499386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
1500386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_handle_event(ctx, stream, event_ssrc_collision);
1501386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1502386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1503386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1504386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* get tag length from stream context */
1505386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  tag_len = auth_get_tag_length(stream->rtcp_auth);
1506386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1507386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1508386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set encryption start and encryption length - if we're not
1509386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * providing confidentiality, set enc_start to NULL
1510386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1511386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1512386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
1513386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1514386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* all of the packet, except the header, gets encrypted */
1515386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* NOTE: hdr->length is not usable - it refers to only the first
1516386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 RTCP report in the compound packet! */
1517386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1518386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 multiples of 32-bits (RFC 3550 6.1) */
1519386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  trailer = (uint32_t *) ((char *)enc_start + enc_octet_len);
1520386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1521386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtcp_services & sec_serv_conf) {
1522386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    *trailer = htonl(SRTCP_E_BIT);     /* set encrypt bit */
1523386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
1524386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_start = NULL;
1525386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_octet_len = 0;
1526386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	/* 0 is network-order independant */
1527386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    *trailer = 0x00000000;     /* set encrypt bit */
1528386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1529386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1530386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1531386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set the auth_start and auth_tag pointers to the proper locations
1532386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * (note that srtpc *always* provides authentication, unlike srtp)
1533386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1534386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* Note: This would need to change for optional mikey data */
1535386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_start = (uint32_t *)hdr;
1536386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t);
1537386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1538386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* perform EKT processing if needed */
1539386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len,
1540386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		 rdbx_get_packet_index(&stream->rtp_rdbx));
1541386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1542386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1543386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * check sequence number for overruns, and copy it into the packet
1544386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if its value isn't too big
1545386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1546386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = rdb_increment(&stream->rtcp_rdb);
1547386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1548386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1549386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  seq_num = rdb_get_value(&stream->rtcp_rdb);
1550386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *trailer |= htonl(seq_num);
1551386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "srtcp index: %x", seq_num);
1552386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1553386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1554386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're using rindael counter mode, set nonce and seq
1555386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1556386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtcp_cipher->type == &aes_icm) {
1557386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    v128_t iv;
1558386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1559386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
1560386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = hdr->ssrc;  /* still in network order! */
1561386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[2] = htonl(seq_num >> 16);
1562386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[3] = htonl(seq_num << 16);
1563386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtcp_cipher->state, &iv);
1564386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1565386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
1566386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    v128_t iv;
1567386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1568386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* otherwise, just set the index to seq_num */
1569386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
1570386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = 0;
1571386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[2] = 0;
1572386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[3] = htonl(seq_num);
1573386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_set_iv(stream->rtcp_cipher, &iv);
1574386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1575386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1576386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_cipher_fail;
1577386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1578386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1579386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're authenticating using a universal hash, put the keystream
1580386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * prefix into the authentication tag
1581386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1582386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1583386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* if auth_start is non-null, then put keystream into tag  */
1584386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (auth_start) {
1585386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1586386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* put keystream prefix into auth_tag */
1587386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1588386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1589386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1590386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "keystream prefix: %s",
1591386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		octet_string_hex_string(auth_tag, prefix_len));
1592386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1593386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1594386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
1595386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1596386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1597386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* if we're encrypting, exor keystream into the message */
1598386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (enc_start) {
1599386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_encrypt(stream->rtcp_cipher,
1600386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			    (uint8_t *)enc_start, &enc_octet_len);
1601386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1602386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
1603386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1604386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1605386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize auth func context */
1606386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_start(stream->rtcp_auth);
1607386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1608386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1609386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * run auth func over packet (including trailer), and write the
1610386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * result at auth_tag
1611386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1612386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = auth_compute(stream->rtcp_auth,
1613386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			(uint8_t *)auth_start,
1614386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			(*pkt_octet_len) + sizeof(srtcp_trailer_t),
1615386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			auth_tag);
1616386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "srtcp auth tag:    %s",
1617386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(auth_tag, tag_len));
1618386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1619386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_auth_fail;
1620386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1621386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* increase the packet length by the length of the auth tag and seq_num*/
1622386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
1623386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1624386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1625386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1626386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1627386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1628386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1629386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
1630386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
1631386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *enc_start;      /* pointer to start of encrypted portion  */
1632386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *auth_start;     /* pointer to start of auth. portion      */
1633386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t *trailer;        /* pointer to start of trailer            */
1634386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
1635386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
1636386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
1637386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint8_t tag_copy[SRTP_MAX_TAG_LEN];
1638386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  err_status_t status;
1639386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  unsigned auth_len;
1640386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int tag_len;
1641386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  srtp_stream_ctx_t *stream;
1642386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int prefix_len;
1643386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  uint32_t seq_num;
1644386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int e_bit_in_packet;     /* whether the E-bit was found in the packet */
1645386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  int sec_serv_confidentiality; /* whether confidentiality was requested */
1646386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1647386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we assume the hdr is 32-bit aligned to start */
1648386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1649386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * look up ssrc in srtp_stream list, and process the packet with
1650386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the appropriate stream.  if we haven't seen this stream before,
1651386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * there's only one key for this srtp_session, and the cipher
1652386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * supports key-sharing, then we assume that a new stream using
1653386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * that key has just started up
1654386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1655386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  stream = srtp_get_stream(ctx, hdr->ssrc);
1656386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == NULL) {
1657386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (ctx->stream_template != NULL) {
1658386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream = ctx->stream_template;
1659386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1660386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /*
1661386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * check to see if stream_template has an EKT data structure, in
1662386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * which case we initialize the template using the EKT policy
1663386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * referenced by that data (which consists of decrypting the
1664386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * master key from the EKT field)
1665386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       *
1666386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * this function initializes a *provisional* stream, and this
1667386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * stream should not be accepted until and unless the packet
1668386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       * passes its authentication check
1669386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari       */
1670386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      if (stream->ekt != NULL) {
1671386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	status = srtp_stream_init_from_ekt(stream, srtcp_hdr, *pkt_octet_len);
1672386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	if (status)
1673386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	  return status;
1674386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      }
1675386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1676386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)",
1677386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		  hdr->ssrc);
1678386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
1679386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      /* no template stream, so we return an error */
1680386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_no_ctx;
1681386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1682386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1683386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1684386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf ||
1685386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream->rtcp_services == sec_serv_conf_and_auth;
1686386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1687386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* get tag length from stream context */
1688386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  tag_len = auth_get_tag_length(stream->rtcp_auth);
1689386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1690386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1691386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set encryption start, encryption length, and trailer
1692386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1693386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  enc_octet_len = *pkt_octet_len -
1694386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari                  (octets_in_rtcp_header + tag_len + sizeof(srtcp_trailer_t));
1695386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* index & E (encryption) bit follow normal data.  hdr->len
1696386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 is the number of words (32-bit) in the normal packet minus 1 */
1697386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* This should point trailer to the word past the end of the
1698386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	 normal data. */
1699386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* This would need to be modified for optional mikey data */
1700386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1701386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
1702386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *	 multiples of 32-bits (RFC 3550 6.1)
1703386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1704386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  trailer = (uint32_t *) ((char *) hdr +
1705386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		     *pkt_octet_len -(tag_len + sizeof(srtcp_trailer_t)));
1706386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  e_bit_in_packet = (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT;
1707386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (e_bit_in_packet != sec_serv_confidentiality) {
1708386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_cant_check;
1709386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1710386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (sec_serv_confidentiality) {
1711386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
1712386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
1713386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_octet_len = 0;
1714386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    enc_start = NULL; /* this indicates that there's no encryption */
1715386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1716386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1717386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1718386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * set the auth_start and auth_tag pointers to the proper locations
1719386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * (note that srtcp *always* uses authentication, unlike srtp)
1720386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1721386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_start = (uint32_t *)hdr;
1722386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_len = *pkt_octet_len - tag_len;
1723386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_tag = (uint8_t *)hdr + auth_len;
1724386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1725386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1726386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if EKT is in use, then we make a copy of the tag from the packet,
1727386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * and then zeroize the location of the base tag
1728386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1729386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * we first re-position the auth_tag pointer so that it points to
1730386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the base tag
1731386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1732386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->ekt) {
1733386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_tag -= ekt_octets_after_base_tag(stream->ekt);
1734386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    memcpy(tag_copy, auth_tag, tag_len);
1735386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    octet_string_set_to_zero(auth_tag, tag_len);
1736386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_tag = tag_copy;
1737386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    auth_len += tag_len;
1738386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1739386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1740386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1741386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * check the sequence number for replays
1742386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1743386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* this is easier than dealing with bitfield access */
1744386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK;
1745386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "srtcp index: %x", seq_num);
1746386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = rdb_check(&stream->rtcp_rdb, seq_num);
1747386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1748386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return status;
1749386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1750386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1751386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're using aes counter mode, set nonce and seq
1752386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1753386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->rtcp_cipher->type == &aes_icm) {
1754386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    v128_t iv;
1755386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1756386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
1757386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = hdr->ssrc; /* still in network order! */
1758386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[2] = htonl(seq_num >> 16);
1759386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[3] = htonl(seq_num << 16);
1760386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtcp_cipher->state, &iv);
1761386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1762386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  } else {
1763386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    v128_t iv;
1764386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1765386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* otherwise, just set the index to seq_num */
1766386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[0] = 0;
1767386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[1] = 0;
1768386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[2] = 0;
1769386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    iv.v32[3] = htonl(seq_num);
1770386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_set_iv(stream->rtcp_cipher, &iv);
1771386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1772386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1773386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1774386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_cipher_fail;
1775386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1776386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* initialize auth func context */
1777386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  auth_start(stream->rtcp_auth);
1778386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1779386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* run auth func over packet, put result into tmp_tag */
1780386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  status = auth_compute(stream->rtcp_auth, (uint8_t *)auth_start,
1781386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			auth_len, tmp_tag);
1782386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "srtcp computed tag:       %s",
1783386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(tmp_tag, tag_len));
1784386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (status)
1785386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_auth_fail;
1786386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1787386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* compare the tag just computed with the one in the packet */
1788386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  debug_print(mod_srtp, "srtcp tag from packet:    %s",
1789386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari	      octet_string_hex_string(auth_tag, tag_len));
1790386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))
1791386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_auth_fail;
1792386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1793386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1794386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if we're authenticating using a universal hash, put the keystream
1795386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * prefix into the authentication tag
1796386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1797386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  prefix_len = auth_get_prefix_length(stream->rtcp_auth);
1798386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (prefix_len) {
1799386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);
1800386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    debug_print(mod_srtp, "keystream prefix: %s",
1801386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		octet_string_hex_string(auth_tag, prefix_len));
1802386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1803386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
1804386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1805386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1806386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* if we're decrypting, exor keystream into the message */
1807386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (enc_start) {
1808386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = cipher_encrypt(stream->rtcp_cipher,
1809386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari			    (uint8_t *)enc_start, &enc_octet_len);
1810386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1811386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return err_status_cipher_fail;
1812386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1813386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1814386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* decrease the packet length by the length of the auth tag and seq_num */
1815386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));
1816386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1817386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1818386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if EKT is in effect, subtract the EKT data out of the packet
1819386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * length
1820386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1821386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  *pkt_octet_len -= ekt_octets_after_base_tag(stream->ekt);
1822386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1823386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1824386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * verify that stream is for received traffic - this check will
1825386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * detect SSRC collisions, since a stream that appears in both
1826386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * srtp_protect() and srtp_unprotect() will fail this test in one of
1827386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * those functions.
1828386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   *
1829386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * we do this check *after* the authentication check, so that the
1830386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * latter check will catch any attempts to fool us into thinking
1831386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * that we've got a collision
1832386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1833386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream->direction != dir_srtp_receiver) {
1834386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (stream->direction == dir_unknown) {
1835386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      stream->direction = dir_srtp_receiver;
1836386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    } else {
1837386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      srtp_handle_event(ctx, stream, event_ssrc_collision);
1838386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    }
1839386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1840386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1841386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /*
1842386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * if the stream is a 'provisional' one, in which the template context
1843386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * is used, then we need to allocate a new stream at this point, since
1844386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   * the authentication passed
1845386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari   */
1846386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  if (stream == ctx->stream_template) {
1847386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    srtp_stream_ctx_t *new_stream;
1848386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1849386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /*
1850386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * allocate and initialize a new stream
1851386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     *
1852386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * note that we indicate failure if we can't allocate the new
1853386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * stream, and some implementations will want to not return
1854386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     * failure here
1855386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari     */
1856386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
1857386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    if (status)
1858386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari      return status;
1859386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1860386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* add new stream to the head of the stream_list */
1861386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    new_stream->next = ctx->stream_list;
1862386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    ctx->stream_list = new_stream;
1863386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1864386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* set stream (the pointer used in this function) */
1865386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    stream = new_stream;
1866386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1867386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1868386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* we've passed the authentication check, so add seq_num to the rdb */
1869386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  rdb_add_index(&stream->rtcp_rdb, seq_num);
1870386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1871386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1872386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1873386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1874386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1875386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1876386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1877386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/*
1878386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * dtls keying for srtp
1879386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */
1880386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1881386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1882386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_from_profile_for_rtp(crypto_policy_t *policy,
1883386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari				       srtp_profile_t profile) {
1884386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1885386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set SRTP policy from the SRTP profile in the key set */
1886386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(profile) {
1887386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_80:
1888386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1889386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1890386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1891386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_32:
1892386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_32(policy);
1893386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1894386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1895386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_80:
1896386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1897386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1898386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1899386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* the following profiles are not (yet) supported */
1900386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_32:
1901386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_80:
1902386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_32:
1903386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1904386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1905386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1906386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1907386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1908386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1909386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1910386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t
1911386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaricrypto_policy_set_from_profile_for_rtcp(crypto_policy_t *policy,
1912386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari					srtp_profile_t profile) {
1913386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1914386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  /* set SRTP policy from the SRTP profile in the key set */
1915386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(profile) {
1916386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_80:
1917386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1918386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1919386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_32:
1920386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
1921386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1922386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_80:
1923386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
1924386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1925386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* the following profiles are not (yet) supported */
1926386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_32:
1927386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_80:
1928386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_32:
1929386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1930386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return err_status_bad_param;
1931386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1932386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1933386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  return err_status_ok;
1934386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1935386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1936386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarivoid
1937386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariappend_salt_to_key(uint8_t *key, unsigned int bytes_in_key,
1938386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari		   uint8_t *salt, unsigned int bytes_in_salt) {
1939386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1940386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  memcpy(key + bytes_in_key, salt, bytes_in_salt);
1941386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1942386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1943386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1944386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariunsigned int
1945386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_profile_get_master_key_length(srtp_profile_t profile) {
1946386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1947386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(profile) {
1948386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_80:
1949386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 16;
1950386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1951386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_32:
1952386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 16;
1953386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1954386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_80:
1955386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 16;
1956386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1957386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* the following profiles are not (yet) supported */
1958386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_32:
1959386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_80:
1960386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_32:
1961386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1962386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 0;  /* indicate error by returning a zero */
1963386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1964386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1965386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1966386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagariunsigned int
1967386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarisrtp_profile_get_master_salt_length(srtp_profile_t profile) {
1968386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari
1969386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  switch(profile) {
1970386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_80:
1971386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 14;
1972386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1973386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes128_cm_sha1_32:
1974386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 14;
1975386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1976386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_80:
1977386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 14;
1978386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    break;
1979386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    /* the following profiles are not (yet) supported */
1980386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_null_sha1_32:
1981386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_80:
1982386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  case srtp_profile_aes256_cm_sha1_32:
1983386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  default:
1984386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari    return 0;  /* indicate error by returning a zero */
1985386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari  }
1986386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}
1987