corrected copyright
[gnutls.git] / lib / ext / srtp.c
blob95d7a3fb8969245579caa473983c73dfe6226f86
1 /*
2 * Copyright (C) 2012 Free Software Foundation
3 *
4 * Author: Martin Storsjo
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include "gnutls_int.h"
24 #include "gnutls_auth.h"
25 #include "gnutls_errors.h"
26 #include "gnutls_num.h"
27 #include <ext/srtp.h>
29 static int _gnutls_srtp_recv_params (gnutls_session_t session,
30 const uint8_t * data,
31 size_t data_size);
32 static int _gnutls_srtp_send_params (gnutls_session_t session,
33 gnutls_buffer_st* extdata);
35 static int _gnutls_srtp_unpack (gnutls_buffer_st * ps,
36 extension_priv_data_t * _priv);
37 static int _gnutls_srtp_pack (extension_priv_data_t _priv,
38 gnutls_buffer_st * ps);
39 static void _gnutls_srtp_deinit_data (extension_priv_data_t priv);
42 extension_entry_st ext_mod_srtp = {
43 .name = "SRTP",
44 .type = GNUTLS_EXTENSION_SRTP,
45 .parse_type = GNUTLS_EXT_APPLICATION,
47 .recv_func = _gnutls_srtp_recv_params,
48 .send_func = _gnutls_srtp_send_params,
49 .pack_func = _gnutls_srtp_pack,
50 .unpack_func = _gnutls_srtp_unpack,
51 .deinit_func = _gnutls_srtp_deinit_data,
54 typedef struct
56 const char *name;
57 gnutls_srtp_profile_t id;
58 unsigned int key_length;
59 unsigned int salt_length;
60 } srtp_profile_st;
62 static const srtp_profile_st profile_names[] = {
64 "SRTP_AES128_CM_HMAC_SHA1_80",
65 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_80,
66 16,14
69 "SRTP_AES128_CM_HMAC_SHA1_32",
70 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_32,
71 16,14
74 "SRTP_NULL_HMAC_SHA1_80",
75 GNUTLS_SRTP_NULL_HMAC_SHA1_80,
76 16,14
79 "SRTP_NULL_SHA1_32",
80 GNUTLS_SRTP_NULL_HMAC_SHA1_32,
81 16,14
84 NULL,
85 0,0,0
89 static const srtp_profile_st *get_profile (gnutls_srtp_profile_t profile)
91 const srtp_profile_st *p = profile_names;
92 while (p->name != NULL)
94 if (p->id == profile)
95 return p;
96 p++;
98 return NULL;
101 static gnutls_srtp_profile_t find_profile (const char *str, const char *end)
103 const srtp_profile_st *prof = profile_names;
104 unsigned int len;
105 if (end != NULL)
107 len = end - str;
109 else
111 len = strlen (str);
114 while (prof->name != NULL)
116 if (strlen (prof->name) == len && !strncmp (str, prof->name, len))
118 return prof->id;
120 prof++;
122 return 0;
126 * gnutls_srtp_get_profile_id
127 * @name: The name of the profile to look up
128 * @profile: Will hold the profile id
130 * This function allows you to look up a profile based on a string.
132 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
133 * otherwise a negative error code is returned.
135 * Since 3.1.4
137 int gnutls_srtp_get_profile_id (const char *name,
138 gnutls_srtp_profile_t *profile)
140 *profile = find_profile (name, NULL);
141 if (*profile == 0)
143 return GNUTLS_E_ILLEGAL_PARAMETER;
145 return 0;
148 #define MAX_PROFILES_IN_SRTP_EXTENSION 256
151 * gnutls_srtp_get_profile_name
152 * @profile: The profile to look up a string for
154 * This function allows you to get the corresponding name for a
155 * SRTP protection profile.
157 * Returns: On success, the name of a SRTP profile as a string,
158 * otherwise NULL.
160 * Since 3.1.4
162 const char *gnutls_srtp_get_profile_name (gnutls_srtp_profile_t profile)
164 const srtp_profile_st *p = get_profile(profile);
166 if (p != NULL)
167 return p->name;
169 return NULL;
172 static int
173 _gnutls_srtp_recv_params (gnutls_session_t session,
174 const uint8_t *data, size_t _data_size)
176 unsigned int i;
177 int ret;
178 const uint8_t *p = data;
179 int len;
180 ssize_t data_size = _data_size;
181 srtp_ext_st *priv;
182 extension_priv_data_t epriv;
183 uint16_t profile;
185 ret =
186 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
187 &epriv);
188 if (ret < 0)
189 return 0;
191 priv = epriv.ptr;
193 DECR_LENGTH_RET (data_size, 2, 0);
194 len = _gnutls_read_uint16 (p);
195 p += 2;
197 if (len+1 > data_size)
198 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
200 if (session->security_parameters.entity == GNUTLS_SERVER)
202 if (len > MAX_PROFILES_IN_SRTP_EXTENSION*2)
203 return 0;
205 else
207 if (len != 2)
208 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
211 while (len > 0)
213 DECR_LEN (data_size, 2);
214 profile = _gnutls_read_uint16 (p);
216 for (i = 0; i < priv->profiles_size;i++)
218 if (priv->profiles[i] == profile)
220 priv->selected_profile = profile;
221 break;
224 p += 2;
225 len -= 2;
228 DECR_LEN (data_size, 1);
229 priv->mki_size = *p;
230 p++;
232 if (priv->mki_size > 0)
234 DECR_LEN (data_size, priv->mki_size);
235 memcpy(priv->mki, p, priv->mki_size);
236 priv->mki_received = 1;
239 return 0;
242 static int
243 _gnutls_srtp_send_params (gnutls_session_t session,
244 gnutls_buffer_st* extdata)
246 unsigned i;
247 int total_size = 0, ret;
248 srtp_ext_st *priv;
249 extension_priv_data_t epriv;
251 ret =
252 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
253 &epriv);
254 if (ret < 0)
255 return 0;
257 priv = epriv.ptr;
259 if (priv->profiles_size == 0)
260 return 0;
262 if (session->security_parameters.entity == GNUTLS_SERVER)
264 /* Don't send anything if no matching profile was found */
265 if (priv->selected_profile == 0)
266 return 0;
268 ret = _gnutls_buffer_append_prefix(extdata, 16, 2);
269 if (ret < 0)
270 return gnutls_assert_val(ret);
271 ret = _gnutls_buffer_append_prefix(extdata, 16, priv->selected_profile);
272 if (ret < 0)
273 return gnutls_assert_val(ret);
274 total_size = 4;
276 else
278 ret = _gnutls_buffer_append_prefix(extdata, 16, 2 * priv->profiles_size);
279 if (ret < 0)
280 return gnutls_assert_val(ret);
282 for (i = 0; i < priv->profiles_size; i++)
284 ret = _gnutls_buffer_append_prefix(extdata, 16, priv->profiles[i]);
285 if (ret < 0)
286 return gnutls_assert_val(ret);
288 total_size = 2 + 2 * priv->profiles_size;
291 /* use_mki */
292 ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki, priv->mki_size);
293 if (ret < 0)
294 return gnutls_assert_val(ret);
296 return total_size + 1;
300 * gnutls_srtp_get_selected_profile:
301 * @session: is a #gnutls_session_t structure.
302 * @profile: will hold the profile
304 * This function allows you to get the negotiated SRTP profile.
306 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
307 * otherwise a negative error code is returned.
309 * Since 3.1.4
312 gnutls_srtp_get_selected_profile (gnutls_session_t session,
313 gnutls_srtp_profile_t *profile)
315 srtp_ext_st *priv;
316 int ret;
317 extension_priv_data_t epriv;
319 ret =
320 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
321 &epriv);
322 if (ret < 0)
324 gnutls_assert ();
325 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
328 priv = epriv.ptr;
330 if (priv->selected_profile == 0)
332 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
335 *profile = priv->selected_profile;
337 return 0;
341 * gnutls_srtp_get_mki:
342 * @session: is a #gnutls_session_t structure.
343 * @mki: will hold the MKI
345 * This function exports the negotiated Master Key Identifier,
346 * received by the peer if any. The returned value in @mki should be
347 * treated as constant and valid only during the session's lifetime.
349 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
350 * otherwise a negative error code is returned.
352 * Since 3.1.4
355 gnutls_srtp_get_mki (gnutls_session_t session,
356 gnutls_datum_t *mki)
358 srtp_ext_st *priv;
359 int ret;
360 extension_priv_data_t epriv;
362 ret =
363 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
364 &epriv);
365 if (ret < 0)
366 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
368 priv = epriv.ptr;
370 if (priv->mki_received == 0)
371 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
373 mki->data = priv->mki;
374 mki->size = priv->mki_size;
376 return 0;
380 * gnutls_srtp_set_mki:
381 * @session: is a #gnutls_session_t structure.
382 * @mki: holds the MKI
384 * This function sets the Master Key Identifier, to be
385 * used by this session (if any).
387 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
388 * otherwise a negative error code is returned.
390 * Since 3.1.4
393 gnutls_srtp_set_mki (gnutls_session_t session,
394 const gnutls_datum_t *mki)
396 int ret;
397 srtp_ext_st *priv;
398 extension_priv_data_t epriv;
400 ret =
401 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
402 &epriv);
403 if (ret < 0)
405 priv = gnutls_calloc (1, sizeof (*priv));
406 if (priv == NULL)
408 gnutls_assert ();
409 return GNUTLS_E_MEMORY_ERROR;
411 epriv.ptr = priv;
412 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
413 epriv);
415 else
416 priv = epriv.ptr;
418 if (mki->size > 0 && mki->size <= sizeof(priv->mki))
420 priv->mki_size = mki->size;
421 memcpy(priv->mki, mki->data, mki->size);
423 else
424 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
426 return 0;
430 * gnutls_srtp_set_profile:
431 * @session: is a #gnutls_session_t structure.
432 * @profile: is the profile id to add.
434 * This function is to be used by both clients and servers, to declare
435 * what SRTP profiles they support, to negotiate with the peer.
437 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
438 * otherwise a negative error code is returned.
440 * Since 3.1.4
443 gnutls_srtp_set_profile (gnutls_session_t session,
444 gnutls_srtp_profile_t profile)
446 int ret;
447 srtp_ext_st *priv;
448 extension_priv_data_t epriv;
450 ret =
451 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
452 &epriv);
453 if (ret < 0)
455 priv = gnutls_calloc (1, sizeof (*priv));
456 if (priv == NULL)
458 gnutls_assert ();
459 return GNUTLS_E_MEMORY_ERROR;
461 epriv.ptr = priv;
462 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
463 epriv);
465 else
466 priv = epriv.ptr;
468 if (priv->profiles_size < MAX_SRTP_PROFILES)
469 priv->profiles_size++;
470 priv->profiles[priv->profiles_size - 1] = profile;
472 return 0;
476 * gnutls_srtp_set_profile_direct:
477 * @session: is a #gnutls_session_t structure.
478 * @profiles: is a string that contains the supported SRTP profiles,
479 * separated by colons.
480 * @err_pos: In case of an error this will have the position in the string the error occured, may be NULL.
482 * This function is to be used by both clients and servers, to declare
483 * what SRTP profiles they support, to negotiate with the peer.
485 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
486 * %GNUTLS_E_SUCCESS on success, or an error code.
488 * Since 3.1.4
491 gnutls_srtp_set_profile_direct (gnutls_session_t session,
492 const char *profiles, const char **err_pos)
494 int ret;
495 srtp_ext_st *priv;
496 extension_priv_data_t epriv;
497 int set = 0;
498 const char *col;
499 gnutls_srtp_profile_t id;
501 ret =
502 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
503 &epriv);
504 if (ret < 0)
506 set = 1;
507 priv = gnutls_calloc (1, sizeof (*priv));
508 if (priv == NULL)
510 if (err_pos != NULL)
511 *err_pos = profiles;
512 gnutls_assert ();
513 return GNUTLS_E_MEMORY_ERROR;
515 epriv.ptr = priv;
517 else
518 priv = epriv.ptr;
522 col = strchr (profiles, ':');
523 id = find_profile (profiles, col);
524 if (id == 0)
526 if (set != 0)
527 gnutls_free (priv);
528 if (err_pos != NULL)
529 *err_pos = profiles;
530 return GNUTLS_E_INVALID_REQUEST;
533 if (priv->profiles_size < MAX_SRTP_PROFILES)
535 priv->profiles_size++;
537 priv->profiles[priv->profiles_size - 1] = id;
538 profiles = col + 1;
539 } while (col != NULL);
541 if (set != 0)
542 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
543 epriv);
545 return 0;
549 * gnutls_srtp_get_keys:
550 * @session: is a #gnutls_session_t structure.
551 * @key_material: Space to hold the generated key material
552 * @key_material_size: The maximum size of the key material
553 * @client_key: The master client write key, pointing inside the key material
554 * @server_key: The master server write key, pointing inside the key material
555 * @client_salt: The master client write salt, pointing inside the key material
556 * @server_salt: The master server write salt, pointing inside the key material
558 * This is a helper function to generate the keying material for SRTP.
559 * It requires the space of the key material to be pre-allocated (should be at least
560 * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key
561 * and @server_salt are convenience datums that point inside the key material. They may
562 * be %NULL.
564 * Returns: On success the size of the key material is returned,
565 * otherwise, %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
566 * sufficient, or a negative error code.
568 * Since 3.1.4
571 gnutls_srtp_get_keys (gnutls_session_t session,
572 void *key_material,
573 unsigned int key_material_size,
574 gnutls_datum_t *client_key,
575 gnutls_datum_t *client_salt,
576 gnutls_datum_t *server_key,
577 gnutls_datum_t *server_salt)
579 int ret;
580 const srtp_profile_st *p;
581 gnutls_srtp_profile_t profile;
582 unsigned int msize;
583 uint8_t *km = key_material;
585 ret = gnutls_srtp_get_selected_profile (session, &profile);
586 if (ret < 0)
587 return gnutls_assert_val(ret);
589 p = get_profile(profile);
590 if (p == NULL)
591 return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
593 msize = 2*(p->key_length+p->salt_length);
594 if (msize > key_material_size)
595 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
597 if (msize == 0)
598 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
600 ret = gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp")-1, "EXTRACTOR-dtls_srtp", 0, 0,
601 NULL, msize, key_material);
602 if (ret < 0)
603 return gnutls_assert_val(ret);
605 if (client_key)
607 client_key->data = km;
608 client_key->size = p->key_length;
611 if (server_key)
613 server_key->data = km + p->key_length;
614 server_key->size = p->key_length;
617 if (client_salt)
619 client_salt->data = km + 2*p->key_length;
620 client_salt->size = p->salt_length;
623 if (server_salt)
625 server_salt->data = km + 2*p->key_length + p->salt_length;
626 server_salt->size = p->salt_length;
629 return msize;
632 static void
633 _gnutls_srtp_deinit_data (extension_priv_data_t priv)
635 gnutls_free (priv.ptr);
638 static int
639 _gnutls_srtp_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
641 srtp_ext_st *priv = epriv.ptr;
642 unsigned int i;
643 int ret;
645 BUFFER_APPEND_NUM (ps, priv->profiles_size);
646 for (i = 0; i < priv->profiles_size; i++)
648 BUFFER_APPEND_NUM (ps, priv->profiles[i]);
651 BUFFER_APPEND_NUM (ps, priv->mki_received);
652 if (priv->mki_received)
654 BUFFER_APPEND_NUM (ps, priv->selected_profile);
655 BUFFER_APPEND_PFX4 (ps, priv->mki, priv->mki_size);
657 return 0;
660 static int
661 _gnutls_srtp_unpack (gnutls_buffer_st * ps,
662 extension_priv_data_t * _priv)
664 srtp_ext_st *priv;
665 unsigned int i;
666 int ret;
667 extension_priv_data_t epriv;
669 priv = gnutls_calloc (1, sizeof (*priv));
670 if (priv == NULL)
672 gnutls_assert ();
673 return GNUTLS_E_MEMORY_ERROR;
676 BUFFER_POP_NUM (ps, priv->profiles_size);
677 for (i = 0; i < priv->profiles_size; i++)
679 BUFFER_POP_NUM (ps, priv->profiles[i]);
681 BUFFER_POP_NUM (ps, priv->selected_profile);
683 BUFFER_POP_NUM (ps, priv->mki_received);
684 if (priv->mki_received)
686 BUFFER_POP_NUM (ps, priv->mki_size);
687 BUFFER_POP (ps, priv->mki, priv->mki_size);
690 epriv.ptr = priv;
691 *_priv = epriv;
693 return 0;
695 error:
696 gnutls_free (priv);
697 return ret;