xref: /aosp_15_r20/external/libsrtp2/srtp/srtp.c (revision 90e502c7aef8d77d0622bb67d75435c6190cfc1a)
1*90e502c7SAndroid Build Coastguard Worker /*
2*90e502c7SAndroid Build Coastguard Worker  * srtp.c
3*90e502c7SAndroid Build Coastguard Worker  *
4*90e502c7SAndroid Build Coastguard Worker  * the secure real-time transport protocol
5*90e502c7SAndroid Build Coastguard Worker  *
6*90e502c7SAndroid Build Coastguard Worker  * David A. McGrew
7*90e502c7SAndroid Build Coastguard Worker  * Cisco Systems, Inc.
8*90e502c7SAndroid Build Coastguard Worker  */
9*90e502c7SAndroid Build Coastguard Worker /*
10*90e502c7SAndroid Build Coastguard Worker  *
11*90e502c7SAndroid Build Coastguard Worker  * Copyright (c) 2001-2017, Cisco Systems, Inc.
12*90e502c7SAndroid Build Coastguard Worker  * All rights reserved.
13*90e502c7SAndroid Build Coastguard Worker  *
14*90e502c7SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
15*90e502c7SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
16*90e502c7SAndroid Build Coastguard Worker  * are met:
17*90e502c7SAndroid Build Coastguard Worker  *
18*90e502c7SAndroid Build Coastguard Worker  *   Redistributions of source code must retain the above copyright
19*90e502c7SAndroid Build Coastguard Worker  *   notice, this list of conditions and the following disclaimer.
20*90e502c7SAndroid Build Coastguard Worker  *
21*90e502c7SAndroid Build Coastguard Worker  *   Redistributions in binary form must reproduce the above
22*90e502c7SAndroid Build Coastguard Worker  *   copyright notice, this list of conditions and the following
23*90e502c7SAndroid Build Coastguard Worker  *   disclaimer in the documentation and/or other materials provided
24*90e502c7SAndroid Build Coastguard Worker  *   with the distribution.
25*90e502c7SAndroid Build Coastguard Worker  *
26*90e502c7SAndroid Build Coastguard Worker  *   Neither the name of the Cisco Systems, Inc. nor the names of its
27*90e502c7SAndroid Build Coastguard Worker  *   contributors may be used to endorse or promote products derived
28*90e502c7SAndroid Build Coastguard Worker  *   from this software without specific prior written permission.
29*90e502c7SAndroid Build Coastguard Worker  *
30*90e502c7SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31*90e502c7SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32*90e502c7SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33*90e502c7SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34*90e502c7SAndroid Build Coastguard Worker  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35*90e502c7SAndroid Build Coastguard Worker  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36*90e502c7SAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37*90e502c7SAndroid Build Coastguard Worker  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*90e502c7SAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*90e502c7SAndroid Build Coastguard Worker  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40*90e502c7SAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41*90e502c7SAndroid Build Coastguard Worker  * OF THE POSSIBILITY OF SUCH DAMAGE.
42*90e502c7SAndroid Build Coastguard Worker  *
43*90e502c7SAndroid Build Coastguard Worker  */
44*90e502c7SAndroid Build Coastguard Worker 
45*90e502c7SAndroid Build Coastguard Worker // Leave this as the top level import. Ensures the existence of defines
46*90e502c7SAndroid Build Coastguard Worker #include "config.h"
47*90e502c7SAndroid Build Coastguard Worker 
48*90e502c7SAndroid Build Coastguard Worker #include "srtp_priv.h"
49*90e502c7SAndroid Build Coastguard Worker #include "crypto_types.h"
50*90e502c7SAndroid Build Coastguard Worker #include "err.h"
51*90e502c7SAndroid Build Coastguard Worker #include "ekt.h"   /* for SRTP Encrypted Key Transport */
52*90e502c7SAndroid Build Coastguard Worker #include "alloc.h" /* for srtp_crypto_alloc() */
53*90e502c7SAndroid Build Coastguard Worker 
54*90e502c7SAndroid Build Coastguard Worker #ifdef GCM
55*90e502c7SAndroid Build Coastguard Worker #include "aes_gcm.h" /* for AES GCM mode */
56*90e502c7SAndroid Build Coastguard Worker #endif
57*90e502c7SAndroid Build Coastguard Worker 
58*90e502c7SAndroid Build Coastguard Worker #ifdef OPENSSL_KDF
59*90e502c7SAndroid Build Coastguard Worker #include <openssl/kdf.h>
60*90e502c7SAndroid Build Coastguard Worker #include "aes_icm_ext.h"
61*90e502c7SAndroid Build Coastguard Worker #endif
62*90e502c7SAndroid Build Coastguard Worker 
63*90e502c7SAndroid Build Coastguard Worker #include <limits.h>
64*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
65*90e502c7SAndroid Build Coastguard Worker #include <netinet/in.h>
66*90e502c7SAndroid Build Coastguard Worker #elif defined(HAVE_WINSOCK2_H)
67*90e502c7SAndroid Build Coastguard Worker #include <winsock2.h>
68*90e502c7SAndroid Build Coastguard Worker #endif
69*90e502c7SAndroid Build Coastguard Worker 
70*90e502c7SAndroid Build Coastguard Worker /* the debug module for srtp */
71*90e502c7SAndroid Build Coastguard Worker srtp_debug_module_t mod_srtp = {
72*90e502c7SAndroid Build Coastguard Worker     0,     /* debugging is off by default */
73*90e502c7SAndroid Build Coastguard Worker     "srtp" /* printable name for module */
74*90e502c7SAndroid Build Coastguard Worker };
75*90e502c7SAndroid Build Coastguard Worker 
76*90e502c7SAndroid Build Coastguard Worker #define octets_in_rtp_header 12
77*90e502c7SAndroid Build Coastguard Worker #define uint32s_in_rtp_header 3
78*90e502c7SAndroid Build Coastguard Worker #define octets_in_rtcp_header 8
79*90e502c7SAndroid Build Coastguard Worker #define uint32s_in_rtcp_header 2
80*90e502c7SAndroid Build Coastguard Worker #define octets_in_rtp_extn_hdr 4
81*90e502c7SAndroid Build Coastguard Worker 
srtp_validate_rtp_header(void * rtp_hdr,int * pkt_octet_len)82*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr,
83*90e502c7SAndroid Build Coastguard Worker                                                   int *pkt_octet_len)
84*90e502c7SAndroid Build Coastguard Worker {
85*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
86*90e502c7SAndroid Build Coastguard Worker     int rtp_header_len;
87*90e502c7SAndroid Build Coastguard Worker 
88*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < octets_in_rtp_header)
89*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
90*90e502c7SAndroid Build Coastguard Worker 
91*90e502c7SAndroid Build Coastguard Worker     /* Check RTP header length */
92*90e502c7SAndroid Build Coastguard Worker     rtp_header_len = octets_in_rtp_header + 4 * hdr->cc;
93*90e502c7SAndroid Build Coastguard Worker     if (hdr->x == 1)
94*90e502c7SAndroid Build Coastguard Worker         rtp_header_len += octets_in_rtp_extn_hdr;
95*90e502c7SAndroid Build Coastguard Worker 
96*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < rtp_header_len)
97*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
98*90e502c7SAndroid Build Coastguard Worker 
99*90e502c7SAndroid Build Coastguard Worker     /* Verifing profile length. */
100*90e502c7SAndroid Build Coastguard Worker     if (hdr->x == 1) {
101*90e502c7SAndroid Build Coastguard Worker         srtp_hdr_xtnd_t *xtn_hdr =
102*90e502c7SAndroid Build Coastguard Worker             (srtp_hdr_xtnd_t *)((uint32_t *)hdr + uint32s_in_rtp_header +
103*90e502c7SAndroid Build Coastguard Worker                                 hdr->cc);
104*90e502c7SAndroid Build Coastguard Worker         int profile_len = ntohs(xtn_hdr->length);
105*90e502c7SAndroid Build Coastguard Worker         rtp_header_len += profile_len * 4;
106*90e502c7SAndroid Build Coastguard Worker         /* profile length counts the number of 32-bit words */
107*90e502c7SAndroid Build Coastguard Worker         if (*pkt_octet_len < rtp_header_len)
108*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_param;
109*90e502c7SAndroid Build Coastguard Worker     }
110*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
111*90e502c7SAndroid Build Coastguard Worker }
112*90e502c7SAndroid Build Coastguard Worker 
srtp_get_version_string()113*90e502c7SAndroid Build Coastguard Worker const char *srtp_get_version_string()
114*90e502c7SAndroid Build Coastguard Worker {
115*90e502c7SAndroid Build Coastguard Worker     /*
116*90e502c7SAndroid Build Coastguard Worker      * Simply return the autotools generated string
117*90e502c7SAndroid Build Coastguard Worker      */
118*90e502c7SAndroid Build Coastguard Worker     return SRTP_VER_STRING;
119*90e502c7SAndroid Build Coastguard Worker }
120*90e502c7SAndroid Build Coastguard Worker 
srtp_get_version()121*90e502c7SAndroid Build Coastguard Worker unsigned int srtp_get_version()
122*90e502c7SAndroid Build Coastguard Worker {
123*90e502c7SAndroid Build Coastguard Worker     unsigned int major = 0, minor = 0, micro = 0;
124*90e502c7SAndroid Build Coastguard Worker     unsigned int rv = 0;
125*90e502c7SAndroid Build Coastguard Worker     int parse_rv;
126*90e502c7SAndroid Build Coastguard Worker 
127*90e502c7SAndroid Build Coastguard Worker     /*
128*90e502c7SAndroid Build Coastguard Worker      * Parse the autotools generated version
129*90e502c7SAndroid Build Coastguard Worker      */
130*90e502c7SAndroid Build Coastguard Worker     parse_rv = sscanf(SRTP_VERSION, "%u.%u.%u", &major, &minor, &micro);
131*90e502c7SAndroid Build Coastguard Worker     if (parse_rv != 3) {
132*90e502c7SAndroid Build Coastguard Worker         /*
133*90e502c7SAndroid Build Coastguard Worker          * We're expected to parse all 3 version levels.
134*90e502c7SAndroid Build Coastguard Worker          * If not, then this must not be an official release.
135*90e502c7SAndroid Build Coastguard Worker          * Return all zeros on the version
136*90e502c7SAndroid Build Coastguard Worker          */
137*90e502c7SAndroid Build Coastguard Worker         return (0);
138*90e502c7SAndroid Build Coastguard Worker     }
139*90e502c7SAndroid Build Coastguard Worker 
140*90e502c7SAndroid Build Coastguard Worker     /*
141*90e502c7SAndroid Build Coastguard Worker      * We allow 8 bits for the major and minor, while
142*90e502c7SAndroid Build Coastguard Worker      * allowing 16 bits for the micro.  16 bits for the micro
143*90e502c7SAndroid Build Coastguard Worker      * may be beneficial for a continuous delivery model
144*90e502c7SAndroid Build Coastguard Worker      * in the future.
145*90e502c7SAndroid Build Coastguard Worker      */
146*90e502c7SAndroid Build Coastguard Worker     rv |= (major & 0xFF) << 24;
147*90e502c7SAndroid Build Coastguard Worker     rv |= (minor & 0xFF) << 16;
148*90e502c7SAndroid Build Coastguard Worker     rv |= micro & 0xFF;
149*90e502c7SAndroid Build Coastguard Worker     return rv;
150*90e502c7SAndroid Build Coastguard Worker }
151*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_dealloc(srtp_stream_ctx_t * stream,const srtp_stream_ctx_t * stream_template)152*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream,
153*90e502c7SAndroid Build Coastguard Worker                                       const srtp_stream_ctx_t *stream_template)
154*90e502c7SAndroid Build Coastguard Worker {
155*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
156*90e502c7SAndroid Build Coastguard Worker     unsigned int i = 0;
157*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
158*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *template_session_keys = NULL;
159*90e502c7SAndroid Build Coastguard Worker 
160*90e502c7SAndroid Build Coastguard Worker     /*
161*90e502c7SAndroid Build Coastguard Worker      * we use a conservative deallocation strategy - if any deallocation
162*90e502c7SAndroid Build Coastguard Worker      * fails, then we report that fact without trying to deallocate
163*90e502c7SAndroid Build Coastguard Worker      * anything else
164*90e502c7SAndroid Build Coastguard Worker      */
165*90e502c7SAndroid Build Coastguard Worker     if (stream->session_keys) {
166*90e502c7SAndroid Build Coastguard Worker         for (i = 0; i < stream->num_master_keys; i++) {
167*90e502c7SAndroid Build Coastguard Worker             session_keys = &stream->session_keys[i];
168*90e502c7SAndroid Build Coastguard Worker 
169*90e502c7SAndroid Build Coastguard Worker             if (stream_template &&
170*90e502c7SAndroid Build Coastguard Worker                 stream->num_master_keys == stream_template->num_master_keys) {
171*90e502c7SAndroid Build Coastguard Worker                 template_session_keys = &stream_template->session_keys[i];
172*90e502c7SAndroid Build Coastguard Worker             } else {
173*90e502c7SAndroid Build Coastguard Worker                 template_session_keys = NULL;
174*90e502c7SAndroid Build Coastguard Worker             }
175*90e502c7SAndroid Build Coastguard Worker 
176*90e502c7SAndroid Build Coastguard Worker             /*
177*90e502c7SAndroid Build Coastguard Worker             * deallocate cipher, if it is not the same as that in template
178*90e502c7SAndroid Build Coastguard Worker             */
179*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
180*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtp_cipher == template_session_keys->rtp_cipher) {
181*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
182*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->rtp_cipher) {
183*90e502c7SAndroid Build Coastguard Worker                 status = srtp_cipher_dealloc(session_keys->rtp_cipher);
184*90e502c7SAndroid Build Coastguard Worker                 if (status)
185*90e502c7SAndroid Build Coastguard Worker                     return status;
186*90e502c7SAndroid Build Coastguard Worker             }
187*90e502c7SAndroid Build Coastguard Worker 
188*90e502c7SAndroid Build Coastguard Worker             /*
189*90e502c7SAndroid Build Coastguard Worker              * deallocate auth function, if it is not the same as that in
190*90e502c7SAndroid Build Coastguard Worker              * template
191*90e502c7SAndroid Build Coastguard Worker              */
192*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
193*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtp_auth == template_session_keys->rtp_auth) {
194*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
195*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->rtp_auth) {
196*90e502c7SAndroid Build Coastguard Worker                 status = srtp_auth_dealloc(session_keys->rtp_auth);
197*90e502c7SAndroid Build Coastguard Worker                 if (status)
198*90e502c7SAndroid Build Coastguard Worker                     return status;
199*90e502c7SAndroid Build Coastguard Worker             }
200*90e502c7SAndroid Build Coastguard Worker 
201*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
202*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtp_xtn_hdr_cipher ==
203*90e502c7SAndroid Build Coastguard Worker                     template_session_keys->rtp_xtn_hdr_cipher) {
204*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
205*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->rtp_xtn_hdr_cipher) {
206*90e502c7SAndroid Build Coastguard Worker                 status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher);
207*90e502c7SAndroid Build Coastguard Worker                 if (status)
208*90e502c7SAndroid Build Coastguard Worker                     return status;
209*90e502c7SAndroid Build Coastguard Worker             }
210*90e502c7SAndroid Build Coastguard Worker 
211*90e502c7SAndroid Build Coastguard Worker             /*
212*90e502c7SAndroid Build Coastguard Worker              * deallocate rtcp cipher, if it is not the same as that in
213*90e502c7SAndroid Build Coastguard Worker              * template
214*90e502c7SAndroid Build Coastguard Worker              */
215*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
216*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtcp_cipher ==
217*90e502c7SAndroid Build Coastguard Worker                     template_session_keys->rtcp_cipher) {
218*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
219*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->rtcp_cipher) {
220*90e502c7SAndroid Build Coastguard Worker                 status = srtp_cipher_dealloc(session_keys->rtcp_cipher);
221*90e502c7SAndroid Build Coastguard Worker                 if (status)
222*90e502c7SAndroid Build Coastguard Worker                     return status;
223*90e502c7SAndroid Build Coastguard Worker             }
224*90e502c7SAndroid Build Coastguard Worker 
225*90e502c7SAndroid Build Coastguard Worker             /*
226*90e502c7SAndroid Build Coastguard Worker              * deallocate rtcp auth function, if it is not the same as that in
227*90e502c7SAndroid Build Coastguard Worker              * template
228*90e502c7SAndroid Build Coastguard Worker              */
229*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
230*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtcp_auth == template_session_keys->rtcp_auth) {
231*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
232*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->rtcp_auth) {
233*90e502c7SAndroid Build Coastguard Worker                 status = srtp_auth_dealloc(session_keys->rtcp_auth);
234*90e502c7SAndroid Build Coastguard Worker                 if (status)
235*90e502c7SAndroid Build Coastguard Worker                     return status;
236*90e502c7SAndroid Build Coastguard Worker             }
237*90e502c7SAndroid Build Coastguard Worker 
238*90e502c7SAndroid Build Coastguard Worker             /*
239*90e502c7SAndroid Build Coastguard Worker              * zeroize the salt value
240*90e502c7SAndroid Build Coastguard Worker              */
241*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(session_keys->salt, SRTP_AEAD_SALT_LEN);
242*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(session_keys->c_salt, SRTP_AEAD_SALT_LEN);
243*90e502c7SAndroid Build Coastguard Worker 
244*90e502c7SAndroid Build Coastguard Worker             if (session_keys->mki_id) {
245*90e502c7SAndroid Build Coastguard Worker                 octet_string_set_to_zero(session_keys->mki_id,
246*90e502c7SAndroid Build Coastguard Worker                                          session_keys->mki_size);
247*90e502c7SAndroid Build Coastguard Worker                 srtp_crypto_free(session_keys->mki_id);
248*90e502c7SAndroid Build Coastguard Worker                 session_keys->mki_id = NULL;
249*90e502c7SAndroid Build Coastguard Worker             }
250*90e502c7SAndroid Build Coastguard Worker 
251*90e502c7SAndroid Build Coastguard Worker             /*
252*90e502c7SAndroid Build Coastguard Worker              * deallocate key usage limit, if it is not the same as that in
253*90e502c7SAndroid Build Coastguard Worker              * template
254*90e502c7SAndroid Build Coastguard Worker              */
255*90e502c7SAndroid Build Coastguard Worker             if (template_session_keys &&
256*90e502c7SAndroid Build Coastguard Worker                 session_keys->limit == template_session_keys->limit) {
257*90e502c7SAndroid Build Coastguard Worker                 /* do nothing */
258*90e502c7SAndroid Build Coastguard Worker             } else if (session_keys->limit) {
259*90e502c7SAndroid Build Coastguard Worker                 srtp_crypto_free(session_keys->limit);
260*90e502c7SAndroid Build Coastguard Worker             }
261*90e502c7SAndroid Build Coastguard Worker         }
262*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_free(stream->session_keys);
263*90e502c7SAndroid Build Coastguard Worker     }
264*90e502c7SAndroid Build Coastguard Worker 
265*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdbx_dealloc(&stream->rtp_rdbx);
266*90e502c7SAndroid Build Coastguard Worker     if (status)
267*90e502c7SAndroid Build Coastguard Worker         return status;
268*90e502c7SAndroid Build Coastguard Worker 
269*90e502c7SAndroid Build Coastguard Worker     /* DAM - need to deallocate EKT here */
270*90e502c7SAndroid Build Coastguard Worker 
271*90e502c7SAndroid Build Coastguard Worker     if (stream_template &&
272*90e502c7SAndroid Build Coastguard Worker         stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) {
273*90e502c7SAndroid Build Coastguard Worker         /* do nothing */
274*90e502c7SAndroid Build Coastguard Worker     } else if (stream->enc_xtn_hdr) {
275*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_free(stream->enc_xtn_hdr);
276*90e502c7SAndroid Build Coastguard Worker     }
277*90e502c7SAndroid Build Coastguard Worker 
278*90e502c7SAndroid Build Coastguard Worker     /* deallocate srtp stream context */
279*90e502c7SAndroid Build Coastguard Worker     srtp_crypto_free(stream);
280*90e502c7SAndroid Build Coastguard Worker 
281*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
282*90e502c7SAndroid Build Coastguard Worker }
283*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_alloc(srtp_stream_ctx_t ** str_ptr,const srtp_policy_t * p)284*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
285*90e502c7SAndroid Build Coastguard Worker                                     const srtp_policy_t *p)
286*90e502c7SAndroid Build Coastguard Worker {
287*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *str;
288*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t stat;
289*90e502c7SAndroid Build Coastguard Worker     unsigned int i = 0;
290*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
291*90e502c7SAndroid Build Coastguard Worker 
292*90e502c7SAndroid Build Coastguard Worker     /*
293*90e502c7SAndroid Build Coastguard Worker      * This function allocates the stream context, rtp and rtcp ciphers
294*90e502c7SAndroid Build Coastguard Worker      * and auth functions, and key limit structure.  If there is a
295*90e502c7SAndroid Build Coastguard Worker      * failure during allocation, we free all previously allocated
296*90e502c7SAndroid Build Coastguard Worker      * memory and return a failure code.  The code could probably
297*90e502c7SAndroid Build Coastguard Worker      * be improved, but it works and should be clear.
298*90e502c7SAndroid Build Coastguard Worker      */
299*90e502c7SAndroid Build Coastguard Worker 
300*90e502c7SAndroid Build Coastguard Worker     /* allocate srtp stream and set str_ptr */
301*90e502c7SAndroid Build Coastguard Worker     str = (srtp_stream_ctx_t *)srtp_crypto_alloc(sizeof(srtp_stream_ctx_t));
302*90e502c7SAndroid Build Coastguard Worker     if (str == NULL)
303*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_alloc_fail;
304*90e502c7SAndroid Build Coastguard Worker 
305*90e502c7SAndroid Build Coastguard Worker     *str_ptr = str;
306*90e502c7SAndroid Build Coastguard Worker 
307*90e502c7SAndroid Build Coastguard Worker     /*
308*90e502c7SAndroid Build Coastguard Worker      *To keep backwards API compatible if someone is using multiple master
309*90e502c7SAndroid Build Coastguard Worker      * keys then key should be set to NULL
310*90e502c7SAndroid Build Coastguard Worker      */
311*90e502c7SAndroid Build Coastguard Worker     if (p->key != NULL) {
312*90e502c7SAndroid Build Coastguard Worker         str->num_master_keys = 1;
313*90e502c7SAndroid Build Coastguard Worker     } else {
314*90e502c7SAndroid Build Coastguard Worker         str->num_master_keys = p->num_master_keys;
315*90e502c7SAndroid Build Coastguard Worker     }
316*90e502c7SAndroid Build Coastguard Worker 
317*90e502c7SAndroid Build Coastguard Worker     str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(
318*90e502c7SAndroid Build Coastguard Worker         sizeof(srtp_session_keys_t) * str->num_master_keys);
319*90e502c7SAndroid Build Coastguard Worker 
320*90e502c7SAndroid Build Coastguard Worker     if (str->session_keys == NULL) {
321*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(str, NULL);
322*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_alloc_fail;
323*90e502c7SAndroid Build Coastguard Worker     }
324*90e502c7SAndroid Build Coastguard Worker 
325*90e502c7SAndroid Build Coastguard Worker     for (i = 0; i < str->num_master_keys; i++) {
326*90e502c7SAndroid Build Coastguard Worker         session_keys = &str->session_keys[i];
327*90e502c7SAndroid Build Coastguard Worker 
328*90e502c7SAndroid Build Coastguard Worker         /* allocate cipher */
329*90e502c7SAndroid Build Coastguard Worker         stat = srtp_crypto_kernel_alloc_cipher(
330*90e502c7SAndroid Build Coastguard Worker             p->rtp.cipher_type, &session_keys->rtp_cipher,
331*90e502c7SAndroid Build Coastguard Worker             p->rtp.cipher_key_len, p->rtp.auth_tag_len);
332*90e502c7SAndroid Build Coastguard Worker         if (stat) {
333*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
334*90e502c7SAndroid Build Coastguard Worker             return stat;
335*90e502c7SAndroid Build Coastguard Worker         }
336*90e502c7SAndroid Build Coastguard Worker 
337*90e502c7SAndroid Build Coastguard Worker         /* allocate auth function */
338*90e502c7SAndroid Build Coastguard Worker         stat = srtp_crypto_kernel_alloc_auth(
339*90e502c7SAndroid Build Coastguard Worker             p->rtp.auth_type, &session_keys->rtp_auth, p->rtp.auth_key_len,
340*90e502c7SAndroid Build Coastguard Worker             p->rtp.auth_tag_len);
341*90e502c7SAndroid Build Coastguard Worker         if (stat) {
342*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
343*90e502c7SAndroid Build Coastguard Worker             return stat;
344*90e502c7SAndroid Build Coastguard Worker         }
345*90e502c7SAndroid Build Coastguard Worker 
346*90e502c7SAndroid Build Coastguard Worker         /*
347*90e502c7SAndroid Build Coastguard Worker          * ...and now the RTCP-specific initialization - first, allocate
348*90e502c7SAndroid Build Coastguard Worker          * the cipher
349*90e502c7SAndroid Build Coastguard Worker          */
350*90e502c7SAndroid Build Coastguard Worker         stat = srtp_crypto_kernel_alloc_cipher(
351*90e502c7SAndroid Build Coastguard Worker             p->rtcp.cipher_type, &session_keys->rtcp_cipher,
352*90e502c7SAndroid Build Coastguard Worker             p->rtcp.cipher_key_len, p->rtcp.auth_tag_len);
353*90e502c7SAndroid Build Coastguard Worker         if (stat) {
354*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
355*90e502c7SAndroid Build Coastguard Worker             return stat;
356*90e502c7SAndroid Build Coastguard Worker         }
357*90e502c7SAndroid Build Coastguard Worker 
358*90e502c7SAndroid Build Coastguard Worker         /* allocate auth function */
359*90e502c7SAndroid Build Coastguard Worker         stat = srtp_crypto_kernel_alloc_auth(
360*90e502c7SAndroid Build Coastguard Worker             p->rtcp.auth_type, &session_keys->rtcp_auth, p->rtcp.auth_key_len,
361*90e502c7SAndroid Build Coastguard Worker             p->rtcp.auth_tag_len);
362*90e502c7SAndroid Build Coastguard Worker         if (stat) {
363*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
364*90e502c7SAndroid Build Coastguard Worker             return stat;
365*90e502c7SAndroid Build Coastguard Worker         }
366*90e502c7SAndroid Build Coastguard Worker 
367*90e502c7SAndroid Build Coastguard Worker         session_keys->mki_id = NULL;
368*90e502c7SAndroid Build Coastguard Worker 
369*90e502c7SAndroid Build Coastguard Worker         /* allocate key limit structure */
370*90e502c7SAndroid Build Coastguard Worker         session_keys->limit = (srtp_key_limit_ctx_t *)srtp_crypto_alloc(
371*90e502c7SAndroid Build Coastguard Worker             sizeof(srtp_key_limit_ctx_t));
372*90e502c7SAndroid Build Coastguard Worker         if (session_keys->limit == NULL) {
373*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
374*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_alloc_fail;
375*90e502c7SAndroid Build Coastguard Worker         }
376*90e502c7SAndroid Build Coastguard Worker     }
377*90e502c7SAndroid Build Coastguard Worker 
378*90e502c7SAndroid Build Coastguard Worker     /* allocate ekt data associated with stream */
379*90e502c7SAndroid Build Coastguard Worker     stat = srtp_ekt_alloc(&str->ekt, p->ekt);
380*90e502c7SAndroid Build Coastguard Worker     if (stat) {
381*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(str, NULL);
382*90e502c7SAndroid Build Coastguard Worker         return stat;
383*90e502c7SAndroid Build Coastguard Worker     }
384*90e502c7SAndroid Build Coastguard Worker 
385*90e502c7SAndroid Build Coastguard Worker     if (p->enc_xtn_hdr && p->enc_xtn_hdr_count > 0) {
386*90e502c7SAndroid Build Coastguard Worker         srtp_cipher_type_id_t enc_xtn_hdr_cipher_type;
387*90e502c7SAndroid Build Coastguard Worker         int enc_xtn_hdr_cipher_key_len;
388*90e502c7SAndroid Build Coastguard Worker 
389*90e502c7SAndroid Build Coastguard Worker         str->enc_xtn_hdr = (int *)srtp_crypto_alloc(p->enc_xtn_hdr_count *
390*90e502c7SAndroid Build Coastguard Worker                                                     sizeof(p->enc_xtn_hdr[0]));
391*90e502c7SAndroid Build Coastguard Worker         if (!str->enc_xtn_hdr) {
392*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(str, NULL);
393*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_alloc_fail;
394*90e502c7SAndroid Build Coastguard Worker         }
395*90e502c7SAndroid Build Coastguard Worker         memcpy(str->enc_xtn_hdr, p->enc_xtn_hdr,
396*90e502c7SAndroid Build Coastguard Worker                p->enc_xtn_hdr_count * sizeof(p->enc_xtn_hdr[0]));
397*90e502c7SAndroid Build Coastguard Worker         str->enc_xtn_hdr_count = p->enc_xtn_hdr_count;
398*90e502c7SAndroid Build Coastguard Worker 
399*90e502c7SAndroid Build Coastguard Worker         /*
400*90e502c7SAndroid Build Coastguard Worker          * For GCM ciphers, the corresponding ICM cipher is used for header
401*90e502c7SAndroid Build Coastguard Worker          * extensions encryption.
402*90e502c7SAndroid Build Coastguard Worker          */
403*90e502c7SAndroid Build Coastguard Worker         switch (p->rtp.cipher_type) {
404*90e502c7SAndroid Build Coastguard Worker         case SRTP_AES_GCM_128:
405*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_type = SRTP_AES_ICM_128;
406*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT;
407*90e502c7SAndroid Build Coastguard Worker             break;
408*90e502c7SAndroid Build Coastguard Worker         case SRTP_AES_GCM_256:
409*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_type = SRTP_AES_ICM_256;
410*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT;
411*90e502c7SAndroid Build Coastguard Worker             break;
412*90e502c7SAndroid Build Coastguard Worker         default:
413*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_type = p->rtp.cipher_type;
414*90e502c7SAndroid Build Coastguard Worker             enc_xtn_hdr_cipher_key_len = p->rtp.cipher_key_len;
415*90e502c7SAndroid Build Coastguard Worker             break;
416*90e502c7SAndroid Build Coastguard Worker         }
417*90e502c7SAndroid Build Coastguard Worker 
418*90e502c7SAndroid Build Coastguard Worker         for (i = 0; i < str->num_master_keys; i++) {
419*90e502c7SAndroid Build Coastguard Worker             session_keys = &str->session_keys[i];
420*90e502c7SAndroid Build Coastguard Worker 
421*90e502c7SAndroid Build Coastguard Worker             /* allocate cipher for extensions header encryption */
422*90e502c7SAndroid Build Coastguard Worker             stat = srtp_crypto_kernel_alloc_cipher(
423*90e502c7SAndroid Build Coastguard Worker                 enc_xtn_hdr_cipher_type, &session_keys->rtp_xtn_hdr_cipher,
424*90e502c7SAndroid Build Coastguard Worker                 enc_xtn_hdr_cipher_key_len, 0);
425*90e502c7SAndroid Build Coastguard Worker             if (stat) {
426*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_dealloc(str, NULL);
427*90e502c7SAndroid Build Coastguard Worker                 return stat;
428*90e502c7SAndroid Build Coastguard Worker             }
429*90e502c7SAndroid Build Coastguard Worker         }
430*90e502c7SAndroid Build Coastguard Worker     } else {
431*90e502c7SAndroid Build Coastguard Worker         for (i = 0; i < str->num_master_keys; i++) {
432*90e502c7SAndroid Build Coastguard Worker             session_keys = &str->session_keys[i];
433*90e502c7SAndroid Build Coastguard Worker             session_keys->rtp_xtn_hdr_cipher = NULL;
434*90e502c7SAndroid Build Coastguard Worker         }
435*90e502c7SAndroid Build Coastguard Worker 
436*90e502c7SAndroid Build Coastguard Worker         str->enc_xtn_hdr = NULL;
437*90e502c7SAndroid Build Coastguard Worker         str->enc_xtn_hdr_count = 0;
438*90e502c7SAndroid Build Coastguard Worker     }
439*90e502c7SAndroid Build Coastguard Worker 
440*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
441*90e502c7SAndroid Build Coastguard Worker }
442*90e502c7SAndroid Build Coastguard Worker 
443*90e502c7SAndroid Build Coastguard Worker /*
444*90e502c7SAndroid Build Coastguard Worker  * srtp_stream_clone(stream_template, new) allocates a new stream and
445*90e502c7SAndroid Build Coastguard Worker  * initializes it using the cipher and auth of the stream_template
446*90e502c7SAndroid Build Coastguard Worker  *
447*90e502c7SAndroid Build Coastguard Worker  * the only unique data in a cloned stream is the replay database and
448*90e502c7SAndroid Build Coastguard Worker  * the SSRC
449*90e502c7SAndroid Build Coastguard Worker  */
450*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_clone(const srtp_stream_ctx_t * stream_template,uint32_t ssrc,srtp_stream_ctx_t ** str_ptr)451*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
452*90e502c7SAndroid Build Coastguard Worker                                     uint32_t ssrc,
453*90e502c7SAndroid Build Coastguard Worker                                     srtp_stream_ctx_t **str_ptr)
454*90e502c7SAndroid Build Coastguard Worker {
455*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
456*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *str;
457*90e502c7SAndroid Build Coastguard Worker     unsigned int i = 0;
458*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
459*90e502c7SAndroid Build Coastguard Worker     const srtp_session_keys_t *template_session_keys = NULL;
460*90e502c7SAndroid Build Coastguard Worker 
461*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ntohl(ssrc));
462*90e502c7SAndroid Build Coastguard Worker 
463*90e502c7SAndroid Build Coastguard Worker     /* allocate srtp stream and set str_ptr */
464*90e502c7SAndroid Build Coastguard Worker     str = (srtp_stream_ctx_t *)srtp_crypto_alloc(sizeof(srtp_stream_ctx_t));
465*90e502c7SAndroid Build Coastguard Worker     if (str == NULL)
466*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_alloc_fail;
467*90e502c7SAndroid Build Coastguard Worker     *str_ptr = str;
468*90e502c7SAndroid Build Coastguard Worker 
469*90e502c7SAndroid Build Coastguard Worker     str->num_master_keys = stream_template->num_master_keys;
470*90e502c7SAndroid Build Coastguard Worker     str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(
471*90e502c7SAndroid Build Coastguard Worker         sizeof(srtp_session_keys_t) * str->num_master_keys);
472*90e502c7SAndroid Build Coastguard Worker 
473*90e502c7SAndroid Build Coastguard Worker     if (str->session_keys == NULL) {
474*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(*str_ptr, stream_template);
475*90e502c7SAndroid Build Coastguard Worker         *str_ptr = NULL;
476*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_alloc_fail;
477*90e502c7SAndroid Build Coastguard Worker     }
478*90e502c7SAndroid Build Coastguard Worker 
479*90e502c7SAndroid Build Coastguard Worker     for (i = 0; i < stream_template->num_master_keys; i++) {
480*90e502c7SAndroid Build Coastguard Worker         session_keys = &str->session_keys[i];
481*90e502c7SAndroid Build Coastguard Worker         template_session_keys = &stream_template->session_keys[i];
482*90e502c7SAndroid Build Coastguard Worker 
483*90e502c7SAndroid Build Coastguard Worker         /* set cipher and auth pointers to those of the template */
484*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher = template_session_keys->rtp_cipher;
485*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_auth = template_session_keys->rtp_auth;
486*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_xtn_hdr_cipher =
487*90e502c7SAndroid Build Coastguard Worker             template_session_keys->rtp_xtn_hdr_cipher;
488*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_cipher = template_session_keys->rtcp_cipher;
489*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_auth = template_session_keys->rtcp_auth;
490*90e502c7SAndroid Build Coastguard Worker         session_keys->mki_size = template_session_keys->mki_size;
491*90e502c7SAndroid Build Coastguard Worker 
492*90e502c7SAndroid Build Coastguard Worker         if (template_session_keys->mki_size == 0) {
493*90e502c7SAndroid Build Coastguard Worker             session_keys->mki_id = NULL;
494*90e502c7SAndroid Build Coastguard Worker         } else {
495*90e502c7SAndroid Build Coastguard Worker             session_keys->mki_id =
496*90e502c7SAndroid Build Coastguard Worker                 srtp_crypto_alloc(template_session_keys->mki_size);
497*90e502c7SAndroid Build Coastguard Worker 
498*90e502c7SAndroid Build Coastguard Worker             if (session_keys->mki_id == NULL) {
499*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_dealloc(*str_ptr, stream_template);
500*90e502c7SAndroid Build Coastguard Worker                 *str_ptr = NULL;
501*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_init_fail;
502*90e502c7SAndroid Build Coastguard Worker             }
503*90e502c7SAndroid Build Coastguard Worker             memcpy(session_keys->mki_id, template_session_keys->mki_id,
504*90e502c7SAndroid Build Coastguard Worker                    session_keys->mki_size);
505*90e502c7SAndroid Build Coastguard Worker         }
506*90e502c7SAndroid Build Coastguard Worker         /* Copy the salt values */
507*90e502c7SAndroid Build Coastguard Worker         memcpy(session_keys->salt, template_session_keys->salt,
508*90e502c7SAndroid Build Coastguard Worker                SRTP_AEAD_SALT_LEN);
509*90e502c7SAndroid Build Coastguard Worker         memcpy(session_keys->c_salt, template_session_keys->c_salt,
510*90e502c7SAndroid Build Coastguard Worker                SRTP_AEAD_SALT_LEN);
511*90e502c7SAndroid Build Coastguard Worker 
512*90e502c7SAndroid Build Coastguard Worker         /* set key limit to point to that of the template */
513*90e502c7SAndroid Build Coastguard Worker         status = srtp_key_limit_clone(template_session_keys->limit,
514*90e502c7SAndroid Build Coastguard Worker                                       &session_keys->limit);
515*90e502c7SAndroid Build Coastguard Worker         if (status) {
516*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(*str_ptr, stream_template);
517*90e502c7SAndroid Build Coastguard Worker             *str_ptr = NULL;
518*90e502c7SAndroid Build Coastguard Worker             return status;
519*90e502c7SAndroid Build Coastguard Worker         }
520*90e502c7SAndroid Build Coastguard Worker     }
521*90e502c7SAndroid Build Coastguard Worker 
522*90e502c7SAndroid Build Coastguard Worker     /* initialize replay databases */
523*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdbx_init(
524*90e502c7SAndroid Build Coastguard Worker         &str->rtp_rdbx, srtp_rdbx_get_window_size(&stream_template->rtp_rdbx));
525*90e502c7SAndroid Build Coastguard Worker     if (status) {
526*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(*str_ptr, stream_template);
527*90e502c7SAndroid Build Coastguard Worker         *str_ptr = NULL;
528*90e502c7SAndroid Build Coastguard Worker         return status;
529*90e502c7SAndroid Build Coastguard Worker     }
530*90e502c7SAndroid Build Coastguard Worker     srtp_rdb_init(&str->rtcp_rdb);
531*90e502c7SAndroid Build Coastguard Worker     str->allow_repeat_tx = stream_template->allow_repeat_tx;
532*90e502c7SAndroid Build Coastguard Worker 
533*90e502c7SAndroid Build Coastguard Worker     /* set ssrc to that provided */
534*90e502c7SAndroid Build Coastguard Worker     str->ssrc = ssrc;
535*90e502c7SAndroid Build Coastguard Worker 
536*90e502c7SAndroid Build Coastguard Worker     /* reset pending ROC */
537*90e502c7SAndroid Build Coastguard Worker     str->pending_roc = 0;
538*90e502c7SAndroid Build Coastguard Worker 
539*90e502c7SAndroid Build Coastguard Worker     /* set direction and security services */
540*90e502c7SAndroid Build Coastguard Worker     str->direction = stream_template->direction;
541*90e502c7SAndroid Build Coastguard Worker     str->rtp_services = stream_template->rtp_services;
542*90e502c7SAndroid Build Coastguard Worker     str->rtcp_services = stream_template->rtcp_services;
543*90e502c7SAndroid Build Coastguard Worker 
544*90e502c7SAndroid Build Coastguard Worker     /* set pointer to EKT data associated with stream */
545*90e502c7SAndroid Build Coastguard Worker     str->ekt = stream_template->ekt;
546*90e502c7SAndroid Build Coastguard Worker 
547*90e502c7SAndroid Build Coastguard Worker     /* copy information about extensions header encryption */
548*90e502c7SAndroid Build Coastguard Worker     str->enc_xtn_hdr = stream_template->enc_xtn_hdr;
549*90e502c7SAndroid Build Coastguard Worker     str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count;
550*90e502c7SAndroid Build Coastguard Worker 
551*90e502c7SAndroid Build Coastguard Worker     /* defensive coding */
552*90e502c7SAndroid Build Coastguard Worker     str->next = NULL;
553*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
554*90e502c7SAndroid Build Coastguard Worker }
555*90e502c7SAndroid Build Coastguard Worker 
556*90e502c7SAndroid Build Coastguard Worker /*
557*90e502c7SAndroid Build Coastguard Worker  * key derivation functions, internal to libSRTP
558*90e502c7SAndroid Build Coastguard Worker  *
559*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_t is a key derivation context
560*90e502c7SAndroid Build Coastguard Worker  *
561*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_init(&kdf, cipher_id, k, keylen) initializes kdf to use cipher
562*90e502c7SAndroid Build Coastguard Worker  * described by cipher_id, with the master key k with length in octets keylen.
563*90e502c7SAndroid Build Coastguard Worker  *
564*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key
565*90e502c7SAndroid Build Coastguard Worker  * corresponding to label l and puts it into kl; the length
566*90e502c7SAndroid Build Coastguard Worker  * of the key in octets is provided as keylen.  this function
567*90e502c7SAndroid Build Coastguard Worker  * should be called once for each subkey that is derived.
568*90e502c7SAndroid Build Coastguard Worker  *
569*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_clear(&kdf) zeroizes and deallocates the kdf state
570*90e502c7SAndroid Build Coastguard Worker  */
571*90e502c7SAndroid Build Coastguard Worker 
572*90e502c7SAndroid Build Coastguard Worker typedef enum {
573*90e502c7SAndroid Build Coastguard Worker     label_rtp_encryption = 0x00,
574*90e502c7SAndroid Build Coastguard Worker     label_rtp_msg_auth = 0x01,
575*90e502c7SAndroid Build Coastguard Worker     label_rtp_salt = 0x02,
576*90e502c7SAndroid Build Coastguard Worker     label_rtcp_encryption = 0x03,
577*90e502c7SAndroid Build Coastguard Worker     label_rtcp_msg_auth = 0x04,
578*90e502c7SAndroid Build Coastguard Worker     label_rtcp_salt = 0x05,
579*90e502c7SAndroid Build Coastguard Worker     label_rtp_header_encryption = 0x06,
580*90e502c7SAndroid Build Coastguard Worker     label_rtp_header_salt = 0x07
581*90e502c7SAndroid Build Coastguard Worker } srtp_prf_label;
582*90e502c7SAndroid Build Coastguard Worker 
583*90e502c7SAndroid Build Coastguard Worker #define MAX_SRTP_KEY_LEN 256
584*90e502c7SAndroid Build Coastguard Worker 
585*90e502c7SAndroid Build Coastguard Worker #if defined(OPENSSL) && defined(OPENSSL_KDF)
586*90e502c7SAndroid Build Coastguard Worker #define MAX_SRTP_AESKEY_LEN 32
587*90e502c7SAndroid Build Coastguard Worker #define MAX_SRTP_SALT_LEN 14
588*90e502c7SAndroid Build Coastguard Worker 
589*90e502c7SAndroid Build Coastguard Worker /*
590*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_t represents a key derivation function.  The SRTP
591*90e502c7SAndroid Build Coastguard Worker  * default KDF is the only one implemented at present.
592*90e502c7SAndroid Build Coastguard Worker  */
593*90e502c7SAndroid Build Coastguard Worker typedef struct {
594*90e502c7SAndroid Build Coastguard Worker     uint8_t master_key[MAX_SRTP_AESKEY_LEN];
595*90e502c7SAndroid Build Coastguard Worker     uint8_t master_salt[MAX_SRTP_SALT_LEN];
596*90e502c7SAndroid Build Coastguard Worker     const EVP_CIPHER *evp;
597*90e502c7SAndroid Build Coastguard Worker } srtp_kdf_t;
598*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_init(srtp_kdf_t * kdf,const uint8_t * key,int key_len,int salt_len)599*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf,
600*90e502c7SAndroid Build Coastguard Worker                                        const uint8_t *key,
601*90e502c7SAndroid Build Coastguard Worker                                        int key_len,
602*90e502c7SAndroid Build Coastguard Worker                                        int salt_len)
603*90e502c7SAndroid Build Coastguard Worker {
604*90e502c7SAndroid Build Coastguard Worker     memset(kdf, 0x0, sizeof(srtp_kdf_t));
605*90e502c7SAndroid Build Coastguard Worker 
606*90e502c7SAndroid Build Coastguard Worker     /* The NULL cipher has zero key length */
607*90e502c7SAndroid Build Coastguard Worker     if (key_len == 0)
608*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_ok;
609*90e502c7SAndroid Build Coastguard Worker 
610*90e502c7SAndroid Build Coastguard Worker     if ((key_len > MAX_SRTP_AESKEY_LEN) || (salt_len > MAX_SRTP_SALT_LEN)) {
611*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
612*90e502c7SAndroid Build Coastguard Worker     }
613*90e502c7SAndroid Build Coastguard Worker     switch (key_len) {
614*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_256_KEYSIZE:
615*90e502c7SAndroid Build Coastguard Worker         kdf->evp = EVP_aes_256_ctr();
616*90e502c7SAndroid Build Coastguard Worker         break;
617*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_192_KEYSIZE:
618*90e502c7SAndroid Build Coastguard Worker         kdf->evp = EVP_aes_192_ctr();
619*90e502c7SAndroid Build Coastguard Worker         break;
620*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_128_KEYSIZE:
621*90e502c7SAndroid Build Coastguard Worker         kdf->evp = EVP_aes_128_ctr();
622*90e502c7SAndroid Build Coastguard Worker         break;
623*90e502c7SAndroid Build Coastguard Worker     default:
624*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
625*90e502c7SAndroid Build Coastguard Worker         break;
626*90e502c7SAndroid Build Coastguard Worker     }
627*90e502c7SAndroid Build Coastguard Worker     memcpy(kdf->master_key, key, key_len);
628*90e502c7SAndroid Build Coastguard Worker     memcpy(kdf->master_salt, key + key_len, salt_len);
629*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
630*90e502c7SAndroid Build Coastguard Worker }
631*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_generate(srtp_kdf_t * kdf,srtp_prf_label label,uint8_t * key,unsigned int length)632*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf,
633*90e502c7SAndroid Build Coastguard Worker                                            srtp_prf_label label,
634*90e502c7SAndroid Build Coastguard Worker                                            uint8_t *key,
635*90e502c7SAndroid Build Coastguard Worker                                            unsigned int length)
636*90e502c7SAndroid Build Coastguard Worker {
637*90e502c7SAndroid Build Coastguard Worker     int ret;
638*90e502c7SAndroid Build Coastguard Worker 
639*90e502c7SAndroid Build Coastguard Worker     /* The NULL cipher will not have an EVP */
640*90e502c7SAndroid Build Coastguard Worker     if (!kdf->evp)
641*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_ok;
642*90e502c7SAndroid Build Coastguard Worker     octet_string_set_to_zero(key, length);
643*90e502c7SAndroid Build Coastguard Worker 
644*90e502c7SAndroid Build Coastguard Worker     /*
645*90e502c7SAndroid Build Coastguard Worker      * Invoke the OpenSSL SRTP KDF function
646*90e502c7SAndroid Build Coastguard Worker      * This is useful if OpenSSL is in FIPS mode and FIP
647*90e502c7SAndroid Build Coastguard Worker      * compliance is required for SRTP.
648*90e502c7SAndroid Build Coastguard Worker      */
649*90e502c7SAndroid Build Coastguard Worker     ret = kdf_srtp(kdf->evp, (char *)&kdf->master_key,
650*90e502c7SAndroid Build Coastguard Worker                    (char *)&kdf->master_salt, NULL, NULL, label, (char *)key);
651*90e502c7SAndroid Build Coastguard Worker     if (ret == -1) {
652*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_algo_fail);
653*90e502c7SAndroid Build Coastguard Worker     }
654*90e502c7SAndroid Build Coastguard Worker 
655*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
656*90e502c7SAndroid Build Coastguard Worker }
657*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_clear(srtp_kdf_t * kdf)658*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf)
659*90e502c7SAndroid Build Coastguard Worker {
660*90e502c7SAndroid Build Coastguard Worker     octet_string_set_to_zero(kdf->master_key, MAX_SRTP_AESKEY_LEN);
661*90e502c7SAndroid Build Coastguard Worker     octet_string_set_to_zero(kdf->master_salt, MAX_SRTP_SALT_LEN);
662*90e502c7SAndroid Build Coastguard Worker     kdf->evp = NULL;
663*90e502c7SAndroid Build Coastguard Worker 
664*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
665*90e502c7SAndroid Build Coastguard Worker }
666*90e502c7SAndroid Build Coastguard Worker 
667*90e502c7SAndroid Build Coastguard Worker #else  /* if OPENSSL_KDF */
668*90e502c7SAndroid Build Coastguard Worker 
669*90e502c7SAndroid Build Coastguard Worker /*
670*90e502c7SAndroid Build Coastguard Worker  * srtp_kdf_t represents a key derivation function.  The SRTP
671*90e502c7SAndroid Build Coastguard Worker  * default KDF is the only one implemented at present.
672*90e502c7SAndroid Build Coastguard Worker  */
673*90e502c7SAndroid Build Coastguard Worker typedef struct {
674*90e502c7SAndroid Build Coastguard Worker     srtp_cipher_t *cipher; /* cipher used for key derivation  */
675*90e502c7SAndroid Build Coastguard Worker } srtp_kdf_t;
676*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_init(srtp_kdf_t * kdf,const uint8_t * key,int key_len)677*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf,
678*90e502c7SAndroid Build Coastguard Worker                                        const uint8_t *key,
679*90e502c7SAndroid Build Coastguard Worker                                        int key_len)
680*90e502c7SAndroid Build Coastguard Worker {
681*90e502c7SAndroid Build Coastguard Worker     srtp_cipher_type_id_t cipher_id;
682*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t stat;
683*90e502c7SAndroid Build Coastguard Worker 
684*90e502c7SAndroid Build Coastguard Worker     switch (key_len) {
685*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_256_KEY_LEN_WSALT:
686*90e502c7SAndroid Build Coastguard Worker         cipher_id = SRTP_AES_ICM_256;
687*90e502c7SAndroid Build Coastguard Worker         break;
688*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_192_KEY_LEN_WSALT:
689*90e502c7SAndroid Build Coastguard Worker         cipher_id = SRTP_AES_ICM_192;
690*90e502c7SAndroid Build Coastguard Worker         break;
691*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_128_KEY_LEN_WSALT:
692*90e502c7SAndroid Build Coastguard Worker         cipher_id = SRTP_AES_ICM_128;
693*90e502c7SAndroid Build Coastguard Worker         break;
694*90e502c7SAndroid Build Coastguard Worker     default:
695*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
696*90e502c7SAndroid Build Coastguard Worker         break;
697*90e502c7SAndroid Build Coastguard Worker     }
698*90e502c7SAndroid Build Coastguard Worker 
699*90e502c7SAndroid Build Coastguard Worker     stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0);
700*90e502c7SAndroid Build Coastguard Worker     if (stat)
701*90e502c7SAndroid Build Coastguard Worker         return stat;
702*90e502c7SAndroid Build Coastguard Worker 
703*90e502c7SAndroid Build Coastguard Worker     stat = srtp_cipher_init(kdf->cipher, key);
704*90e502c7SAndroid Build Coastguard Worker     if (stat) {
705*90e502c7SAndroid Build Coastguard Worker         srtp_cipher_dealloc(kdf->cipher);
706*90e502c7SAndroid Build Coastguard Worker         return stat;
707*90e502c7SAndroid Build Coastguard Worker     }
708*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
709*90e502c7SAndroid Build Coastguard Worker }
710*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_generate(srtp_kdf_t * kdf,srtp_prf_label label,uint8_t * key,unsigned int length)711*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf,
712*90e502c7SAndroid Build Coastguard Worker                                            srtp_prf_label label,
713*90e502c7SAndroid Build Coastguard Worker                                            uint8_t *key,
714*90e502c7SAndroid Build Coastguard Worker                                            unsigned int length)
715*90e502c7SAndroid Build Coastguard Worker {
716*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
717*90e502c7SAndroid Build Coastguard Worker     v128_t nonce;
718*90e502c7SAndroid Build Coastguard Worker 
719*90e502c7SAndroid Build Coastguard Worker     /* set eigth octet of nonce to <label>, set the rest of it to zero */
720*90e502c7SAndroid Build Coastguard Worker     v128_set_to_zero(&nonce);
721*90e502c7SAndroid Build Coastguard Worker     nonce.v8[7] = label;
722*90e502c7SAndroid Build Coastguard Worker 
723*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_iv(kdf->cipher, (uint8_t *)&nonce,
724*90e502c7SAndroid Build Coastguard Worker                                 srtp_direction_encrypt);
725*90e502c7SAndroid Build Coastguard Worker     if (status)
726*90e502c7SAndroid Build Coastguard Worker         return status;
727*90e502c7SAndroid Build Coastguard Worker 
728*90e502c7SAndroid Build Coastguard Worker     /* generate keystream output */
729*90e502c7SAndroid Build Coastguard Worker     octet_string_set_to_zero(key, length);
730*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_encrypt(kdf->cipher, key, &length);
731*90e502c7SAndroid Build Coastguard Worker     if (status)
732*90e502c7SAndroid Build Coastguard Worker         return status;
733*90e502c7SAndroid Build Coastguard Worker 
734*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
735*90e502c7SAndroid Build Coastguard Worker }
736*90e502c7SAndroid Build Coastguard Worker 
srtp_kdf_clear(srtp_kdf_t * kdf)737*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf)
738*90e502c7SAndroid Build Coastguard Worker {
739*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
740*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_dealloc(kdf->cipher);
741*90e502c7SAndroid Build Coastguard Worker     if (status)
742*90e502c7SAndroid Build Coastguard Worker         return status;
743*90e502c7SAndroid Build Coastguard Worker     kdf->cipher = NULL;
744*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
745*90e502c7SAndroid Build Coastguard Worker }
746*90e502c7SAndroid Build Coastguard Worker #endif /* else OPENSSL_KDF */
747*90e502c7SAndroid Build Coastguard Worker 
748*90e502c7SAndroid Build Coastguard Worker /*
749*90e502c7SAndroid Build Coastguard Worker  *  end of key derivation functions
750*90e502c7SAndroid Build Coastguard Worker  */
751*90e502c7SAndroid Build Coastguard Worker 
752*90e502c7SAndroid Build Coastguard Worker /* Get the base key length corresponding to a given combined key+salt
753*90e502c7SAndroid Build Coastguard Worker  * length for the given cipher.
754*90e502c7SAndroid Build Coastguard Worker  * TODO: key and salt lengths should be separate fields in the policy.  */
base_key_length(const srtp_cipher_type_t * cipher,int key_length)755*90e502c7SAndroid Build Coastguard Worker static inline int base_key_length(const srtp_cipher_type_t *cipher,
756*90e502c7SAndroid Build Coastguard Worker                                   int key_length)
757*90e502c7SAndroid Build Coastguard Worker {
758*90e502c7SAndroid Build Coastguard Worker     switch (cipher->id) {
759*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_128:
760*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_192:
761*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_ICM_256:
762*90e502c7SAndroid Build Coastguard Worker         /* The legacy modes are derived from
763*90e502c7SAndroid Build Coastguard Worker          * the configured key length on the policy */
764*90e502c7SAndroid Build Coastguard Worker         return key_length - SRTP_SALT_LEN;
765*90e502c7SAndroid Build Coastguard Worker         break;
766*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_GCM_128:
767*90e502c7SAndroid Build Coastguard Worker         return key_length - SRTP_AEAD_SALT_LEN;
768*90e502c7SAndroid Build Coastguard Worker         break;
769*90e502c7SAndroid Build Coastguard Worker     case SRTP_AES_GCM_256:
770*90e502c7SAndroid Build Coastguard Worker         return key_length - SRTP_AEAD_SALT_LEN;
771*90e502c7SAndroid Build Coastguard Worker         break;
772*90e502c7SAndroid Build Coastguard Worker     default:
773*90e502c7SAndroid Build Coastguard Worker         return key_length;
774*90e502c7SAndroid Build Coastguard Worker         break;
775*90e502c7SAndroid Build Coastguard Worker     }
776*90e502c7SAndroid Build Coastguard Worker }
777*90e502c7SAndroid Build Coastguard Worker 
srtp_validate_policy_master_keys(const srtp_policy_t * policy)778*90e502c7SAndroid Build Coastguard Worker unsigned int srtp_validate_policy_master_keys(const srtp_policy_t *policy)
779*90e502c7SAndroid Build Coastguard Worker {
780*90e502c7SAndroid Build Coastguard Worker     unsigned long i = 0;
781*90e502c7SAndroid Build Coastguard Worker 
782*90e502c7SAndroid Build Coastguard Worker     if (policy->key == NULL) {
783*90e502c7SAndroid Build Coastguard Worker         if (policy->num_master_keys <= 0)
784*90e502c7SAndroid Build Coastguard Worker             return 0;
785*90e502c7SAndroid Build Coastguard Worker 
786*90e502c7SAndroid Build Coastguard Worker         if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS)
787*90e502c7SAndroid Build Coastguard Worker             return 0;
788*90e502c7SAndroid Build Coastguard Worker 
789*90e502c7SAndroid Build Coastguard Worker         for (i = 0; i < policy->num_master_keys; i++) {
790*90e502c7SAndroid Build Coastguard Worker             if (policy->keys[i]->key == NULL)
791*90e502c7SAndroid Build Coastguard Worker                 return 0;
792*90e502c7SAndroid Build Coastguard Worker             if (policy->keys[i]->mki_size > SRTP_MAX_MKI_LEN)
793*90e502c7SAndroid Build Coastguard Worker                 return 0;
794*90e502c7SAndroid Build Coastguard Worker         }
795*90e502c7SAndroid Build Coastguard Worker     }
796*90e502c7SAndroid Build Coastguard Worker 
797*90e502c7SAndroid Build Coastguard Worker     return 1;
798*90e502c7SAndroid Build Coastguard Worker }
799*90e502c7SAndroid Build Coastguard Worker 
srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t * stream,unsigned int use_mki,unsigned int mki_index)800*90e502c7SAndroid Build Coastguard Worker srtp_session_keys_t *srtp_get_session_keys_with_mki_index(
801*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream,
802*90e502c7SAndroid Build Coastguard Worker     unsigned int use_mki,
803*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_index)
804*90e502c7SAndroid Build Coastguard Worker {
805*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
806*90e502c7SAndroid Build Coastguard Worker         if (mki_index >= stream->num_master_keys) {
807*90e502c7SAndroid Build Coastguard Worker             return NULL;
808*90e502c7SAndroid Build Coastguard Worker         }
809*90e502c7SAndroid Build Coastguard Worker         return &stream->session_keys[mki_index];
810*90e502c7SAndroid Build Coastguard Worker     }
811*90e502c7SAndroid Build Coastguard Worker 
812*90e502c7SAndroid Build Coastguard Worker     return &stream->session_keys[0];
813*90e502c7SAndroid Build Coastguard Worker }
814*90e502c7SAndroid Build Coastguard Worker 
srtp_inject_mki(uint8_t * mki_tag_location,srtp_session_keys_t * session_keys,unsigned int use_mki)815*90e502c7SAndroid Build Coastguard Worker unsigned int srtp_inject_mki(uint8_t *mki_tag_location,
816*90e502c7SAndroid Build Coastguard Worker                              srtp_session_keys_t *session_keys,
817*90e502c7SAndroid Build Coastguard Worker                              unsigned int use_mki)
818*90e502c7SAndroid Build Coastguard Worker {
819*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
820*90e502c7SAndroid Build Coastguard Worker 
821*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
822*90e502c7SAndroid Build Coastguard Worker         mki_size = session_keys->mki_size;
823*90e502c7SAndroid Build Coastguard Worker 
824*90e502c7SAndroid Build Coastguard Worker         if (mki_size != 0) {
825*90e502c7SAndroid Build Coastguard Worker             // Write MKI into memory
826*90e502c7SAndroid Build Coastguard Worker             memcpy(mki_tag_location, session_keys->mki_id, mki_size);
827*90e502c7SAndroid Build Coastguard Worker         }
828*90e502c7SAndroid Build Coastguard Worker     }
829*90e502c7SAndroid Build Coastguard Worker 
830*90e502c7SAndroid Build Coastguard Worker     return mki_size;
831*90e502c7SAndroid Build Coastguard Worker }
832*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_init_all_master_keys(srtp_stream_ctx_t * srtp,unsigned char * key,srtp_master_key_t ** keys,const unsigned int max_master_keys)833*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_init_all_master_keys(
834*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *srtp,
835*90e502c7SAndroid Build Coastguard Worker     unsigned char *key,
836*90e502c7SAndroid Build Coastguard Worker     srtp_master_key_t **keys,
837*90e502c7SAndroid Build Coastguard Worker     const unsigned int max_master_keys)
838*90e502c7SAndroid Build Coastguard Worker {
839*90e502c7SAndroid Build Coastguard Worker     unsigned int i = 0;
840*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status = srtp_err_status_ok;
841*90e502c7SAndroid Build Coastguard Worker     srtp_master_key_t single_master_key;
842*90e502c7SAndroid Build Coastguard Worker 
843*90e502c7SAndroid Build Coastguard Worker     if (key != NULL) {
844*90e502c7SAndroid Build Coastguard Worker         srtp->num_master_keys = 1;
845*90e502c7SAndroid Build Coastguard Worker         single_master_key.key = key;
846*90e502c7SAndroid Build Coastguard Worker         single_master_key.mki_id = NULL;
847*90e502c7SAndroid Build Coastguard Worker         single_master_key.mki_size = 0;
848*90e502c7SAndroid Build Coastguard Worker         status = srtp_stream_init_keys(srtp, &single_master_key, 0);
849*90e502c7SAndroid Build Coastguard Worker     } else {
850*90e502c7SAndroid Build Coastguard Worker         srtp->num_master_keys = max_master_keys;
851*90e502c7SAndroid Build Coastguard Worker 
852*90e502c7SAndroid Build Coastguard Worker         for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS;
853*90e502c7SAndroid Build Coastguard Worker              i++) {
854*90e502c7SAndroid Build Coastguard Worker             status = srtp_stream_init_keys(srtp, keys[i], i);
855*90e502c7SAndroid Build Coastguard Worker 
856*90e502c7SAndroid Build Coastguard Worker             if (status) {
857*90e502c7SAndroid Build Coastguard Worker                 return status;
858*90e502c7SAndroid Build Coastguard Worker             }
859*90e502c7SAndroid Build Coastguard Worker         }
860*90e502c7SAndroid Build Coastguard Worker     }
861*90e502c7SAndroid Build Coastguard Worker 
862*90e502c7SAndroid Build Coastguard Worker     return status;
863*90e502c7SAndroid Build Coastguard Worker }
864*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_init_keys(srtp_stream_ctx_t * srtp,srtp_master_key_t * master_key,const unsigned int current_mki_index)865*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
866*90e502c7SAndroid Build Coastguard Worker                                         srtp_master_key_t *master_key,
867*90e502c7SAndroid Build Coastguard Worker                                         const unsigned int current_mki_index)
868*90e502c7SAndroid Build Coastguard Worker {
869*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t stat;
870*90e502c7SAndroid Build Coastguard Worker     srtp_kdf_t kdf;
871*90e502c7SAndroid Build Coastguard Worker     uint8_t tmp_key[MAX_SRTP_KEY_LEN];
872*90e502c7SAndroid Build Coastguard Worker     int kdf_keylen = 30, rtp_keylen, rtcp_keylen;
873*90e502c7SAndroid Build Coastguard Worker     int rtp_base_key_len, rtp_salt_len;
874*90e502c7SAndroid Build Coastguard Worker     int rtcp_base_key_len, rtcp_salt_len;
875*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
876*90e502c7SAndroid Build Coastguard Worker     unsigned char *key = master_key->key;
877*90e502c7SAndroid Build Coastguard Worker 
878*90e502c7SAndroid Build Coastguard Worker     /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */
879*90e502c7SAndroid Build Coastguard Worker     /* TODO: kdf algorithm, master key length, and master salt length should
880*90e502c7SAndroid Build Coastguard Worker      * be part of srtp_policy_t.
881*90e502c7SAndroid Build Coastguard Worker     */
882*90e502c7SAndroid Build Coastguard Worker     session_keys = &srtp->session_keys[current_mki_index];
883*90e502c7SAndroid Build Coastguard Worker 
884*90e502c7SAndroid Build Coastguard Worker /* initialize key limit to maximum value */
885*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
886*90e502c7SAndroid Build Coastguard Worker     {
887*90e502c7SAndroid Build Coastguard Worker         uint64_t temp;
888*90e502c7SAndroid Build Coastguard Worker         temp = make64(UINT_MAX, UINT_MAX);
889*90e502c7SAndroid Build Coastguard Worker         srtp_key_limit_set(session_keys->limit, temp);
890*90e502c7SAndroid Build Coastguard Worker     }
891*90e502c7SAndroid Build Coastguard Worker #else
892*90e502c7SAndroid Build Coastguard Worker     srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL);
893*90e502c7SAndroid Build Coastguard Worker #endif
894*90e502c7SAndroid Build Coastguard Worker 
895*90e502c7SAndroid Build Coastguard Worker     if (master_key->mki_size != 0) {
896*90e502c7SAndroid Build Coastguard Worker         session_keys->mki_id = srtp_crypto_alloc(master_key->mki_size);
897*90e502c7SAndroid Build Coastguard Worker 
898*90e502c7SAndroid Build Coastguard Worker         if (session_keys->mki_id == NULL) {
899*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_init_fail;
900*90e502c7SAndroid Build Coastguard Worker         }
901*90e502c7SAndroid Build Coastguard Worker         memcpy(session_keys->mki_id, master_key->mki_id, master_key->mki_size);
902*90e502c7SAndroid Build Coastguard Worker     } else {
903*90e502c7SAndroid Build Coastguard Worker         session_keys->mki_id = NULL;
904*90e502c7SAndroid Build Coastguard Worker     }
905*90e502c7SAndroid Build Coastguard Worker 
906*90e502c7SAndroid Build Coastguard Worker     session_keys->mki_size = master_key->mki_size;
907*90e502c7SAndroid Build Coastguard Worker 
908*90e502c7SAndroid Build Coastguard Worker     rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher);
909*90e502c7SAndroid Build Coastguard Worker     rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher);
910*90e502c7SAndroid Build Coastguard Worker     rtp_base_key_len =
911*90e502c7SAndroid Build Coastguard Worker         base_key_length(session_keys->rtp_cipher->type, rtp_keylen);
912*90e502c7SAndroid Build Coastguard Worker     rtp_salt_len = rtp_keylen - rtp_base_key_len;
913*90e502c7SAndroid Build Coastguard Worker 
914*90e502c7SAndroid Build Coastguard Worker     if (rtp_keylen > kdf_keylen) {
915*90e502c7SAndroid Build Coastguard Worker         kdf_keylen = 46; /* AES-CTR mode is always used for KDF */
916*90e502c7SAndroid Build Coastguard Worker     }
917*90e502c7SAndroid Build Coastguard Worker 
918*90e502c7SAndroid Build Coastguard Worker     if (rtcp_keylen > kdf_keylen) {
919*90e502c7SAndroid Build Coastguard Worker         kdf_keylen = 46; /* AES-CTR mode is always used for KDF */
920*90e502c7SAndroid Build Coastguard Worker     }
921*90e502c7SAndroid Build Coastguard Worker 
922*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtp key len: %d", rtp_keylen);
923*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp key len: %d", rtcp_keylen);
924*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "base key len: %d", rtp_base_key_len);
925*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "kdf key len: %d", kdf_keylen);
926*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "rtp salt len: %d", rtp_salt_len);
927*90e502c7SAndroid Build Coastguard Worker 
928*90e502c7SAndroid Build Coastguard Worker     /*
929*90e502c7SAndroid Build Coastguard Worker      * Make sure the key given to us is 'zero' appended.  GCM
930*90e502c7SAndroid Build Coastguard Worker      * mode uses a shorter master SALT (96 bits), but still relies on
931*90e502c7SAndroid Build Coastguard Worker      * the legacy CTR mode KDF, which uses a 112 bit master SALT.
932*90e502c7SAndroid Build Coastguard Worker      */
933*90e502c7SAndroid Build Coastguard Worker     memset(tmp_key, 0x0, MAX_SRTP_KEY_LEN);
934*90e502c7SAndroid Build Coastguard Worker     memcpy(tmp_key, key, (rtp_base_key_len + rtp_salt_len));
935*90e502c7SAndroid Build Coastguard Worker 
936*90e502c7SAndroid Build Coastguard Worker /* initialize KDF state     */
937*90e502c7SAndroid Build Coastguard Worker #if defined(OPENSSL) && defined(OPENSSL_KDF)
938*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, rtp_base_key_len,
939*90e502c7SAndroid Build Coastguard Worker                          rtp_salt_len);
940*90e502c7SAndroid Build Coastguard Worker #else
941*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, kdf_keylen);
942*90e502c7SAndroid Build Coastguard Worker #endif
943*90e502c7SAndroid Build Coastguard Worker     if (stat) {
944*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
945*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
946*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
947*90e502c7SAndroid Build Coastguard Worker     }
948*90e502c7SAndroid Build Coastguard Worker 
949*90e502c7SAndroid Build Coastguard Worker     /* generate encryption key  */
950*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_generate(&kdf, label_rtp_encryption, tmp_key,
951*90e502c7SAndroid Build Coastguard Worker                              rtp_base_key_len);
952*90e502c7SAndroid Build Coastguard Worker     if (stat) {
953*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
954*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
955*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
956*90e502c7SAndroid Build Coastguard Worker     }
957*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "cipher key: %s",
958*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(tmp_key, rtp_base_key_len));
959*90e502c7SAndroid Build Coastguard Worker 
960*90e502c7SAndroid Build Coastguard Worker     /*
961*90e502c7SAndroid Build Coastguard Worker      * if the cipher in the srtp context uses a salt, then we need
962*90e502c7SAndroid Build Coastguard Worker      * to generate the salt value
963*90e502c7SAndroid Build Coastguard Worker      */
964*90e502c7SAndroid Build Coastguard Worker     if (rtp_salt_len > 0) {
965*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL);
966*90e502c7SAndroid Build Coastguard Worker 
967*90e502c7SAndroid Build Coastguard Worker         /* generate encryption salt, put after encryption key */
968*90e502c7SAndroid Build Coastguard Worker         stat = srtp_kdf_generate(&kdf, label_rtp_salt,
969*90e502c7SAndroid Build Coastguard Worker                                  tmp_key + rtp_base_key_len, rtp_salt_len);
970*90e502c7SAndroid Build Coastguard Worker         if (stat) {
971*90e502c7SAndroid Build Coastguard Worker             /* zeroize temp buffer */
972*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
973*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_init_fail;
974*90e502c7SAndroid Build Coastguard Worker         }
975*90e502c7SAndroid Build Coastguard Worker         memcpy(session_keys->salt, tmp_key + rtp_base_key_len,
976*90e502c7SAndroid Build Coastguard Worker                SRTP_AEAD_SALT_LEN);
977*90e502c7SAndroid Build Coastguard Worker     }
978*90e502c7SAndroid Build Coastguard Worker     if (rtp_salt_len > 0) {
979*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "cipher salt: %s",
980*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(tmp_key + rtp_base_key_len,
981*90e502c7SAndroid Build Coastguard Worker                                                  rtp_salt_len));
982*90e502c7SAndroid Build Coastguard Worker     }
983*90e502c7SAndroid Build Coastguard Worker 
984*90e502c7SAndroid Build Coastguard Worker     /* initialize cipher */
985*90e502c7SAndroid Build Coastguard Worker     stat = srtp_cipher_init(session_keys->rtp_cipher, tmp_key);
986*90e502c7SAndroid Build Coastguard Worker     if (stat) {
987*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
988*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
989*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
990*90e502c7SAndroid Build Coastguard Worker     }
991*90e502c7SAndroid Build Coastguard Worker 
992*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_xtn_hdr_cipher) {
993*90e502c7SAndroid Build Coastguard Worker         /* generate extensions header encryption key  */
994*90e502c7SAndroid Build Coastguard Worker         int rtp_xtn_hdr_keylen;
995*90e502c7SAndroid Build Coastguard Worker         int rtp_xtn_hdr_base_key_len;
996*90e502c7SAndroid Build Coastguard Worker         int rtp_xtn_hdr_salt_len;
997*90e502c7SAndroid Build Coastguard Worker         srtp_kdf_t tmp_kdf;
998*90e502c7SAndroid Build Coastguard Worker         srtp_kdf_t *xtn_hdr_kdf;
999*90e502c7SAndroid Build Coastguard Worker 
1000*90e502c7SAndroid Build Coastguard Worker         if (session_keys->rtp_xtn_hdr_cipher->type !=
1001*90e502c7SAndroid Build Coastguard Worker             session_keys->rtp_cipher->type) {
1002*90e502c7SAndroid Build Coastguard Worker             /*
1003*90e502c7SAndroid Build Coastguard Worker              * With GCM ciphers, the header extensions are still encrypted using
1004*90e502c7SAndroid Build Coastguard Worker              * the corresponding ICM cipher.
1005*90e502c7SAndroid Build Coastguard Worker              * See https://tools.ietf.org/html/rfc7714#section-8.3
1006*90e502c7SAndroid Build Coastguard Worker              */
1007*90e502c7SAndroid Build Coastguard Worker             uint8_t tmp_xtn_hdr_key[MAX_SRTP_KEY_LEN];
1008*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_keylen =
1009*90e502c7SAndroid Build Coastguard Worker                 srtp_cipher_get_key_length(session_keys->rtp_xtn_hdr_cipher);
1010*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_base_key_len = base_key_length(
1011*90e502c7SAndroid Build Coastguard Worker                 session_keys->rtp_xtn_hdr_cipher->type, rtp_xtn_hdr_keylen);
1012*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_salt_len =
1013*90e502c7SAndroid Build Coastguard Worker                 rtp_xtn_hdr_keylen - rtp_xtn_hdr_base_key_len;
1014*90e502c7SAndroid Build Coastguard Worker             if (rtp_xtn_hdr_salt_len > rtp_salt_len) {
1015*90e502c7SAndroid Build Coastguard Worker                 switch (session_keys->rtp_cipher->type->id) {
1016*90e502c7SAndroid Build Coastguard Worker                 case SRTP_AES_GCM_128:
1017*90e502c7SAndroid Build Coastguard Worker                 case SRTP_AES_GCM_256:
1018*90e502c7SAndroid Build Coastguard Worker                     /*
1019*90e502c7SAndroid Build Coastguard Worker                      * The shorter GCM salt is padded to the required ICM salt
1020*90e502c7SAndroid Build Coastguard Worker                      * length.
1021*90e502c7SAndroid Build Coastguard Worker                      */
1022*90e502c7SAndroid Build Coastguard Worker                     rtp_xtn_hdr_salt_len = rtp_salt_len;
1023*90e502c7SAndroid Build Coastguard Worker                     break;
1024*90e502c7SAndroid Build Coastguard Worker                 default:
1025*90e502c7SAndroid Build Coastguard Worker                     /* zeroize temp buffer */
1026*90e502c7SAndroid Build Coastguard Worker                     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1027*90e502c7SAndroid Build Coastguard Worker                     return srtp_err_status_bad_param;
1028*90e502c7SAndroid Build Coastguard Worker                 }
1029*90e502c7SAndroid Build Coastguard Worker             }
1030*90e502c7SAndroid Build Coastguard Worker             memset(tmp_xtn_hdr_key, 0x0, MAX_SRTP_KEY_LEN);
1031*90e502c7SAndroid Build Coastguard Worker             memcpy(tmp_xtn_hdr_key, key,
1032*90e502c7SAndroid Build Coastguard Worker                    (rtp_xtn_hdr_base_key_len + rtp_xtn_hdr_salt_len));
1033*90e502c7SAndroid Build Coastguard Worker             xtn_hdr_kdf = &tmp_kdf;
1034*90e502c7SAndroid Build Coastguard Worker 
1035*90e502c7SAndroid Build Coastguard Worker /* initialize KDF state */
1036*90e502c7SAndroid Build Coastguard Worker #if defined(OPENSSL) && defined(OPENSSL_KDF)
1037*90e502c7SAndroid Build Coastguard Worker             stat =
1038*90e502c7SAndroid Build Coastguard Worker                 srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key,
1039*90e502c7SAndroid Build Coastguard Worker                               rtp_xtn_hdr_base_key_len, rtp_xtn_hdr_salt_len);
1040*90e502c7SAndroid Build Coastguard Worker #else
1041*90e502c7SAndroid Build Coastguard Worker             stat = srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key,
1042*90e502c7SAndroid Build Coastguard Worker                                  kdf_keylen);
1043*90e502c7SAndroid Build Coastguard Worker #endif
1044*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(tmp_xtn_hdr_key, MAX_SRTP_KEY_LEN);
1045*90e502c7SAndroid Build Coastguard Worker             if (stat) {
1046*90e502c7SAndroid Build Coastguard Worker                 /* zeroize temp buffer */
1047*90e502c7SAndroid Build Coastguard Worker                 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1048*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_init_fail;
1049*90e502c7SAndroid Build Coastguard Worker             }
1050*90e502c7SAndroid Build Coastguard Worker         } else {
1051*90e502c7SAndroid Build Coastguard Worker             /* Reuse main KDF. */
1052*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_keylen = rtp_keylen;
1053*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_base_key_len = rtp_base_key_len;
1054*90e502c7SAndroid Build Coastguard Worker             rtp_xtn_hdr_salt_len = rtp_salt_len;
1055*90e502c7SAndroid Build Coastguard Worker             xtn_hdr_kdf = &kdf;
1056*90e502c7SAndroid Build Coastguard Worker         }
1057*90e502c7SAndroid Build Coastguard Worker 
1058*90e502c7SAndroid Build Coastguard Worker         stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_encryption,
1059*90e502c7SAndroid Build Coastguard Worker                                  tmp_key, rtp_xtn_hdr_base_key_len);
1060*90e502c7SAndroid Build Coastguard Worker         if (stat) {
1061*90e502c7SAndroid Build Coastguard Worker             /* zeroize temp buffer */
1062*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1063*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_init_fail;
1064*90e502c7SAndroid Build Coastguard Worker         }
1065*90e502c7SAndroid Build Coastguard Worker         debug_print(
1066*90e502c7SAndroid Build Coastguard Worker             mod_srtp, "extensions cipher key: %s",
1067*90e502c7SAndroid Build Coastguard Worker             srtp_octet_string_hex_string(tmp_key, rtp_xtn_hdr_base_key_len));
1068*90e502c7SAndroid Build Coastguard Worker 
1069*90e502c7SAndroid Build Coastguard Worker         /*
1070*90e502c7SAndroid Build Coastguard Worker          * if the cipher in the srtp context uses a salt, then we need
1071*90e502c7SAndroid Build Coastguard Worker          * to generate the salt value
1072*90e502c7SAndroid Build Coastguard Worker          */
1073*90e502c7SAndroid Build Coastguard Worker         if (rtp_xtn_hdr_salt_len > 0) {
1074*90e502c7SAndroid Build Coastguard Worker             debug_print(mod_srtp,
1075*90e502c7SAndroid Build Coastguard Worker                         "found rtp_xtn_hdr_salt_len > 0, generating salt",
1076*90e502c7SAndroid Build Coastguard Worker                         NULL);
1077*90e502c7SAndroid Build Coastguard Worker 
1078*90e502c7SAndroid Build Coastguard Worker             /* generate encryption salt, put after encryption key */
1079*90e502c7SAndroid Build Coastguard Worker             stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt,
1080*90e502c7SAndroid Build Coastguard Worker                                      tmp_key + rtp_xtn_hdr_base_key_len,
1081*90e502c7SAndroid Build Coastguard Worker                                      rtp_xtn_hdr_salt_len);
1082*90e502c7SAndroid Build Coastguard Worker             if (stat) {
1083*90e502c7SAndroid Build Coastguard Worker                 /* zeroize temp buffer */
1084*90e502c7SAndroid Build Coastguard Worker                 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1085*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_init_fail;
1086*90e502c7SAndroid Build Coastguard Worker             }
1087*90e502c7SAndroid Build Coastguard Worker         }
1088*90e502c7SAndroid Build Coastguard Worker         if (rtp_xtn_hdr_salt_len > 0) {
1089*90e502c7SAndroid Build Coastguard Worker             debug_print(
1090*90e502c7SAndroid Build Coastguard Worker                 mod_srtp, "extensions cipher salt: %s",
1091*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(tmp_key + rtp_xtn_hdr_base_key_len,
1092*90e502c7SAndroid Build Coastguard Worker                                              rtp_xtn_hdr_salt_len));
1093*90e502c7SAndroid Build Coastguard Worker         }
1094*90e502c7SAndroid Build Coastguard Worker 
1095*90e502c7SAndroid Build Coastguard Worker         /* initialize extensions header cipher */
1096*90e502c7SAndroid Build Coastguard Worker         stat = srtp_cipher_init(session_keys->rtp_xtn_hdr_cipher, tmp_key);
1097*90e502c7SAndroid Build Coastguard Worker         if (stat) {
1098*90e502c7SAndroid Build Coastguard Worker             /* zeroize temp buffer */
1099*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1100*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_init_fail;
1101*90e502c7SAndroid Build Coastguard Worker         }
1102*90e502c7SAndroid Build Coastguard Worker 
1103*90e502c7SAndroid Build Coastguard Worker         if (xtn_hdr_kdf != &kdf) {
1104*90e502c7SAndroid Build Coastguard Worker             /* release memory for custom header extension encryption kdf */
1105*90e502c7SAndroid Build Coastguard Worker             stat = srtp_kdf_clear(xtn_hdr_kdf);
1106*90e502c7SAndroid Build Coastguard Worker             if (stat) {
1107*90e502c7SAndroid Build Coastguard Worker                 /* zeroize temp buffer */
1108*90e502c7SAndroid Build Coastguard Worker                 octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1109*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_init_fail;
1110*90e502c7SAndroid Build Coastguard Worker             }
1111*90e502c7SAndroid Build Coastguard Worker         }
1112*90e502c7SAndroid Build Coastguard Worker     }
1113*90e502c7SAndroid Build Coastguard Worker 
1114*90e502c7SAndroid Build Coastguard Worker     /* generate authentication key */
1115*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth, tmp_key,
1116*90e502c7SAndroid Build Coastguard Worker                              srtp_auth_get_key_length(session_keys->rtp_auth));
1117*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1118*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1119*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1120*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1121*90e502c7SAndroid Build Coastguard Worker     }
1122*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "auth key:   %s",
1123*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(
1124*90e502c7SAndroid Build Coastguard Worker                     tmp_key, srtp_auth_get_key_length(session_keys->rtp_auth)));
1125*90e502c7SAndroid Build Coastguard Worker 
1126*90e502c7SAndroid Build Coastguard Worker     /* initialize auth function */
1127*90e502c7SAndroid Build Coastguard Worker     stat = srtp_auth_init(session_keys->rtp_auth, tmp_key);
1128*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1129*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1130*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1131*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1132*90e502c7SAndroid Build Coastguard Worker     }
1133*90e502c7SAndroid Build Coastguard Worker 
1134*90e502c7SAndroid Build Coastguard Worker     /*
1135*90e502c7SAndroid Build Coastguard Worker      * ...now initialize SRTCP keys
1136*90e502c7SAndroid Build Coastguard Worker      */
1137*90e502c7SAndroid Build Coastguard Worker 
1138*90e502c7SAndroid Build Coastguard Worker     rtcp_base_key_len =
1139*90e502c7SAndroid Build Coastguard Worker         base_key_length(session_keys->rtcp_cipher->type, rtcp_keylen);
1140*90e502c7SAndroid Build Coastguard Worker     rtcp_salt_len = rtcp_keylen - rtcp_base_key_len;
1141*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "rtcp salt len: %d", rtcp_salt_len);
1142*90e502c7SAndroid Build Coastguard Worker 
1143*90e502c7SAndroid Build Coastguard Worker     /* generate encryption key  */
1144*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_generate(&kdf, label_rtcp_encryption, tmp_key,
1145*90e502c7SAndroid Build Coastguard Worker                              rtcp_base_key_len);
1146*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1147*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1148*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1149*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1150*90e502c7SAndroid Build Coastguard Worker     }
1151*90e502c7SAndroid Build Coastguard Worker 
1152*90e502c7SAndroid Build Coastguard Worker     /*
1153*90e502c7SAndroid Build Coastguard Worker      * if the cipher in the srtp context uses a salt, then we need
1154*90e502c7SAndroid Build Coastguard Worker      * to generate the salt value
1155*90e502c7SAndroid Build Coastguard Worker      */
1156*90e502c7SAndroid Build Coastguard Worker     if (rtcp_salt_len > 0) {
1157*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt",
1158*90e502c7SAndroid Build Coastguard Worker                     NULL);
1159*90e502c7SAndroid Build Coastguard Worker 
1160*90e502c7SAndroid Build Coastguard Worker         /* generate encryption salt, put after encryption key */
1161*90e502c7SAndroid Build Coastguard Worker         stat = srtp_kdf_generate(&kdf, label_rtcp_salt,
1162*90e502c7SAndroid Build Coastguard Worker                                  tmp_key + rtcp_base_key_len, rtcp_salt_len);
1163*90e502c7SAndroid Build Coastguard Worker         if (stat) {
1164*90e502c7SAndroid Build Coastguard Worker             /* zeroize temp buffer */
1165*90e502c7SAndroid Build Coastguard Worker             octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1166*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_init_fail;
1167*90e502c7SAndroid Build Coastguard Worker         }
1168*90e502c7SAndroid Build Coastguard Worker         memcpy(session_keys->c_salt, tmp_key + rtcp_base_key_len,
1169*90e502c7SAndroid Build Coastguard Worker                SRTP_AEAD_SALT_LEN);
1170*90e502c7SAndroid Build Coastguard Worker     }
1171*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "rtcp cipher key: %s",
1172*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(tmp_key, rtcp_base_key_len));
1173*90e502c7SAndroid Build Coastguard Worker     if (rtcp_salt_len > 0) {
1174*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "rtcp cipher salt: %s",
1175*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(tmp_key + rtcp_base_key_len,
1176*90e502c7SAndroid Build Coastguard Worker                                                  rtcp_salt_len));
1177*90e502c7SAndroid Build Coastguard Worker     }
1178*90e502c7SAndroid Build Coastguard Worker 
1179*90e502c7SAndroid Build Coastguard Worker     /* initialize cipher */
1180*90e502c7SAndroid Build Coastguard Worker     stat = srtp_cipher_init(session_keys->rtcp_cipher, tmp_key);
1181*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1182*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1183*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1184*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1185*90e502c7SAndroid Build Coastguard Worker     }
1186*90e502c7SAndroid Build Coastguard Worker 
1187*90e502c7SAndroid Build Coastguard Worker     /* generate authentication key */
1188*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth, tmp_key,
1189*90e502c7SAndroid Build Coastguard Worker                              srtp_auth_get_key_length(session_keys->rtcp_auth));
1190*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1191*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1192*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1193*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1194*90e502c7SAndroid Build Coastguard Worker     }
1195*90e502c7SAndroid Build Coastguard Worker 
1196*90e502c7SAndroid Build Coastguard Worker     debug_print(
1197*90e502c7SAndroid Build Coastguard Worker         mod_srtp, "rtcp auth key:   %s",
1198*90e502c7SAndroid Build Coastguard Worker         srtp_octet_string_hex_string(
1199*90e502c7SAndroid Build Coastguard Worker             tmp_key, srtp_auth_get_key_length(session_keys->rtcp_auth)));
1200*90e502c7SAndroid Build Coastguard Worker 
1201*90e502c7SAndroid Build Coastguard Worker     /* initialize auth function */
1202*90e502c7SAndroid Build Coastguard Worker     stat = srtp_auth_init(session_keys->rtcp_auth, tmp_key);
1203*90e502c7SAndroid Build Coastguard Worker     if (stat) {
1204*90e502c7SAndroid Build Coastguard Worker         /* zeroize temp buffer */
1205*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1206*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1207*90e502c7SAndroid Build Coastguard Worker     }
1208*90e502c7SAndroid Build Coastguard Worker 
1209*90e502c7SAndroid Build Coastguard Worker     /* clear memory then return */
1210*90e502c7SAndroid Build Coastguard Worker     stat = srtp_kdf_clear(&kdf);
1211*90e502c7SAndroid Build Coastguard Worker     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
1212*90e502c7SAndroid Build Coastguard Worker     if (stat)
1213*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_init_fail;
1214*90e502c7SAndroid Build Coastguard Worker 
1215*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1216*90e502c7SAndroid Build Coastguard Worker }
1217*90e502c7SAndroid Build Coastguard Worker 
srtp_stream_init(srtp_stream_ctx_t * srtp,const srtp_policy_t * p)1218*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp,
1219*90e502c7SAndroid Build Coastguard Worker                                    const srtp_policy_t *p)
1220*90e502c7SAndroid Build Coastguard Worker {
1221*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t err;
1222*90e502c7SAndroid Build Coastguard Worker 
1223*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", p->ssrc.value);
1224*90e502c7SAndroid Build Coastguard Worker 
1225*90e502c7SAndroid Build Coastguard Worker     /* initialize replay database */
1226*90e502c7SAndroid Build Coastguard Worker     /*
1227*90e502c7SAndroid Build Coastguard Worker      * window size MUST be at least 64.  MAY be larger.  Values more than
1228*90e502c7SAndroid Build Coastguard Worker      * 2^15 aren't meaningful due to how extended sequence numbers are
1229*90e502c7SAndroid Build Coastguard Worker      * calculated.
1230*90e502c7SAndroid Build Coastguard Worker      * Let a window size of 0 imply the default value.
1231*90e502c7SAndroid Build Coastguard Worker      */
1232*90e502c7SAndroid Build Coastguard Worker 
1233*90e502c7SAndroid Build Coastguard Worker     if (p->window_size != 0 &&
1234*90e502c7SAndroid Build Coastguard Worker         (p->window_size < 64 || p->window_size >= 0x8000))
1235*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
1236*90e502c7SAndroid Build Coastguard Worker 
1237*90e502c7SAndroid Build Coastguard Worker     if (p->window_size != 0)
1238*90e502c7SAndroid Build Coastguard Worker         err = srtp_rdbx_init(&srtp->rtp_rdbx, p->window_size);
1239*90e502c7SAndroid Build Coastguard Worker     else
1240*90e502c7SAndroid Build Coastguard Worker         err = srtp_rdbx_init(&srtp->rtp_rdbx, 128);
1241*90e502c7SAndroid Build Coastguard Worker     if (err)
1242*90e502c7SAndroid Build Coastguard Worker         return err;
1243*90e502c7SAndroid Build Coastguard Worker 
1244*90e502c7SAndroid Build Coastguard Worker     /* set the SSRC value */
1245*90e502c7SAndroid Build Coastguard Worker     srtp->ssrc = htonl(p->ssrc.value);
1246*90e502c7SAndroid Build Coastguard Worker 
1247*90e502c7SAndroid Build Coastguard Worker     /* reset pending ROC */
1248*90e502c7SAndroid Build Coastguard Worker     srtp->pending_roc = 0;
1249*90e502c7SAndroid Build Coastguard Worker 
1250*90e502c7SAndroid Build Coastguard Worker     /* set the security service flags */
1251*90e502c7SAndroid Build Coastguard Worker     srtp->rtp_services = p->rtp.sec_serv;
1252*90e502c7SAndroid Build Coastguard Worker     srtp->rtcp_services = p->rtcp.sec_serv;
1253*90e502c7SAndroid Build Coastguard Worker 
1254*90e502c7SAndroid Build Coastguard Worker     /*
1255*90e502c7SAndroid Build Coastguard Worker      * set direction to unknown - this flag gets checked in srtp_protect(),
1256*90e502c7SAndroid Build Coastguard Worker      * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and
1257*90e502c7SAndroid Build Coastguard Worker      * gets set appropriately if it is set to unknown.
1258*90e502c7SAndroid Build Coastguard Worker      */
1259*90e502c7SAndroid Build Coastguard Worker     srtp->direction = dir_unknown;
1260*90e502c7SAndroid Build Coastguard Worker 
1261*90e502c7SAndroid Build Coastguard Worker     /* initialize SRTCP replay database */
1262*90e502c7SAndroid Build Coastguard Worker     srtp_rdb_init(&srtp->rtcp_rdb);
1263*90e502c7SAndroid Build Coastguard Worker 
1264*90e502c7SAndroid Build Coastguard Worker     /* initialize allow_repeat_tx */
1265*90e502c7SAndroid Build Coastguard Worker     /* guard against uninitialized memory: allow only 0 or 1 here */
1266*90e502c7SAndroid Build Coastguard Worker     if (p->allow_repeat_tx != 0 && p->allow_repeat_tx != 1) {
1267*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_dealloc(&srtp->rtp_rdbx);
1268*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
1269*90e502c7SAndroid Build Coastguard Worker     }
1270*90e502c7SAndroid Build Coastguard Worker     srtp->allow_repeat_tx = p->allow_repeat_tx;
1271*90e502c7SAndroid Build Coastguard Worker 
1272*90e502c7SAndroid Build Coastguard Worker     /* DAM - no RTCP key limit at present */
1273*90e502c7SAndroid Build Coastguard Worker 
1274*90e502c7SAndroid Build Coastguard Worker     /* initialize keys */
1275*90e502c7SAndroid Build Coastguard Worker     err = srtp_stream_init_all_master_keys(srtp, p->key, p->keys,
1276*90e502c7SAndroid Build Coastguard Worker                                            p->num_master_keys);
1277*90e502c7SAndroid Build Coastguard Worker     if (err) {
1278*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_dealloc(&srtp->rtp_rdbx);
1279*90e502c7SAndroid Build Coastguard Worker         return err;
1280*90e502c7SAndroid Build Coastguard Worker     }
1281*90e502c7SAndroid Build Coastguard Worker 
1282*90e502c7SAndroid Build Coastguard Worker     /*
1283*90e502c7SAndroid Build Coastguard Worker      * if EKT is in use, then initialize the EKT data associated with
1284*90e502c7SAndroid Build Coastguard Worker      * the stream
1285*90e502c7SAndroid Build Coastguard Worker      */
1286*90e502c7SAndroid Build Coastguard Worker     err = srtp_ekt_stream_init_from_policy(srtp->ekt, p->ekt);
1287*90e502c7SAndroid Build Coastguard Worker     if (err) {
1288*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_dealloc(&srtp->rtp_rdbx);
1289*90e502c7SAndroid Build Coastguard Worker         return err;
1290*90e502c7SAndroid Build Coastguard Worker     }
1291*90e502c7SAndroid Build Coastguard Worker 
1292*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1293*90e502c7SAndroid Build Coastguard Worker }
1294*90e502c7SAndroid Build Coastguard Worker 
1295*90e502c7SAndroid Build Coastguard Worker /*
1296*90e502c7SAndroid Build Coastguard Worker  * srtp_event_reporter is an event handler function that merely
1297*90e502c7SAndroid Build Coastguard Worker  * reports the events that are reported by the callbacks
1298*90e502c7SAndroid Build Coastguard Worker  */
1299*90e502c7SAndroid Build Coastguard Worker 
srtp_event_reporter(srtp_event_data_t * data)1300*90e502c7SAndroid Build Coastguard Worker void srtp_event_reporter(srtp_event_data_t *data)
1301*90e502c7SAndroid Build Coastguard Worker {
1302*90e502c7SAndroid Build Coastguard Worker     srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ",
1303*90e502c7SAndroid Build Coastguard Worker                     data->ssrc);
1304*90e502c7SAndroid Build Coastguard Worker 
1305*90e502c7SAndroid Build Coastguard Worker     switch (data->event) {
1306*90e502c7SAndroid Build Coastguard Worker     case event_ssrc_collision:
1307*90e502c7SAndroid Build Coastguard Worker         srtp_err_report(srtp_err_level_warning, "\tSSRC collision\n");
1308*90e502c7SAndroid Build Coastguard Worker         break;
1309*90e502c7SAndroid Build Coastguard Worker     case event_key_soft_limit:
1310*90e502c7SAndroid Build Coastguard Worker         srtp_err_report(srtp_err_level_warning,
1311*90e502c7SAndroid Build Coastguard Worker                         "\tkey usage soft limit reached\n");
1312*90e502c7SAndroid Build Coastguard Worker         break;
1313*90e502c7SAndroid Build Coastguard Worker     case event_key_hard_limit:
1314*90e502c7SAndroid Build Coastguard Worker         srtp_err_report(srtp_err_level_warning,
1315*90e502c7SAndroid Build Coastguard Worker                         "\tkey usage hard limit reached\n");
1316*90e502c7SAndroid Build Coastguard Worker         break;
1317*90e502c7SAndroid Build Coastguard Worker     case event_packet_index_limit:
1318*90e502c7SAndroid Build Coastguard Worker         srtp_err_report(srtp_err_level_warning,
1319*90e502c7SAndroid Build Coastguard Worker                         "\tpacket index limit reached\n");
1320*90e502c7SAndroid Build Coastguard Worker         break;
1321*90e502c7SAndroid Build Coastguard Worker     default:
1322*90e502c7SAndroid Build Coastguard Worker         srtp_err_report(srtp_err_level_warning,
1323*90e502c7SAndroid Build Coastguard Worker                         "\tunknown event reported to handler\n");
1324*90e502c7SAndroid Build Coastguard Worker     }
1325*90e502c7SAndroid Build Coastguard Worker }
1326*90e502c7SAndroid Build Coastguard Worker 
1327*90e502c7SAndroid Build Coastguard Worker /*
1328*90e502c7SAndroid Build Coastguard Worker  * srtp_event_handler is a global variable holding a pointer to the
1329*90e502c7SAndroid Build Coastguard Worker  * event handler function; this function is called for any unexpected
1330*90e502c7SAndroid Build Coastguard Worker  * event that needs to be handled out of the SRTP data path.  see
1331*90e502c7SAndroid Build Coastguard Worker  * srtp_event_t in srtp.h for more info
1332*90e502c7SAndroid Build Coastguard Worker  *
1333*90e502c7SAndroid Build Coastguard Worker  * it is okay to set srtp_event_handler to NULL, but we set
1334*90e502c7SAndroid Build Coastguard Worker  * it to the srtp_event_reporter.
1335*90e502c7SAndroid Build Coastguard Worker  */
1336*90e502c7SAndroid Build Coastguard Worker 
1337*90e502c7SAndroid Build Coastguard Worker static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter;
1338*90e502c7SAndroid Build Coastguard Worker 
srtp_install_event_handler(srtp_event_handler_func_t func)1339*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_install_event_handler(srtp_event_handler_func_t func)
1340*90e502c7SAndroid Build Coastguard Worker {
1341*90e502c7SAndroid Build Coastguard Worker     /*
1342*90e502c7SAndroid Build Coastguard Worker      * note that we accept NULL arguments intentionally - calling this
1343*90e502c7SAndroid Build Coastguard Worker      * function with a NULL arguments removes an event handler that's
1344*90e502c7SAndroid Build Coastguard Worker      * been previously installed
1345*90e502c7SAndroid Build Coastguard Worker      */
1346*90e502c7SAndroid Build Coastguard Worker 
1347*90e502c7SAndroid Build Coastguard Worker     /* set global event handling function */
1348*90e502c7SAndroid Build Coastguard Worker     srtp_event_handler = func;
1349*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1350*90e502c7SAndroid Build Coastguard Worker }
1351*90e502c7SAndroid Build Coastguard Worker 
1352*90e502c7SAndroid Build Coastguard Worker /*
1353*90e502c7SAndroid Build Coastguard Worker  * Check if the given extension header id is / should be encrypted.
1354*90e502c7SAndroid Build Coastguard Worker  * Returns 1 if yes, otherwise 0.
1355*90e502c7SAndroid Build Coastguard Worker  */
srtp_protect_extension_header(srtp_stream_ctx_t * stream,int id)1356*90e502c7SAndroid Build Coastguard Worker static int srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id)
1357*90e502c7SAndroid Build Coastguard Worker {
1358*90e502c7SAndroid Build Coastguard Worker     int *enc_xtn_hdr = stream->enc_xtn_hdr;
1359*90e502c7SAndroid Build Coastguard Worker     int count = stream->enc_xtn_hdr_count;
1360*90e502c7SAndroid Build Coastguard Worker 
1361*90e502c7SAndroid Build Coastguard Worker     if (!enc_xtn_hdr || count <= 0) {
1362*90e502c7SAndroid Build Coastguard Worker         return 0;
1363*90e502c7SAndroid Build Coastguard Worker     }
1364*90e502c7SAndroid Build Coastguard Worker 
1365*90e502c7SAndroid Build Coastguard Worker     while (count > 0) {
1366*90e502c7SAndroid Build Coastguard Worker         if (*enc_xtn_hdr == id) {
1367*90e502c7SAndroid Build Coastguard Worker             return 1;
1368*90e502c7SAndroid Build Coastguard Worker         }
1369*90e502c7SAndroid Build Coastguard Worker 
1370*90e502c7SAndroid Build Coastguard Worker         enc_xtn_hdr++;
1371*90e502c7SAndroid Build Coastguard Worker         count--;
1372*90e502c7SAndroid Build Coastguard Worker     }
1373*90e502c7SAndroid Build Coastguard Worker     return 0;
1374*90e502c7SAndroid Build Coastguard Worker }
1375*90e502c7SAndroid Build Coastguard Worker 
1376*90e502c7SAndroid Build Coastguard Worker /*
1377*90e502c7SAndroid Build Coastguard Worker  * extensions header encryption RFC 6904
1378*90e502c7SAndroid Build Coastguard Worker  */
srtp_process_header_encryption(srtp_stream_ctx_t * stream,srtp_hdr_xtnd_t * xtn_hdr,srtp_session_keys_t * session_keys)1379*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_process_header_encryption(
1380*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream,
1381*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_xtnd_t *xtn_hdr,
1382*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys)
1383*90e502c7SAndroid Build Coastguard Worker {
1384*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
1385*90e502c7SAndroid Build Coastguard Worker     uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */
1386*90e502c7SAndroid Build Coastguard Worker     int keystream_pos;
1387*90e502c7SAndroid Build Coastguard Worker     uint8_t *xtn_hdr_data = ((uint8_t *)xtn_hdr) + octets_in_rtp_extn_hdr;
1388*90e502c7SAndroid Build Coastguard Worker     uint8_t *xtn_hdr_end =
1389*90e502c7SAndroid Build Coastguard Worker         xtn_hdr_data + (ntohs(xtn_hdr->length) * sizeof(uint32_t));
1390*90e502c7SAndroid Build Coastguard Worker 
1391*90e502c7SAndroid Build Coastguard Worker     if (ntohs(xtn_hdr->profile_specific) == 0xbede) {
1392*90e502c7SAndroid Build Coastguard Worker         /* RFC 5285, section 4.2. One-Byte Header */
1393*90e502c7SAndroid Build Coastguard Worker         while (xtn_hdr_data < xtn_hdr_end) {
1394*90e502c7SAndroid Build Coastguard Worker             uint8_t xid = (*xtn_hdr_data & 0xf0) >> 4;
1395*90e502c7SAndroid Build Coastguard Worker             unsigned int xlen = (*xtn_hdr_data & 0x0f) + 1;
1396*90e502c7SAndroid Build Coastguard Worker             uint32_t xlen_with_header = 1 + xlen;
1397*90e502c7SAndroid Build Coastguard Worker             xtn_hdr_data++;
1398*90e502c7SAndroid Build Coastguard Worker 
1399*90e502c7SAndroid Build Coastguard Worker             if (xtn_hdr_data + xlen > xtn_hdr_end)
1400*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_parse_err;
1401*90e502c7SAndroid Build Coastguard Worker 
1402*90e502c7SAndroid Build Coastguard Worker             if (xid == 15) {
1403*90e502c7SAndroid Build Coastguard Worker                 /* found header 15, stop further processing. */
1404*90e502c7SAndroid Build Coastguard Worker                 break;
1405*90e502c7SAndroid Build Coastguard Worker             }
1406*90e502c7SAndroid Build Coastguard Worker 
1407*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher,
1408*90e502c7SAndroid Build Coastguard Worker                                         keystream, &xlen_with_header);
1409*90e502c7SAndroid Build Coastguard Worker             if (status)
1410*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_cipher_fail;
1411*90e502c7SAndroid Build Coastguard Worker 
1412*90e502c7SAndroid Build Coastguard Worker             if (srtp_protect_extension_header(stream, xid)) {
1413*90e502c7SAndroid Build Coastguard Worker                 keystream_pos = 1;
1414*90e502c7SAndroid Build Coastguard Worker                 while (xlen > 0) {
1415*90e502c7SAndroid Build Coastguard Worker                     *xtn_hdr_data ^= keystream[keystream_pos++];
1416*90e502c7SAndroid Build Coastguard Worker                     xtn_hdr_data++;
1417*90e502c7SAndroid Build Coastguard Worker                     xlen--;
1418*90e502c7SAndroid Build Coastguard Worker                 }
1419*90e502c7SAndroid Build Coastguard Worker             } else {
1420*90e502c7SAndroid Build Coastguard Worker                 xtn_hdr_data += xlen;
1421*90e502c7SAndroid Build Coastguard Worker             }
1422*90e502c7SAndroid Build Coastguard Worker 
1423*90e502c7SAndroid Build Coastguard Worker             /* skip padding bytes. */
1424*90e502c7SAndroid Build Coastguard Worker             while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) {
1425*90e502c7SAndroid Build Coastguard Worker                 xtn_hdr_data++;
1426*90e502c7SAndroid Build Coastguard Worker             }
1427*90e502c7SAndroid Build Coastguard Worker         }
1428*90e502c7SAndroid Build Coastguard Worker     } else if ((ntohs(xtn_hdr->profile_specific) & 0x1fff) == 0x100) {
1429*90e502c7SAndroid Build Coastguard Worker         /* RFC 5285, section 4.3. Two-Byte Header */
1430*90e502c7SAndroid Build Coastguard Worker         while (xtn_hdr_data + 1 < xtn_hdr_end) {
1431*90e502c7SAndroid Build Coastguard Worker             uint8_t xid = *xtn_hdr_data;
1432*90e502c7SAndroid Build Coastguard Worker             unsigned int xlen = *(xtn_hdr_data + 1);
1433*90e502c7SAndroid Build Coastguard Worker             uint32_t xlen_with_header = 2 + xlen;
1434*90e502c7SAndroid Build Coastguard Worker             xtn_hdr_data += 2;
1435*90e502c7SAndroid Build Coastguard Worker 
1436*90e502c7SAndroid Build Coastguard Worker             if (xtn_hdr_data + xlen > xtn_hdr_end)
1437*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_parse_err;
1438*90e502c7SAndroid Build Coastguard Worker 
1439*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher,
1440*90e502c7SAndroid Build Coastguard Worker                                         keystream, &xlen_with_header);
1441*90e502c7SAndroid Build Coastguard Worker             if (status)
1442*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_cipher_fail;
1443*90e502c7SAndroid Build Coastguard Worker 
1444*90e502c7SAndroid Build Coastguard Worker             if (xlen > 0 && srtp_protect_extension_header(stream, xid)) {
1445*90e502c7SAndroid Build Coastguard Worker                 keystream_pos = 2;
1446*90e502c7SAndroid Build Coastguard Worker                 while (xlen > 0) {
1447*90e502c7SAndroid Build Coastguard Worker                     *xtn_hdr_data ^= keystream[keystream_pos++];
1448*90e502c7SAndroid Build Coastguard Worker                     xtn_hdr_data++;
1449*90e502c7SAndroid Build Coastguard Worker                     xlen--;
1450*90e502c7SAndroid Build Coastguard Worker                 }
1451*90e502c7SAndroid Build Coastguard Worker             } else {
1452*90e502c7SAndroid Build Coastguard Worker                 xtn_hdr_data += xlen;
1453*90e502c7SAndroid Build Coastguard Worker             }
1454*90e502c7SAndroid Build Coastguard Worker 
1455*90e502c7SAndroid Build Coastguard Worker             /* skip padding bytes. */
1456*90e502c7SAndroid Build Coastguard Worker             while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) {
1457*90e502c7SAndroid Build Coastguard Worker                 xtn_hdr_data++;
1458*90e502c7SAndroid Build Coastguard Worker             }
1459*90e502c7SAndroid Build Coastguard Worker         }
1460*90e502c7SAndroid Build Coastguard Worker     } else {
1461*90e502c7SAndroid Build Coastguard Worker         /* unsupported extension header format. */
1462*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_parse_err;
1463*90e502c7SAndroid Build Coastguard Worker     }
1464*90e502c7SAndroid Build Coastguard Worker 
1465*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1466*90e502c7SAndroid Build Coastguard Worker }
1467*90e502c7SAndroid Build Coastguard Worker 
1468*90e502c7SAndroid Build Coastguard Worker /*
1469*90e502c7SAndroid Build Coastguard Worker  * AEAD uses a new IV formation method.  This function implements
1470*90e502c7SAndroid Build Coastguard Worker  * section 8.1. (SRTP IV Formation for AES-GCM) of RFC7714.
1471*90e502c7SAndroid Build Coastguard Worker  * The calculation is defined as, where (+) is the xor operation:
1472*90e502c7SAndroid Build Coastguard Worker  *
1473*90e502c7SAndroid Build Coastguard Worker  *
1474*90e502c7SAndroid Build Coastguard Worker  *              0  0  0  0  0  0  0  0  0  0  1  1
1475*90e502c7SAndroid Build Coastguard Worker  *              0  1  2  3  4  5  6  7  8  9  0  1
1476*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+
1477*90e502c7SAndroid Build Coastguard Worker  *            |00|00|    SSRC   |     ROC   | SEQ |---+
1478*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+   |
1479*90e502c7SAndroid Build Coastguard Worker  *                                                    |
1480*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+   |
1481*90e502c7SAndroid Build Coastguard Worker  *            |         Encryption Salt           |->(+)
1482*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+   |
1483*90e502c7SAndroid Build Coastguard Worker  *                                                    |
1484*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+   |
1485*90e502c7SAndroid Build Coastguard Worker  *            |       Initialization Vector       |<--+
1486*90e502c7SAndroid Build Coastguard Worker  *            +--+--+--+--+--+--+--+--+--+--+--+--+*
1487*90e502c7SAndroid Build Coastguard Worker  *
1488*90e502c7SAndroid Build Coastguard Worker  * Input:  *session_keys - pointer to SRTP stream context session keys,
1489*90e502c7SAndroid Build Coastguard Worker  *                         used to retrieve the SALT
1490*90e502c7SAndroid Build Coastguard Worker  *         *iv     - Pointer to receive the calculated IV
1491*90e502c7SAndroid Build Coastguard Worker  *         *seq    - The ROC and SEQ value to use for the
1492*90e502c7SAndroid Build Coastguard Worker  *                   IV calculation.
1493*90e502c7SAndroid Build Coastguard Worker  *         *hdr    - The RTP header, used to get the SSRC value
1494*90e502c7SAndroid Build Coastguard Worker  *
1495*90e502c7SAndroid Build Coastguard Worker  */
1496*90e502c7SAndroid Build Coastguard Worker 
srtp_calc_aead_iv(srtp_session_keys_t * session_keys,v128_t * iv,srtp_xtd_seq_num_t * seq,srtp_hdr_t * hdr)1497*90e502c7SAndroid Build Coastguard Worker static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys,
1498*90e502c7SAndroid Build Coastguard Worker                               v128_t *iv,
1499*90e502c7SAndroid Build Coastguard Worker                               srtp_xtd_seq_num_t *seq,
1500*90e502c7SAndroid Build Coastguard Worker                               srtp_hdr_t *hdr)
1501*90e502c7SAndroid Build Coastguard Worker {
1502*90e502c7SAndroid Build Coastguard Worker     v128_t in;
1503*90e502c7SAndroid Build Coastguard Worker     v128_t salt;
1504*90e502c7SAndroid Build Coastguard Worker 
1505*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1506*90e502c7SAndroid Build Coastguard Worker     uint32_t local_roc = ((high32(*seq) << 16) | (low32(*seq) >> 16));
1507*90e502c7SAndroid Build Coastguard Worker     uint16_t local_seq = (uint16_t)(low32(*seq));
1508*90e502c7SAndroid Build Coastguard Worker #else
1509*90e502c7SAndroid Build Coastguard Worker     uint32_t local_roc = (uint32_t)(*seq >> 16);
1510*90e502c7SAndroid Build Coastguard Worker     uint16_t local_seq = (uint16_t)*seq;
1511*90e502c7SAndroid Build Coastguard Worker #endif
1512*90e502c7SAndroid Build Coastguard Worker 
1513*90e502c7SAndroid Build Coastguard Worker     memset(&in, 0, sizeof(v128_t));
1514*90e502c7SAndroid Build Coastguard Worker     memset(&salt, 0, sizeof(v128_t));
1515*90e502c7SAndroid Build Coastguard Worker 
1516*90e502c7SAndroid Build Coastguard Worker     in.v16[5] = htons(local_seq);
1517*90e502c7SAndroid Build Coastguard Worker     local_roc = htonl(local_roc);
1518*90e502c7SAndroid Build Coastguard Worker     memcpy(&in.v16[3], &local_roc, sizeof(local_roc));
1519*90e502c7SAndroid Build Coastguard Worker 
1520*90e502c7SAndroid Build Coastguard Worker     /*
1521*90e502c7SAndroid Build Coastguard Worker      * Copy in the RTP SSRC value
1522*90e502c7SAndroid Build Coastguard Worker      */
1523*90e502c7SAndroid Build Coastguard Worker     memcpy(&in.v8[2], &hdr->ssrc, 4);
1524*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "Pre-salted RTP IV = %s\n", v128_hex_string(&in));
1525*90e502c7SAndroid Build Coastguard Worker 
1526*90e502c7SAndroid Build Coastguard Worker     /*
1527*90e502c7SAndroid Build Coastguard Worker      * Get the SALT value from the context
1528*90e502c7SAndroid Build Coastguard Worker      */
1529*90e502c7SAndroid Build Coastguard Worker     memcpy(salt.v8, session_keys->salt, SRTP_AEAD_SALT_LEN);
1530*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "RTP SALT = %s\n", v128_hex_string(&salt));
1531*90e502c7SAndroid Build Coastguard Worker 
1532*90e502c7SAndroid Build Coastguard Worker     /*
1533*90e502c7SAndroid Build Coastguard Worker      * Finally, apply tyhe SALT to the input
1534*90e502c7SAndroid Build Coastguard Worker      */
1535*90e502c7SAndroid Build Coastguard Worker     v128_xor(iv, &in, &salt);
1536*90e502c7SAndroid Build Coastguard Worker }
1537*90e502c7SAndroid Build Coastguard Worker 
srtp_get_session_keys(srtp_stream_ctx_t * stream,uint8_t * hdr,const unsigned int * pkt_octet_len,unsigned int * mki_size)1538*90e502c7SAndroid Build Coastguard Worker srtp_session_keys_t *srtp_get_session_keys(srtp_stream_ctx_t *stream,
1539*90e502c7SAndroid Build Coastguard Worker                                            uint8_t *hdr,
1540*90e502c7SAndroid Build Coastguard Worker                                            const unsigned int *pkt_octet_len,
1541*90e502c7SAndroid Build Coastguard Worker                                            unsigned int *mki_size)
1542*90e502c7SAndroid Build Coastguard Worker {
1543*90e502c7SAndroid Build Coastguard Worker     unsigned int base_mki_start_location = *pkt_octet_len;
1544*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_start_location = 0;
1545*90e502c7SAndroid Build Coastguard Worker     unsigned int tag_len = 0;
1546*90e502c7SAndroid Build Coastguard Worker     unsigned int i = 0;
1547*90e502c7SAndroid Build Coastguard Worker 
1548*90e502c7SAndroid Build Coastguard Worker     // Determine the authentication tag size
1549*90e502c7SAndroid Build Coastguard Worker     if (stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
1550*90e502c7SAndroid Build Coastguard Worker         stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_256) {
1551*90e502c7SAndroid Build Coastguard Worker         tag_len = 0;
1552*90e502c7SAndroid Build Coastguard Worker     } else {
1553*90e502c7SAndroid Build Coastguard Worker         tag_len = srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth);
1554*90e502c7SAndroid Build Coastguard Worker     }
1555*90e502c7SAndroid Build Coastguard Worker 
1556*90e502c7SAndroid Build Coastguard Worker     if (tag_len > base_mki_start_location) {
1557*90e502c7SAndroid Build Coastguard Worker         *mki_size = 0;
1558*90e502c7SAndroid Build Coastguard Worker         return NULL;
1559*90e502c7SAndroid Build Coastguard Worker     }
1560*90e502c7SAndroid Build Coastguard Worker 
1561*90e502c7SAndroid Build Coastguard Worker     base_mki_start_location -= tag_len;
1562*90e502c7SAndroid Build Coastguard Worker 
1563*90e502c7SAndroid Build Coastguard Worker     for (i = 0; i < stream->num_master_keys; i++) {
1564*90e502c7SAndroid Build Coastguard Worker         if (stream->session_keys[i].mki_size != 0 &&
1565*90e502c7SAndroid Build Coastguard Worker             stream->session_keys[i].mki_size <= base_mki_start_location) {
1566*90e502c7SAndroid Build Coastguard Worker             *mki_size = stream->session_keys[i].mki_size;
1567*90e502c7SAndroid Build Coastguard Worker             mki_start_location = base_mki_start_location - *mki_size;
1568*90e502c7SAndroid Build Coastguard Worker 
1569*90e502c7SAndroid Build Coastguard Worker             if (memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id,
1570*90e502c7SAndroid Build Coastguard Worker                        *mki_size) == 0) {
1571*90e502c7SAndroid Build Coastguard Worker                 return &stream->session_keys[i];
1572*90e502c7SAndroid Build Coastguard Worker             }
1573*90e502c7SAndroid Build Coastguard Worker         }
1574*90e502c7SAndroid Build Coastguard Worker     }
1575*90e502c7SAndroid Build Coastguard Worker 
1576*90e502c7SAndroid Build Coastguard Worker     *mki_size = 0;
1577*90e502c7SAndroid Build Coastguard Worker     return NULL;
1578*90e502c7SAndroid Build Coastguard Worker }
1579*90e502c7SAndroid Build Coastguard Worker 
srtp_estimate_index(srtp_rdbx_t * rdbx,uint32_t roc,srtp_xtd_seq_num_t * est,srtp_sequence_number_t seq,int * delta)1580*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_estimate_index(srtp_rdbx_t *rdbx,
1581*90e502c7SAndroid Build Coastguard Worker                                              uint32_t roc,
1582*90e502c7SAndroid Build Coastguard Worker                                              srtp_xtd_seq_num_t *est,
1583*90e502c7SAndroid Build Coastguard Worker                                              srtp_sequence_number_t seq,
1584*90e502c7SAndroid Build Coastguard Worker                                              int *delta)
1585*90e502c7SAndroid Build Coastguard Worker {
1586*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1587*90e502c7SAndroid Build Coastguard Worker     uint32_t internal_pkt_idx_reduced;
1588*90e502c7SAndroid Build Coastguard Worker     uint32_t external_pkt_idx_reduced;
1589*90e502c7SAndroid Build Coastguard Worker     uint32_t internal_roc;
1590*90e502c7SAndroid Build Coastguard Worker     uint32_t roc_difference;
1591*90e502c7SAndroid Build Coastguard Worker #endif
1592*90e502c7SAndroid Build Coastguard Worker 
1593*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1594*90e502c7SAndroid Build Coastguard Worker     *est = (srtp_xtd_seq_num_t)make64(roc >> 16, (roc << 16) | seq);
1595*90e502c7SAndroid Build Coastguard Worker     *delta = low32(est) - rdbx->index;
1596*90e502c7SAndroid Build Coastguard Worker #else
1597*90e502c7SAndroid Build Coastguard Worker     *est = (srtp_xtd_seq_num_t)(((uint64_t)roc) << 16) | seq;
1598*90e502c7SAndroid Build Coastguard Worker     *delta = (int)(*est - rdbx->index);
1599*90e502c7SAndroid Build Coastguard Worker #endif
1600*90e502c7SAndroid Build Coastguard Worker 
1601*90e502c7SAndroid Build Coastguard Worker     if (*est > rdbx->index) {
1602*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1603*90e502c7SAndroid Build Coastguard Worker         internal_roc = (uint32_t)(rdbx->index >> 16);
1604*90e502c7SAndroid Build Coastguard Worker         roc_difference = roc - internal_roc;
1605*90e502c7SAndroid Build Coastguard Worker         if (roc_difference > 1) {
1606*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1607*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_adv;
1608*90e502c7SAndroid Build Coastguard Worker         }
1609*90e502c7SAndroid Build Coastguard Worker 
1610*90e502c7SAndroid Build Coastguard Worker         internal_pkt_idx_reduced = (uint32_t)(rdbx->index & 0xFFFF);
1611*90e502c7SAndroid Build Coastguard Worker         external_pkt_idx_reduced = (uint32_t)((roc_difference << 16) | seq);
1612*90e502c7SAndroid Build Coastguard Worker 
1613*90e502c7SAndroid Build Coastguard Worker         if (external_pkt_idx_reduced - internal_pkt_idx_reduced >
1614*90e502c7SAndroid Build Coastguard Worker             seq_num_median) {
1615*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1616*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_adv;
1617*90e502c7SAndroid Build Coastguard Worker         }
1618*90e502c7SAndroid Build Coastguard Worker #else
1619*90e502c7SAndroid Build Coastguard Worker         if (*est - rdbx->index > seq_num_median) {
1620*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1621*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_adv;
1622*90e502c7SAndroid Build Coastguard Worker         }
1623*90e502c7SAndroid Build Coastguard Worker #endif
1624*90e502c7SAndroid Build Coastguard Worker     } else if (*est < rdbx->index) {
1625*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1626*90e502c7SAndroid Build Coastguard Worker 
1627*90e502c7SAndroid Build Coastguard Worker         internal_roc = (uint32_t)(rdbx->index >> 16);
1628*90e502c7SAndroid Build Coastguard Worker         roc_difference = internal_roc - roc;
1629*90e502c7SAndroid Build Coastguard Worker         if (roc_difference > 1) {
1630*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1631*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_adv;
1632*90e502c7SAndroid Build Coastguard Worker         }
1633*90e502c7SAndroid Build Coastguard Worker 
1634*90e502c7SAndroid Build Coastguard Worker         internal_pkt_idx_reduced =
1635*90e502c7SAndroid Build Coastguard Worker             (uint32_t)((roc_difference << 16) | rdbx->index & 0xFFFF);
1636*90e502c7SAndroid Build Coastguard Worker         external_pkt_idx_reduced = (uint32_t)(seq);
1637*90e502c7SAndroid Build Coastguard Worker 
1638*90e502c7SAndroid Build Coastguard Worker         if (internal_pkt_idx_reduced - external_pkt_idx_reduced >
1639*90e502c7SAndroid Build Coastguard Worker             seq_num_median) {
1640*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1641*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_old;
1642*90e502c7SAndroid Build Coastguard Worker         }
1643*90e502c7SAndroid Build Coastguard Worker #else
1644*90e502c7SAndroid Build Coastguard Worker         if (rdbx->index - *est > seq_num_median) {
1645*90e502c7SAndroid Build Coastguard Worker             *delta = 0;
1646*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_pkt_idx_old;
1647*90e502c7SAndroid Build Coastguard Worker         }
1648*90e502c7SAndroid Build Coastguard Worker #endif
1649*90e502c7SAndroid Build Coastguard Worker     }
1650*90e502c7SAndroid Build Coastguard Worker 
1651*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1652*90e502c7SAndroid Build Coastguard Worker }
1653*90e502c7SAndroid Build Coastguard Worker 
srtp_get_est_pkt_index(srtp_hdr_t * hdr,srtp_stream_ctx_t * stream,srtp_xtd_seq_num_t * est,int * delta)1654*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_get_est_pkt_index(srtp_hdr_t *hdr,
1655*90e502c7SAndroid Build Coastguard Worker                                                 srtp_stream_ctx_t *stream,
1656*90e502c7SAndroid Build Coastguard Worker                                                 srtp_xtd_seq_num_t *est,
1657*90e502c7SAndroid Build Coastguard Worker                                                 int *delta)
1658*90e502c7SAndroid Build Coastguard Worker {
1659*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t result = srtp_err_status_ok;
1660*90e502c7SAndroid Build Coastguard Worker 
1661*90e502c7SAndroid Build Coastguard Worker     if (stream->pending_roc) {
1662*90e502c7SAndroid Build Coastguard Worker         result = srtp_estimate_index(&stream->rtp_rdbx, stream->pending_roc,
1663*90e502c7SAndroid Build Coastguard Worker                                      est, ntohs(hdr->seq), delta);
1664*90e502c7SAndroid Build Coastguard Worker     } else {
1665*90e502c7SAndroid Build Coastguard Worker         /* estimate packet index from seq. num. in header */
1666*90e502c7SAndroid Build Coastguard Worker         *delta =
1667*90e502c7SAndroid Build Coastguard Worker             srtp_rdbx_estimate_index(&stream->rtp_rdbx, est, ntohs(hdr->seq));
1668*90e502c7SAndroid Build Coastguard Worker     }
1669*90e502c7SAndroid Build Coastguard Worker 
1670*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1671*90e502c7SAndroid Build Coastguard Worker     debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est),
1672*90e502c7SAndroid Build Coastguard Worker                  low32(*est));
1673*90e502c7SAndroid Build Coastguard Worker #else
1674*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "estimated u_packet index: %016llx", *est);
1675*90e502c7SAndroid Build Coastguard Worker #endif
1676*90e502c7SAndroid Build Coastguard Worker     return result;
1677*90e502c7SAndroid Build Coastguard Worker }
1678*90e502c7SAndroid Build Coastguard Worker 
1679*90e502c7SAndroid Build Coastguard Worker /*
1680*90e502c7SAndroid Build Coastguard Worker  * This function handles outgoing SRTP packets while in AEAD mode,
1681*90e502c7SAndroid Build Coastguard Worker  * which currently supports AES-GCM encryption.  All packets are
1682*90e502c7SAndroid Build Coastguard Worker  * encrypted and authenticated.
1683*90e502c7SAndroid Build Coastguard Worker  */
srtp_protect_aead(srtp_ctx_t * ctx,srtp_stream_ctx_t * stream,void * rtp_hdr,unsigned int * pkt_octet_len,srtp_session_keys_t * session_keys,unsigned int use_mki)1684*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
1685*90e502c7SAndroid Build Coastguard Worker                                            srtp_stream_ctx_t *stream,
1686*90e502c7SAndroid Build Coastguard Worker                                            void *rtp_hdr,
1687*90e502c7SAndroid Build Coastguard Worker                                            unsigned int *pkt_octet_len,
1688*90e502c7SAndroid Build Coastguard Worker                                            srtp_session_keys_t *session_keys,
1689*90e502c7SAndroid Build Coastguard Worker                                            unsigned int use_mki)
1690*90e502c7SAndroid Build Coastguard Worker {
1691*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
1692*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;    /* pointer to start of encrypted portion  */
1693*90e502c7SAndroid Build Coastguard Worker     int enc_octet_len = 0;  /* number of octets in encrypted portion  */
1694*90e502c7SAndroid Build Coastguard Worker     srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr        */
1695*90e502c7SAndroid Build Coastguard Worker     int delta;              /* delta of local pkt idx and that in hdr */
1696*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
1697*90e502c7SAndroid Build Coastguard Worker     uint32_t tag_len;
1698*90e502c7SAndroid Build Coastguard Worker     v128_t iv;
1699*90e502c7SAndroid Build Coastguard Worker     unsigned int aad_len;
1700*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_xtnd_t *xtn_hdr = NULL;
1701*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
1702*90e502c7SAndroid Build Coastguard Worker     uint8_t *mki_location = NULL;
1703*90e502c7SAndroid Build Coastguard Worker 
1704*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "function srtp_protect_aead", NULL);
1705*90e502c7SAndroid Build Coastguard Worker 
1706*90e502c7SAndroid Build Coastguard Worker     /*
1707*90e502c7SAndroid Build Coastguard Worker      * update the key usage limit, and check it to make sure that we
1708*90e502c7SAndroid Build Coastguard Worker      * didn't just hit either the soft limit or the hard limit, and call
1709*90e502c7SAndroid Build Coastguard Worker      * the event handler if we hit either.
1710*90e502c7SAndroid Build Coastguard Worker      */
1711*90e502c7SAndroid Build Coastguard Worker     switch (srtp_key_limit_update(session_keys->limit)) {
1712*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_normal:
1713*90e502c7SAndroid Build Coastguard Worker         break;
1714*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_hard_limit:
1715*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_hard_limit);
1716*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_key_expired;
1717*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_soft_limit:
1718*90e502c7SAndroid Build Coastguard Worker     default:
1719*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_soft_limit);
1720*90e502c7SAndroid Build Coastguard Worker         break;
1721*90e502c7SAndroid Build Coastguard Worker     }
1722*90e502c7SAndroid Build Coastguard Worker 
1723*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream */
1724*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth);
1725*90e502c7SAndroid Build Coastguard Worker 
1726*90e502c7SAndroid Build Coastguard Worker     /*
1727*90e502c7SAndroid Build Coastguard Worker      * find starting point for encryption and length of data to be
1728*90e502c7SAndroid Build Coastguard Worker      * encrypted - the encrypted portion starts after the rtp header
1729*90e502c7SAndroid Build Coastguard Worker      * extension, if present; otherwise, it starts after the last csrc,
1730*90e502c7SAndroid Build Coastguard Worker      * if any are present
1731*90e502c7SAndroid Build Coastguard Worker      */
1732*90e502c7SAndroid Build Coastguard Worker     enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
1733*90e502c7SAndroid Build Coastguard Worker     if (hdr->x == 1) {
1734*90e502c7SAndroid Build Coastguard Worker         xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
1735*90e502c7SAndroid Build Coastguard Worker         enc_start += (ntohs(xtn_hdr->length) + 1);
1736*90e502c7SAndroid Build Coastguard Worker     }
1737*90e502c7SAndroid Build Coastguard Worker     /* note: the passed size is without the auth tag */
1738*90e502c7SAndroid Build Coastguard Worker     if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
1739*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_parse_err;
1740*90e502c7SAndroid Build Coastguard Worker     enc_octet_len =
1741*90e502c7SAndroid Build Coastguard Worker         (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr));
1742*90e502c7SAndroid Build Coastguard Worker     if (enc_octet_len < 0)
1743*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_parse_err;
1744*90e502c7SAndroid Build Coastguard Worker 
1745*90e502c7SAndroid Build Coastguard Worker     /*
1746*90e502c7SAndroid Build Coastguard Worker      * estimate the packet index using the start of the replay window
1747*90e502c7SAndroid Build Coastguard Worker      * and the sequence number from the header
1748*90e502c7SAndroid Build Coastguard Worker      */
1749*90e502c7SAndroid Build Coastguard Worker     delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
1750*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
1751*90e502c7SAndroid Build Coastguard Worker     if (status) {
1752*90e502c7SAndroid Build Coastguard Worker         if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) {
1753*90e502c7SAndroid Build Coastguard Worker             return status; /* we've been asked to reuse an index */
1754*90e502c7SAndroid Build Coastguard Worker         }
1755*90e502c7SAndroid Build Coastguard Worker     } else {
1756*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
1757*90e502c7SAndroid Build Coastguard Worker     }
1758*90e502c7SAndroid Build Coastguard Worker 
1759*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1760*90e502c7SAndroid Build Coastguard Worker     debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est),
1761*90e502c7SAndroid Build Coastguard Worker                  low32(est));
1762*90e502c7SAndroid Build Coastguard Worker #else
1763*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "estimated packet index: %016llx", est);
1764*90e502c7SAndroid Build Coastguard Worker #endif
1765*90e502c7SAndroid Build Coastguard Worker 
1766*90e502c7SAndroid Build Coastguard Worker     /*
1767*90e502c7SAndroid Build Coastguard Worker      * AEAD uses a new IV formation method
1768*90e502c7SAndroid Build Coastguard Worker      */
1769*90e502c7SAndroid Build Coastguard Worker     srtp_calc_aead_iv(session_keys, &iv, &est, hdr);
1770*90e502c7SAndroid Build Coastguard Worker /* shift est, put into network byte order */
1771*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1772*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(
1773*90e502c7SAndroid Build Coastguard Worker         make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
1774*90e502c7SAndroid Build Coastguard Worker #else
1775*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(est << 16);
1776*90e502c7SAndroid Build Coastguard Worker #endif
1777*90e502c7SAndroid Build Coastguard Worker 
1778*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
1779*90e502c7SAndroid Build Coastguard Worker                                 srtp_direction_encrypt);
1780*90e502c7SAndroid Build Coastguard Worker     if (!status && session_keys->rtp_xtn_hdr_cipher) {
1781*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
1782*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc;
1783*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = est;
1784*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
1785*90e502c7SAndroid Build Coastguard Worker                                     (uint8_t *)&iv, srtp_direction_encrypt);
1786*90e502c7SAndroid Build Coastguard Worker     }
1787*90e502c7SAndroid Build Coastguard Worker     if (status) {
1788*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
1789*90e502c7SAndroid Build Coastguard Worker     }
1790*90e502c7SAndroid Build Coastguard Worker 
1791*90e502c7SAndroid Build Coastguard Worker     if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
1792*90e502c7SAndroid Build Coastguard Worker         /*
1793*90e502c7SAndroid Build Coastguard Worker          * extensions header encryption RFC 6904
1794*90e502c7SAndroid Build Coastguard Worker          */
1795*90e502c7SAndroid Build Coastguard Worker         status = srtp_process_header_encryption(stream, xtn_hdr, session_keys);
1796*90e502c7SAndroid Build Coastguard Worker         if (status) {
1797*90e502c7SAndroid Build Coastguard Worker             return status;
1798*90e502c7SAndroid Build Coastguard Worker         }
1799*90e502c7SAndroid Build Coastguard Worker     }
1800*90e502c7SAndroid Build Coastguard Worker 
1801*90e502c7SAndroid Build Coastguard Worker     /*
1802*90e502c7SAndroid Build Coastguard Worker      * Set the AAD over the RTP header
1803*90e502c7SAndroid Build Coastguard Worker      */
1804*90e502c7SAndroid Build Coastguard Worker     aad_len = (uint8_t *)enc_start - (uint8_t *)hdr;
1805*90e502c7SAndroid Build Coastguard Worker     status =
1806*90e502c7SAndroid Build Coastguard Worker         srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len);
1807*90e502c7SAndroid Build Coastguard Worker     if (status) {
1808*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_cipher_fail);
1809*90e502c7SAndroid Build Coastguard Worker     }
1810*90e502c7SAndroid Build Coastguard Worker 
1811*90e502c7SAndroid Build Coastguard Worker     /* Encrypt the payload  */
1812*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start,
1813*90e502c7SAndroid Build Coastguard Worker                                  (unsigned int *)&enc_octet_len);
1814*90e502c7SAndroid Build Coastguard Worker     if (status) {
1815*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
1816*90e502c7SAndroid Build Coastguard Worker     }
1817*90e502c7SAndroid Build Coastguard Worker     /*
1818*90e502c7SAndroid Build Coastguard Worker      * If we're doing GCM, we need to get the tag
1819*90e502c7SAndroid Build Coastguard Worker      * and append that to the output
1820*90e502c7SAndroid Build Coastguard Worker      */
1821*90e502c7SAndroid Build Coastguard Worker     status =
1822*90e502c7SAndroid Build Coastguard Worker         srtp_cipher_get_tag(session_keys->rtp_cipher,
1823*90e502c7SAndroid Build Coastguard Worker                             (uint8_t *)enc_start + enc_octet_len, &tag_len);
1824*90e502c7SAndroid Build Coastguard Worker     if (status) {
1825*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_cipher_fail);
1826*90e502c7SAndroid Build Coastguard Worker     }
1827*90e502c7SAndroid Build Coastguard Worker 
1828*90e502c7SAndroid Build Coastguard Worker     mki_location = (uint8_t *)hdr + *pkt_octet_len + tag_len;
1829*90e502c7SAndroid Build Coastguard Worker     mki_size = srtp_inject_mki(mki_location, session_keys, use_mki);
1830*90e502c7SAndroid Build Coastguard Worker 
1831*90e502c7SAndroid Build Coastguard Worker     /* increase the packet length by the length of the auth tag */
1832*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += tag_len;
1833*90e502c7SAndroid Build Coastguard Worker 
1834*90e502c7SAndroid Build Coastguard Worker     /* increase the packet length by the length of the mki_size */
1835*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += mki_size;
1836*90e502c7SAndroid Build Coastguard Worker 
1837*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
1838*90e502c7SAndroid Build Coastguard Worker }
1839*90e502c7SAndroid Build Coastguard Worker 
1840*90e502c7SAndroid Build Coastguard Worker /*
1841*90e502c7SAndroid Build Coastguard Worker  * This function handles incoming SRTP packets while in AEAD mode,
1842*90e502c7SAndroid Build Coastguard Worker  * which currently supports AES-GCM encryption.  All packets are
1843*90e502c7SAndroid Build Coastguard Worker  * encrypted and authenticated.  Note, the auth tag is at the end
1844*90e502c7SAndroid Build Coastguard Worker  * of the packet stream and is automatically checked by GCM
1845*90e502c7SAndroid Build Coastguard Worker  * when decrypting the payload.
1846*90e502c7SAndroid Build Coastguard Worker  */
srtp_unprotect_aead(srtp_ctx_t * ctx,srtp_stream_ctx_t * stream,int delta,srtp_xtd_seq_num_t est,void * srtp_hdr,unsigned int * pkt_octet_len,srtp_session_keys_t * session_keys,unsigned int mki_size)1847*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx,
1848*90e502c7SAndroid Build Coastguard Worker                                              srtp_stream_ctx_t *stream,
1849*90e502c7SAndroid Build Coastguard Worker                                              int delta,
1850*90e502c7SAndroid Build Coastguard Worker                                              srtp_xtd_seq_num_t est,
1851*90e502c7SAndroid Build Coastguard Worker                                              void *srtp_hdr,
1852*90e502c7SAndroid Build Coastguard Worker                                              unsigned int *pkt_octet_len,
1853*90e502c7SAndroid Build Coastguard Worker                                              srtp_session_keys_t *session_keys,
1854*90e502c7SAndroid Build Coastguard Worker                                              unsigned int mki_size)
1855*90e502c7SAndroid Build Coastguard Worker {
1856*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
1857*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
1858*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
1859*90e502c7SAndroid Build Coastguard Worker     v128_t iv;
1860*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
1861*90e502c7SAndroid Build Coastguard Worker     int tag_len;
1862*90e502c7SAndroid Build Coastguard Worker     unsigned int aad_len;
1863*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_xtnd_t *xtn_hdr = NULL;
1864*90e502c7SAndroid Build Coastguard Worker 
1865*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "function srtp_unprotect_aead", NULL);
1866*90e502c7SAndroid Build Coastguard Worker 
1867*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1868*90e502c7SAndroid Build Coastguard Worker     debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),
1869*90e502c7SAndroid Build Coastguard Worker                  low32(est));
1870*90e502c7SAndroid Build Coastguard Worker #else
1871*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "estimated u_packet index: %016llx", est);
1872*90e502c7SAndroid Build Coastguard Worker #endif
1873*90e502c7SAndroid Build Coastguard Worker 
1874*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream */
1875*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth);
1876*90e502c7SAndroid Build Coastguard Worker 
1877*90e502c7SAndroid Build Coastguard Worker     /*
1878*90e502c7SAndroid Build Coastguard Worker      * AEAD uses a new IV formation method
1879*90e502c7SAndroid Build Coastguard Worker      */
1880*90e502c7SAndroid Build Coastguard Worker     srtp_calc_aead_iv(session_keys, &iv, &est, hdr);
1881*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
1882*90e502c7SAndroid Build Coastguard Worker                                 srtp_direction_decrypt);
1883*90e502c7SAndroid Build Coastguard Worker     if (!status && session_keys->rtp_xtn_hdr_cipher) {
1884*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
1885*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc;
1886*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
1887*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(
1888*90e502c7SAndroid Build Coastguard Worker             make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
1889*90e502c7SAndroid Build Coastguard Worker #else
1890*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(est << 16);
1891*90e502c7SAndroid Build Coastguard Worker #endif
1892*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
1893*90e502c7SAndroid Build Coastguard Worker                                     (uint8_t *)&iv, srtp_direction_encrypt);
1894*90e502c7SAndroid Build Coastguard Worker     }
1895*90e502c7SAndroid Build Coastguard Worker     if (status) {
1896*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
1897*90e502c7SAndroid Build Coastguard Worker     }
1898*90e502c7SAndroid Build Coastguard Worker 
1899*90e502c7SAndroid Build Coastguard Worker     /*
1900*90e502c7SAndroid Build Coastguard Worker      * find starting point for decryption and length of data to be
1901*90e502c7SAndroid Build Coastguard Worker      * decrypted - the encrypted portion starts after the rtp header
1902*90e502c7SAndroid Build Coastguard Worker      * extension, if present; otherwise, it starts after the last csrc,
1903*90e502c7SAndroid Build Coastguard Worker      * if any are present
1904*90e502c7SAndroid Build Coastguard Worker      */
1905*90e502c7SAndroid Build Coastguard Worker     enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
1906*90e502c7SAndroid Build Coastguard Worker     if (hdr->x == 1) {
1907*90e502c7SAndroid Build Coastguard Worker         xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
1908*90e502c7SAndroid Build Coastguard Worker         enc_start += (ntohs(xtn_hdr->length) + 1);
1909*90e502c7SAndroid Build Coastguard Worker     }
1910*90e502c7SAndroid Build Coastguard Worker     if (!((uint8_t *)enc_start <=
1911*90e502c7SAndroid Build Coastguard Worker           (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
1912*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_parse_err;
1913*90e502c7SAndroid Build Coastguard Worker     /*
1914*90e502c7SAndroid Build Coastguard Worker      * We pass the tag down to the cipher when doing GCM mode
1915*90e502c7SAndroid Build Coastguard Worker      */
1916*90e502c7SAndroid Build Coastguard Worker     enc_octet_len = (unsigned int)(*pkt_octet_len - mki_size -
1917*90e502c7SAndroid Build Coastguard Worker                                    ((uint8_t *)enc_start - (uint8_t *)hdr));
1918*90e502c7SAndroid Build Coastguard Worker 
1919*90e502c7SAndroid Build Coastguard Worker     /*
1920*90e502c7SAndroid Build Coastguard Worker      * Sanity check the encrypted payload length against
1921*90e502c7SAndroid Build Coastguard Worker      * the tag size.  It must always be at least as large
1922*90e502c7SAndroid Build Coastguard Worker      * as the tag length.
1923*90e502c7SAndroid Build Coastguard Worker      */
1924*90e502c7SAndroid Build Coastguard Worker     if (enc_octet_len < (unsigned int)tag_len) {
1925*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
1926*90e502c7SAndroid Build Coastguard Worker     }
1927*90e502c7SAndroid Build Coastguard Worker 
1928*90e502c7SAndroid Build Coastguard Worker     /*
1929*90e502c7SAndroid Build Coastguard Worker      * update the key usage limit, and check it to make sure that we
1930*90e502c7SAndroid Build Coastguard Worker      * didn't just hit either the soft limit or the hard limit, and call
1931*90e502c7SAndroid Build Coastguard Worker      * the event handler if we hit either.
1932*90e502c7SAndroid Build Coastguard Worker      */
1933*90e502c7SAndroid Build Coastguard Worker     switch (srtp_key_limit_update(session_keys->limit)) {
1934*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_normal:
1935*90e502c7SAndroid Build Coastguard Worker         break;
1936*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_soft_limit:
1937*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_soft_limit);
1938*90e502c7SAndroid Build Coastguard Worker         break;
1939*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_hard_limit:
1940*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_hard_limit);
1941*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_key_expired;
1942*90e502c7SAndroid Build Coastguard Worker     default:
1943*90e502c7SAndroid Build Coastguard Worker         break;
1944*90e502c7SAndroid Build Coastguard Worker     }
1945*90e502c7SAndroid Build Coastguard Worker 
1946*90e502c7SAndroid Build Coastguard Worker     /*
1947*90e502c7SAndroid Build Coastguard Worker      * Set the AAD for AES-GCM, which is the RTP header
1948*90e502c7SAndroid Build Coastguard Worker      */
1949*90e502c7SAndroid Build Coastguard Worker     aad_len = (uint8_t *)enc_start - (uint8_t *)hdr;
1950*90e502c7SAndroid Build Coastguard Worker     status =
1951*90e502c7SAndroid Build Coastguard Worker         srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len);
1952*90e502c7SAndroid Build Coastguard Worker     if (status) {
1953*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_cipher_fail);
1954*90e502c7SAndroid Build Coastguard Worker     }
1955*90e502c7SAndroid Build Coastguard Worker 
1956*90e502c7SAndroid Build Coastguard Worker     /* Decrypt the ciphertext.  This also checks the auth tag based
1957*90e502c7SAndroid Build Coastguard Worker      * on the AAD we just specified above */
1958*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t *)enc_start,
1959*90e502c7SAndroid Build Coastguard Worker                                  &enc_octet_len);
1960*90e502c7SAndroid Build Coastguard Worker     if (status) {
1961*90e502c7SAndroid Build Coastguard Worker         return status;
1962*90e502c7SAndroid Build Coastguard Worker     }
1963*90e502c7SAndroid Build Coastguard Worker 
1964*90e502c7SAndroid Build Coastguard Worker     if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
1965*90e502c7SAndroid Build Coastguard Worker         /*
1966*90e502c7SAndroid Build Coastguard Worker          * extensions header encryption RFC 6904
1967*90e502c7SAndroid Build Coastguard Worker          */
1968*90e502c7SAndroid Build Coastguard Worker         status = srtp_process_header_encryption(stream, xtn_hdr, session_keys);
1969*90e502c7SAndroid Build Coastguard Worker         if (status) {
1970*90e502c7SAndroid Build Coastguard Worker             return status;
1971*90e502c7SAndroid Build Coastguard Worker         }
1972*90e502c7SAndroid Build Coastguard Worker     }
1973*90e502c7SAndroid Build Coastguard Worker 
1974*90e502c7SAndroid Build Coastguard Worker     /*
1975*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for received traffic - this check will
1976*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
1977*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
1978*90e502c7SAndroid Build Coastguard Worker      * those functions.
1979*90e502c7SAndroid Build Coastguard Worker      *
1980*90e502c7SAndroid Build Coastguard Worker      * we do this check *after* the authentication check, so that the
1981*90e502c7SAndroid Build Coastguard Worker      * latter check will catch any attempts to fool us into thinking
1982*90e502c7SAndroid Build Coastguard Worker      * that we've got a collision
1983*90e502c7SAndroid Build Coastguard Worker      */
1984*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_receiver) {
1985*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
1986*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_receiver;
1987*90e502c7SAndroid Build Coastguard Worker         } else {
1988*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
1989*90e502c7SAndroid Build Coastguard Worker         }
1990*90e502c7SAndroid Build Coastguard Worker     }
1991*90e502c7SAndroid Build Coastguard Worker 
1992*90e502c7SAndroid Build Coastguard Worker     /*
1993*90e502c7SAndroid Build Coastguard Worker      * if the stream is a 'provisional' one, in which the template context
1994*90e502c7SAndroid Build Coastguard Worker      * is used, then we need to allocate a new stream at this point, since
1995*90e502c7SAndroid Build Coastguard Worker      * the authentication passed
1996*90e502c7SAndroid Build Coastguard Worker      */
1997*90e502c7SAndroid Build Coastguard Worker     if (stream == ctx->stream_template) {
1998*90e502c7SAndroid Build Coastguard Worker         srtp_stream_ctx_t *new_stream;
1999*90e502c7SAndroid Build Coastguard Worker 
2000*90e502c7SAndroid Build Coastguard Worker         /*
2001*90e502c7SAndroid Build Coastguard Worker          * allocate and initialize a new stream
2002*90e502c7SAndroid Build Coastguard Worker          *
2003*90e502c7SAndroid Build Coastguard Worker          * note that we indicate failure if we can't allocate the new
2004*90e502c7SAndroid Build Coastguard Worker          * stream, and some implementations will want to not return
2005*90e502c7SAndroid Build Coastguard Worker          * failure here
2006*90e502c7SAndroid Build Coastguard Worker          */
2007*90e502c7SAndroid Build Coastguard Worker         status =
2008*90e502c7SAndroid Build Coastguard Worker             srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
2009*90e502c7SAndroid Build Coastguard Worker         if (status) {
2010*90e502c7SAndroid Build Coastguard Worker             return status;
2011*90e502c7SAndroid Build Coastguard Worker         }
2012*90e502c7SAndroid Build Coastguard Worker 
2013*90e502c7SAndroid Build Coastguard Worker         /* add new stream to the head of the stream_list */
2014*90e502c7SAndroid Build Coastguard Worker         new_stream->next = ctx->stream_list;
2015*90e502c7SAndroid Build Coastguard Worker         ctx->stream_list = new_stream;
2016*90e502c7SAndroid Build Coastguard Worker 
2017*90e502c7SAndroid Build Coastguard Worker         /* set stream (the pointer used in this function) */
2018*90e502c7SAndroid Build Coastguard Worker         stream = new_stream;
2019*90e502c7SAndroid Build Coastguard Worker     }
2020*90e502c7SAndroid Build Coastguard Worker 
2021*90e502c7SAndroid Build Coastguard Worker     /*
2022*90e502c7SAndroid Build Coastguard Worker      * the message authentication function passed, so add the packet
2023*90e502c7SAndroid Build Coastguard Worker      * index into the replay database
2024*90e502c7SAndroid Build Coastguard Worker      */
2025*90e502c7SAndroid Build Coastguard Worker     srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
2026*90e502c7SAndroid Build Coastguard Worker 
2027*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the auth tag */
2028*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= tag_len;
2029*90e502c7SAndroid Build Coastguard Worker 
2030*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the mki_size */
2031*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= mki_size;
2032*90e502c7SAndroid Build Coastguard Worker 
2033*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2034*90e502c7SAndroid Build Coastguard Worker }
2035*90e502c7SAndroid Build Coastguard Worker 
srtp_protect(srtp_ctx_t * ctx,void * rtp_hdr,int * pkt_octet_len)2036*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_protect(srtp_ctx_t *ctx,
2037*90e502c7SAndroid Build Coastguard Worker                                void *rtp_hdr,
2038*90e502c7SAndroid Build Coastguard Worker                                int *pkt_octet_len)
2039*90e502c7SAndroid Build Coastguard Worker {
2040*90e502c7SAndroid Build Coastguard Worker     return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0);
2041*90e502c7SAndroid Build Coastguard Worker }
2042*90e502c7SAndroid Build Coastguard Worker 
srtp_protect_mki(srtp_ctx_t * ctx,void * rtp_hdr,int * pkt_octet_len,unsigned int use_mki,unsigned int mki_index)2043*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
2044*90e502c7SAndroid Build Coastguard Worker                                    void *rtp_hdr,
2045*90e502c7SAndroid Build Coastguard Worker                                    int *pkt_octet_len,
2046*90e502c7SAndroid Build Coastguard Worker                                    unsigned int use_mki,
2047*90e502c7SAndroid Build Coastguard Worker                                    unsigned int mki_index)
2048*90e502c7SAndroid Build Coastguard Worker {
2049*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
2050*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;      /* pointer to start of encrypted portion  */
2051*90e502c7SAndroid Build Coastguard Worker     uint32_t *auth_start;     /* pointer to start of auth. portion      */
2052*90e502c7SAndroid Build Coastguard Worker     int enc_octet_len = 0;    /* number of octets in encrypted portion  */
2053*90e502c7SAndroid Build Coastguard Worker     srtp_xtd_seq_num_t est;   /* estimated xtd_seq_num_t of *hdr        */
2054*90e502c7SAndroid Build Coastguard Worker     int delta;                /* delta of local pkt idx and that in hdr */
2055*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
2056*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2057*90e502c7SAndroid Build Coastguard Worker     int tag_len;
2058*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
2059*90e502c7SAndroid Build Coastguard Worker     uint32_t prefix_len;
2060*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_xtnd_t *xtn_hdr = NULL;
2061*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
2062*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
2063*90e502c7SAndroid Build Coastguard Worker     uint8_t *mki_location = NULL;
2064*90e502c7SAndroid Build Coastguard Worker     int advance_packet_index = 0;
2065*90e502c7SAndroid Build Coastguard Worker 
2066*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "function srtp_protect", NULL);
2067*90e502c7SAndroid Build Coastguard Worker 
2068*90e502c7SAndroid Build Coastguard Worker     /* we assume the hdr is 32-bit aligned to start */
2069*90e502c7SAndroid Build Coastguard Worker 
2070*90e502c7SAndroid Build Coastguard Worker     /* Verify RTP header */
2071*90e502c7SAndroid Build Coastguard Worker     status = srtp_validate_rtp_header(rtp_hdr, pkt_octet_len);
2072*90e502c7SAndroid Build Coastguard Worker     if (status)
2073*90e502c7SAndroid Build Coastguard Worker         return status;
2074*90e502c7SAndroid Build Coastguard Worker 
2075*90e502c7SAndroid Build Coastguard Worker     /* check the packet length - it must at least contain a full header */
2076*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < octets_in_rtp_header)
2077*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2078*90e502c7SAndroid Build Coastguard Worker 
2079*90e502c7SAndroid Build Coastguard Worker     /*
2080*90e502c7SAndroid Build Coastguard Worker      * look up ssrc in srtp_stream list, and process the packet with
2081*90e502c7SAndroid Build Coastguard Worker      * the appropriate stream.  if we haven't seen this stream before,
2082*90e502c7SAndroid Build Coastguard Worker      * there's a template key for this srtp_session, and the cipher
2083*90e502c7SAndroid Build Coastguard Worker      * supports key-sharing, then we assume that a new stream using
2084*90e502c7SAndroid Build Coastguard Worker      * that key has just started up
2085*90e502c7SAndroid Build Coastguard Worker      */
2086*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(ctx, hdr->ssrc);
2087*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
2088*90e502c7SAndroid Build Coastguard Worker         if (ctx->stream_template != NULL) {
2089*90e502c7SAndroid Build Coastguard Worker             srtp_stream_ctx_t *new_stream;
2090*90e502c7SAndroid Build Coastguard Worker 
2091*90e502c7SAndroid Build Coastguard Worker             /* allocate and initialize a new stream */
2092*90e502c7SAndroid Build Coastguard Worker             status =
2093*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
2094*90e502c7SAndroid Build Coastguard Worker             if (status)
2095*90e502c7SAndroid Build Coastguard Worker                 return status;
2096*90e502c7SAndroid Build Coastguard Worker 
2097*90e502c7SAndroid Build Coastguard Worker             /* add new stream to the head of the stream_list */
2098*90e502c7SAndroid Build Coastguard Worker             new_stream->next = ctx->stream_list;
2099*90e502c7SAndroid Build Coastguard Worker             ctx->stream_list = new_stream;
2100*90e502c7SAndroid Build Coastguard Worker 
2101*90e502c7SAndroid Build Coastguard Worker             /* set direction to outbound */
2102*90e502c7SAndroid Build Coastguard Worker             new_stream->direction = dir_srtp_sender;
2103*90e502c7SAndroid Build Coastguard Worker 
2104*90e502c7SAndroid Build Coastguard Worker             /* set stream (the pointer used in this function) */
2105*90e502c7SAndroid Build Coastguard Worker             stream = new_stream;
2106*90e502c7SAndroid Build Coastguard Worker         } else {
2107*90e502c7SAndroid Build Coastguard Worker             /* no template stream, so we return an error */
2108*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_no_ctx;
2109*90e502c7SAndroid Build Coastguard Worker         }
2110*90e502c7SAndroid Build Coastguard Worker     }
2111*90e502c7SAndroid Build Coastguard Worker 
2112*90e502c7SAndroid Build Coastguard Worker     /*
2113*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for sending traffic - this check will
2114*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
2115*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
2116*90e502c7SAndroid Build Coastguard Worker      * those functions.
2117*90e502c7SAndroid Build Coastguard Worker      */
2118*90e502c7SAndroid Build Coastguard Worker 
2119*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_sender) {
2120*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
2121*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_sender;
2122*90e502c7SAndroid Build Coastguard Worker         } else {
2123*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
2124*90e502c7SAndroid Build Coastguard Worker         }
2125*90e502c7SAndroid Build Coastguard Worker     }
2126*90e502c7SAndroid Build Coastguard Worker 
2127*90e502c7SAndroid Build Coastguard Worker     session_keys =
2128*90e502c7SAndroid Build Coastguard Worker         srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index);
2129*90e502c7SAndroid Build Coastguard Worker 
2130*90e502c7SAndroid Build Coastguard Worker     if (session_keys == NULL)
2131*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_mki;
2132*90e502c7SAndroid Build Coastguard Worker 
2133*90e502c7SAndroid Build Coastguard Worker     /*
2134*90e502c7SAndroid Build Coastguard Worker      * Check if this is an AEAD stream (GCM mode).  If so, then dispatch
2135*90e502c7SAndroid Build Coastguard Worker      * the request to our AEAD handler.
2136*90e502c7SAndroid Build Coastguard Worker      */
2137*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
2138*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
2139*90e502c7SAndroid Build Coastguard Worker         return srtp_protect_aead(ctx, stream, rtp_hdr,
2140*90e502c7SAndroid Build Coastguard Worker                                  (unsigned int *)pkt_octet_len, session_keys,
2141*90e502c7SAndroid Build Coastguard Worker                                  use_mki);
2142*90e502c7SAndroid Build Coastguard Worker     }
2143*90e502c7SAndroid Build Coastguard Worker 
2144*90e502c7SAndroid Build Coastguard Worker     /*
2145*90e502c7SAndroid Build Coastguard Worker      * update the key usage limit, and check it to make sure that we
2146*90e502c7SAndroid Build Coastguard Worker      * didn't just hit either the soft limit or the hard limit, and call
2147*90e502c7SAndroid Build Coastguard Worker      * the event handler if we hit either.
2148*90e502c7SAndroid Build Coastguard Worker      */
2149*90e502c7SAndroid Build Coastguard Worker     switch (srtp_key_limit_update(session_keys->limit)) {
2150*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_normal:
2151*90e502c7SAndroid Build Coastguard Worker         break;
2152*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_soft_limit:
2153*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_soft_limit);
2154*90e502c7SAndroid Build Coastguard Worker         break;
2155*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_hard_limit:
2156*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_hard_limit);
2157*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_key_expired;
2158*90e502c7SAndroid Build Coastguard Worker     default:
2159*90e502c7SAndroid Build Coastguard Worker         break;
2160*90e502c7SAndroid Build Coastguard Worker     }
2161*90e502c7SAndroid Build Coastguard Worker 
2162*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream */
2163*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth);
2164*90e502c7SAndroid Build Coastguard Worker 
2165*90e502c7SAndroid Build Coastguard Worker     /*
2166*90e502c7SAndroid Build Coastguard Worker      * find starting point for encryption and length of data to be
2167*90e502c7SAndroid Build Coastguard Worker      * encrypted - the encrypted portion starts after the rtp header
2168*90e502c7SAndroid Build Coastguard Worker      * extension, if present; otherwise, it starts after the last csrc,
2169*90e502c7SAndroid Build Coastguard Worker      * if any are present
2170*90e502c7SAndroid Build Coastguard Worker      *
2171*90e502c7SAndroid Build Coastguard Worker      * if we're not providing confidentiality, set enc_start to NULL
2172*90e502c7SAndroid Build Coastguard Worker      */
2173*90e502c7SAndroid Build Coastguard Worker     if (stream->rtp_services & sec_serv_conf) {
2174*90e502c7SAndroid Build Coastguard Worker         enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
2175*90e502c7SAndroid Build Coastguard Worker         if (hdr->x == 1) {
2176*90e502c7SAndroid Build Coastguard Worker             xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
2177*90e502c7SAndroid Build Coastguard Worker             enc_start += (ntohs(xtn_hdr->length) + 1);
2178*90e502c7SAndroid Build Coastguard Worker         }
2179*90e502c7SAndroid Build Coastguard Worker         /* note: the passed size is without the auth tag */
2180*90e502c7SAndroid Build Coastguard Worker         if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
2181*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_parse_err;
2182*90e502c7SAndroid Build Coastguard Worker         enc_octet_len =
2183*90e502c7SAndroid Build Coastguard Worker             (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr));
2184*90e502c7SAndroid Build Coastguard Worker         if (enc_octet_len < 0)
2185*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_parse_err;
2186*90e502c7SAndroid Build Coastguard Worker     } else {
2187*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL;
2188*90e502c7SAndroid Build Coastguard Worker     }
2189*90e502c7SAndroid Build Coastguard Worker 
2190*90e502c7SAndroid Build Coastguard Worker     mki_location = (uint8_t *)hdr + *pkt_octet_len;
2191*90e502c7SAndroid Build Coastguard Worker     mki_size = srtp_inject_mki(mki_location, session_keys, use_mki);
2192*90e502c7SAndroid Build Coastguard Worker 
2193*90e502c7SAndroid Build Coastguard Worker     /*
2194*90e502c7SAndroid Build Coastguard Worker      * if we're providing authentication, set the auth_start and auth_tag
2195*90e502c7SAndroid Build Coastguard Worker      * pointers to the proper locations; otherwise, set auth_start to NULL
2196*90e502c7SAndroid Build Coastguard Worker      * to indicate that no authentication is needed
2197*90e502c7SAndroid Build Coastguard Worker      */
2198*90e502c7SAndroid Build Coastguard Worker     if (stream->rtp_services & sec_serv_auth) {
2199*90e502c7SAndroid Build Coastguard Worker         auth_start = (uint32_t *)hdr;
2200*90e502c7SAndroid Build Coastguard Worker         auth_tag = (uint8_t *)hdr + *pkt_octet_len + mki_size;
2201*90e502c7SAndroid Build Coastguard Worker     } else {
2202*90e502c7SAndroid Build Coastguard Worker         auth_start = NULL;
2203*90e502c7SAndroid Build Coastguard Worker         auth_tag = NULL;
2204*90e502c7SAndroid Build Coastguard Worker     }
2205*90e502c7SAndroid Build Coastguard Worker 
2206*90e502c7SAndroid Build Coastguard Worker     /*
2207*90e502c7SAndroid Build Coastguard Worker      * estimate the packet index using the start of the replay window
2208*90e502c7SAndroid Build Coastguard Worker      * and the sequence number from the header
2209*90e502c7SAndroid Build Coastguard Worker      */
2210*90e502c7SAndroid Build Coastguard Worker     status = srtp_get_est_pkt_index(hdr, stream, &est, &delta);
2211*90e502c7SAndroid Build Coastguard Worker 
2212*90e502c7SAndroid Build Coastguard Worker     if (status && (status != srtp_err_status_pkt_idx_adv))
2213*90e502c7SAndroid Build Coastguard Worker         return status;
2214*90e502c7SAndroid Build Coastguard Worker 
2215*90e502c7SAndroid Build Coastguard Worker     if (status == srtp_err_status_pkt_idx_adv)
2216*90e502c7SAndroid Build Coastguard Worker         advance_packet_index = 1;
2217*90e502c7SAndroid Build Coastguard Worker 
2218*90e502c7SAndroid Build Coastguard Worker     if (advance_packet_index) {
2219*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16),
2220*90e502c7SAndroid Build Coastguard Worker                               (uint16_t)(est & 0xFFFF));
2221*90e502c7SAndroid Build Coastguard Worker         stream->pending_roc = 0;
2222*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_add_index(&stream->rtp_rdbx, 0);
2223*90e502c7SAndroid Build Coastguard Worker     } else {
2224*90e502c7SAndroid Build Coastguard Worker         status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
2225*90e502c7SAndroid Build Coastguard Worker         if (status) {
2226*90e502c7SAndroid Build Coastguard Worker             if (status != srtp_err_status_replay_fail ||
2227*90e502c7SAndroid Build Coastguard Worker                 !stream->allow_repeat_tx)
2228*90e502c7SAndroid Build Coastguard Worker                 return status; /* we've been asked to reuse an index */
2229*90e502c7SAndroid Build Coastguard Worker         }
2230*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
2231*90e502c7SAndroid Build Coastguard Worker     }
2232*90e502c7SAndroid Build Coastguard Worker 
2233*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2234*90e502c7SAndroid Build Coastguard Worker     debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est),
2235*90e502c7SAndroid Build Coastguard Worker                  low32(est));
2236*90e502c7SAndroid Build Coastguard Worker #else
2237*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "estimated packet index: %016llx", est);
2238*90e502c7SAndroid Build Coastguard Worker #endif
2239*90e502c7SAndroid Build Coastguard Worker 
2240*90e502c7SAndroid Build Coastguard Worker     /*
2241*90e502c7SAndroid Build Coastguard Worker      * if we're using rindael counter mode, set nonce and seq
2242*90e502c7SAndroid Build Coastguard Worker      */
2243*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 ||
2244*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 ||
2245*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) {
2246*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
2247*90e502c7SAndroid Build Coastguard Worker 
2248*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
2249*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc;
2250*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2251*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(
2252*90e502c7SAndroid Build Coastguard Worker             make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
2253*90e502c7SAndroid Build Coastguard Worker #else
2254*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(est << 16);
2255*90e502c7SAndroid Build Coastguard Worker #endif
2256*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
2257*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_encrypt);
2258*90e502c7SAndroid Build Coastguard Worker         if (!status && session_keys->rtp_xtn_hdr_cipher) {
2259*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
2260*90e502c7SAndroid Build Coastguard Worker                                         (uint8_t *)&iv, srtp_direction_encrypt);
2261*90e502c7SAndroid Build Coastguard Worker         }
2262*90e502c7SAndroid Build Coastguard Worker     } else {
2263*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
2264*90e502c7SAndroid Build Coastguard Worker 
2265*90e502c7SAndroid Build Coastguard Worker /* otherwise, set the index to est */
2266*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2267*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
2268*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = 0;
2269*90e502c7SAndroid Build Coastguard Worker #else
2270*90e502c7SAndroid Build Coastguard Worker         iv.v64[0] = 0;
2271*90e502c7SAndroid Build Coastguard Worker #endif
2272*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(est);
2273*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
2274*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_encrypt);
2275*90e502c7SAndroid Build Coastguard Worker         if (!status && session_keys->rtp_xtn_hdr_cipher) {
2276*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
2277*90e502c7SAndroid Build Coastguard Worker                                         (uint8_t *)&iv, srtp_direction_encrypt);
2278*90e502c7SAndroid Build Coastguard Worker         }
2279*90e502c7SAndroid Build Coastguard Worker     }
2280*90e502c7SAndroid Build Coastguard Worker     if (status)
2281*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
2282*90e502c7SAndroid Build Coastguard Worker 
2283*90e502c7SAndroid Build Coastguard Worker /* shift est, put into network byte order */
2284*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2285*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(
2286*90e502c7SAndroid Build Coastguard Worker         make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
2287*90e502c7SAndroid Build Coastguard Worker #else
2288*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(est << 16);
2289*90e502c7SAndroid Build Coastguard Worker #endif
2290*90e502c7SAndroid Build Coastguard Worker 
2291*90e502c7SAndroid Build Coastguard Worker     /*
2292*90e502c7SAndroid Build Coastguard Worker      * if we're authenticating using a universal hash, put the keystream
2293*90e502c7SAndroid Build Coastguard Worker      * prefix into the authentication tag
2294*90e502c7SAndroid Build Coastguard Worker      */
2295*90e502c7SAndroid Build Coastguard Worker     if (auth_start) {
2296*90e502c7SAndroid Build Coastguard Worker         prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth);
2297*90e502c7SAndroid Build Coastguard Worker         if (prefix_len) {
2298*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_output(session_keys->rtp_cipher, auth_tag,
2299*90e502c7SAndroid Build Coastguard Worker                                         &prefix_len);
2300*90e502c7SAndroid Build Coastguard Worker             if (status)
2301*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_cipher_fail;
2302*90e502c7SAndroid Build Coastguard Worker             debug_print(mod_srtp, "keystream prefix: %s",
2303*90e502c7SAndroid Build Coastguard Worker                         srtp_octet_string_hex_string(auth_tag, prefix_len));
2304*90e502c7SAndroid Build Coastguard Worker         }
2305*90e502c7SAndroid Build Coastguard Worker     }
2306*90e502c7SAndroid Build Coastguard Worker 
2307*90e502c7SAndroid Build Coastguard Worker     if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
2308*90e502c7SAndroid Build Coastguard Worker         /*
2309*90e502c7SAndroid Build Coastguard Worker          * extensions header encryption RFC 6904
2310*90e502c7SAndroid Build Coastguard Worker          */
2311*90e502c7SAndroid Build Coastguard Worker         status = srtp_process_header_encryption(stream, xtn_hdr, session_keys);
2312*90e502c7SAndroid Build Coastguard Worker         if (status) {
2313*90e502c7SAndroid Build Coastguard Worker             return status;
2314*90e502c7SAndroid Build Coastguard Worker         }
2315*90e502c7SAndroid Build Coastguard Worker     }
2316*90e502c7SAndroid Build Coastguard Worker 
2317*90e502c7SAndroid Build Coastguard Worker     /* if we're encrypting, exor keystream into the message */
2318*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
2319*90e502c7SAndroid Build Coastguard Worker         status =
2320*90e502c7SAndroid Build Coastguard Worker             srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start,
2321*90e502c7SAndroid Build Coastguard Worker                                 (unsigned int *)&enc_octet_len);
2322*90e502c7SAndroid Build Coastguard Worker         if (status)
2323*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
2324*90e502c7SAndroid Build Coastguard Worker     }
2325*90e502c7SAndroid Build Coastguard Worker 
2326*90e502c7SAndroid Build Coastguard Worker     /*
2327*90e502c7SAndroid Build Coastguard Worker      *  if we're authenticating, run authentication function and put result
2328*90e502c7SAndroid Build Coastguard Worker      *  into the auth_tag
2329*90e502c7SAndroid Build Coastguard Worker      */
2330*90e502c7SAndroid Build Coastguard Worker     if (auth_start) {
2331*90e502c7SAndroid Build Coastguard Worker         /* initialize auth func context */
2332*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_start(session_keys->rtp_auth);
2333*90e502c7SAndroid Build Coastguard Worker         if (status)
2334*90e502c7SAndroid Build Coastguard Worker             return status;
2335*90e502c7SAndroid Build Coastguard Worker 
2336*90e502c7SAndroid Build Coastguard Worker         /* run auth func over packet */
2337*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start,
2338*90e502c7SAndroid Build Coastguard Worker                                   *pkt_octet_len);
2339*90e502c7SAndroid Build Coastguard Worker         if (status)
2340*90e502c7SAndroid Build Coastguard Worker             return status;
2341*90e502c7SAndroid Build Coastguard Worker 
2342*90e502c7SAndroid Build Coastguard Worker         /* run auth func over ROC, put result into auth_tag */
2343*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "estimated packet index: %016llx", est);
2344*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4,
2345*90e502c7SAndroid Build Coastguard Worker                                    auth_tag);
2346*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "srtp auth tag:    %s",
2347*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(auth_tag, tag_len));
2348*90e502c7SAndroid Build Coastguard Worker         if (status)
2349*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_auth_fail;
2350*90e502c7SAndroid Build Coastguard Worker     }
2351*90e502c7SAndroid Build Coastguard Worker 
2352*90e502c7SAndroid Build Coastguard Worker     if (auth_tag) {
2353*90e502c7SAndroid Build Coastguard Worker         /* increase the packet length by the length of the auth tag */
2354*90e502c7SAndroid Build Coastguard Worker         *pkt_octet_len += tag_len;
2355*90e502c7SAndroid Build Coastguard Worker     }
2356*90e502c7SAndroid Build Coastguard Worker 
2357*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
2358*90e502c7SAndroid Build Coastguard Worker         /* increate the packet length by the mki size */
2359*90e502c7SAndroid Build Coastguard Worker         *pkt_octet_len += mki_size;
2360*90e502c7SAndroid Build Coastguard Worker     }
2361*90e502c7SAndroid Build Coastguard Worker 
2362*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2363*90e502c7SAndroid Build Coastguard Worker }
2364*90e502c7SAndroid Build Coastguard Worker 
srtp_unprotect(srtp_ctx_t * ctx,void * srtp_hdr,int * pkt_octet_len)2365*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_unprotect(srtp_ctx_t *ctx,
2366*90e502c7SAndroid Build Coastguard Worker                                  void *srtp_hdr,
2367*90e502c7SAndroid Build Coastguard Worker                                  int *pkt_octet_len)
2368*90e502c7SAndroid Build Coastguard Worker {
2369*90e502c7SAndroid Build Coastguard Worker     return srtp_unprotect_mki(ctx, srtp_hdr, pkt_octet_len, 0);
2370*90e502c7SAndroid Build Coastguard Worker }
2371*90e502c7SAndroid Build Coastguard Worker 
srtp_unprotect_mki(srtp_ctx_t * ctx,void * srtp_hdr,int * pkt_octet_len,unsigned int use_mki)2372*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
2373*90e502c7SAndroid Build Coastguard Worker                                      void *srtp_hdr,
2374*90e502c7SAndroid Build Coastguard Worker                                      int *pkt_octet_len,
2375*90e502c7SAndroid Build Coastguard Worker                                      unsigned int use_mki)
2376*90e502c7SAndroid Build Coastguard Worker {
2377*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
2378*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
2379*90e502c7SAndroid Build Coastguard Worker     uint32_t *auth_start;           /* pointer to start of auth. portion      */
2380*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
2381*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL;       /* location of auth_tag within packet     */
2382*90e502c7SAndroid Build Coastguard Worker     srtp_xtd_seq_num_t est;         /* estimated xtd_seq_num_t of *hdr        */
2383*90e502c7SAndroid Build Coastguard Worker     int delta;                      /* delta of local pkt idx and that in hdr */
2384*90e502c7SAndroid Build Coastguard Worker     v128_t iv;
2385*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2386*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
2387*90e502c7SAndroid Build Coastguard Worker     uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
2388*90e502c7SAndroid Build Coastguard Worker     uint32_t tag_len, prefix_len;
2389*90e502c7SAndroid Build Coastguard Worker     srtp_hdr_xtnd_t *xtn_hdr = NULL;
2390*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
2391*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
2392*90e502c7SAndroid Build Coastguard Worker     int advance_packet_index = 0;
2393*90e502c7SAndroid Build Coastguard Worker     uint32_t roc_to_set = 0;
2394*90e502c7SAndroid Build Coastguard Worker     uint16_t seq_to_set = 0;
2395*90e502c7SAndroid Build Coastguard Worker 
2396*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "function srtp_unprotect", NULL);
2397*90e502c7SAndroid Build Coastguard Worker 
2398*90e502c7SAndroid Build Coastguard Worker     /* we assume the hdr is 32-bit aligned to start */
2399*90e502c7SAndroid Build Coastguard Worker 
2400*90e502c7SAndroid Build Coastguard Worker     /* Verify RTP header */
2401*90e502c7SAndroid Build Coastguard Worker     status = srtp_validate_rtp_header(srtp_hdr, pkt_octet_len);
2402*90e502c7SAndroid Build Coastguard Worker     if (status)
2403*90e502c7SAndroid Build Coastguard Worker         return status;
2404*90e502c7SAndroid Build Coastguard Worker 
2405*90e502c7SAndroid Build Coastguard Worker     /* check the packet length - it must at least contain a full header */
2406*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < octets_in_rtp_header)
2407*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2408*90e502c7SAndroid Build Coastguard Worker 
2409*90e502c7SAndroid Build Coastguard Worker     /*
2410*90e502c7SAndroid Build Coastguard Worker      * look up ssrc in srtp_stream list, and process the packet with
2411*90e502c7SAndroid Build Coastguard Worker      * the appropriate stream.  if we haven't seen this stream before,
2412*90e502c7SAndroid Build Coastguard Worker      * there's only one key for this srtp_session, and the cipher
2413*90e502c7SAndroid Build Coastguard Worker      * supports key-sharing, then we assume that a new stream using
2414*90e502c7SAndroid Build Coastguard Worker      * that key has just started up
2415*90e502c7SAndroid Build Coastguard Worker      */
2416*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(ctx, hdr->ssrc);
2417*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
2418*90e502c7SAndroid Build Coastguard Worker         if (ctx->stream_template != NULL) {
2419*90e502c7SAndroid Build Coastguard Worker             stream = ctx->stream_template;
2420*90e502c7SAndroid Build Coastguard Worker             debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)",
2421*90e502c7SAndroid Build Coastguard Worker                         ntohl(hdr->ssrc));
2422*90e502c7SAndroid Build Coastguard Worker 
2423*90e502c7SAndroid Build Coastguard Worker /*
2424*90e502c7SAndroid Build Coastguard Worker  * set estimated packet index to sequence number from header,
2425*90e502c7SAndroid Build Coastguard Worker  * and set delta equal to the same value
2426*90e502c7SAndroid Build Coastguard Worker  */
2427*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2428*90e502c7SAndroid Build Coastguard Worker             est = (srtp_xtd_seq_num_t)make64(0, ntohs(hdr->seq));
2429*90e502c7SAndroid Build Coastguard Worker             delta = low32(est);
2430*90e502c7SAndroid Build Coastguard Worker #else
2431*90e502c7SAndroid Build Coastguard Worker             est = (srtp_xtd_seq_num_t)ntohs(hdr->seq);
2432*90e502c7SAndroid Build Coastguard Worker             delta = (int)est;
2433*90e502c7SAndroid Build Coastguard Worker #endif
2434*90e502c7SAndroid Build Coastguard Worker         } else {
2435*90e502c7SAndroid Build Coastguard Worker             /*
2436*90e502c7SAndroid Build Coastguard Worker              * no stream corresponding to SSRC found, and we don't do
2437*90e502c7SAndroid Build Coastguard Worker              * key-sharing, so return an error
2438*90e502c7SAndroid Build Coastguard Worker              */
2439*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_no_ctx;
2440*90e502c7SAndroid Build Coastguard Worker         }
2441*90e502c7SAndroid Build Coastguard Worker     } else {
2442*90e502c7SAndroid Build Coastguard Worker         status = srtp_get_est_pkt_index(hdr, stream, &est, &delta);
2443*90e502c7SAndroid Build Coastguard Worker 
2444*90e502c7SAndroid Build Coastguard Worker         if (status && (status != srtp_err_status_pkt_idx_adv))
2445*90e502c7SAndroid Build Coastguard Worker             return status;
2446*90e502c7SAndroid Build Coastguard Worker 
2447*90e502c7SAndroid Build Coastguard Worker         if (status == srtp_err_status_pkt_idx_adv) {
2448*90e502c7SAndroid Build Coastguard Worker             advance_packet_index = 1;
2449*90e502c7SAndroid Build Coastguard Worker             roc_to_set = (uint32_t)(est >> 16);
2450*90e502c7SAndroid Build Coastguard Worker             seq_to_set = (uint16_t)(est & 0xFFFF);
2451*90e502c7SAndroid Build Coastguard Worker         }
2452*90e502c7SAndroid Build Coastguard Worker 
2453*90e502c7SAndroid Build Coastguard Worker         /* check replay database */
2454*90e502c7SAndroid Build Coastguard Worker         if (!advance_packet_index) {
2455*90e502c7SAndroid Build Coastguard Worker             status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
2456*90e502c7SAndroid Build Coastguard Worker             if (status)
2457*90e502c7SAndroid Build Coastguard Worker                 return status;
2458*90e502c7SAndroid Build Coastguard Worker         }
2459*90e502c7SAndroid Build Coastguard Worker     }
2460*90e502c7SAndroid Build Coastguard Worker 
2461*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2462*90e502c7SAndroid Build Coastguard Worker     debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),
2463*90e502c7SAndroid Build Coastguard Worker                  low32(est));
2464*90e502c7SAndroid Build Coastguard Worker #else
2465*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "estimated u_packet index: %016llx", est);
2466*90e502c7SAndroid Build Coastguard Worker #endif
2467*90e502c7SAndroid Build Coastguard Worker 
2468*90e502c7SAndroid Build Coastguard Worker     /* Determine if MKI is being used and what session keys should be used */
2469*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
2470*90e502c7SAndroid Build Coastguard Worker         session_keys = srtp_get_session_keys(
2471*90e502c7SAndroid Build Coastguard Worker             stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len,
2472*90e502c7SAndroid Build Coastguard Worker             &mki_size);
2473*90e502c7SAndroid Build Coastguard Worker 
2474*90e502c7SAndroid Build Coastguard Worker         if (session_keys == NULL)
2475*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_mki;
2476*90e502c7SAndroid Build Coastguard Worker     } else {
2477*90e502c7SAndroid Build Coastguard Worker         session_keys = &stream->session_keys[0];
2478*90e502c7SAndroid Build Coastguard Worker     }
2479*90e502c7SAndroid Build Coastguard Worker 
2480*90e502c7SAndroid Build Coastguard Worker     /*
2481*90e502c7SAndroid Build Coastguard Worker      * Check if this is an AEAD stream (GCM mode).  If so, then dispatch
2482*90e502c7SAndroid Build Coastguard Worker      * the request to our AEAD handler.
2483*90e502c7SAndroid Build Coastguard Worker      */
2484*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
2485*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
2486*90e502c7SAndroid Build Coastguard Worker         return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr,
2487*90e502c7SAndroid Build Coastguard Worker                                    (unsigned int *)pkt_octet_len, session_keys,
2488*90e502c7SAndroid Build Coastguard Worker                                    mki_size);
2489*90e502c7SAndroid Build Coastguard Worker     }
2490*90e502c7SAndroid Build Coastguard Worker 
2491*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream */
2492*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth);
2493*90e502c7SAndroid Build Coastguard Worker 
2494*90e502c7SAndroid Build Coastguard Worker     /*
2495*90e502c7SAndroid Build Coastguard Worker      * set the cipher's IV properly, depending on whatever cipher we
2496*90e502c7SAndroid Build Coastguard Worker      * happen to be using
2497*90e502c7SAndroid Build Coastguard Worker      */
2498*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 ||
2499*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 ||
2500*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) {
2501*90e502c7SAndroid Build Coastguard Worker         /* aes counter mode */
2502*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
2503*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc; /* still in network order */
2504*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2505*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(
2506*90e502c7SAndroid Build Coastguard Worker             make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
2507*90e502c7SAndroid Build Coastguard Worker #else
2508*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(est << 16);
2509*90e502c7SAndroid Build Coastguard Worker #endif
2510*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
2511*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_decrypt);
2512*90e502c7SAndroid Build Coastguard Worker         if (!status && session_keys->rtp_xtn_hdr_cipher) {
2513*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
2514*90e502c7SAndroid Build Coastguard Worker                                         (uint8_t *)&iv, srtp_direction_decrypt);
2515*90e502c7SAndroid Build Coastguard Worker         }
2516*90e502c7SAndroid Build Coastguard Worker     } else {
2517*90e502c7SAndroid Build Coastguard Worker /* no particular format - set the iv to the pakcet index */
2518*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2519*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
2520*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = 0;
2521*90e502c7SAndroid Build Coastguard Worker #else
2522*90e502c7SAndroid Build Coastguard Worker         iv.v64[0] = 0;
2523*90e502c7SAndroid Build Coastguard Worker #endif
2524*90e502c7SAndroid Build Coastguard Worker         iv.v64[1] = be64_to_cpu(est);
2525*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv,
2526*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_decrypt);
2527*90e502c7SAndroid Build Coastguard Worker         if (!status && session_keys->rtp_xtn_hdr_cipher) {
2528*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher,
2529*90e502c7SAndroid Build Coastguard Worker                                         (uint8_t *)&iv, srtp_direction_decrypt);
2530*90e502c7SAndroid Build Coastguard Worker         }
2531*90e502c7SAndroid Build Coastguard Worker     }
2532*90e502c7SAndroid Build Coastguard Worker     if (status)
2533*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
2534*90e502c7SAndroid Build Coastguard Worker 
2535*90e502c7SAndroid Build Coastguard Worker /* shift est, put into network byte order */
2536*90e502c7SAndroid Build Coastguard Worker #ifdef NO_64BIT_MATH
2537*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(
2538*90e502c7SAndroid Build Coastguard Worker         make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16));
2539*90e502c7SAndroid Build Coastguard Worker #else
2540*90e502c7SAndroid Build Coastguard Worker     est = be64_to_cpu(est << 16);
2541*90e502c7SAndroid Build Coastguard Worker #endif
2542*90e502c7SAndroid Build Coastguard Worker 
2543*90e502c7SAndroid Build Coastguard Worker     /*
2544*90e502c7SAndroid Build Coastguard Worker      * find starting point for decryption and length of data to be
2545*90e502c7SAndroid Build Coastguard Worker      * decrypted - the encrypted portion starts after the rtp header
2546*90e502c7SAndroid Build Coastguard Worker      * extension, if present; otherwise, it starts after the last csrc,
2547*90e502c7SAndroid Build Coastguard Worker      * if any are present
2548*90e502c7SAndroid Build Coastguard Worker      *
2549*90e502c7SAndroid Build Coastguard Worker      * if we're not providing confidentiality, set enc_start to NULL
2550*90e502c7SAndroid Build Coastguard Worker      */
2551*90e502c7SAndroid Build Coastguard Worker     if (stream->rtp_services & sec_serv_conf) {
2552*90e502c7SAndroid Build Coastguard Worker         enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
2553*90e502c7SAndroid Build Coastguard Worker         if (hdr->x == 1) {
2554*90e502c7SAndroid Build Coastguard Worker             xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
2555*90e502c7SAndroid Build Coastguard Worker             enc_start += (ntohs(xtn_hdr->length) + 1);
2556*90e502c7SAndroid Build Coastguard Worker         }
2557*90e502c7SAndroid Build Coastguard Worker         if (!((uint8_t *)enc_start <=
2558*90e502c7SAndroid Build Coastguard Worker               (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
2559*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_parse_err;
2560*90e502c7SAndroid Build Coastguard Worker         enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size -
2561*90e502c7SAndroid Build Coastguard Worker                                    ((uint8_t *)enc_start - (uint8_t *)hdr));
2562*90e502c7SAndroid Build Coastguard Worker     } else {
2563*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL;
2564*90e502c7SAndroid Build Coastguard Worker     }
2565*90e502c7SAndroid Build Coastguard Worker 
2566*90e502c7SAndroid Build Coastguard Worker     /*
2567*90e502c7SAndroid Build Coastguard Worker      * if we're providing authentication, set the auth_start and auth_tag
2568*90e502c7SAndroid Build Coastguard Worker      * pointers to the proper locations; otherwise, set auth_start to NULL
2569*90e502c7SAndroid Build Coastguard Worker      * to indicate that no authentication is needed
2570*90e502c7SAndroid Build Coastguard Worker      */
2571*90e502c7SAndroid Build Coastguard Worker     if (stream->rtp_services & sec_serv_auth) {
2572*90e502c7SAndroid Build Coastguard Worker         auth_start = (uint32_t *)hdr;
2573*90e502c7SAndroid Build Coastguard Worker         auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
2574*90e502c7SAndroid Build Coastguard Worker     } else {
2575*90e502c7SAndroid Build Coastguard Worker         auth_start = NULL;
2576*90e502c7SAndroid Build Coastguard Worker         auth_tag = NULL;
2577*90e502c7SAndroid Build Coastguard Worker     }
2578*90e502c7SAndroid Build Coastguard Worker 
2579*90e502c7SAndroid Build Coastguard Worker     /*
2580*90e502c7SAndroid Build Coastguard Worker      * if we expect message authentication, run the authentication
2581*90e502c7SAndroid Build Coastguard Worker      * function and compare the result with the value of the auth_tag
2582*90e502c7SAndroid Build Coastguard Worker      */
2583*90e502c7SAndroid Build Coastguard Worker     if (auth_start) {
2584*90e502c7SAndroid Build Coastguard Worker         /*
2585*90e502c7SAndroid Build Coastguard Worker          * if we're using a universal hash, then we need to compute the
2586*90e502c7SAndroid Build Coastguard Worker          * keystream prefix for encrypting the universal hash output
2587*90e502c7SAndroid Build Coastguard Worker          *
2588*90e502c7SAndroid Build Coastguard Worker          * if the keystream prefix length is zero, then we know that
2589*90e502c7SAndroid Build Coastguard Worker          * the authenticator isn't using a universal hash function
2590*90e502c7SAndroid Build Coastguard Worker          */
2591*90e502c7SAndroid Build Coastguard Worker         if (session_keys->rtp_auth->prefix_len != 0) {
2592*90e502c7SAndroid Build Coastguard Worker             prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth);
2593*90e502c7SAndroid Build Coastguard Worker             status = srtp_cipher_output(session_keys->rtp_cipher, tmp_tag,
2594*90e502c7SAndroid Build Coastguard Worker                                         &prefix_len);
2595*90e502c7SAndroid Build Coastguard Worker             debug_print(mod_srtp, "keystream prefix: %s",
2596*90e502c7SAndroid Build Coastguard Worker                         srtp_octet_string_hex_string(tmp_tag, prefix_len));
2597*90e502c7SAndroid Build Coastguard Worker             if (status)
2598*90e502c7SAndroid Build Coastguard Worker                 return srtp_err_status_cipher_fail;
2599*90e502c7SAndroid Build Coastguard Worker         }
2600*90e502c7SAndroid Build Coastguard Worker 
2601*90e502c7SAndroid Build Coastguard Worker         /* initialize auth func context */
2602*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_start(session_keys->rtp_auth);
2603*90e502c7SAndroid Build Coastguard Worker         if (status)
2604*90e502c7SAndroid Build Coastguard Worker             return status;
2605*90e502c7SAndroid Build Coastguard Worker 
2606*90e502c7SAndroid Build Coastguard Worker         /* now compute auth function over packet */
2607*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start,
2608*90e502c7SAndroid Build Coastguard Worker                                   *pkt_octet_len - tag_len - mki_size);
2609*90e502c7SAndroid Build Coastguard Worker 
2610*90e502c7SAndroid Build Coastguard Worker         /* run auth func over ROC, then write tmp tag */
2611*90e502c7SAndroid Build Coastguard Worker         status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4,
2612*90e502c7SAndroid Build Coastguard Worker                                    tmp_tag);
2613*90e502c7SAndroid Build Coastguard Worker 
2614*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "computed auth tag:    %s",
2615*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(tmp_tag, tag_len));
2616*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "packet auth tag:      %s",
2617*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(auth_tag, tag_len));
2618*90e502c7SAndroid Build Coastguard Worker         if (status)
2619*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_auth_fail;
2620*90e502c7SAndroid Build Coastguard Worker 
2621*90e502c7SAndroid Build Coastguard Worker         if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len))
2622*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_auth_fail;
2623*90e502c7SAndroid Build Coastguard Worker     }
2624*90e502c7SAndroid Build Coastguard Worker 
2625*90e502c7SAndroid Build Coastguard Worker     /*
2626*90e502c7SAndroid Build Coastguard Worker      * update the key usage limit, and check it to make sure that we
2627*90e502c7SAndroid Build Coastguard Worker      * didn't just hit either the soft limit or the hard limit, and call
2628*90e502c7SAndroid Build Coastguard Worker      * the event handler if we hit either.
2629*90e502c7SAndroid Build Coastguard Worker      */
2630*90e502c7SAndroid Build Coastguard Worker     switch (srtp_key_limit_update(session_keys->limit)) {
2631*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_normal:
2632*90e502c7SAndroid Build Coastguard Worker         break;
2633*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_soft_limit:
2634*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_soft_limit);
2635*90e502c7SAndroid Build Coastguard Worker         break;
2636*90e502c7SAndroid Build Coastguard Worker     case srtp_key_event_hard_limit:
2637*90e502c7SAndroid Build Coastguard Worker         srtp_handle_event(ctx, stream, event_key_hard_limit);
2638*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_key_expired;
2639*90e502c7SAndroid Build Coastguard Worker     default:
2640*90e502c7SAndroid Build Coastguard Worker         break;
2641*90e502c7SAndroid Build Coastguard Worker     }
2642*90e502c7SAndroid Build Coastguard Worker 
2643*90e502c7SAndroid Build Coastguard Worker     if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
2644*90e502c7SAndroid Build Coastguard Worker         /* extensions header encryption RFC 6904 */
2645*90e502c7SAndroid Build Coastguard Worker         status = srtp_process_header_encryption(stream, xtn_hdr, session_keys);
2646*90e502c7SAndroid Build Coastguard Worker         if (status) {
2647*90e502c7SAndroid Build Coastguard Worker             return status;
2648*90e502c7SAndroid Build Coastguard Worker         }
2649*90e502c7SAndroid Build Coastguard Worker     }
2650*90e502c7SAndroid Build Coastguard Worker 
2651*90e502c7SAndroid Build Coastguard Worker     /* if we're decrypting, add keystream into ciphertext */
2652*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
2653*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_decrypt(session_keys->rtp_cipher,
2654*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)enc_start, &enc_octet_len);
2655*90e502c7SAndroid Build Coastguard Worker         if (status)
2656*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
2657*90e502c7SAndroid Build Coastguard Worker     }
2658*90e502c7SAndroid Build Coastguard Worker 
2659*90e502c7SAndroid Build Coastguard Worker     /*
2660*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for received traffic - this check will
2661*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
2662*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
2663*90e502c7SAndroid Build Coastguard Worker      * those functions.
2664*90e502c7SAndroid Build Coastguard Worker      *
2665*90e502c7SAndroid Build Coastguard Worker      * we do this check *after* the authentication check, so that the
2666*90e502c7SAndroid Build Coastguard Worker      * latter check will catch any attempts to fool us into thinking
2667*90e502c7SAndroid Build Coastguard Worker      * that we've got a collision
2668*90e502c7SAndroid Build Coastguard Worker      */
2669*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_receiver) {
2670*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
2671*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_receiver;
2672*90e502c7SAndroid Build Coastguard Worker         } else {
2673*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
2674*90e502c7SAndroid Build Coastguard Worker         }
2675*90e502c7SAndroid Build Coastguard Worker     }
2676*90e502c7SAndroid Build Coastguard Worker 
2677*90e502c7SAndroid Build Coastguard Worker     /*
2678*90e502c7SAndroid Build Coastguard Worker      * if the stream is a 'provisional' one, in which the template context
2679*90e502c7SAndroid Build Coastguard Worker      * is used, then we need to allocate a new stream at this point, since
2680*90e502c7SAndroid Build Coastguard Worker      * the authentication passed
2681*90e502c7SAndroid Build Coastguard Worker      */
2682*90e502c7SAndroid Build Coastguard Worker     if (stream == ctx->stream_template) {
2683*90e502c7SAndroid Build Coastguard Worker         srtp_stream_ctx_t *new_stream;
2684*90e502c7SAndroid Build Coastguard Worker 
2685*90e502c7SAndroid Build Coastguard Worker         /*
2686*90e502c7SAndroid Build Coastguard Worker          * allocate and initialize a new stream
2687*90e502c7SAndroid Build Coastguard Worker          *
2688*90e502c7SAndroid Build Coastguard Worker          * note that we indicate failure if we can't allocate the new
2689*90e502c7SAndroid Build Coastguard Worker          * stream, and some implementations will want to not return
2690*90e502c7SAndroid Build Coastguard Worker          * failure here
2691*90e502c7SAndroid Build Coastguard Worker          */
2692*90e502c7SAndroid Build Coastguard Worker         status =
2693*90e502c7SAndroid Build Coastguard Worker             srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
2694*90e502c7SAndroid Build Coastguard Worker         if (status)
2695*90e502c7SAndroid Build Coastguard Worker             return status;
2696*90e502c7SAndroid Build Coastguard Worker 
2697*90e502c7SAndroid Build Coastguard Worker         /* add new stream to the head of the stream_list */
2698*90e502c7SAndroid Build Coastguard Worker         new_stream->next = ctx->stream_list;
2699*90e502c7SAndroid Build Coastguard Worker         ctx->stream_list = new_stream;
2700*90e502c7SAndroid Build Coastguard Worker 
2701*90e502c7SAndroid Build Coastguard Worker         /* set stream (the pointer used in this function) */
2702*90e502c7SAndroid Build Coastguard Worker         stream = new_stream;
2703*90e502c7SAndroid Build Coastguard Worker     }
2704*90e502c7SAndroid Build Coastguard Worker 
2705*90e502c7SAndroid Build Coastguard Worker     /*
2706*90e502c7SAndroid Build Coastguard Worker      * the message authentication function passed, so add the packet
2707*90e502c7SAndroid Build Coastguard Worker      * index into the replay database
2708*90e502c7SAndroid Build Coastguard Worker      */
2709*90e502c7SAndroid Build Coastguard Worker     if (advance_packet_index) {
2710*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, roc_to_set, seq_to_set);
2711*90e502c7SAndroid Build Coastguard Worker         stream->pending_roc = 0;
2712*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_add_index(&stream->rtp_rdbx, 0);
2713*90e502c7SAndroid Build Coastguard Worker     } else {
2714*90e502c7SAndroid Build Coastguard Worker         srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
2715*90e502c7SAndroid Build Coastguard Worker     }
2716*90e502c7SAndroid Build Coastguard Worker 
2717*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the auth tag */
2718*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= tag_len;
2719*90e502c7SAndroid Build Coastguard Worker 
2720*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the mki size */
2721*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= mki_size;
2722*90e502c7SAndroid Build Coastguard Worker 
2723*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2724*90e502c7SAndroid Build Coastguard Worker }
2725*90e502c7SAndroid Build Coastguard Worker 
srtp_init()2726*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_init()
2727*90e502c7SAndroid Build Coastguard Worker {
2728*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2729*90e502c7SAndroid Build Coastguard Worker 
2730*90e502c7SAndroid Build Coastguard Worker     /* initialize crypto kernel */
2731*90e502c7SAndroid Build Coastguard Worker     status = srtp_crypto_kernel_init();
2732*90e502c7SAndroid Build Coastguard Worker     if (status)
2733*90e502c7SAndroid Build Coastguard Worker         return status;
2734*90e502c7SAndroid Build Coastguard Worker 
2735*90e502c7SAndroid Build Coastguard Worker     /* load srtp debug module into the kernel */
2736*90e502c7SAndroid Build Coastguard Worker     status = srtp_crypto_kernel_load_debug_module(&mod_srtp);
2737*90e502c7SAndroid Build Coastguard Worker     if (status)
2738*90e502c7SAndroid Build Coastguard Worker         return status;
2739*90e502c7SAndroid Build Coastguard Worker 
2740*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2741*90e502c7SAndroid Build Coastguard Worker }
2742*90e502c7SAndroid Build Coastguard Worker 
srtp_shutdown()2743*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_shutdown()
2744*90e502c7SAndroid Build Coastguard Worker {
2745*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2746*90e502c7SAndroid Build Coastguard Worker 
2747*90e502c7SAndroid Build Coastguard Worker     /* shut down crypto kernel */
2748*90e502c7SAndroid Build Coastguard Worker     status = srtp_crypto_kernel_shutdown();
2749*90e502c7SAndroid Build Coastguard Worker     if (status)
2750*90e502c7SAndroid Build Coastguard Worker         return status;
2751*90e502c7SAndroid Build Coastguard Worker 
2752*90e502c7SAndroid Build Coastguard Worker     /* shutting down crypto kernel frees the srtp debug module as well */
2753*90e502c7SAndroid Build Coastguard Worker 
2754*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2755*90e502c7SAndroid Build Coastguard Worker }
2756*90e502c7SAndroid Build Coastguard Worker 
2757*90e502c7SAndroid Build Coastguard Worker /*
2758*90e502c7SAndroid Build Coastguard Worker  * The following code is under consideration for removal.  See
2759*90e502c7SAndroid Build Coastguard Worker  * SRTP_MAX_TRAILER_LEN
2760*90e502c7SAndroid Build Coastguard Worker  */
2761*90e502c7SAndroid Build Coastguard Worker #if 0
2762*90e502c7SAndroid Build Coastguard Worker 
2763*90e502c7SAndroid Build Coastguard Worker /*
2764*90e502c7SAndroid Build Coastguard Worker  * srtp_get_trailer_length(&a) returns the number of octets that will
2765*90e502c7SAndroid Build Coastguard Worker  * be added to an RTP packet by the SRTP processing.  This value
2766*90e502c7SAndroid Build Coastguard Worker  * is constant for a given srtp_stream_t (i.e. between initializations).
2767*90e502c7SAndroid Build Coastguard Worker  */
2768*90e502c7SAndroid Build Coastguard Worker 
2769*90e502c7SAndroid Build Coastguard Worker int
2770*90e502c7SAndroid Build Coastguard Worker srtp_get_trailer_length(const srtp_stream_t s) {
2771*90e502c7SAndroid Build Coastguard Worker   return srtp_auth_get_tag_length(s->rtp_auth);
2772*90e502c7SAndroid Build Coastguard Worker }
2773*90e502c7SAndroid Build Coastguard Worker 
2774*90e502c7SAndroid Build Coastguard Worker #endif
2775*90e502c7SAndroid Build Coastguard Worker 
2776*90e502c7SAndroid Build Coastguard Worker /*
2777*90e502c7SAndroid Build Coastguard Worker  * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
2778*90e502c7SAndroid Build Coastguard Worker  * to ssrc, or NULL if no stream exists for that ssrc
2779*90e502c7SAndroid Build Coastguard Worker  *
2780*90e502c7SAndroid Build Coastguard Worker  * this is an internal function
2781*90e502c7SAndroid Build Coastguard Worker  */
2782*90e502c7SAndroid Build Coastguard Worker 
srtp_get_stream(srtp_t srtp,uint32_t ssrc)2783*90e502c7SAndroid Build Coastguard Worker srtp_stream_ctx_t *srtp_get_stream(srtp_t srtp, uint32_t ssrc)
2784*90e502c7SAndroid Build Coastguard Worker {
2785*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
2786*90e502c7SAndroid Build Coastguard Worker 
2787*90e502c7SAndroid Build Coastguard Worker     /* walk down list until ssrc is found */
2788*90e502c7SAndroid Build Coastguard Worker     stream = srtp->stream_list;
2789*90e502c7SAndroid Build Coastguard Worker     while (stream != NULL) {
2790*90e502c7SAndroid Build Coastguard Worker         if (stream->ssrc == ssrc)
2791*90e502c7SAndroid Build Coastguard Worker             return stream;
2792*90e502c7SAndroid Build Coastguard Worker         stream = stream->next;
2793*90e502c7SAndroid Build Coastguard Worker     }
2794*90e502c7SAndroid Build Coastguard Worker 
2795*90e502c7SAndroid Build Coastguard Worker     /* we haven't found our ssrc, so return a null */
2796*90e502c7SAndroid Build Coastguard Worker     return NULL;
2797*90e502c7SAndroid Build Coastguard Worker }
2798*90e502c7SAndroid Build Coastguard Worker 
srtp_dealloc(srtp_t session)2799*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_dealloc(srtp_t session)
2800*90e502c7SAndroid Build Coastguard Worker {
2801*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
2802*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2803*90e502c7SAndroid Build Coastguard Worker 
2804*90e502c7SAndroid Build Coastguard Worker     /*
2805*90e502c7SAndroid Build Coastguard Worker      * we take a conservative deallocation strategy - if we encounter an
2806*90e502c7SAndroid Build Coastguard Worker      * error deallocating a stream, then we stop trying to deallocate
2807*90e502c7SAndroid Build Coastguard Worker      * memory and just return an error
2808*90e502c7SAndroid Build Coastguard Worker      */
2809*90e502c7SAndroid Build Coastguard Worker 
2810*90e502c7SAndroid Build Coastguard Worker     /* walk list of streams, deallocating as we go */
2811*90e502c7SAndroid Build Coastguard Worker     stream = session->stream_list;
2812*90e502c7SAndroid Build Coastguard Worker     while (stream != NULL) {
2813*90e502c7SAndroid Build Coastguard Worker         srtp_stream_t next = stream->next;
2814*90e502c7SAndroid Build Coastguard Worker         status = srtp_stream_dealloc(stream, session->stream_template);
2815*90e502c7SAndroid Build Coastguard Worker         if (status)
2816*90e502c7SAndroid Build Coastguard Worker             return status;
2817*90e502c7SAndroid Build Coastguard Worker         stream = next;
2818*90e502c7SAndroid Build Coastguard Worker     }
2819*90e502c7SAndroid Build Coastguard Worker 
2820*90e502c7SAndroid Build Coastguard Worker     /* deallocate stream template, if there is one */
2821*90e502c7SAndroid Build Coastguard Worker     if (session->stream_template != NULL) {
2822*90e502c7SAndroid Build Coastguard Worker         status = srtp_stream_dealloc(session->stream_template, NULL);
2823*90e502c7SAndroid Build Coastguard Worker         if (status)
2824*90e502c7SAndroid Build Coastguard Worker             return status;
2825*90e502c7SAndroid Build Coastguard Worker     }
2826*90e502c7SAndroid Build Coastguard Worker 
2827*90e502c7SAndroid Build Coastguard Worker     /* deallocate session context */
2828*90e502c7SAndroid Build Coastguard Worker     srtp_crypto_free(session);
2829*90e502c7SAndroid Build Coastguard Worker 
2830*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2831*90e502c7SAndroid Build Coastguard Worker }
2832*90e502c7SAndroid Build Coastguard Worker 
srtp_add_stream(srtp_t session,const srtp_policy_t * policy)2833*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy)
2834*90e502c7SAndroid Build Coastguard Worker {
2835*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2836*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t tmp;
2837*90e502c7SAndroid Build Coastguard Worker 
2838*90e502c7SAndroid Build Coastguard Worker     /* sanity check arguments */
2839*90e502c7SAndroid Build Coastguard Worker     if ((session == NULL) || (policy == NULL) ||
2840*90e502c7SAndroid Build Coastguard Worker         (!srtp_validate_policy_master_keys(policy)))
2841*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2842*90e502c7SAndroid Build Coastguard Worker 
2843*90e502c7SAndroid Build Coastguard Worker     /* allocate stream  */
2844*90e502c7SAndroid Build Coastguard Worker     status = srtp_stream_alloc(&tmp, policy);
2845*90e502c7SAndroid Build Coastguard Worker     if (status) {
2846*90e502c7SAndroid Build Coastguard Worker         return status;
2847*90e502c7SAndroid Build Coastguard Worker     }
2848*90e502c7SAndroid Build Coastguard Worker 
2849*90e502c7SAndroid Build Coastguard Worker     /* initialize stream  */
2850*90e502c7SAndroid Build Coastguard Worker     status = srtp_stream_init(tmp, policy);
2851*90e502c7SAndroid Build Coastguard Worker     if (status) {
2852*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(tmp, NULL);
2853*90e502c7SAndroid Build Coastguard Worker         return status;
2854*90e502c7SAndroid Build Coastguard Worker     }
2855*90e502c7SAndroid Build Coastguard Worker 
2856*90e502c7SAndroid Build Coastguard Worker     /*
2857*90e502c7SAndroid Build Coastguard Worker      * set the head of the stream list or the template to point to the
2858*90e502c7SAndroid Build Coastguard Worker      * stream that we've just alloced and init'ed, depending on whether
2859*90e502c7SAndroid Build Coastguard Worker      * or not it has a wildcard SSRC value or not
2860*90e502c7SAndroid Build Coastguard Worker      *
2861*90e502c7SAndroid Build Coastguard Worker      * if the template stream has already been set, then the policy is
2862*90e502c7SAndroid Build Coastguard Worker      * inconsistent, so we return a bad_param error code
2863*90e502c7SAndroid Build Coastguard Worker      */
2864*90e502c7SAndroid Build Coastguard Worker     switch (policy->ssrc.type) {
2865*90e502c7SAndroid Build Coastguard Worker     case (ssrc_any_outbound):
2866*90e502c7SAndroid Build Coastguard Worker         if (session->stream_template) {
2867*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(tmp, NULL);
2868*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_param;
2869*90e502c7SAndroid Build Coastguard Worker         }
2870*90e502c7SAndroid Build Coastguard Worker         session->stream_template = tmp;
2871*90e502c7SAndroid Build Coastguard Worker         session->stream_template->direction = dir_srtp_sender;
2872*90e502c7SAndroid Build Coastguard Worker         break;
2873*90e502c7SAndroid Build Coastguard Worker     case (ssrc_any_inbound):
2874*90e502c7SAndroid Build Coastguard Worker         if (session->stream_template) {
2875*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(tmp, NULL);
2876*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_param;
2877*90e502c7SAndroid Build Coastguard Worker         }
2878*90e502c7SAndroid Build Coastguard Worker         session->stream_template = tmp;
2879*90e502c7SAndroid Build Coastguard Worker         session->stream_template->direction = dir_srtp_receiver;
2880*90e502c7SAndroid Build Coastguard Worker         break;
2881*90e502c7SAndroid Build Coastguard Worker     case (ssrc_specific):
2882*90e502c7SAndroid Build Coastguard Worker         tmp->next = session->stream_list;
2883*90e502c7SAndroid Build Coastguard Worker         session->stream_list = tmp;
2884*90e502c7SAndroid Build Coastguard Worker         break;
2885*90e502c7SAndroid Build Coastguard Worker     case (ssrc_undefined):
2886*90e502c7SAndroid Build Coastguard Worker     default:
2887*90e502c7SAndroid Build Coastguard Worker         srtp_stream_dealloc(tmp, NULL);
2888*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2889*90e502c7SAndroid Build Coastguard Worker     }
2890*90e502c7SAndroid Build Coastguard Worker 
2891*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2892*90e502c7SAndroid Build Coastguard Worker }
2893*90e502c7SAndroid Build Coastguard Worker 
srtp_create(srtp_t * session,const srtp_policy_t * policy)2894*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_create(srtp_t *session, /* handle for session     */
2895*90e502c7SAndroid Build Coastguard Worker                               const srtp_policy_t *policy)
2896*90e502c7SAndroid Build Coastguard Worker { /* SRTP policy (list)     */
2897*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t stat;
2898*90e502c7SAndroid Build Coastguard Worker     srtp_ctx_t *ctx;
2899*90e502c7SAndroid Build Coastguard Worker 
2900*90e502c7SAndroid Build Coastguard Worker     /* sanity check arguments */
2901*90e502c7SAndroid Build Coastguard Worker     if (session == NULL)
2902*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2903*90e502c7SAndroid Build Coastguard Worker 
2904*90e502c7SAndroid Build Coastguard Worker     /* allocate srtp context and set ctx_ptr */
2905*90e502c7SAndroid Build Coastguard Worker     ctx = (srtp_ctx_t *)srtp_crypto_alloc(sizeof(srtp_ctx_t));
2906*90e502c7SAndroid Build Coastguard Worker     if (ctx == NULL)
2907*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_alloc_fail;
2908*90e502c7SAndroid Build Coastguard Worker     *session = ctx;
2909*90e502c7SAndroid Build Coastguard Worker 
2910*90e502c7SAndroid Build Coastguard Worker     /*
2911*90e502c7SAndroid Build Coastguard Worker      * loop over elements in the policy list, allocating and
2912*90e502c7SAndroid Build Coastguard Worker      * initializing a stream for each element
2913*90e502c7SAndroid Build Coastguard Worker      */
2914*90e502c7SAndroid Build Coastguard Worker     ctx->stream_template = NULL;
2915*90e502c7SAndroid Build Coastguard Worker     ctx->stream_list = NULL;
2916*90e502c7SAndroid Build Coastguard Worker     ctx->user_data = NULL;
2917*90e502c7SAndroid Build Coastguard Worker     while (policy != NULL) {
2918*90e502c7SAndroid Build Coastguard Worker         stat = srtp_add_stream(ctx, policy);
2919*90e502c7SAndroid Build Coastguard Worker         if (stat) {
2920*90e502c7SAndroid Build Coastguard Worker             /* clean up everything */
2921*90e502c7SAndroid Build Coastguard Worker             srtp_dealloc(*session);
2922*90e502c7SAndroid Build Coastguard Worker             *session = NULL;
2923*90e502c7SAndroid Build Coastguard Worker             return stat;
2924*90e502c7SAndroid Build Coastguard Worker         }
2925*90e502c7SAndroid Build Coastguard Worker 
2926*90e502c7SAndroid Build Coastguard Worker         /* set policy to next item in list  */
2927*90e502c7SAndroid Build Coastguard Worker         policy = policy->next;
2928*90e502c7SAndroid Build Coastguard Worker     }
2929*90e502c7SAndroid Build Coastguard Worker 
2930*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2931*90e502c7SAndroid Build Coastguard Worker }
2932*90e502c7SAndroid Build Coastguard Worker 
srtp_remove_stream(srtp_t session,uint32_t ssrc)2933*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_remove_stream(srtp_t session, uint32_t ssrc)
2934*90e502c7SAndroid Build Coastguard Worker {
2935*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream, *last_stream;
2936*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2937*90e502c7SAndroid Build Coastguard Worker 
2938*90e502c7SAndroid Build Coastguard Worker     /* sanity check arguments */
2939*90e502c7SAndroid Build Coastguard Worker     if (session == NULL)
2940*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2941*90e502c7SAndroid Build Coastguard Worker 
2942*90e502c7SAndroid Build Coastguard Worker     /* find stream in list; complain if not found */
2943*90e502c7SAndroid Build Coastguard Worker     last_stream = stream = session->stream_list;
2944*90e502c7SAndroid Build Coastguard Worker     while ((stream != NULL) && (ssrc != stream->ssrc)) {
2945*90e502c7SAndroid Build Coastguard Worker         last_stream = stream;
2946*90e502c7SAndroid Build Coastguard Worker         stream = stream->next;
2947*90e502c7SAndroid Build Coastguard Worker     }
2948*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL)
2949*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_no_ctx;
2950*90e502c7SAndroid Build Coastguard Worker 
2951*90e502c7SAndroid Build Coastguard Worker     /* remove stream from the list */
2952*90e502c7SAndroid Build Coastguard Worker     if (last_stream == stream)
2953*90e502c7SAndroid Build Coastguard Worker         /* stream was first in list */
2954*90e502c7SAndroid Build Coastguard Worker         session->stream_list = stream->next;
2955*90e502c7SAndroid Build Coastguard Worker     else
2956*90e502c7SAndroid Build Coastguard Worker         last_stream->next = stream->next;
2957*90e502c7SAndroid Build Coastguard Worker 
2958*90e502c7SAndroid Build Coastguard Worker     /* deallocate the stream */
2959*90e502c7SAndroid Build Coastguard Worker     status = srtp_stream_dealloc(stream, session->stream_template);
2960*90e502c7SAndroid Build Coastguard Worker     if (status)
2961*90e502c7SAndroid Build Coastguard Worker         return status;
2962*90e502c7SAndroid Build Coastguard Worker 
2963*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2964*90e502c7SAndroid Build Coastguard Worker }
2965*90e502c7SAndroid Build Coastguard Worker 
srtp_update(srtp_t session,const srtp_policy_t * policy)2966*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy)
2967*90e502c7SAndroid Build Coastguard Worker {
2968*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t stat;
2969*90e502c7SAndroid Build Coastguard Worker 
2970*90e502c7SAndroid Build Coastguard Worker     /* sanity check arguments */
2971*90e502c7SAndroid Build Coastguard Worker     if ((session == NULL) || (policy == NULL) ||
2972*90e502c7SAndroid Build Coastguard Worker         (!srtp_validate_policy_master_keys(policy))) {
2973*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2974*90e502c7SAndroid Build Coastguard Worker     }
2975*90e502c7SAndroid Build Coastguard Worker 
2976*90e502c7SAndroid Build Coastguard Worker     while (policy != NULL) {
2977*90e502c7SAndroid Build Coastguard Worker         stat = srtp_update_stream(session, policy);
2978*90e502c7SAndroid Build Coastguard Worker         if (stat) {
2979*90e502c7SAndroid Build Coastguard Worker             return stat;
2980*90e502c7SAndroid Build Coastguard Worker         }
2981*90e502c7SAndroid Build Coastguard Worker 
2982*90e502c7SAndroid Build Coastguard Worker         /* set policy to next item in list  */
2983*90e502c7SAndroid Build Coastguard Worker         policy = policy->next;
2984*90e502c7SAndroid Build Coastguard Worker     }
2985*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
2986*90e502c7SAndroid Build Coastguard Worker }
2987*90e502c7SAndroid Build Coastguard Worker 
update_template_streams(srtp_t session,const srtp_policy_t * policy)2988*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t update_template_streams(srtp_t session,
2989*90e502c7SAndroid Build Coastguard Worker                                                  const srtp_policy_t *policy)
2990*90e502c7SAndroid Build Coastguard Worker {
2991*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
2992*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t new_stream_template;
2993*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t new_stream_list = NULL;
2994*90e502c7SAndroid Build Coastguard Worker 
2995*90e502c7SAndroid Build Coastguard Worker     if (session->stream_template == NULL) {
2996*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
2997*90e502c7SAndroid Build Coastguard Worker     }
2998*90e502c7SAndroid Build Coastguard Worker 
2999*90e502c7SAndroid Build Coastguard Worker     /* allocate new template stream  */
3000*90e502c7SAndroid Build Coastguard Worker     status = srtp_stream_alloc(&new_stream_template, policy);
3001*90e502c7SAndroid Build Coastguard Worker     if (status) {
3002*90e502c7SAndroid Build Coastguard Worker         return status;
3003*90e502c7SAndroid Build Coastguard Worker     }
3004*90e502c7SAndroid Build Coastguard Worker 
3005*90e502c7SAndroid Build Coastguard Worker     /* initialize new template stream  */
3006*90e502c7SAndroid Build Coastguard Worker     status = srtp_stream_init(new_stream_template, policy);
3007*90e502c7SAndroid Build Coastguard Worker     if (status) {
3008*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_free(new_stream_template);
3009*90e502c7SAndroid Build Coastguard Worker         return status;
3010*90e502c7SAndroid Build Coastguard Worker     }
3011*90e502c7SAndroid Build Coastguard Worker 
3012*90e502c7SAndroid Build Coastguard Worker     /* for all old templated streams */
3013*90e502c7SAndroid Build Coastguard Worker     for (;;) {
3014*90e502c7SAndroid Build Coastguard Worker         srtp_stream_t stream;
3015*90e502c7SAndroid Build Coastguard Worker         uint32_t ssrc;
3016*90e502c7SAndroid Build Coastguard Worker         srtp_xtd_seq_num_t old_index;
3017*90e502c7SAndroid Build Coastguard Worker         srtp_rdb_t old_rtcp_rdb;
3018*90e502c7SAndroid Build Coastguard Worker 
3019*90e502c7SAndroid Build Coastguard Worker         stream = session->stream_list;
3020*90e502c7SAndroid Build Coastguard Worker         while ((stream != NULL) &&
3021*90e502c7SAndroid Build Coastguard Worker                (stream->session_keys[0].rtp_auth !=
3022*90e502c7SAndroid Build Coastguard Worker                 session->stream_template->session_keys[0].rtp_auth)) {
3023*90e502c7SAndroid Build Coastguard Worker             stream = stream->next;
3024*90e502c7SAndroid Build Coastguard Worker         }
3025*90e502c7SAndroid Build Coastguard Worker         if (stream == NULL) {
3026*90e502c7SAndroid Build Coastguard Worker             /* no more templated streams */
3027*90e502c7SAndroid Build Coastguard Worker             break;
3028*90e502c7SAndroid Build Coastguard Worker         }
3029*90e502c7SAndroid Build Coastguard Worker 
3030*90e502c7SAndroid Build Coastguard Worker         /* save old extendard seq */
3031*90e502c7SAndroid Build Coastguard Worker         ssrc = stream->ssrc;
3032*90e502c7SAndroid Build Coastguard Worker         old_index = stream->rtp_rdbx.index;
3033*90e502c7SAndroid Build Coastguard Worker         old_rtcp_rdb = stream->rtcp_rdb;
3034*90e502c7SAndroid Build Coastguard Worker 
3035*90e502c7SAndroid Build Coastguard Worker         /* remove stream */
3036*90e502c7SAndroid Build Coastguard Worker         status = srtp_remove_stream(session, ssrc);
3037*90e502c7SAndroid Build Coastguard Worker         if (status) {
3038*90e502c7SAndroid Build Coastguard Worker             /* free new allocations */
3039*90e502c7SAndroid Build Coastguard Worker             while (new_stream_list != NULL) {
3040*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_t next = new_stream_list->next;
3041*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_dealloc(new_stream_list, new_stream_template);
3042*90e502c7SAndroid Build Coastguard Worker                 new_stream_list = next;
3043*90e502c7SAndroid Build Coastguard Worker             }
3044*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(new_stream_template, NULL);
3045*90e502c7SAndroid Build Coastguard Worker             return status;
3046*90e502c7SAndroid Build Coastguard Worker         }
3047*90e502c7SAndroid Build Coastguard Worker 
3048*90e502c7SAndroid Build Coastguard Worker         /* allocate and initialize a new stream */
3049*90e502c7SAndroid Build Coastguard Worker         status = srtp_stream_clone(new_stream_template, ssrc, &stream);
3050*90e502c7SAndroid Build Coastguard Worker         if (status) {
3051*90e502c7SAndroid Build Coastguard Worker             /* free new allocations */
3052*90e502c7SAndroid Build Coastguard Worker             while (new_stream_list != NULL) {
3053*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_t next = new_stream_list->next;
3054*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_dealloc(new_stream_list, new_stream_template);
3055*90e502c7SAndroid Build Coastguard Worker                 new_stream_list = next;
3056*90e502c7SAndroid Build Coastguard Worker             }
3057*90e502c7SAndroid Build Coastguard Worker             srtp_stream_dealloc(new_stream_template, NULL);
3058*90e502c7SAndroid Build Coastguard Worker             return status;
3059*90e502c7SAndroid Build Coastguard Worker         }
3060*90e502c7SAndroid Build Coastguard Worker 
3061*90e502c7SAndroid Build Coastguard Worker         /* add new stream to the head of the new_stream_list */
3062*90e502c7SAndroid Build Coastguard Worker         stream->next = new_stream_list;
3063*90e502c7SAndroid Build Coastguard Worker         new_stream_list = stream;
3064*90e502c7SAndroid Build Coastguard Worker 
3065*90e502c7SAndroid Build Coastguard Worker         /* restore old extended seq */
3066*90e502c7SAndroid Build Coastguard Worker         stream->rtp_rdbx.index = old_index;
3067*90e502c7SAndroid Build Coastguard Worker         stream->rtcp_rdb = old_rtcp_rdb;
3068*90e502c7SAndroid Build Coastguard Worker     }
3069*90e502c7SAndroid Build Coastguard Worker     /* dealloc old template */
3070*90e502c7SAndroid Build Coastguard Worker     srtp_stream_dealloc(session->stream_template, NULL);
3071*90e502c7SAndroid Build Coastguard Worker     /* set new template */
3072*90e502c7SAndroid Build Coastguard Worker     session->stream_template = new_stream_template;
3073*90e502c7SAndroid Build Coastguard Worker     /* add new list */
3074*90e502c7SAndroid Build Coastguard Worker     if (new_stream_list) {
3075*90e502c7SAndroid Build Coastguard Worker         srtp_stream_t tail = new_stream_list;
3076*90e502c7SAndroid Build Coastguard Worker         while (tail->next) {
3077*90e502c7SAndroid Build Coastguard Worker             tail = tail->next;
3078*90e502c7SAndroid Build Coastguard Worker         }
3079*90e502c7SAndroid Build Coastguard Worker         tail->next = session->stream_list;
3080*90e502c7SAndroid Build Coastguard Worker         session->stream_list = new_stream_list;
3081*90e502c7SAndroid Build Coastguard Worker     }
3082*90e502c7SAndroid Build Coastguard Worker     return status;
3083*90e502c7SAndroid Build Coastguard Worker }
3084*90e502c7SAndroid Build Coastguard Worker 
update_stream(srtp_t session,const srtp_policy_t * policy)3085*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t update_stream(srtp_t session,
3086*90e502c7SAndroid Build Coastguard Worker                                        const srtp_policy_t *policy)
3087*90e502c7SAndroid Build Coastguard Worker {
3088*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
3089*90e502c7SAndroid Build Coastguard Worker     srtp_xtd_seq_num_t old_index;
3090*90e502c7SAndroid Build Coastguard Worker     srtp_rdb_t old_rtcp_rdb;
3091*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t stream;
3092*90e502c7SAndroid Build Coastguard Worker 
3093*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(session, htonl(policy->ssrc.value));
3094*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
3095*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
3096*90e502c7SAndroid Build Coastguard Worker     }
3097*90e502c7SAndroid Build Coastguard Worker 
3098*90e502c7SAndroid Build Coastguard Worker     /* save old extendard seq */
3099*90e502c7SAndroid Build Coastguard Worker     old_index = stream->rtp_rdbx.index;
3100*90e502c7SAndroid Build Coastguard Worker     old_rtcp_rdb = stream->rtcp_rdb;
3101*90e502c7SAndroid Build Coastguard Worker 
3102*90e502c7SAndroid Build Coastguard Worker     status = srtp_remove_stream(session, htonl(policy->ssrc.value));
3103*90e502c7SAndroid Build Coastguard Worker     if (status) {
3104*90e502c7SAndroid Build Coastguard Worker         return status;
3105*90e502c7SAndroid Build Coastguard Worker     }
3106*90e502c7SAndroid Build Coastguard Worker 
3107*90e502c7SAndroid Build Coastguard Worker     status = srtp_add_stream(session, policy);
3108*90e502c7SAndroid Build Coastguard Worker     if (status) {
3109*90e502c7SAndroid Build Coastguard Worker         return status;
3110*90e502c7SAndroid Build Coastguard Worker     }
3111*90e502c7SAndroid Build Coastguard Worker 
3112*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(session, htonl(policy->ssrc.value));
3113*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
3114*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_fail;
3115*90e502c7SAndroid Build Coastguard Worker     }
3116*90e502c7SAndroid Build Coastguard Worker 
3117*90e502c7SAndroid Build Coastguard Worker     /* restore old extended seq */
3118*90e502c7SAndroid Build Coastguard Worker     stream->rtp_rdbx.index = old_index;
3119*90e502c7SAndroid Build Coastguard Worker     stream->rtcp_rdb = old_rtcp_rdb;
3120*90e502c7SAndroid Build Coastguard Worker 
3121*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
3122*90e502c7SAndroid Build Coastguard Worker }
3123*90e502c7SAndroid Build Coastguard Worker 
srtp_update_stream(srtp_t session,const srtp_policy_t * policy)3124*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_update_stream(srtp_t session,
3125*90e502c7SAndroid Build Coastguard Worker                                      const srtp_policy_t *policy)
3126*90e502c7SAndroid Build Coastguard Worker {
3127*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
3128*90e502c7SAndroid Build Coastguard Worker 
3129*90e502c7SAndroid Build Coastguard Worker     /* sanity check arguments */
3130*90e502c7SAndroid Build Coastguard Worker     if ((session == NULL) || (policy == NULL) ||
3131*90e502c7SAndroid Build Coastguard Worker         (!srtp_validate_policy_master_keys(policy)))
3132*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
3133*90e502c7SAndroid Build Coastguard Worker 
3134*90e502c7SAndroid Build Coastguard Worker     switch (policy->ssrc.type) {
3135*90e502c7SAndroid Build Coastguard Worker     case (ssrc_any_outbound):
3136*90e502c7SAndroid Build Coastguard Worker     case (ssrc_any_inbound):
3137*90e502c7SAndroid Build Coastguard Worker         status = update_template_streams(session, policy);
3138*90e502c7SAndroid Build Coastguard Worker         break;
3139*90e502c7SAndroid Build Coastguard Worker     case (ssrc_specific):
3140*90e502c7SAndroid Build Coastguard Worker         status = update_stream(session, policy);
3141*90e502c7SAndroid Build Coastguard Worker         break;
3142*90e502c7SAndroid Build Coastguard Worker     case (ssrc_undefined):
3143*90e502c7SAndroid Build Coastguard Worker     default:
3144*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
3145*90e502c7SAndroid Build Coastguard Worker     }
3146*90e502c7SAndroid Build Coastguard Worker 
3147*90e502c7SAndroid Build Coastguard Worker     return status;
3148*90e502c7SAndroid Build Coastguard Worker }
3149*90e502c7SAndroid Build Coastguard Worker 
3150*90e502c7SAndroid Build Coastguard Worker /*
3151*90e502c7SAndroid Build Coastguard Worker  * The default policy - provides a convenient way for callers to use
3152*90e502c7SAndroid Build Coastguard Worker  * the default security policy
3153*90e502c7SAndroid Build Coastguard Worker  *
3154*90e502c7SAndroid Build Coastguard Worker  * The default policy is defined in RFC 3711
3155*90e502c7SAndroid Build Coastguard Worker  * (Section 5. Default and mandatory-to-implement Transforms)
3156*90e502c7SAndroid Build Coastguard Worker  *
3157*90e502c7SAndroid Build Coastguard Worker  */
3158*90e502c7SAndroid Build Coastguard Worker 
3159*90e502c7SAndroid Build Coastguard Worker /*
3160*90e502c7SAndroid Build Coastguard Worker  * NOTE: cipher_key_len is really key len (128 bits) plus salt len
3161*90e502c7SAndroid Build Coastguard Worker  *  (112 bits)
3162*90e502c7SAndroid Build Coastguard Worker  */
3163*90e502c7SAndroid Build Coastguard Worker /* There are hard-coded 16's for base_key_len in the key generation code */
3164*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t * p)3165*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p)
3166*90e502c7SAndroid Build Coastguard Worker {
3167*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_128;
3168*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len =
3169*90e502c7SAndroid Build Coastguard Worker         SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */
3170*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3171*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3172*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
3173*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3174*90e502c7SAndroid Build Coastguard Worker }
3175*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t * p)3176*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p)
3177*90e502c7SAndroid Build Coastguard Worker {
3178*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_128;
3179*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len =
3180*90e502c7SAndroid Build Coastguard Worker         SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */
3181*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3182*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3183*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
3184*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3185*90e502c7SAndroid Build Coastguard Worker }
3186*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t * p)3187*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p)
3188*90e502c7SAndroid Build Coastguard Worker {
3189*90e502c7SAndroid Build Coastguard Worker     /*
3190*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 4568
3191*90e502c7SAndroid Build Coastguard Worker      *
3192*90e502c7SAndroid Build Coastguard Worker      * note that this crypto policy is intended for SRTP, but not SRTCP
3193*90e502c7SAndroid Build Coastguard Worker      */
3194*90e502c7SAndroid Build Coastguard Worker 
3195*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_128;
3196*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len =
3197*90e502c7SAndroid Build Coastguard Worker         SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */
3198*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3199*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* 160 bit key               */
3200*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 4;  /* 32 bit tag                */
3201*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3202*90e502c7SAndroid Build Coastguard Worker }
3203*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t * p)3204*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p)
3205*90e502c7SAndroid Build Coastguard Worker {
3206*90e502c7SAndroid Build Coastguard Worker     /*
3207*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 4568
3208*90e502c7SAndroid Build Coastguard Worker      *
3209*90e502c7SAndroid Build Coastguard Worker      * note that this crypto policy is intended for SRTP, but not SRTCP
3210*90e502c7SAndroid Build Coastguard Worker      */
3211*90e502c7SAndroid Build Coastguard Worker 
3212*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_128;
3213*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len =
3214*90e502c7SAndroid Build Coastguard Worker         SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */
3215*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH;
3216*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3217*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 0;
3218*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf;
3219*90e502c7SAndroid Build Coastguard Worker }
3220*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t * p)3221*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p)
3222*90e502c7SAndroid Build Coastguard Worker {
3223*90e502c7SAndroid Build Coastguard Worker     /*
3224*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 4568
3225*90e502c7SAndroid Build Coastguard Worker      */
3226*90e502c7SAndroid Build Coastguard Worker 
3227*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_NULL_CIPHER;
3228*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = 0;
3229*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3230*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20;
3231*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 10;
3232*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_auth;
3233*90e502c7SAndroid Build Coastguard Worker }
3234*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t * p)3235*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p)
3236*90e502c7SAndroid Build Coastguard Worker {
3237*90e502c7SAndroid Build Coastguard Worker     /*
3238*90e502c7SAndroid Build Coastguard Worker      * Should only be used for testing
3239*90e502c7SAndroid Build Coastguard Worker      */
3240*90e502c7SAndroid Build Coastguard Worker 
3241*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_NULL_CIPHER;
3242*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = 0;
3243*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH;
3244*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3245*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 0;
3246*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_none;
3247*90e502c7SAndroid Build Coastguard Worker }
3248*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t * p)3249*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p)
3250*90e502c7SAndroid Build Coastguard Worker {
3251*90e502c7SAndroid Build Coastguard Worker     /*
3252*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 6188
3253*90e502c7SAndroid Build Coastguard Worker      */
3254*90e502c7SAndroid Build Coastguard Worker 
3255*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_256;
3256*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT;
3257*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3258*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3259*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
3260*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3261*90e502c7SAndroid Build Coastguard Worker }
3262*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t * p)3263*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p)
3264*90e502c7SAndroid Build Coastguard Worker {
3265*90e502c7SAndroid Build Coastguard Worker     /*
3266*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 6188
3267*90e502c7SAndroid Build Coastguard Worker      *
3268*90e502c7SAndroid Build Coastguard Worker      * note that this crypto policy is intended for SRTP, but not SRTCP
3269*90e502c7SAndroid Build Coastguard Worker      */
3270*90e502c7SAndroid Build Coastguard Worker 
3271*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_256;
3272*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT;
3273*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3274*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3275*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 4;  /* default 80 bits per RFC 3711 */
3276*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3277*90e502c7SAndroid Build Coastguard Worker }
3278*90e502c7SAndroid Build Coastguard Worker 
3279*90e502c7SAndroid Build Coastguard Worker /*
3280*90e502c7SAndroid Build Coastguard Worker  * AES-256 with no authentication.
3281*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t * p)3282*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p)
3283*90e502c7SAndroid Build Coastguard Worker {
3284*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_256;
3285*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT;
3286*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH;
3287*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3288*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 0;
3289*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf;
3290*90e502c7SAndroid Build Coastguard Worker }
3291*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t * p)3292*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p)
3293*90e502c7SAndroid Build Coastguard Worker {
3294*90e502c7SAndroid Build Coastguard Worker     /*
3295*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 6188
3296*90e502c7SAndroid Build Coastguard Worker      */
3297*90e502c7SAndroid Build Coastguard Worker 
3298*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_192;
3299*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT;
3300*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3301*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3302*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */
3303*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3304*90e502c7SAndroid Build Coastguard Worker }
3305*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t * p)3306*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p)
3307*90e502c7SAndroid Build Coastguard Worker {
3308*90e502c7SAndroid Build Coastguard Worker     /*
3309*90e502c7SAndroid Build Coastguard Worker      * corresponds to RFC 6188
3310*90e502c7SAndroid Build Coastguard Worker      *
3311*90e502c7SAndroid Build Coastguard Worker      * note that this crypto policy is intended for SRTP, but not SRTCP
3312*90e502c7SAndroid Build Coastguard Worker      */
3313*90e502c7SAndroid Build Coastguard Worker 
3314*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_192;
3315*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT;
3316*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_HMAC_SHA1;
3317*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 20; /* default 160 bits per RFC 3711 */
3318*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 4;  /* default 80 bits per RFC 3711 */
3319*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3320*90e502c7SAndroid Build Coastguard Worker }
3321*90e502c7SAndroid Build Coastguard Worker 
3322*90e502c7SAndroid Build Coastguard Worker /*
3323*90e502c7SAndroid Build Coastguard Worker  * AES-192 with no authentication.
3324*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t * p)3325*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p)
3326*90e502c7SAndroid Build Coastguard Worker {
3327*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_ICM_192;
3328*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT;
3329*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH;
3330*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3331*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 0;
3332*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf;
3333*90e502c7SAndroid Build Coastguard Worker }
3334*90e502c7SAndroid Build Coastguard Worker 
3335*90e502c7SAndroid Build Coastguard Worker /*
3336*90e502c7SAndroid Build Coastguard Worker  * AES-128 GCM mode with 8 octet auth tag.
3337*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t * p)3338*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p)
3339*90e502c7SAndroid Build Coastguard Worker {
3340*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_128;
3341*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT;
3342*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3343*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3344*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 8; /* 8 octet tag length */
3345*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3346*90e502c7SAndroid Build Coastguard Worker }
3347*90e502c7SAndroid Build Coastguard Worker 
3348*90e502c7SAndroid Build Coastguard Worker /*
3349*90e502c7SAndroid Build Coastguard Worker  * AES-256 GCM mode with 8 octet auth tag.
3350*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t * p)3351*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p)
3352*90e502c7SAndroid Build Coastguard Worker {
3353*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_256;
3354*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT;
3355*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3356*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3357*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 8; /* 8 octet tag length */
3358*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3359*90e502c7SAndroid Build Coastguard Worker }
3360*90e502c7SAndroid Build Coastguard Worker 
3361*90e502c7SAndroid Build Coastguard Worker /*
3362*90e502c7SAndroid Build Coastguard Worker  * AES-128 GCM mode with 8 octet auth tag, no RTCP encryption.
3363*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t * p)3364*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p)
3365*90e502c7SAndroid Build Coastguard Worker {
3366*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_128;
3367*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT;
3368*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3369*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3370*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 8;         /* 8 octet tag length */
3371*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_auth; /* This only applies to RTCP */
3372*90e502c7SAndroid Build Coastguard Worker }
3373*90e502c7SAndroid Build Coastguard Worker 
3374*90e502c7SAndroid Build Coastguard Worker /*
3375*90e502c7SAndroid Build Coastguard Worker  * AES-256 GCM mode with 8 octet auth tag, no RTCP encryption.
3376*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t * p)3377*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p)
3378*90e502c7SAndroid Build Coastguard Worker {
3379*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_256;
3380*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT;
3381*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3382*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3383*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 8;         /* 8 octet tag length */
3384*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_auth; /* This only applies to RTCP */
3385*90e502c7SAndroid Build Coastguard Worker }
3386*90e502c7SAndroid Build Coastguard Worker 
3387*90e502c7SAndroid Build Coastguard Worker /*
3388*90e502c7SAndroid Build Coastguard Worker  * AES-128 GCM mode with 16 octet auth tag.
3389*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t * p)3390*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p)
3391*90e502c7SAndroid Build Coastguard Worker {
3392*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_128;
3393*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT;
3394*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3395*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3396*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 16; /* 16 octet tag length */
3397*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3398*90e502c7SAndroid Build Coastguard Worker }
3399*90e502c7SAndroid Build Coastguard Worker 
3400*90e502c7SAndroid Build Coastguard Worker /*
3401*90e502c7SAndroid Build Coastguard Worker  * AES-256 GCM mode with 16 octet auth tag.
3402*90e502c7SAndroid Build Coastguard Worker  */
srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t * p)3403*90e502c7SAndroid Build Coastguard Worker void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p)
3404*90e502c7SAndroid Build Coastguard Worker {
3405*90e502c7SAndroid Build Coastguard Worker     p->cipher_type = SRTP_AES_GCM_256;
3406*90e502c7SAndroid Build Coastguard Worker     p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT;
3407*90e502c7SAndroid Build Coastguard Worker     p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */
3408*90e502c7SAndroid Build Coastguard Worker     p->auth_key_len = 0;
3409*90e502c7SAndroid Build Coastguard Worker     p->auth_tag_len = 16; /* 16 octet tag length */
3410*90e502c7SAndroid Build Coastguard Worker     p->sec_serv = sec_serv_conf_and_auth;
3411*90e502c7SAndroid Build Coastguard Worker }
3412*90e502c7SAndroid Build Coastguard Worker 
3413*90e502c7SAndroid Build Coastguard Worker /*
3414*90e502c7SAndroid Build Coastguard Worker  * secure rtcp functions
3415*90e502c7SAndroid Build Coastguard Worker  */
3416*90e502c7SAndroid Build Coastguard Worker 
3417*90e502c7SAndroid Build Coastguard Worker /*
3418*90e502c7SAndroid Build Coastguard Worker  * AEAD uses a new IV formation method.  This function implements
3419*90e502c7SAndroid Build Coastguard Worker  * section 9.1 (SRTCP IV Formation for AES-GCM) from RFC7714.
3420*90e502c7SAndroid Build Coastguard Worker  * The calculation is defined as, where (+) is the xor operation:
3421*90e502c7SAndroid Build Coastguard Worker  *
3422*90e502c7SAndroid Build Coastguard Worker  *                0  1  2  3  4  5  6  7  8  9 10 11
3423*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+
3424*90e502c7SAndroid Build Coastguard Worker  *               |00|00|    SSRC   |00|00|0+SRTCP Idx|---+
3425*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+   |
3426*90e502c7SAndroid Build Coastguard Worker  *                                                       |
3427*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+   |
3428*90e502c7SAndroid Build Coastguard Worker  *               |         Encryption Salt           |->(+)
3429*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+   |
3430*90e502c7SAndroid Build Coastguard Worker  *                                                       |
3431*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+   |
3432*90e502c7SAndroid Build Coastguard Worker  *               |       Initialization Vector       |<--+
3433*90e502c7SAndroid Build Coastguard Worker  *               +--+--+--+--+--+--+--+--+--+--+--+--+*
3434*90e502c7SAndroid Build Coastguard Worker  *
3435*90e502c7SAndroid Build Coastguard Worker  * Input:  *session_keys - pointer to SRTP stream context session keys,
3436*90e502c7SAndroid Build Coastguard Worker  *                        used to retrieve the SALT
3437*90e502c7SAndroid Build Coastguard Worker  *         *iv           - Pointer to recieve the calculated IV
3438*90e502c7SAndroid Build Coastguard Worker  *         seq_num       - The SEQ value to use for the IV calculation.
3439*90e502c7SAndroid Build Coastguard Worker  *         *hdr          - The RTP header, used to get the SSRC value
3440*90e502c7SAndroid Build Coastguard Worker  *
3441*90e502c7SAndroid Build Coastguard Worker  * Returns: srtp_err_status_ok if no error or srtp_err_status_bad_param
3442*90e502c7SAndroid Build Coastguard Worker  *          if seq_num is invalid
3443*90e502c7SAndroid Build Coastguard Worker  *
3444*90e502c7SAndroid Build Coastguard Worker  */
srtp_calc_aead_iv_srtcp(srtp_session_keys_t * session_keys,v128_t * iv,uint32_t seq_num,srtcp_hdr_t * hdr)3445*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_calc_aead_iv_srtcp(
3446*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys,
3447*90e502c7SAndroid Build Coastguard Worker     v128_t *iv,
3448*90e502c7SAndroid Build Coastguard Worker     uint32_t seq_num,
3449*90e502c7SAndroid Build Coastguard Worker     srtcp_hdr_t *hdr)
3450*90e502c7SAndroid Build Coastguard Worker {
3451*90e502c7SAndroid Build Coastguard Worker     v128_t in;
3452*90e502c7SAndroid Build Coastguard Worker     v128_t salt;
3453*90e502c7SAndroid Build Coastguard Worker 
3454*90e502c7SAndroid Build Coastguard Worker     memset(&in, 0, sizeof(v128_t));
3455*90e502c7SAndroid Build Coastguard Worker     memset(&salt, 0, sizeof(v128_t));
3456*90e502c7SAndroid Build Coastguard Worker 
3457*90e502c7SAndroid Build Coastguard Worker     in.v16[0] = 0;
3458*90e502c7SAndroid Build Coastguard Worker     memcpy(&in.v16[1], &hdr->ssrc, 4); /* still in network order! */
3459*90e502c7SAndroid Build Coastguard Worker     in.v16[3] = 0;
3460*90e502c7SAndroid Build Coastguard Worker 
3461*90e502c7SAndroid Build Coastguard Worker     /*
3462*90e502c7SAndroid Build Coastguard Worker      *  The SRTCP index (seq_num) spans bits 0 through 30 inclusive.
3463*90e502c7SAndroid Build Coastguard Worker      *  The most significant bit should be zero.
3464*90e502c7SAndroid Build Coastguard Worker      */
3465*90e502c7SAndroid Build Coastguard Worker     if (seq_num & 0x80000000UL) {
3466*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
3467*90e502c7SAndroid Build Coastguard Worker     }
3468*90e502c7SAndroid Build Coastguard Worker     in.v32[2] = htonl(seq_num);
3469*90e502c7SAndroid Build Coastguard Worker 
3470*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "Pre-salted RTCP IV = %s\n", v128_hex_string(&in));
3471*90e502c7SAndroid Build Coastguard Worker 
3472*90e502c7SAndroid Build Coastguard Worker     /*
3473*90e502c7SAndroid Build Coastguard Worker      * Get the SALT value from the context
3474*90e502c7SAndroid Build Coastguard Worker      */
3475*90e502c7SAndroid Build Coastguard Worker     memcpy(salt.v8, session_keys->c_salt, 12);
3476*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "RTCP SALT = %s\n", v128_hex_string(&salt));
3477*90e502c7SAndroid Build Coastguard Worker 
3478*90e502c7SAndroid Build Coastguard Worker     /*
3479*90e502c7SAndroid Build Coastguard Worker      * Finally, apply the SALT to the input
3480*90e502c7SAndroid Build Coastguard Worker      */
3481*90e502c7SAndroid Build Coastguard Worker     v128_xor(iv, &in, &salt);
3482*90e502c7SAndroid Build Coastguard Worker 
3483*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
3484*90e502c7SAndroid Build Coastguard Worker }
3485*90e502c7SAndroid Build Coastguard Worker 
3486*90e502c7SAndroid Build Coastguard Worker /*
3487*90e502c7SAndroid Build Coastguard Worker  * This code handles AEAD ciphers for outgoing RTCP.  We currently support
3488*90e502c7SAndroid Build Coastguard Worker  * AES-GCM mode with 128 or 256 bit keys.
3489*90e502c7SAndroid Build Coastguard Worker  */
srtp_protect_rtcp_aead(srtp_t ctx,srtp_stream_ctx_t * stream,void * rtcp_hdr,unsigned int * pkt_octet_len,srtp_session_keys_t * session_keys,unsigned int use_mki)3490*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_protect_rtcp_aead(
3491*90e502c7SAndroid Build Coastguard Worker     srtp_t ctx,
3492*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream,
3493*90e502c7SAndroid Build Coastguard Worker     void *rtcp_hdr,
3494*90e502c7SAndroid Build Coastguard Worker     unsigned int *pkt_octet_len,
3495*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys,
3496*90e502c7SAndroid Build Coastguard Worker     unsigned int use_mki)
3497*90e502c7SAndroid Build Coastguard Worker {
3498*90e502c7SAndroid Build Coastguard Worker     srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
3499*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
3500*90e502c7SAndroid Build Coastguard Worker     uint32_t *trailer_p;            /* pointer to start of trailer            */
3501*90e502c7SAndroid Build Coastguard Worker     uint32_t trailer;               /* trailer value                          */
3502*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
3503*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL;       /* location of auth_tag within packet     */
3504*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
3505*90e502c7SAndroid Build Coastguard Worker     uint32_t tag_len;
3506*90e502c7SAndroid Build Coastguard Worker     uint32_t seq_num;
3507*90e502c7SAndroid Build Coastguard Worker     v128_t iv;
3508*90e502c7SAndroid Build Coastguard Worker     uint32_t tseq;
3509*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
3510*90e502c7SAndroid Build Coastguard Worker 
3511*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream context */
3512*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
3513*90e502c7SAndroid Build Coastguard Worker 
3514*90e502c7SAndroid Build Coastguard Worker     /*
3515*90e502c7SAndroid Build Coastguard Worker      * set encryption start and encryption length - if we're not
3516*90e502c7SAndroid Build Coastguard Worker      * providing confidentiality, set enc_start to NULL
3517*90e502c7SAndroid Build Coastguard Worker      */
3518*90e502c7SAndroid Build Coastguard Worker     enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
3519*90e502c7SAndroid Build Coastguard Worker     enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
3520*90e502c7SAndroid Build Coastguard Worker 
3521*90e502c7SAndroid Build Coastguard Worker     /* NOTE: hdr->length is not usable - it refers to only the first
3522*90e502c7SAndroid Build Coastguard Worker      * RTCP report in the compound packet!
3523*90e502c7SAndroid Build Coastguard Worker      */
3524*90e502c7SAndroid Build Coastguard Worker     trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len);
3525*90e502c7SAndroid Build Coastguard Worker 
3526*90e502c7SAndroid Build Coastguard Worker     if (stream->rtcp_services & sec_serv_conf) {
3527*90e502c7SAndroid Build Coastguard Worker         trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
3528*90e502c7SAndroid Build Coastguard Worker     } else {
3529*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL;
3530*90e502c7SAndroid Build Coastguard Worker         enc_octet_len = 0;
3531*90e502c7SAndroid Build Coastguard Worker         /* 0 is network-order independant */
3532*90e502c7SAndroid Build Coastguard Worker         trailer = 0x00000000; /* set encrypt bit */
3533*90e502c7SAndroid Build Coastguard Worker     }
3534*90e502c7SAndroid Build Coastguard Worker 
3535*90e502c7SAndroid Build Coastguard Worker     mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len +
3536*90e502c7SAndroid Build Coastguard Worker                                    sizeof(srtcp_trailer_t),
3537*90e502c7SAndroid Build Coastguard Worker                                session_keys, use_mki);
3538*90e502c7SAndroid Build Coastguard Worker 
3539*90e502c7SAndroid Build Coastguard Worker     /*
3540*90e502c7SAndroid Build Coastguard Worker      * set the auth_tag pointer to the proper location, which is after
3541*90e502c7SAndroid Build Coastguard Worker      * the payload, but before the trailer
3542*90e502c7SAndroid Build Coastguard Worker      * (note that srtpc *always* provides authentication, unlike srtp)
3543*90e502c7SAndroid Build Coastguard Worker      */
3544*90e502c7SAndroid Build Coastguard Worker     /* Note: This would need to change for optional mikey data */
3545*90e502c7SAndroid Build Coastguard Worker     auth_tag = (uint8_t *)hdr + *pkt_octet_len;
3546*90e502c7SAndroid Build Coastguard Worker 
3547*90e502c7SAndroid Build Coastguard Worker     /*
3548*90e502c7SAndroid Build Coastguard Worker      * check sequence number for overruns, and copy it into the packet
3549*90e502c7SAndroid Build Coastguard Worker      * if its value isn't too big
3550*90e502c7SAndroid Build Coastguard Worker      */
3551*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdb_increment(&stream->rtcp_rdb);
3552*90e502c7SAndroid Build Coastguard Worker     if (status) {
3553*90e502c7SAndroid Build Coastguard Worker         return status;
3554*90e502c7SAndroid Build Coastguard Worker     }
3555*90e502c7SAndroid Build Coastguard Worker     seq_num = srtp_rdb_get_value(&stream->rtcp_rdb);
3556*90e502c7SAndroid Build Coastguard Worker     trailer |= htonl(seq_num);
3557*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp index: %x", seq_num);
3558*90e502c7SAndroid Build Coastguard Worker 
3559*90e502c7SAndroid Build Coastguard Worker     memcpy(trailer_p, &trailer, sizeof(trailer));
3560*90e502c7SAndroid Build Coastguard Worker 
3561*90e502c7SAndroid Build Coastguard Worker     /*
3562*90e502c7SAndroid Build Coastguard Worker      * Calculate and set the IV
3563*90e502c7SAndroid Build Coastguard Worker      */
3564*90e502c7SAndroid Build Coastguard Worker     status = srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr);
3565*90e502c7SAndroid Build Coastguard Worker     if (status) {
3566*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
3567*90e502c7SAndroid Build Coastguard Worker     }
3568*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
3569*90e502c7SAndroid Build Coastguard Worker                                 srtp_direction_encrypt);
3570*90e502c7SAndroid Build Coastguard Worker     if (status) {
3571*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
3572*90e502c7SAndroid Build Coastguard Worker     }
3573*90e502c7SAndroid Build Coastguard Worker 
3574*90e502c7SAndroid Build Coastguard Worker     /*
3575*90e502c7SAndroid Build Coastguard Worker      * Set the AAD for GCM mode
3576*90e502c7SAndroid Build Coastguard Worker      */
3577*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
3578*90e502c7SAndroid Build Coastguard Worker         /*
3579*90e502c7SAndroid Build Coastguard Worker          * If payload encryption is enabled, then the AAD consist of
3580*90e502c7SAndroid Build Coastguard Worker          * the RTCP header and the seq# at the end of the packet
3581*90e502c7SAndroid Build Coastguard Worker          */
3582*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr,
3583*90e502c7SAndroid Build Coastguard Worker                                      octets_in_rtcp_header);
3584*90e502c7SAndroid Build Coastguard Worker         if (status) {
3585*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3586*90e502c7SAndroid Build Coastguard Worker         }
3587*90e502c7SAndroid Build Coastguard Worker     } else {
3588*90e502c7SAndroid Build Coastguard Worker         /*
3589*90e502c7SAndroid Build Coastguard Worker          * Since payload encryption is not enabled, we must authenticate
3590*90e502c7SAndroid Build Coastguard Worker          * the entire packet as described in RFC 7714 (Section 9.3. Data
3591*90e502c7SAndroid Build Coastguard Worker          * Types in Unencrypted SRTCP Compound Packets)
3592*90e502c7SAndroid Build Coastguard Worker          */
3593*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr,
3594*90e502c7SAndroid Build Coastguard Worker                                      *pkt_octet_len);
3595*90e502c7SAndroid Build Coastguard Worker         if (status) {
3596*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3597*90e502c7SAndroid Build Coastguard Worker         }
3598*90e502c7SAndroid Build Coastguard Worker     }
3599*90e502c7SAndroid Build Coastguard Worker     /*
3600*90e502c7SAndroid Build Coastguard Worker      * Process the sequence# as AAD
3601*90e502c7SAndroid Build Coastguard Worker      */
3602*90e502c7SAndroid Build Coastguard Worker     tseq = trailer;
3603*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq,
3604*90e502c7SAndroid Build Coastguard Worker                                  sizeof(srtcp_trailer_t));
3605*90e502c7SAndroid Build Coastguard Worker     if (status) {
3606*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_cipher_fail);
3607*90e502c7SAndroid Build Coastguard Worker     }
3608*90e502c7SAndroid Build Coastguard Worker 
3609*90e502c7SAndroid Build Coastguard Worker     /* if we're encrypting, exor keystream into the message */
3610*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
3611*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_encrypt(session_keys->rtcp_cipher,
3612*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)enc_start, &enc_octet_len);
3613*90e502c7SAndroid Build Coastguard Worker         if (status) {
3614*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
3615*90e502c7SAndroid Build Coastguard Worker         }
3616*90e502c7SAndroid Build Coastguard Worker         /*
3617*90e502c7SAndroid Build Coastguard Worker          * Get the tag and append that to the output
3618*90e502c7SAndroid Build Coastguard Worker          */
3619*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_get_tag(session_keys->rtcp_cipher,
3620*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)auth_tag, &tag_len);
3621*90e502c7SAndroid Build Coastguard Worker         if (status) {
3622*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3623*90e502c7SAndroid Build Coastguard Worker         }
3624*90e502c7SAndroid Build Coastguard Worker         enc_octet_len += tag_len;
3625*90e502c7SAndroid Build Coastguard Worker     } else {
3626*90e502c7SAndroid Build Coastguard Worker         /*
3627*90e502c7SAndroid Build Coastguard Worker          * Even though we're not encrypting the payload, we need
3628*90e502c7SAndroid Build Coastguard Worker          * to run the cipher to get the auth tag.
3629*90e502c7SAndroid Build Coastguard Worker          */
3630*90e502c7SAndroid Build Coastguard Worker         unsigned int nolen = 0;
3631*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_encrypt(session_keys->rtcp_cipher, NULL, &nolen);
3632*90e502c7SAndroid Build Coastguard Worker         if (status) {
3633*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
3634*90e502c7SAndroid Build Coastguard Worker         }
3635*90e502c7SAndroid Build Coastguard Worker         /*
3636*90e502c7SAndroid Build Coastguard Worker          * Get the tag and append that to the output
3637*90e502c7SAndroid Build Coastguard Worker          */
3638*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_get_tag(session_keys->rtcp_cipher,
3639*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)auth_tag, &tag_len);
3640*90e502c7SAndroid Build Coastguard Worker         if (status) {
3641*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3642*90e502c7SAndroid Build Coastguard Worker         }
3643*90e502c7SAndroid Build Coastguard Worker         enc_octet_len += tag_len;
3644*90e502c7SAndroid Build Coastguard Worker     }
3645*90e502c7SAndroid Build Coastguard Worker 
3646*90e502c7SAndroid Build Coastguard Worker     /* increase the packet length by the length of the auth tag and seq_num*/
3647*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
3648*90e502c7SAndroid Build Coastguard Worker 
3649*90e502c7SAndroid Build Coastguard Worker     /* increase the packet by the mki_size */
3650*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += mki_size;
3651*90e502c7SAndroid Build Coastguard Worker 
3652*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
3653*90e502c7SAndroid Build Coastguard Worker }
3654*90e502c7SAndroid Build Coastguard Worker 
3655*90e502c7SAndroid Build Coastguard Worker /*
3656*90e502c7SAndroid Build Coastguard Worker  * This function handles incoming SRTCP packets while in AEAD mode,
3657*90e502c7SAndroid Build Coastguard Worker  * which currently supports AES-GCM encryption.  Note, the auth tag is
3658*90e502c7SAndroid Build Coastguard Worker  * at the end of the packet stream and is automatically checked by GCM
3659*90e502c7SAndroid Build Coastguard Worker  * when decrypting the payload.
3660*90e502c7SAndroid Build Coastguard Worker  */
srtp_unprotect_rtcp_aead(srtp_t ctx,srtp_stream_ctx_t * stream,void * srtcp_hdr,unsigned int * pkt_octet_len,srtp_session_keys_t * session_keys,unsigned int use_mki)3661*90e502c7SAndroid Build Coastguard Worker static srtp_err_status_t srtp_unprotect_rtcp_aead(
3662*90e502c7SAndroid Build Coastguard Worker     srtp_t ctx,
3663*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream,
3664*90e502c7SAndroid Build Coastguard Worker     void *srtcp_hdr,
3665*90e502c7SAndroid Build Coastguard Worker     unsigned int *pkt_octet_len,
3666*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys,
3667*90e502c7SAndroid Build Coastguard Worker     unsigned int use_mki)
3668*90e502c7SAndroid Build Coastguard Worker {
3669*90e502c7SAndroid Build Coastguard Worker     srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
3670*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
3671*90e502c7SAndroid Build Coastguard Worker     uint32_t *trailer_p;            /* pointer to start of trailer            */
3672*90e502c7SAndroid Build Coastguard Worker     uint32_t trailer;               /* trailer value                          */
3673*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
3674*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL;       /* location of auth_tag within packet     */
3675*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
3676*90e502c7SAndroid Build Coastguard Worker     int tag_len;
3677*90e502c7SAndroid Build Coastguard Worker     unsigned int tmp_len;
3678*90e502c7SAndroid Build Coastguard Worker     uint32_t seq_num;
3679*90e502c7SAndroid Build Coastguard Worker     v128_t iv;
3680*90e502c7SAndroid Build Coastguard Worker     uint32_t tseq;
3681*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
3682*90e502c7SAndroid Build Coastguard Worker 
3683*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream context */
3684*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
3685*90e502c7SAndroid Build Coastguard Worker 
3686*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
3687*90e502c7SAndroid Build Coastguard Worker         mki_size = session_keys->mki_size;
3688*90e502c7SAndroid Build Coastguard Worker     }
3689*90e502c7SAndroid Build Coastguard Worker 
3690*90e502c7SAndroid Build Coastguard Worker     /*
3691*90e502c7SAndroid Build Coastguard Worker      * set encryption start, encryption length, and trailer
3692*90e502c7SAndroid Build Coastguard Worker      */
3693*90e502c7SAndroid Build Coastguard Worker     /* index & E (encryption) bit follow normal data. hdr->len is the number of
3694*90e502c7SAndroid Build Coastguard Worker      * words (32-bit) in the normal packet minus 1
3695*90e502c7SAndroid Build Coastguard Worker      */
3696*90e502c7SAndroid Build Coastguard Worker     /* This should point trailer to the word past the end of the normal data. */
3697*90e502c7SAndroid Build Coastguard Worker     /* This would need to be modified for optional mikey data */
3698*90e502c7SAndroid Build Coastguard Worker     trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
3699*90e502c7SAndroid Build Coastguard Worker                              sizeof(srtcp_trailer_t) - mki_size);
3700*90e502c7SAndroid Build Coastguard Worker     memcpy(&trailer, trailer_p, sizeof(trailer));
3701*90e502c7SAndroid Build Coastguard Worker 
3702*90e502c7SAndroid Build Coastguard Worker     /*
3703*90e502c7SAndroid Build Coastguard Worker      * We pass the tag down to the cipher when doing GCM mode
3704*90e502c7SAndroid Build Coastguard Worker      */
3705*90e502c7SAndroid Build Coastguard Worker     enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header +
3706*90e502c7SAndroid Build Coastguard Worker                                       sizeof(srtcp_trailer_t) + mki_size);
3707*90e502c7SAndroid Build Coastguard Worker     auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len - mki_size -
3708*90e502c7SAndroid Build Coastguard Worker                sizeof(srtcp_trailer_t);
3709*90e502c7SAndroid Build Coastguard Worker 
3710*90e502c7SAndroid Build Coastguard Worker     if (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) {
3711*90e502c7SAndroid Build Coastguard Worker         enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
3712*90e502c7SAndroid Build Coastguard Worker     } else {
3713*90e502c7SAndroid Build Coastguard Worker         enc_octet_len = 0;
3714*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL; /* this indicates that there's no encryption */
3715*90e502c7SAndroid Build Coastguard Worker     }
3716*90e502c7SAndroid Build Coastguard Worker 
3717*90e502c7SAndroid Build Coastguard Worker     /*
3718*90e502c7SAndroid Build Coastguard Worker      * check the sequence number for replays
3719*90e502c7SAndroid Build Coastguard Worker      */
3720*90e502c7SAndroid Build Coastguard Worker     /* this is easier than dealing with bitfield access */
3721*90e502c7SAndroid Build Coastguard Worker     seq_num = ntohl(trailer) & SRTCP_INDEX_MASK;
3722*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp index: %x", seq_num);
3723*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdb_check(&stream->rtcp_rdb, seq_num);
3724*90e502c7SAndroid Build Coastguard Worker     if (status) {
3725*90e502c7SAndroid Build Coastguard Worker         return status;
3726*90e502c7SAndroid Build Coastguard Worker     }
3727*90e502c7SAndroid Build Coastguard Worker 
3728*90e502c7SAndroid Build Coastguard Worker     /*
3729*90e502c7SAndroid Build Coastguard Worker      * Calculate and set the IV
3730*90e502c7SAndroid Build Coastguard Worker      */
3731*90e502c7SAndroid Build Coastguard Worker     status = srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr);
3732*90e502c7SAndroid Build Coastguard Worker     if (status) {
3733*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
3734*90e502c7SAndroid Build Coastguard Worker     }
3735*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
3736*90e502c7SAndroid Build Coastguard Worker                                 srtp_direction_decrypt);
3737*90e502c7SAndroid Build Coastguard Worker     if (status) {
3738*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
3739*90e502c7SAndroid Build Coastguard Worker     }
3740*90e502c7SAndroid Build Coastguard Worker 
3741*90e502c7SAndroid Build Coastguard Worker     /*
3742*90e502c7SAndroid Build Coastguard Worker      * Set the AAD for GCM mode
3743*90e502c7SAndroid Build Coastguard Worker      */
3744*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
3745*90e502c7SAndroid Build Coastguard Worker         /*
3746*90e502c7SAndroid Build Coastguard Worker          * If payload encryption is enabled, then the AAD consist of
3747*90e502c7SAndroid Build Coastguard Worker          * the RTCP header and the seq# at the end of the packet
3748*90e502c7SAndroid Build Coastguard Worker          */
3749*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr,
3750*90e502c7SAndroid Build Coastguard Worker                                      octets_in_rtcp_header);
3751*90e502c7SAndroid Build Coastguard Worker         if (status) {
3752*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3753*90e502c7SAndroid Build Coastguard Worker         }
3754*90e502c7SAndroid Build Coastguard Worker     } else {
3755*90e502c7SAndroid Build Coastguard Worker         /*
3756*90e502c7SAndroid Build Coastguard Worker          * Since payload encryption is not enabled, we must authenticate
3757*90e502c7SAndroid Build Coastguard Worker          * the entire packet as described in RFC 7714 (Section 9.3. Data
3758*90e502c7SAndroid Build Coastguard Worker          * Types in Unencrypted SRTCP Compound Packets)
3759*90e502c7SAndroid Build Coastguard Worker          */
3760*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_aad(
3761*90e502c7SAndroid Build Coastguard Worker             session_keys->rtcp_cipher, (uint8_t *)hdr,
3762*90e502c7SAndroid Build Coastguard Worker             (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size));
3763*90e502c7SAndroid Build Coastguard Worker         if (status) {
3764*90e502c7SAndroid Build Coastguard Worker             return (srtp_err_status_cipher_fail);
3765*90e502c7SAndroid Build Coastguard Worker         }
3766*90e502c7SAndroid Build Coastguard Worker     }
3767*90e502c7SAndroid Build Coastguard Worker 
3768*90e502c7SAndroid Build Coastguard Worker     /*
3769*90e502c7SAndroid Build Coastguard Worker      * Process the sequence# as AAD
3770*90e502c7SAndroid Build Coastguard Worker      */
3771*90e502c7SAndroid Build Coastguard Worker     tseq = trailer;
3772*90e502c7SAndroid Build Coastguard Worker     status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq,
3773*90e502c7SAndroid Build Coastguard Worker                                  sizeof(srtcp_trailer_t));
3774*90e502c7SAndroid Build Coastguard Worker     if (status) {
3775*90e502c7SAndroid Build Coastguard Worker         return (srtp_err_status_cipher_fail);
3776*90e502c7SAndroid Build Coastguard Worker     }
3777*90e502c7SAndroid Build Coastguard Worker 
3778*90e502c7SAndroid Build Coastguard Worker     /* if we're decrypting, exor keystream into the message */
3779*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
3780*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
3781*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)enc_start, &enc_octet_len);
3782*90e502c7SAndroid Build Coastguard Worker         if (status) {
3783*90e502c7SAndroid Build Coastguard Worker             return status;
3784*90e502c7SAndroid Build Coastguard Worker         }
3785*90e502c7SAndroid Build Coastguard Worker     } else {
3786*90e502c7SAndroid Build Coastguard Worker         /*
3787*90e502c7SAndroid Build Coastguard Worker          * Still need to run the cipher to check the tag
3788*90e502c7SAndroid Build Coastguard Worker          */
3789*90e502c7SAndroid Build Coastguard Worker         tmp_len = tag_len;
3790*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
3791*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)auth_tag, &tmp_len);
3792*90e502c7SAndroid Build Coastguard Worker         if (status) {
3793*90e502c7SAndroid Build Coastguard Worker             return status;
3794*90e502c7SAndroid Build Coastguard Worker         }
3795*90e502c7SAndroid Build Coastguard Worker     }
3796*90e502c7SAndroid Build Coastguard Worker 
3797*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the auth tag and seq_num*/
3798*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t) + mki_size);
3799*90e502c7SAndroid Build Coastguard Worker 
3800*90e502c7SAndroid Build Coastguard Worker     /*
3801*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for received traffic - this check will
3802*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
3803*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
3804*90e502c7SAndroid Build Coastguard Worker      * those functions.
3805*90e502c7SAndroid Build Coastguard Worker      *
3806*90e502c7SAndroid Build Coastguard Worker      * we do this check *after* the authentication check, so that the
3807*90e502c7SAndroid Build Coastguard Worker      * latter check will catch any attempts to fool us into thinking
3808*90e502c7SAndroid Build Coastguard Worker      * that we've got a collision
3809*90e502c7SAndroid Build Coastguard Worker      */
3810*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_receiver) {
3811*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
3812*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_receiver;
3813*90e502c7SAndroid Build Coastguard Worker         } else {
3814*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
3815*90e502c7SAndroid Build Coastguard Worker         }
3816*90e502c7SAndroid Build Coastguard Worker     }
3817*90e502c7SAndroid Build Coastguard Worker 
3818*90e502c7SAndroid Build Coastguard Worker     /*
3819*90e502c7SAndroid Build Coastguard Worker      * if the stream is a 'provisional' one, in which the template context
3820*90e502c7SAndroid Build Coastguard Worker      * is used, then we need to allocate a new stream at this point, since
3821*90e502c7SAndroid Build Coastguard Worker      * the authentication passed
3822*90e502c7SAndroid Build Coastguard Worker      */
3823*90e502c7SAndroid Build Coastguard Worker     if (stream == ctx->stream_template) {
3824*90e502c7SAndroid Build Coastguard Worker         srtp_stream_ctx_t *new_stream;
3825*90e502c7SAndroid Build Coastguard Worker 
3826*90e502c7SAndroid Build Coastguard Worker         /*
3827*90e502c7SAndroid Build Coastguard Worker          * allocate and initialize a new stream
3828*90e502c7SAndroid Build Coastguard Worker          *
3829*90e502c7SAndroid Build Coastguard Worker          * note that we indicate failure if we can't allocate the new
3830*90e502c7SAndroid Build Coastguard Worker          * stream, and some implementations will want to not return
3831*90e502c7SAndroid Build Coastguard Worker          * failure here
3832*90e502c7SAndroid Build Coastguard Worker          */
3833*90e502c7SAndroid Build Coastguard Worker         status =
3834*90e502c7SAndroid Build Coastguard Worker             srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
3835*90e502c7SAndroid Build Coastguard Worker         if (status) {
3836*90e502c7SAndroid Build Coastguard Worker             return status;
3837*90e502c7SAndroid Build Coastguard Worker         }
3838*90e502c7SAndroid Build Coastguard Worker 
3839*90e502c7SAndroid Build Coastguard Worker         /* add new stream to the head of the stream_list */
3840*90e502c7SAndroid Build Coastguard Worker         new_stream->next = ctx->stream_list;
3841*90e502c7SAndroid Build Coastguard Worker         ctx->stream_list = new_stream;
3842*90e502c7SAndroid Build Coastguard Worker 
3843*90e502c7SAndroid Build Coastguard Worker         /* set stream (the pointer used in this function) */
3844*90e502c7SAndroid Build Coastguard Worker         stream = new_stream;
3845*90e502c7SAndroid Build Coastguard Worker     }
3846*90e502c7SAndroid Build Coastguard Worker 
3847*90e502c7SAndroid Build Coastguard Worker     /* we've passed the authentication check, so add seq_num to the rdb */
3848*90e502c7SAndroid Build Coastguard Worker     srtp_rdb_add_index(&stream->rtcp_rdb, seq_num);
3849*90e502c7SAndroid Build Coastguard Worker 
3850*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
3851*90e502c7SAndroid Build Coastguard Worker }
3852*90e502c7SAndroid Build Coastguard Worker 
srtp_protect_rtcp(srtp_t ctx,void * rtcp_hdr,int * pkt_octet_len)3853*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_protect_rtcp(srtp_t ctx,
3854*90e502c7SAndroid Build Coastguard Worker                                     void *rtcp_hdr,
3855*90e502c7SAndroid Build Coastguard Worker                                     int *pkt_octet_len)
3856*90e502c7SAndroid Build Coastguard Worker {
3857*90e502c7SAndroid Build Coastguard Worker     return srtp_protect_rtcp_mki(ctx, rtcp_hdr, pkt_octet_len, 0, 0);
3858*90e502c7SAndroid Build Coastguard Worker }
3859*90e502c7SAndroid Build Coastguard Worker 
srtp_protect_rtcp_mki(srtp_t ctx,void * rtcp_hdr,int * pkt_octet_len,unsigned int use_mki,unsigned int mki_index)3860*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx,
3861*90e502c7SAndroid Build Coastguard Worker                                         void *rtcp_hdr,
3862*90e502c7SAndroid Build Coastguard Worker                                         int *pkt_octet_len,
3863*90e502c7SAndroid Build Coastguard Worker                                         unsigned int use_mki,
3864*90e502c7SAndroid Build Coastguard Worker                                         unsigned int mki_index)
3865*90e502c7SAndroid Build Coastguard Worker {
3866*90e502c7SAndroid Build Coastguard Worker     srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
3867*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
3868*90e502c7SAndroid Build Coastguard Worker     uint32_t *auth_start;           /* pointer to start of auth. portion      */
3869*90e502c7SAndroid Build Coastguard Worker     uint32_t *trailer_p;            /* pointer to start of trailer            */
3870*90e502c7SAndroid Build Coastguard Worker     uint32_t trailer;               /* trailer value                          */
3871*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
3872*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL;       /* location of auth_tag within packet     */
3873*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
3874*90e502c7SAndroid Build Coastguard Worker     int tag_len;
3875*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
3876*90e502c7SAndroid Build Coastguard Worker     uint32_t prefix_len;
3877*90e502c7SAndroid Build Coastguard Worker     uint32_t seq_num;
3878*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
3879*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
3880*90e502c7SAndroid Build Coastguard Worker 
3881*90e502c7SAndroid Build Coastguard Worker     /* we assume the hdr is 32-bit aligned to start */
3882*90e502c7SAndroid Build Coastguard Worker 
3883*90e502c7SAndroid Build Coastguard Worker     /* check the packet length - it must at least contain a full header */
3884*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < octets_in_rtcp_header)
3885*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
3886*90e502c7SAndroid Build Coastguard Worker 
3887*90e502c7SAndroid Build Coastguard Worker     /*
3888*90e502c7SAndroid Build Coastguard Worker      * look up ssrc in srtp_stream list, and process the packet with
3889*90e502c7SAndroid Build Coastguard Worker      * the appropriate stream.  if we haven't seen this stream before,
3890*90e502c7SAndroid Build Coastguard Worker      * there's only one key for this srtp_session, and the cipher
3891*90e502c7SAndroid Build Coastguard Worker      * supports key-sharing, then we assume that a new stream using
3892*90e502c7SAndroid Build Coastguard Worker      * that key has just started up
3893*90e502c7SAndroid Build Coastguard Worker      */
3894*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(ctx, hdr->ssrc);
3895*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
3896*90e502c7SAndroid Build Coastguard Worker         if (ctx->stream_template != NULL) {
3897*90e502c7SAndroid Build Coastguard Worker             srtp_stream_ctx_t *new_stream;
3898*90e502c7SAndroid Build Coastguard Worker 
3899*90e502c7SAndroid Build Coastguard Worker             /* allocate and initialize a new stream */
3900*90e502c7SAndroid Build Coastguard Worker             status =
3901*90e502c7SAndroid Build Coastguard Worker                 srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
3902*90e502c7SAndroid Build Coastguard Worker             if (status)
3903*90e502c7SAndroid Build Coastguard Worker                 return status;
3904*90e502c7SAndroid Build Coastguard Worker 
3905*90e502c7SAndroid Build Coastguard Worker             /* add new stream to the head of the stream_list */
3906*90e502c7SAndroid Build Coastguard Worker             new_stream->next = ctx->stream_list;
3907*90e502c7SAndroid Build Coastguard Worker             ctx->stream_list = new_stream;
3908*90e502c7SAndroid Build Coastguard Worker 
3909*90e502c7SAndroid Build Coastguard Worker             /* set stream (the pointer used in this function) */
3910*90e502c7SAndroid Build Coastguard Worker             stream = new_stream;
3911*90e502c7SAndroid Build Coastguard Worker         } else {
3912*90e502c7SAndroid Build Coastguard Worker             /* no template stream, so we return an error */
3913*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_no_ctx;
3914*90e502c7SAndroid Build Coastguard Worker         }
3915*90e502c7SAndroid Build Coastguard Worker     }
3916*90e502c7SAndroid Build Coastguard Worker 
3917*90e502c7SAndroid Build Coastguard Worker     /*
3918*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for sending traffic - this check will
3919*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
3920*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
3921*90e502c7SAndroid Build Coastguard Worker      * those functions.
3922*90e502c7SAndroid Build Coastguard Worker      */
3923*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_sender) {
3924*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
3925*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_sender;
3926*90e502c7SAndroid Build Coastguard Worker         } else {
3927*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
3928*90e502c7SAndroid Build Coastguard Worker         }
3929*90e502c7SAndroid Build Coastguard Worker     }
3930*90e502c7SAndroid Build Coastguard Worker 
3931*90e502c7SAndroid Build Coastguard Worker     session_keys =
3932*90e502c7SAndroid Build Coastguard Worker         srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index);
3933*90e502c7SAndroid Build Coastguard Worker 
3934*90e502c7SAndroid Build Coastguard Worker     if (session_keys == NULL)
3935*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_mki;
3936*90e502c7SAndroid Build Coastguard Worker 
3937*90e502c7SAndroid Build Coastguard Worker     /*
3938*90e502c7SAndroid Build Coastguard Worker      * Check if this is an AEAD stream (GCM mode).  If so, then dispatch
3939*90e502c7SAndroid Build Coastguard Worker      * the request to our AEAD handler.
3940*90e502c7SAndroid Build Coastguard Worker      */
3941*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
3942*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
3943*90e502c7SAndroid Build Coastguard Worker         return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr,
3944*90e502c7SAndroid Build Coastguard Worker                                       (unsigned int *)pkt_octet_len,
3945*90e502c7SAndroid Build Coastguard Worker                                       session_keys, use_mki);
3946*90e502c7SAndroid Build Coastguard Worker     }
3947*90e502c7SAndroid Build Coastguard Worker 
3948*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream context */
3949*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
3950*90e502c7SAndroid Build Coastguard Worker 
3951*90e502c7SAndroid Build Coastguard Worker     /*
3952*90e502c7SAndroid Build Coastguard Worker      * set encryption start and encryption length - if we're not
3953*90e502c7SAndroid Build Coastguard Worker      * providing confidentiality, set enc_start to NULL
3954*90e502c7SAndroid Build Coastguard Worker      */
3955*90e502c7SAndroid Build Coastguard Worker     enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
3956*90e502c7SAndroid Build Coastguard Worker     enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
3957*90e502c7SAndroid Build Coastguard Worker 
3958*90e502c7SAndroid Build Coastguard Worker     /* all of the packet, except the header, gets encrypted */
3959*90e502c7SAndroid Build Coastguard Worker     /*
3960*90e502c7SAndroid Build Coastguard Worker      * NOTE: hdr->length is not usable - it refers to only the first RTCP report
3961*90e502c7SAndroid Build Coastguard Worker      * in the compound packet!
3962*90e502c7SAndroid Build Coastguard Worker      */
3963*90e502c7SAndroid Build Coastguard Worker     trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len);
3964*90e502c7SAndroid Build Coastguard Worker 
3965*90e502c7SAndroid Build Coastguard Worker     if (stream->rtcp_services & sec_serv_conf) {
3966*90e502c7SAndroid Build Coastguard Worker         trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
3967*90e502c7SAndroid Build Coastguard Worker     } else {
3968*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL;
3969*90e502c7SAndroid Build Coastguard Worker         enc_octet_len = 0;
3970*90e502c7SAndroid Build Coastguard Worker         /* 0 is network-order independant */
3971*90e502c7SAndroid Build Coastguard Worker         trailer = 0x00000000; /* set encrypt bit */
3972*90e502c7SAndroid Build Coastguard Worker     }
3973*90e502c7SAndroid Build Coastguard Worker 
3974*90e502c7SAndroid Build Coastguard Worker     mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len +
3975*90e502c7SAndroid Build Coastguard Worker                                    sizeof(srtcp_trailer_t),
3976*90e502c7SAndroid Build Coastguard Worker                                session_keys, use_mki);
3977*90e502c7SAndroid Build Coastguard Worker 
3978*90e502c7SAndroid Build Coastguard Worker     /*
3979*90e502c7SAndroid Build Coastguard Worker      * set the auth_start and auth_tag pointers to the proper locations
3980*90e502c7SAndroid Build Coastguard Worker      * (note that srtpc *always* provides authentication, unlike srtp)
3981*90e502c7SAndroid Build Coastguard Worker      */
3982*90e502c7SAndroid Build Coastguard Worker     /* Note: This would need to change for optional mikey data */
3983*90e502c7SAndroid Build Coastguard Worker     auth_start = (uint32_t *)hdr;
3984*90e502c7SAndroid Build Coastguard Worker     auth_tag =
3985*90e502c7SAndroid Build Coastguard Worker         (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size;
3986*90e502c7SAndroid Build Coastguard Worker 
3987*90e502c7SAndroid Build Coastguard Worker     /* perform EKT processing if needed */
3988*90e502c7SAndroid Build Coastguard Worker     srtp_ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len,
3989*90e502c7SAndroid Build Coastguard Worker                         srtp_rdbx_get_packet_index(&stream->rtp_rdbx));
3990*90e502c7SAndroid Build Coastguard Worker 
3991*90e502c7SAndroid Build Coastguard Worker     /*
3992*90e502c7SAndroid Build Coastguard Worker      * check sequence number for overruns, and copy it into the packet
3993*90e502c7SAndroid Build Coastguard Worker      * if its value isn't too big
3994*90e502c7SAndroid Build Coastguard Worker      */
3995*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdb_increment(&stream->rtcp_rdb);
3996*90e502c7SAndroid Build Coastguard Worker     if (status)
3997*90e502c7SAndroid Build Coastguard Worker         return status;
3998*90e502c7SAndroid Build Coastguard Worker     seq_num = srtp_rdb_get_value(&stream->rtcp_rdb);
3999*90e502c7SAndroid Build Coastguard Worker     trailer |= htonl(seq_num);
4000*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp index: %x", seq_num);
4001*90e502c7SAndroid Build Coastguard Worker 
4002*90e502c7SAndroid Build Coastguard Worker     memcpy(trailer_p, &trailer, sizeof(trailer));
4003*90e502c7SAndroid Build Coastguard Worker 
4004*90e502c7SAndroid Build Coastguard Worker     /*
4005*90e502c7SAndroid Build Coastguard Worker      * if we're using rindael counter mode, set nonce and seq
4006*90e502c7SAndroid Build Coastguard Worker      */
4007*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 ||
4008*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 ||
4009*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) {
4010*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
4011*90e502c7SAndroid Build Coastguard Worker 
4012*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
4013*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc; /* still in network order! */
4014*90e502c7SAndroid Build Coastguard Worker         iv.v32[2] = htonl(seq_num >> 16);
4015*90e502c7SAndroid Build Coastguard Worker         iv.v32[3] = htonl(seq_num << 16);
4016*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
4017*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_encrypt);
4018*90e502c7SAndroid Build Coastguard Worker 
4019*90e502c7SAndroid Build Coastguard Worker     } else {
4020*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
4021*90e502c7SAndroid Build Coastguard Worker 
4022*90e502c7SAndroid Build Coastguard Worker         /* otherwise, just set the index to seq_num */
4023*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
4024*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = 0;
4025*90e502c7SAndroid Build Coastguard Worker         iv.v32[2] = 0;
4026*90e502c7SAndroid Build Coastguard Worker         iv.v32[3] = htonl(seq_num);
4027*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
4028*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_encrypt);
4029*90e502c7SAndroid Build Coastguard Worker     }
4030*90e502c7SAndroid Build Coastguard Worker     if (status)
4031*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
4032*90e502c7SAndroid Build Coastguard Worker 
4033*90e502c7SAndroid Build Coastguard Worker     /*
4034*90e502c7SAndroid Build Coastguard Worker      * if we're authenticating using a universal hash, put the keystream
4035*90e502c7SAndroid Build Coastguard Worker      * prefix into the authentication tag
4036*90e502c7SAndroid Build Coastguard Worker      */
4037*90e502c7SAndroid Build Coastguard Worker 
4038*90e502c7SAndroid Build Coastguard Worker     /* if auth_start is non-null, then put keystream into tag  */
4039*90e502c7SAndroid Build Coastguard Worker     if (auth_start) {
4040*90e502c7SAndroid Build Coastguard Worker         /* put keystream prefix into auth_tag */
4041*90e502c7SAndroid Build Coastguard Worker         prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth);
4042*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag,
4043*90e502c7SAndroid Build Coastguard Worker                                     &prefix_len);
4044*90e502c7SAndroid Build Coastguard Worker 
4045*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "keystream prefix: %s",
4046*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(auth_tag, prefix_len));
4047*90e502c7SAndroid Build Coastguard Worker 
4048*90e502c7SAndroid Build Coastguard Worker         if (status)
4049*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
4050*90e502c7SAndroid Build Coastguard Worker     }
4051*90e502c7SAndroid Build Coastguard Worker 
4052*90e502c7SAndroid Build Coastguard Worker     /* if we're encrypting, exor keystream into the message */
4053*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
4054*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_encrypt(session_keys->rtcp_cipher,
4055*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)enc_start, &enc_octet_len);
4056*90e502c7SAndroid Build Coastguard Worker         if (status)
4057*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
4058*90e502c7SAndroid Build Coastguard Worker     }
4059*90e502c7SAndroid Build Coastguard Worker 
4060*90e502c7SAndroid Build Coastguard Worker     /* initialize auth func context */
4061*90e502c7SAndroid Build Coastguard Worker     srtp_auth_start(session_keys->rtcp_auth);
4062*90e502c7SAndroid Build Coastguard Worker 
4063*90e502c7SAndroid Build Coastguard Worker     /*
4064*90e502c7SAndroid Build Coastguard Worker      * run auth func over packet (including trailer), and write the
4065*90e502c7SAndroid Build Coastguard Worker      * result at auth_tag
4066*90e502c7SAndroid Build Coastguard Worker      */
4067*90e502c7SAndroid Build Coastguard Worker     status =
4068*90e502c7SAndroid Build Coastguard Worker         srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start,
4069*90e502c7SAndroid Build Coastguard Worker                           (*pkt_octet_len) + sizeof(srtcp_trailer_t), auth_tag);
4070*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp auth tag:    %s",
4071*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(auth_tag, tag_len));
4072*90e502c7SAndroid Build Coastguard Worker     if (status)
4073*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_auth_fail;
4074*90e502c7SAndroid Build Coastguard Worker 
4075*90e502c7SAndroid Build Coastguard Worker     /* increase the packet length by the length of the auth tag and seq_num*/
4076*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
4077*90e502c7SAndroid Build Coastguard Worker 
4078*90e502c7SAndroid Build Coastguard Worker     /* increase the packet by the mki_size */
4079*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len += mki_size;
4080*90e502c7SAndroid Build Coastguard Worker 
4081*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4082*90e502c7SAndroid Build Coastguard Worker }
4083*90e502c7SAndroid Build Coastguard Worker 
srtp_unprotect_rtcp(srtp_t ctx,void * srtcp_hdr,int * pkt_octet_len)4084*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx,
4085*90e502c7SAndroid Build Coastguard Worker                                       void *srtcp_hdr,
4086*90e502c7SAndroid Build Coastguard Worker                                       int *pkt_octet_len)
4087*90e502c7SAndroid Build Coastguard Worker {
4088*90e502c7SAndroid Build Coastguard Worker     return srtp_unprotect_rtcp_mki(ctx, srtcp_hdr, pkt_octet_len, 0);
4089*90e502c7SAndroid Build Coastguard Worker }
4090*90e502c7SAndroid Build Coastguard Worker 
srtp_unprotect_rtcp_mki(srtp_t ctx,void * srtcp_hdr,int * pkt_octet_len,unsigned int use_mki)4091*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx,
4092*90e502c7SAndroid Build Coastguard Worker                                           void *srtcp_hdr,
4093*90e502c7SAndroid Build Coastguard Worker                                           int *pkt_octet_len,
4094*90e502c7SAndroid Build Coastguard Worker                                           unsigned int use_mki)
4095*90e502c7SAndroid Build Coastguard Worker {
4096*90e502c7SAndroid Build Coastguard Worker     srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
4097*90e502c7SAndroid Build Coastguard Worker     uint32_t *enc_start;            /* pointer to start of encrypted portion  */
4098*90e502c7SAndroid Build Coastguard Worker     uint32_t *auth_start;           /* pointer to start of auth. portion      */
4099*90e502c7SAndroid Build Coastguard Worker     uint32_t *trailer_p;            /* pointer to start of trailer            */
4100*90e502c7SAndroid Build Coastguard Worker     uint32_t trailer;               /* trailer value                          */
4101*90e502c7SAndroid Build Coastguard Worker     unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
4102*90e502c7SAndroid Build Coastguard Worker     uint8_t *auth_tag = NULL;       /* location of auth_tag within packet     */
4103*90e502c7SAndroid Build Coastguard Worker     uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
4104*90e502c7SAndroid Build Coastguard Worker     uint8_t tag_copy[SRTP_MAX_TAG_LEN];
4105*90e502c7SAndroid Build Coastguard Worker     srtp_err_status_t status;
4106*90e502c7SAndroid Build Coastguard Worker     unsigned int auth_len;
4107*90e502c7SAndroid Build Coastguard Worker     int tag_len;
4108*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
4109*90e502c7SAndroid Build Coastguard Worker     uint32_t prefix_len;
4110*90e502c7SAndroid Build Coastguard Worker     uint32_t seq_num;
4111*90e502c7SAndroid Build Coastguard Worker     int e_bit_in_packet; /* whether the E-bit was found in the packet */
4112*90e502c7SAndroid Build Coastguard Worker     int sec_serv_confidentiality; /* whether confidentiality was requested */
4113*90e502c7SAndroid Build Coastguard Worker     unsigned int mki_size = 0;
4114*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_keys = NULL;
4115*90e502c7SAndroid Build Coastguard Worker 
4116*90e502c7SAndroid Build Coastguard Worker     /* we assume the hdr is 32-bit aligned to start */
4117*90e502c7SAndroid Build Coastguard Worker 
4118*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < 0)
4119*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4120*90e502c7SAndroid Build Coastguard Worker 
4121*90e502c7SAndroid Build Coastguard Worker     /*
4122*90e502c7SAndroid Build Coastguard Worker      * check that the length value is sane; we'll check again once we
4123*90e502c7SAndroid Build Coastguard Worker      * know the tag length, but we at least want to know that it is
4124*90e502c7SAndroid Build Coastguard Worker      * a positive value
4125*90e502c7SAndroid Build Coastguard Worker      */
4126*90e502c7SAndroid Build Coastguard Worker     if ((unsigned int)(*pkt_octet_len) <
4127*90e502c7SAndroid Build Coastguard Worker         octets_in_rtcp_header + sizeof(srtcp_trailer_t))
4128*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4129*90e502c7SAndroid Build Coastguard Worker 
4130*90e502c7SAndroid Build Coastguard Worker     /*
4131*90e502c7SAndroid Build Coastguard Worker      * look up ssrc in srtp_stream list, and process the packet with
4132*90e502c7SAndroid Build Coastguard Worker      * the appropriate stream.  if we haven't seen this stream before,
4133*90e502c7SAndroid Build Coastguard Worker      * there's only one key for this srtp_session, and the cipher
4134*90e502c7SAndroid Build Coastguard Worker      * supports key-sharing, then we assume that a new stream using
4135*90e502c7SAndroid Build Coastguard Worker      * that key has just started up
4136*90e502c7SAndroid Build Coastguard Worker      */
4137*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(ctx, hdr->ssrc);
4138*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL) {
4139*90e502c7SAndroid Build Coastguard Worker         if (ctx->stream_template != NULL) {
4140*90e502c7SAndroid Build Coastguard Worker             stream = ctx->stream_template;
4141*90e502c7SAndroid Build Coastguard Worker 
4142*90e502c7SAndroid Build Coastguard Worker             /*
4143*90e502c7SAndroid Build Coastguard Worker              * check to see if stream_template has an EKT data structure, in
4144*90e502c7SAndroid Build Coastguard Worker              * which case we initialize the template using the EKT policy
4145*90e502c7SAndroid Build Coastguard Worker              * referenced by that data (which consists of decrypting the
4146*90e502c7SAndroid Build Coastguard Worker              * master key from the EKT field)
4147*90e502c7SAndroid Build Coastguard Worker              *
4148*90e502c7SAndroid Build Coastguard Worker              * this function initializes a *provisional* stream, and this
4149*90e502c7SAndroid Build Coastguard Worker              * stream should not be accepted until and unless the packet
4150*90e502c7SAndroid Build Coastguard Worker              * passes its authentication check
4151*90e502c7SAndroid Build Coastguard Worker              */
4152*90e502c7SAndroid Build Coastguard Worker             if (stream->ekt != NULL) {
4153*90e502c7SAndroid Build Coastguard Worker                 status = srtp_stream_init_from_ekt(stream, srtcp_hdr,
4154*90e502c7SAndroid Build Coastguard Worker                                                    *pkt_octet_len);
4155*90e502c7SAndroid Build Coastguard Worker                 if (status)
4156*90e502c7SAndroid Build Coastguard Worker                     return status;
4157*90e502c7SAndroid Build Coastguard Worker             }
4158*90e502c7SAndroid Build Coastguard Worker 
4159*90e502c7SAndroid Build Coastguard Worker             debug_print(mod_srtp,
4160*90e502c7SAndroid Build Coastguard Worker                         "srtcp using provisional stream (SSRC: 0x%08x)",
4161*90e502c7SAndroid Build Coastguard Worker                         ntohl(hdr->ssrc));
4162*90e502c7SAndroid Build Coastguard Worker         } else {
4163*90e502c7SAndroid Build Coastguard Worker             /* no template stream, so we return an error */
4164*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_no_ctx;
4165*90e502c7SAndroid Build Coastguard Worker         }
4166*90e502c7SAndroid Build Coastguard Worker     }
4167*90e502c7SAndroid Build Coastguard Worker 
4168*90e502c7SAndroid Build Coastguard Worker     /*
4169*90e502c7SAndroid Build Coastguard Worker      * Determine if MKI is being used and what session keys should be used
4170*90e502c7SAndroid Build Coastguard Worker      */
4171*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
4172*90e502c7SAndroid Build Coastguard Worker         session_keys = srtp_get_session_keys(
4173*90e502c7SAndroid Build Coastguard Worker             stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len,
4174*90e502c7SAndroid Build Coastguard Worker             &mki_size);
4175*90e502c7SAndroid Build Coastguard Worker 
4176*90e502c7SAndroid Build Coastguard Worker         if (session_keys == NULL)
4177*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_mki;
4178*90e502c7SAndroid Build Coastguard Worker     } else {
4179*90e502c7SAndroid Build Coastguard Worker         session_keys = &stream->session_keys[0];
4180*90e502c7SAndroid Build Coastguard Worker     }
4181*90e502c7SAndroid Build Coastguard Worker 
4182*90e502c7SAndroid Build Coastguard Worker     /* get tag length from stream context */
4183*90e502c7SAndroid Build Coastguard Worker     tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
4184*90e502c7SAndroid Build Coastguard Worker 
4185*90e502c7SAndroid Build Coastguard Worker     /* check the packet length - it must contain at least a full RTCP
4186*90e502c7SAndroid Build Coastguard Worker        header, an auth tag (if applicable), and the SRTCP encrypted flag
4187*90e502c7SAndroid Build Coastguard Worker        and 31-bit index value */
4188*90e502c7SAndroid Build Coastguard Worker     if (*pkt_octet_len < (int)(octets_in_rtcp_header + tag_len + mki_size +
4189*90e502c7SAndroid Build Coastguard Worker                                sizeof(srtcp_trailer_t))) {
4190*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4191*90e502c7SAndroid Build Coastguard Worker     }
4192*90e502c7SAndroid Build Coastguard Worker 
4193*90e502c7SAndroid Build Coastguard Worker     /*
4194*90e502c7SAndroid Build Coastguard Worker      * Check if this is an AEAD stream (GCM mode).  If so, then dispatch
4195*90e502c7SAndroid Build Coastguard Worker      * the request to our AEAD handler.
4196*90e502c7SAndroid Build Coastguard Worker      */
4197*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
4198*90e502c7SAndroid Build Coastguard Worker         session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
4199*90e502c7SAndroid Build Coastguard Worker         return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr,
4200*90e502c7SAndroid Build Coastguard Worker                                         (unsigned int *)pkt_octet_len,
4201*90e502c7SAndroid Build Coastguard Worker                                         session_keys, mki_size);
4202*90e502c7SAndroid Build Coastguard Worker     }
4203*90e502c7SAndroid Build Coastguard Worker 
4204*90e502c7SAndroid Build Coastguard Worker     sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf ||
4205*90e502c7SAndroid Build Coastguard Worker                                stream->rtcp_services == sec_serv_conf_and_auth;
4206*90e502c7SAndroid Build Coastguard Worker 
4207*90e502c7SAndroid Build Coastguard Worker     /*
4208*90e502c7SAndroid Build Coastguard Worker      * set encryption start, encryption length, and trailer
4209*90e502c7SAndroid Build Coastguard Worker      */
4210*90e502c7SAndroid Build Coastguard Worker     enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + tag_len +
4211*90e502c7SAndroid Build Coastguard Worker                                       mki_size + sizeof(srtcp_trailer_t));
4212*90e502c7SAndroid Build Coastguard Worker     /*
4213*90e502c7SAndroid Build Coastguard Worker      *index & E (encryption) bit follow normal data. hdr->len is the number of
4214*90e502c7SAndroid Build Coastguard Worker      * words (32-bit) in the normal packet minus 1
4215*90e502c7SAndroid Build Coastguard Worker      */
4216*90e502c7SAndroid Build Coastguard Worker     /* This should point trailer to the word past the end of the normal data. */
4217*90e502c7SAndroid Build Coastguard Worker     /* This would need to be modified for optional mikey data */
4218*90e502c7SAndroid Build Coastguard Worker     trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
4219*90e502c7SAndroid Build Coastguard Worker                              (tag_len + mki_size + sizeof(srtcp_trailer_t)));
4220*90e502c7SAndroid Build Coastguard Worker     memcpy(&trailer, trailer_p, sizeof(trailer));
4221*90e502c7SAndroid Build Coastguard Worker 
4222*90e502c7SAndroid Build Coastguard Worker     e_bit_in_packet =
4223*90e502c7SAndroid Build Coastguard Worker         (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT;
4224*90e502c7SAndroid Build Coastguard Worker     if (e_bit_in_packet != sec_serv_confidentiality) {
4225*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cant_check;
4226*90e502c7SAndroid Build Coastguard Worker     }
4227*90e502c7SAndroid Build Coastguard Worker     if (sec_serv_confidentiality) {
4228*90e502c7SAndroid Build Coastguard Worker         enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
4229*90e502c7SAndroid Build Coastguard Worker     } else {
4230*90e502c7SAndroid Build Coastguard Worker         enc_octet_len = 0;
4231*90e502c7SAndroid Build Coastguard Worker         enc_start = NULL; /* this indicates that there's no encryption */
4232*90e502c7SAndroid Build Coastguard Worker     }
4233*90e502c7SAndroid Build Coastguard Worker 
4234*90e502c7SAndroid Build Coastguard Worker     /*
4235*90e502c7SAndroid Build Coastguard Worker      * set the auth_start and auth_tag pointers to the proper locations
4236*90e502c7SAndroid Build Coastguard Worker      * (note that srtcp *always* uses authentication, unlike srtp)
4237*90e502c7SAndroid Build Coastguard Worker      */
4238*90e502c7SAndroid Build Coastguard Worker     auth_start = (uint32_t *)hdr;
4239*90e502c7SAndroid Build Coastguard Worker 
4240*90e502c7SAndroid Build Coastguard Worker     /*
4241*90e502c7SAndroid Build Coastguard Worker      * The location of the auth tag in the packet needs to know MKI
4242*90e502c7SAndroid Build Coastguard Worker      * could be present.  The data needed to calculate the Auth tag
4243*90e502c7SAndroid Build Coastguard Worker      * must not include the MKI
4244*90e502c7SAndroid Build Coastguard Worker      */
4245*90e502c7SAndroid Build Coastguard Worker     auth_len = *pkt_octet_len - tag_len - mki_size;
4246*90e502c7SAndroid Build Coastguard Worker     auth_tag = (uint8_t *)hdr + auth_len + mki_size;
4247*90e502c7SAndroid Build Coastguard Worker 
4248*90e502c7SAndroid Build Coastguard Worker     /*
4249*90e502c7SAndroid Build Coastguard Worker      * if EKT is in use, then we make a copy of the tag from the packet,
4250*90e502c7SAndroid Build Coastguard Worker      * and then zeroize the location of the base tag
4251*90e502c7SAndroid Build Coastguard Worker      *
4252*90e502c7SAndroid Build Coastguard Worker      * we first re-position the auth_tag pointer so that it points to
4253*90e502c7SAndroid Build Coastguard Worker      * the base tag
4254*90e502c7SAndroid Build Coastguard Worker      */
4255*90e502c7SAndroid Build Coastguard Worker     if (stream->ekt) {
4256*90e502c7SAndroid Build Coastguard Worker         auth_tag -= srtp_ekt_octets_after_base_tag(stream->ekt);
4257*90e502c7SAndroid Build Coastguard Worker         memcpy(tag_copy, auth_tag, tag_len);
4258*90e502c7SAndroid Build Coastguard Worker         octet_string_set_to_zero(auth_tag, tag_len);
4259*90e502c7SAndroid Build Coastguard Worker         auth_tag = tag_copy;
4260*90e502c7SAndroid Build Coastguard Worker         auth_len += tag_len;
4261*90e502c7SAndroid Build Coastguard Worker     }
4262*90e502c7SAndroid Build Coastguard Worker 
4263*90e502c7SAndroid Build Coastguard Worker     /*
4264*90e502c7SAndroid Build Coastguard Worker      * check the sequence number for replays
4265*90e502c7SAndroid Build Coastguard Worker      */
4266*90e502c7SAndroid Build Coastguard Worker     /* this is easier than dealing with bitfield access */
4267*90e502c7SAndroid Build Coastguard Worker     seq_num = ntohl(trailer) & SRTCP_INDEX_MASK;
4268*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp index: %x", seq_num);
4269*90e502c7SAndroid Build Coastguard Worker     status = srtp_rdb_check(&stream->rtcp_rdb, seq_num);
4270*90e502c7SAndroid Build Coastguard Worker     if (status)
4271*90e502c7SAndroid Build Coastguard Worker         return status;
4272*90e502c7SAndroid Build Coastguard Worker 
4273*90e502c7SAndroid Build Coastguard Worker     /*
4274*90e502c7SAndroid Build Coastguard Worker      * if we're using aes counter mode, set nonce and seq
4275*90e502c7SAndroid Build Coastguard Worker      */
4276*90e502c7SAndroid Build Coastguard Worker     if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 ||
4277*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 ||
4278*90e502c7SAndroid Build Coastguard Worker         session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) {
4279*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
4280*90e502c7SAndroid Build Coastguard Worker 
4281*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
4282*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = hdr->ssrc; /* still in network order! */
4283*90e502c7SAndroid Build Coastguard Worker         iv.v32[2] = htonl(seq_num >> 16);
4284*90e502c7SAndroid Build Coastguard Worker         iv.v32[3] = htonl(seq_num << 16);
4285*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
4286*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_decrypt);
4287*90e502c7SAndroid Build Coastguard Worker 
4288*90e502c7SAndroid Build Coastguard Worker     } else {
4289*90e502c7SAndroid Build Coastguard Worker         v128_t iv;
4290*90e502c7SAndroid Build Coastguard Worker 
4291*90e502c7SAndroid Build Coastguard Worker         /* otherwise, just set the index to seq_num */
4292*90e502c7SAndroid Build Coastguard Worker         iv.v32[0] = 0;
4293*90e502c7SAndroid Build Coastguard Worker         iv.v32[1] = 0;
4294*90e502c7SAndroid Build Coastguard Worker         iv.v32[2] = 0;
4295*90e502c7SAndroid Build Coastguard Worker         iv.v32[3] = htonl(seq_num);
4296*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
4297*90e502c7SAndroid Build Coastguard Worker                                     srtp_direction_decrypt);
4298*90e502c7SAndroid Build Coastguard Worker     }
4299*90e502c7SAndroid Build Coastguard Worker     if (status)
4300*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_cipher_fail;
4301*90e502c7SAndroid Build Coastguard Worker 
4302*90e502c7SAndroid Build Coastguard Worker     /* initialize auth func context */
4303*90e502c7SAndroid Build Coastguard Worker     srtp_auth_start(session_keys->rtcp_auth);
4304*90e502c7SAndroid Build Coastguard Worker 
4305*90e502c7SAndroid Build Coastguard Worker     /* run auth func over packet, put result into tmp_tag */
4306*90e502c7SAndroid Build Coastguard Worker     status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start,
4307*90e502c7SAndroid Build Coastguard Worker                                auth_len, tmp_tag);
4308*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp computed tag:       %s",
4309*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(tmp_tag, tag_len));
4310*90e502c7SAndroid Build Coastguard Worker     if (status)
4311*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_auth_fail;
4312*90e502c7SAndroid Build Coastguard Worker 
4313*90e502c7SAndroid Build Coastguard Worker     /* compare the tag just computed with the one in the packet */
4314*90e502c7SAndroid Build Coastguard Worker     debug_print(mod_srtp, "srtcp tag from packet:    %s",
4315*90e502c7SAndroid Build Coastguard Worker                 srtp_octet_string_hex_string(auth_tag, tag_len));
4316*90e502c7SAndroid Build Coastguard Worker     if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len))
4317*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_auth_fail;
4318*90e502c7SAndroid Build Coastguard Worker 
4319*90e502c7SAndroid Build Coastguard Worker     /*
4320*90e502c7SAndroid Build Coastguard Worker      * if we're authenticating using a universal hash, put the keystream
4321*90e502c7SAndroid Build Coastguard Worker      * prefix into the authentication tag
4322*90e502c7SAndroid Build Coastguard Worker      */
4323*90e502c7SAndroid Build Coastguard Worker     prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth);
4324*90e502c7SAndroid Build Coastguard Worker     if (prefix_len) {
4325*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag,
4326*90e502c7SAndroid Build Coastguard Worker                                     &prefix_len);
4327*90e502c7SAndroid Build Coastguard Worker         debug_print(mod_srtp, "keystream prefix: %s",
4328*90e502c7SAndroid Build Coastguard Worker                     srtp_octet_string_hex_string(auth_tag, prefix_len));
4329*90e502c7SAndroid Build Coastguard Worker         if (status)
4330*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
4331*90e502c7SAndroid Build Coastguard Worker     }
4332*90e502c7SAndroid Build Coastguard Worker 
4333*90e502c7SAndroid Build Coastguard Worker     /* if we're decrypting, exor keystream into the message */
4334*90e502c7SAndroid Build Coastguard Worker     if (enc_start) {
4335*90e502c7SAndroid Build Coastguard Worker         status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
4336*90e502c7SAndroid Build Coastguard Worker                                      (uint8_t *)enc_start, &enc_octet_len);
4337*90e502c7SAndroid Build Coastguard Worker         if (status)
4338*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_cipher_fail;
4339*90e502c7SAndroid Build Coastguard Worker     }
4340*90e502c7SAndroid Build Coastguard Worker 
4341*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the auth tag and seq_num */
4342*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));
4343*90e502c7SAndroid Build Coastguard Worker 
4344*90e502c7SAndroid Build Coastguard Worker     /* decrease the packet length by the length of the mki_size */
4345*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= mki_size;
4346*90e502c7SAndroid Build Coastguard Worker 
4347*90e502c7SAndroid Build Coastguard Worker     /*
4348*90e502c7SAndroid Build Coastguard Worker      * if EKT is in effect, subtract the EKT data out of the packet
4349*90e502c7SAndroid Build Coastguard Worker      * length
4350*90e502c7SAndroid Build Coastguard Worker      */
4351*90e502c7SAndroid Build Coastguard Worker     *pkt_octet_len -= srtp_ekt_octets_after_base_tag(stream->ekt);
4352*90e502c7SAndroid Build Coastguard Worker 
4353*90e502c7SAndroid Build Coastguard Worker     /*
4354*90e502c7SAndroid Build Coastguard Worker      * verify that stream is for received traffic - this check will
4355*90e502c7SAndroid Build Coastguard Worker      * detect SSRC collisions, since a stream that appears in both
4356*90e502c7SAndroid Build Coastguard Worker      * srtp_protect() and srtp_unprotect() will fail this test in one of
4357*90e502c7SAndroid Build Coastguard Worker      * those functions.
4358*90e502c7SAndroid Build Coastguard Worker      *
4359*90e502c7SAndroid Build Coastguard Worker      * we do this check *after* the authentication check, so that the
4360*90e502c7SAndroid Build Coastguard Worker      * latter check will catch any attempts to fool us into thinking
4361*90e502c7SAndroid Build Coastguard Worker      * that we've got a collision
4362*90e502c7SAndroid Build Coastguard Worker      */
4363*90e502c7SAndroid Build Coastguard Worker     if (stream->direction != dir_srtp_receiver) {
4364*90e502c7SAndroid Build Coastguard Worker         if (stream->direction == dir_unknown) {
4365*90e502c7SAndroid Build Coastguard Worker             stream->direction = dir_srtp_receiver;
4366*90e502c7SAndroid Build Coastguard Worker         } else {
4367*90e502c7SAndroid Build Coastguard Worker             srtp_handle_event(ctx, stream, event_ssrc_collision);
4368*90e502c7SAndroid Build Coastguard Worker         }
4369*90e502c7SAndroid Build Coastguard Worker     }
4370*90e502c7SAndroid Build Coastguard Worker 
4371*90e502c7SAndroid Build Coastguard Worker     /*
4372*90e502c7SAndroid Build Coastguard Worker      * if the stream is a 'provisional' one, in which the template context
4373*90e502c7SAndroid Build Coastguard Worker      * is used, then we need to allocate a new stream at this point, since
4374*90e502c7SAndroid Build Coastguard Worker      * the authentication passed
4375*90e502c7SAndroid Build Coastguard Worker      */
4376*90e502c7SAndroid Build Coastguard Worker     if (stream == ctx->stream_template) {
4377*90e502c7SAndroid Build Coastguard Worker         srtp_stream_ctx_t *new_stream;
4378*90e502c7SAndroid Build Coastguard Worker 
4379*90e502c7SAndroid Build Coastguard Worker         /*
4380*90e502c7SAndroid Build Coastguard Worker          * allocate and initialize a new stream
4381*90e502c7SAndroid Build Coastguard Worker          *
4382*90e502c7SAndroid Build Coastguard Worker          * note that we indicate failure if we can't allocate the new
4383*90e502c7SAndroid Build Coastguard Worker          * stream, and some implementations will want to not return
4384*90e502c7SAndroid Build Coastguard Worker          * failure here
4385*90e502c7SAndroid Build Coastguard Worker          */
4386*90e502c7SAndroid Build Coastguard Worker         status =
4387*90e502c7SAndroid Build Coastguard Worker             srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
4388*90e502c7SAndroid Build Coastguard Worker         if (status)
4389*90e502c7SAndroid Build Coastguard Worker             return status;
4390*90e502c7SAndroid Build Coastguard Worker 
4391*90e502c7SAndroid Build Coastguard Worker         /* add new stream to the head of the stream_list */
4392*90e502c7SAndroid Build Coastguard Worker         new_stream->next = ctx->stream_list;
4393*90e502c7SAndroid Build Coastguard Worker         ctx->stream_list = new_stream;
4394*90e502c7SAndroid Build Coastguard Worker 
4395*90e502c7SAndroid Build Coastguard Worker         /* set stream (the pointer used in this function) */
4396*90e502c7SAndroid Build Coastguard Worker         stream = new_stream;
4397*90e502c7SAndroid Build Coastguard Worker     }
4398*90e502c7SAndroid Build Coastguard Worker 
4399*90e502c7SAndroid Build Coastguard Worker     /* we've passed the authentication check, so add seq_num to the rdb */
4400*90e502c7SAndroid Build Coastguard Worker     srtp_rdb_add_index(&stream->rtcp_rdb, seq_num);
4401*90e502c7SAndroid Build Coastguard Worker 
4402*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4403*90e502c7SAndroid Build Coastguard Worker }
4404*90e502c7SAndroid Build Coastguard Worker 
4405*90e502c7SAndroid Build Coastguard Worker /*
4406*90e502c7SAndroid Build Coastguard Worker  * user data within srtp_t context
4407*90e502c7SAndroid Build Coastguard Worker  */
4408*90e502c7SAndroid Build Coastguard Worker 
srtp_set_user_data(srtp_t ctx,void * data)4409*90e502c7SAndroid Build Coastguard Worker void srtp_set_user_data(srtp_t ctx, void *data)
4410*90e502c7SAndroid Build Coastguard Worker {
4411*90e502c7SAndroid Build Coastguard Worker     ctx->user_data = data;
4412*90e502c7SAndroid Build Coastguard Worker }
4413*90e502c7SAndroid Build Coastguard Worker 
srtp_get_user_data(srtp_t ctx)4414*90e502c7SAndroid Build Coastguard Worker void *srtp_get_user_data(srtp_t ctx)
4415*90e502c7SAndroid Build Coastguard Worker {
4416*90e502c7SAndroid Build Coastguard Worker     return ctx->user_data;
4417*90e502c7SAndroid Build Coastguard Worker }
4418*90e502c7SAndroid Build Coastguard Worker 
4419*90e502c7SAndroid Build Coastguard Worker /*
4420*90e502c7SAndroid Build Coastguard Worker  * dtls keying for srtp
4421*90e502c7SAndroid Build Coastguard Worker  */
4422*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_from_profile_for_rtp(srtp_crypto_policy_t * policy,srtp_profile_t profile)4423*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(
4424*90e502c7SAndroid Build Coastguard Worker     srtp_crypto_policy_t *policy,
4425*90e502c7SAndroid Build Coastguard Worker     srtp_profile_t profile)
4426*90e502c7SAndroid Build Coastguard Worker {
4427*90e502c7SAndroid Build Coastguard Worker     /* set SRTP policy from the SRTP profile in the key set */
4428*90e502c7SAndroid Build Coastguard Worker     switch (profile) {
4429*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_80:
4430*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
4431*90e502c7SAndroid Build Coastguard Worker         break;
4432*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_32:
4433*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy);
4434*90e502c7SAndroid Build Coastguard Worker         break;
4435*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_80:
4436*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy);
4437*90e502c7SAndroid Build Coastguard Worker         break;
4438*90e502c7SAndroid Build Coastguard Worker #ifdef GCM
4439*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_128_gcm:
4440*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_gcm_128_16_auth(policy);
4441*90e502c7SAndroid Build Coastguard Worker         break;
4442*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_256_gcm:
4443*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_gcm_256_16_auth(policy);
4444*90e502c7SAndroid Build Coastguard Worker         break;
4445*90e502c7SAndroid Build Coastguard Worker #endif
4446*90e502c7SAndroid Build Coastguard Worker     /* the following profiles are not (yet) supported */
4447*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_32:
4448*90e502c7SAndroid Build Coastguard Worker     default:
4449*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4450*90e502c7SAndroid Build Coastguard Worker     }
4451*90e502c7SAndroid Build Coastguard Worker 
4452*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4453*90e502c7SAndroid Build Coastguard Worker }
4454*90e502c7SAndroid Build Coastguard Worker 
srtp_crypto_policy_set_from_profile_for_rtcp(srtp_crypto_policy_t * policy,srtp_profile_t profile)4455*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp(
4456*90e502c7SAndroid Build Coastguard Worker     srtp_crypto_policy_t *policy,
4457*90e502c7SAndroid Build Coastguard Worker     srtp_profile_t profile)
4458*90e502c7SAndroid Build Coastguard Worker {
4459*90e502c7SAndroid Build Coastguard Worker     /* set SRTP policy from the SRTP profile in the key set */
4460*90e502c7SAndroid Build Coastguard Worker     switch (profile) {
4461*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_80:
4462*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
4463*90e502c7SAndroid Build Coastguard Worker         break;
4464*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_32:
4465*90e502c7SAndroid Build Coastguard Worker         /* We do not honor the 32-bit auth tag request since
4466*90e502c7SAndroid Build Coastguard Worker          * this is not compliant with RFC 3711 */
4467*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
4468*90e502c7SAndroid Build Coastguard Worker         break;
4469*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_80:
4470*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy);
4471*90e502c7SAndroid Build Coastguard Worker         break;
4472*90e502c7SAndroid Build Coastguard Worker #ifdef GCM
4473*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_128_gcm:
4474*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_gcm_128_16_auth(policy);
4475*90e502c7SAndroid Build Coastguard Worker         break;
4476*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_256_gcm:
4477*90e502c7SAndroid Build Coastguard Worker         srtp_crypto_policy_set_aes_gcm_256_16_auth(policy);
4478*90e502c7SAndroid Build Coastguard Worker         break;
4479*90e502c7SAndroid Build Coastguard Worker #endif
4480*90e502c7SAndroid Build Coastguard Worker     /* the following profiles are not (yet) supported */
4481*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_32:
4482*90e502c7SAndroid Build Coastguard Worker     default:
4483*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4484*90e502c7SAndroid Build Coastguard Worker     }
4485*90e502c7SAndroid Build Coastguard Worker 
4486*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4487*90e502c7SAndroid Build Coastguard Worker }
4488*90e502c7SAndroid Build Coastguard Worker 
srtp_append_salt_to_key(uint8_t * key,unsigned int bytes_in_key,uint8_t * salt,unsigned int bytes_in_salt)4489*90e502c7SAndroid Build Coastguard Worker void srtp_append_salt_to_key(uint8_t *key,
4490*90e502c7SAndroid Build Coastguard Worker                              unsigned int bytes_in_key,
4491*90e502c7SAndroid Build Coastguard Worker                              uint8_t *salt,
4492*90e502c7SAndroid Build Coastguard Worker                              unsigned int bytes_in_salt)
4493*90e502c7SAndroid Build Coastguard Worker {
4494*90e502c7SAndroid Build Coastguard Worker     memcpy(key + bytes_in_key, salt, bytes_in_salt);
4495*90e502c7SAndroid Build Coastguard Worker }
4496*90e502c7SAndroid Build Coastguard Worker 
srtp_profile_get_master_key_length(srtp_profile_t profile)4497*90e502c7SAndroid Build Coastguard Worker unsigned int srtp_profile_get_master_key_length(srtp_profile_t profile)
4498*90e502c7SAndroid Build Coastguard Worker {
4499*90e502c7SAndroid Build Coastguard Worker     switch (profile) {
4500*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_80:
4501*90e502c7SAndroid Build Coastguard Worker         return SRTP_AES_128_KEY_LEN;
4502*90e502c7SAndroid Build Coastguard Worker         break;
4503*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_32:
4504*90e502c7SAndroid Build Coastguard Worker         return SRTP_AES_128_KEY_LEN;
4505*90e502c7SAndroid Build Coastguard Worker         break;
4506*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_80:
4507*90e502c7SAndroid Build Coastguard Worker         return SRTP_AES_128_KEY_LEN;
4508*90e502c7SAndroid Build Coastguard Worker         break;
4509*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_128_gcm:
4510*90e502c7SAndroid Build Coastguard Worker         return SRTP_AES_128_KEY_LEN;
4511*90e502c7SAndroid Build Coastguard Worker         break;
4512*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_256_gcm:
4513*90e502c7SAndroid Build Coastguard Worker         return SRTP_AES_256_KEY_LEN;
4514*90e502c7SAndroid Build Coastguard Worker         break;
4515*90e502c7SAndroid Build Coastguard Worker     /* the following profiles are not (yet) supported */
4516*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_32:
4517*90e502c7SAndroid Build Coastguard Worker     default:
4518*90e502c7SAndroid Build Coastguard Worker         return 0; /* indicate error by returning a zero */
4519*90e502c7SAndroid Build Coastguard Worker     }
4520*90e502c7SAndroid Build Coastguard Worker }
4521*90e502c7SAndroid Build Coastguard Worker 
srtp_profile_get_master_salt_length(srtp_profile_t profile)4522*90e502c7SAndroid Build Coastguard Worker unsigned int srtp_profile_get_master_salt_length(srtp_profile_t profile)
4523*90e502c7SAndroid Build Coastguard Worker {
4524*90e502c7SAndroid Build Coastguard Worker     switch (profile) {
4525*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_80:
4526*90e502c7SAndroid Build Coastguard Worker         return SRTP_SALT_LEN;
4527*90e502c7SAndroid Build Coastguard Worker         break;
4528*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aes128_cm_sha1_32:
4529*90e502c7SAndroid Build Coastguard Worker         return SRTP_SALT_LEN;
4530*90e502c7SAndroid Build Coastguard Worker         break;
4531*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_80:
4532*90e502c7SAndroid Build Coastguard Worker         return SRTP_SALT_LEN;
4533*90e502c7SAndroid Build Coastguard Worker         break;
4534*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_128_gcm:
4535*90e502c7SAndroid Build Coastguard Worker         return SRTP_AEAD_SALT_LEN;
4536*90e502c7SAndroid Build Coastguard Worker         break;
4537*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_aead_aes_256_gcm:
4538*90e502c7SAndroid Build Coastguard Worker         return SRTP_AEAD_SALT_LEN;
4539*90e502c7SAndroid Build Coastguard Worker         break;
4540*90e502c7SAndroid Build Coastguard Worker     /* the following profiles are not (yet) supported */
4541*90e502c7SAndroid Build Coastguard Worker     case srtp_profile_null_sha1_32:
4542*90e502c7SAndroid Build Coastguard Worker     default:
4543*90e502c7SAndroid Build Coastguard Worker         return 0; /* indicate error by returning a zero */
4544*90e502c7SAndroid Build Coastguard Worker     }
4545*90e502c7SAndroid Build Coastguard Worker }
4546*90e502c7SAndroid Build Coastguard Worker 
stream_get_protect_trailer_length(srtp_stream_ctx_t * stream,uint32_t is_rtp,uint32_t use_mki,uint32_t mki_index,uint32_t * length)4547*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t stream_get_protect_trailer_length(srtp_stream_ctx_t *stream,
4548*90e502c7SAndroid Build Coastguard Worker                                                     uint32_t is_rtp,
4549*90e502c7SAndroid Build Coastguard Worker                                                     uint32_t use_mki,
4550*90e502c7SAndroid Build Coastguard Worker                                                     uint32_t mki_index,
4551*90e502c7SAndroid Build Coastguard Worker                                                     uint32_t *length)
4552*90e502c7SAndroid Build Coastguard Worker {
4553*90e502c7SAndroid Build Coastguard Worker     srtp_session_keys_t *session_key;
4554*90e502c7SAndroid Build Coastguard Worker 
4555*90e502c7SAndroid Build Coastguard Worker     *length = 0;
4556*90e502c7SAndroid Build Coastguard Worker 
4557*90e502c7SAndroid Build Coastguard Worker     if (use_mki) {
4558*90e502c7SAndroid Build Coastguard Worker         if (mki_index >= stream->num_master_keys) {
4559*90e502c7SAndroid Build Coastguard Worker             return srtp_err_status_bad_mki;
4560*90e502c7SAndroid Build Coastguard Worker         }
4561*90e502c7SAndroid Build Coastguard Worker         session_key = &stream->session_keys[mki_index];
4562*90e502c7SAndroid Build Coastguard Worker 
4563*90e502c7SAndroid Build Coastguard Worker         *length += session_key->mki_size;
4564*90e502c7SAndroid Build Coastguard Worker 
4565*90e502c7SAndroid Build Coastguard Worker     } else {
4566*90e502c7SAndroid Build Coastguard Worker         session_key = &stream->session_keys[0];
4567*90e502c7SAndroid Build Coastguard Worker     }
4568*90e502c7SAndroid Build Coastguard Worker     if (is_rtp) {
4569*90e502c7SAndroid Build Coastguard Worker         *length += srtp_auth_get_tag_length(session_key->rtp_auth);
4570*90e502c7SAndroid Build Coastguard Worker     } else {
4571*90e502c7SAndroid Build Coastguard Worker         *length += srtp_auth_get_tag_length(session_key->rtcp_auth);
4572*90e502c7SAndroid Build Coastguard Worker         *length += sizeof(srtcp_trailer_t);
4573*90e502c7SAndroid Build Coastguard Worker     }
4574*90e502c7SAndroid Build Coastguard Worker 
4575*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4576*90e502c7SAndroid Build Coastguard Worker }
4577*90e502c7SAndroid Build Coastguard Worker 
get_protect_trailer_length(srtp_t session,uint32_t is_rtp,uint32_t use_mki,uint32_t mki_index,uint32_t * length)4578*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t get_protect_trailer_length(srtp_t session,
4579*90e502c7SAndroid Build Coastguard Worker                                              uint32_t is_rtp,
4580*90e502c7SAndroid Build Coastguard Worker                                              uint32_t use_mki,
4581*90e502c7SAndroid Build Coastguard Worker                                              uint32_t mki_index,
4582*90e502c7SAndroid Build Coastguard Worker                                              uint32_t *length)
4583*90e502c7SAndroid Build Coastguard Worker {
4584*90e502c7SAndroid Build Coastguard Worker     srtp_stream_ctx_t *stream;
4585*90e502c7SAndroid Build Coastguard Worker 
4586*90e502c7SAndroid Build Coastguard Worker     if (session == NULL) {
4587*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4588*90e502c7SAndroid Build Coastguard Worker     }
4589*90e502c7SAndroid Build Coastguard Worker 
4590*90e502c7SAndroid Build Coastguard Worker     if (session->stream_template == NULL && session->stream_list == NULL) {
4591*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4592*90e502c7SAndroid Build Coastguard Worker     }
4593*90e502c7SAndroid Build Coastguard Worker 
4594*90e502c7SAndroid Build Coastguard Worker     *length = 0;
4595*90e502c7SAndroid Build Coastguard Worker 
4596*90e502c7SAndroid Build Coastguard Worker     stream = session->stream_template;
4597*90e502c7SAndroid Build Coastguard Worker 
4598*90e502c7SAndroid Build Coastguard Worker     if (stream != NULL) {
4599*90e502c7SAndroid Build Coastguard Worker         stream_get_protect_trailer_length(stream, is_rtp, use_mki, mki_index,
4600*90e502c7SAndroid Build Coastguard Worker                                           length);
4601*90e502c7SAndroid Build Coastguard Worker     }
4602*90e502c7SAndroid Build Coastguard Worker 
4603*90e502c7SAndroid Build Coastguard Worker     stream = session->stream_list;
4604*90e502c7SAndroid Build Coastguard Worker 
4605*90e502c7SAndroid Build Coastguard Worker     while (stream != NULL) {
4606*90e502c7SAndroid Build Coastguard Worker         uint32_t temp_length;
4607*90e502c7SAndroid Build Coastguard Worker         if (stream_get_protect_trailer_length(stream, is_rtp, use_mki,
4608*90e502c7SAndroid Build Coastguard Worker                                               mki_index, &temp_length) ==
4609*90e502c7SAndroid Build Coastguard Worker             srtp_err_status_ok) {
4610*90e502c7SAndroid Build Coastguard Worker             if (temp_length > *length) {
4611*90e502c7SAndroid Build Coastguard Worker                 *length = temp_length;
4612*90e502c7SAndroid Build Coastguard Worker             }
4613*90e502c7SAndroid Build Coastguard Worker         }
4614*90e502c7SAndroid Build Coastguard Worker         stream = stream->next;
4615*90e502c7SAndroid Build Coastguard Worker     }
4616*90e502c7SAndroid Build Coastguard Worker 
4617*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4618*90e502c7SAndroid Build Coastguard Worker }
4619*90e502c7SAndroid Build Coastguard Worker 
srtp_get_protect_trailer_length(srtp_t session,uint32_t use_mki,uint32_t mki_index,uint32_t * length)4620*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session,
4621*90e502c7SAndroid Build Coastguard Worker                                                   uint32_t use_mki,
4622*90e502c7SAndroid Build Coastguard Worker                                                   uint32_t mki_index,
4623*90e502c7SAndroid Build Coastguard Worker                                                   uint32_t *length)
4624*90e502c7SAndroid Build Coastguard Worker {
4625*90e502c7SAndroid Build Coastguard Worker     return get_protect_trailer_length(session, 1, use_mki, mki_index, length);
4626*90e502c7SAndroid Build Coastguard Worker }
4627*90e502c7SAndroid Build Coastguard Worker 
srtp_get_protect_rtcp_trailer_length(srtp_t session,uint32_t use_mki,uint32_t mki_index,uint32_t * length)4628*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session,
4629*90e502c7SAndroid Build Coastguard Worker                                                        uint32_t use_mki,
4630*90e502c7SAndroid Build Coastguard Worker                                                        uint32_t mki_index,
4631*90e502c7SAndroid Build Coastguard Worker                                                        uint32_t *length)
4632*90e502c7SAndroid Build Coastguard Worker {
4633*90e502c7SAndroid Build Coastguard Worker     return get_protect_trailer_length(session, 0, use_mki, mki_index, length);
4634*90e502c7SAndroid Build Coastguard Worker }
4635*90e502c7SAndroid Build Coastguard Worker 
4636*90e502c7SAndroid Build Coastguard Worker /*
4637*90e502c7SAndroid Build Coastguard Worker  * SRTP debug interface
4638*90e502c7SAndroid Build Coastguard Worker  */
srtp_set_debug_module(const char * mod_name,int v)4639*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_set_debug_module(const char *mod_name, int v)
4640*90e502c7SAndroid Build Coastguard Worker {
4641*90e502c7SAndroid Build Coastguard Worker     return srtp_crypto_kernel_set_debug_module(mod_name, v);
4642*90e502c7SAndroid Build Coastguard Worker }
4643*90e502c7SAndroid Build Coastguard Worker 
srtp_list_debug_modules(void)4644*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_list_debug_modules(void)
4645*90e502c7SAndroid Build Coastguard Worker {
4646*90e502c7SAndroid Build Coastguard Worker     return srtp_crypto_kernel_list_debug_modules();
4647*90e502c7SAndroid Build Coastguard Worker }
4648*90e502c7SAndroid Build Coastguard Worker 
4649*90e502c7SAndroid Build Coastguard Worker /*
4650*90e502c7SAndroid Build Coastguard Worker  * srtp_log_handler is a global variable holding a pointer to the
4651*90e502c7SAndroid Build Coastguard Worker  * log handler function; this function is called for any log
4652*90e502c7SAndroid Build Coastguard Worker  * output.
4653*90e502c7SAndroid Build Coastguard Worker  */
4654*90e502c7SAndroid Build Coastguard Worker 
4655*90e502c7SAndroid Build Coastguard Worker static srtp_log_handler_func_t *srtp_log_handler = NULL;
4656*90e502c7SAndroid Build Coastguard Worker static void *srtp_log_handler_data = NULL;
4657*90e502c7SAndroid Build Coastguard Worker 
srtp_err_handler(srtp_err_reporting_level_t level,const char * msg)4658*90e502c7SAndroid Build Coastguard Worker void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg)
4659*90e502c7SAndroid Build Coastguard Worker {
4660*90e502c7SAndroid Build Coastguard Worker     if (srtp_log_handler) {
4661*90e502c7SAndroid Build Coastguard Worker         srtp_log_level_t log_level = srtp_log_level_error;
4662*90e502c7SAndroid Build Coastguard Worker         switch (level) {
4663*90e502c7SAndroid Build Coastguard Worker         case srtp_err_level_error:
4664*90e502c7SAndroid Build Coastguard Worker             log_level = srtp_log_level_error;
4665*90e502c7SAndroid Build Coastguard Worker             break;
4666*90e502c7SAndroid Build Coastguard Worker         case srtp_err_level_warning:
4667*90e502c7SAndroid Build Coastguard Worker             log_level = srtp_log_level_warning;
4668*90e502c7SAndroid Build Coastguard Worker             break;
4669*90e502c7SAndroid Build Coastguard Worker         case srtp_err_level_info:
4670*90e502c7SAndroid Build Coastguard Worker             log_level = srtp_log_level_info;
4671*90e502c7SAndroid Build Coastguard Worker             break;
4672*90e502c7SAndroid Build Coastguard Worker         case srtp_err_level_debug:
4673*90e502c7SAndroid Build Coastguard Worker             log_level = srtp_log_level_debug;
4674*90e502c7SAndroid Build Coastguard Worker             break;
4675*90e502c7SAndroid Build Coastguard Worker         }
4676*90e502c7SAndroid Build Coastguard Worker 
4677*90e502c7SAndroid Build Coastguard Worker         srtp_log_handler(log_level, msg, srtp_log_handler_data);
4678*90e502c7SAndroid Build Coastguard Worker     }
4679*90e502c7SAndroid Build Coastguard Worker }
4680*90e502c7SAndroid Build Coastguard Worker 
srtp_install_log_handler(srtp_log_handler_func_t func,void * data)4681*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func,
4682*90e502c7SAndroid Build Coastguard Worker                                            void *data)
4683*90e502c7SAndroid Build Coastguard Worker {
4684*90e502c7SAndroid Build Coastguard Worker     /*
4685*90e502c7SAndroid Build Coastguard Worker      * note that we accept NULL arguments intentionally - calling this
4686*90e502c7SAndroid Build Coastguard Worker      * function with a NULL arguments removes a log handler that's
4687*90e502c7SAndroid Build Coastguard Worker      * been previously installed
4688*90e502c7SAndroid Build Coastguard Worker      */
4689*90e502c7SAndroid Build Coastguard Worker 
4690*90e502c7SAndroid Build Coastguard Worker     if (srtp_log_handler) {
4691*90e502c7SAndroid Build Coastguard Worker         srtp_install_err_report_handler(NULL);
4692*90e502c7SAndroid Build Coastguard Worker     }
4693*90e502c7SAndroid Build Coastguard Worker     srtp_log_handler = func;
4694*90e502c7SAndroid Build Coastguard Worker     srtp_log_handler_data = data;
4695*90e502c7SAndroid Build Coastguard Worker     if (srtp_log_handler) {
4696*90e502c7SAndroid Build Coastguard Worker         srtp_install_err_report_handler(srtp_err_handler);
4697*90e502c7SAndroid Build Coastguard Worker     }
4698*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4699*90e502c7SAndroid Build Coastguard Worker }
4700*90e502c7SAndroid Build Coastguard Worker 
srtp_set_stream_roc(srtp_t session,uint32_t ssrc,uint32_t roc)4701*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_set_stream_roc(srtp_t session,
4702*90e502c7SAndroid Build Coastguard Worker                                       uint32_t ssrc,
4703*90e502c7SAndroid Build Coastguard Worker                                       uint32_t roc)
4704*90e502c7SAndroid Build Coastguard Worker {
4705*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t stream;
4706*90e502c7SAndroid Build Coastguard Worker 
4707*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(session, htonl(ssrc));
4708*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL)
4709*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4710*90e502c7SAndroid Build Coastguard Worker 
4711*90e502c7SAndroid Build Coastguard Worker     stream->pending_roc = roc;
4712*90e502c7SAndroid Build Coastguard Worker 
4713*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4714*90e502c7SAndroid Build Coastguard Worker }
4715*90e502c7SAndroid Build Coastguard Worker 
srtp_get_stream_roc(srtp_t session,uint32_t ssrc,uint32_t * roc)4716*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t srtp_get_stream_roc(srtp_t session,
4717*90e502c7SAndroid Build Coastguard Worker                                       uint32_t ssrc,
4718*90e502c7SAndroid Build Coastguard Worker                                       uint32_t *roc)
4719*90e502c7SAndroid Build Coastguard Worker {
4720*90e502c7SAndroid Build Coastguard Worker     srtp_stream_t stream;
4721*90e502c7SAndroid Build Coastguard Worker 
4722*90e502c7SAndroid Build Coastguard Worker     stream = srtp_get_stream(session, htonl(ssrc));
4723*90e502c7SAndroid Build Coastguard Worker     if (stream == NULL)
4724*90e502c7SAndroid Build Coastguard Worker         return srtp_err_status_bad_param;
4725*90e502c7SAndroid Build Coastguard Worker 
4726*90e502c7SAndroid Build Coastguard Worker     *roc = srtp_rdbx_get_roc(&stream->rtp_rdbx);
4727*90e502c7SAndroid Build Coastguard Worker 
4728*90e502c7SAndroid Build Coastguard Worker     return srtp_err_status_ok;
4729*90e502c7SAndroid Build Coastguard Worker }
4730