Added functions to parse the certificate policies extention.
[gnutls.git] / lib / ext / srtp.c
blobf4e86810d9707269020280d7ec9653d4d75d4dba
1 /*
2 * Copyright (C) 2012 Martin Storsjo
3 * Copyright (C) 2012 Free Software Foundation
4 *
5 * Author: Martin Storsjo
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
24 #include "gnutls_int.h"
25 #include "gnutls_auth.h"
26 #include "gnutls_errors.h"
27 #include "gnutls_num.h"
28 #include <ext/srtp.h>
30 static int _gnutls_srtp_recv_params (gnutls_session_t session,
31 const uint8_t * data,
32 size_t data_size);
33 static int _gnutls_srtp_send_params (gnutls_session_t session,
34 gnutls_buffer_st* extdata);
36 static int _gnutls_srtp_unpack (gnutls_buffer_st * ps,
37 extension_priv_data_t * _priv);
38 static int _gnutls_srtp_pack (extension_priv_data_t _priv,
39 gnutls_buffer_st * ps);
40 static void _gnutls_srtp_deinit_data (extension_priv_data_t priv);
43 extension_entry_st ext_mod_srtp = {
44 .name = "SRTP",
45 .type = GNUTLS_EXTENSION_SRTP,
46 .parse_type = GNUTLS_EXT_APPLICATION,
48 .recv_func = _gnutls_srtp_recv_params,
49 .send_func = _gnutls_srtp_send_params,
50 .pack_func = _gnutls_srtp_pack,
51 .unpack_func = _gnutls_srtp_unpack,
52 .deinit_func = _gnutls_srtp_deinit_data,
55 typedef struct
57 const char *name;
58 gnutls_srtp_profile_t id;
59 unsigned int key_length;
60 unsigned int salt_length;
61 } srtp_profile_st;
63 static const srtp_profile_st profile_names[] = {
65 "SRTP_AES128_CM_HMAC_SHA1_80",
66 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_80,
67 16,14
70 "SRTP_AES128_CM_HMAC_SHA1_32",
71 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_32,
72 16,14
75 "SRTP_NULL_HMAC_SHA1_80",
76 GNUTLS_SRTP_NULL_HMAC_SHA1_80,
77 16,14
80 "SRTP_NULL_SHA1_32",
81 GNUTLS_SRTP_NULL_HMAC_SHA1_32,
82 16,14
85 NULL,
86 0,0,0
90 static const srtp_profile_st *get_profile (gnutls_srtp_profile_t profile)
92 const srtp_profile_st *p = profile_names;
93 while (p->name != NULL)
95 if (p->id == profile)
96 return p;
97 p++;
99 return NULL;
102 static gnutls_srtp_profile_t find_profile (const char *str, const char *end)
104 const srtp_profile_st *prof = profile_names;
105 unsigned int len;
106 if (end != NULL)
108 len = end - str;
110 else
112 len = strlen (str);
115 while (prof->name != NULL)
117 if (strlen (prof->name) == len && !strncmp (str, prof->name, len))
119 return prof->id;
121 prof++;
123 return 0;
127 * gnutls_srtp_get_profile_id
128 * @name: The name of the profile to look up
129 * @profile: Will hold the profile id
131 * This function allows you to look up a profile based on a string.
133 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
134 * otherwise a negative error code is returned.
136 * Since 3.1.4
138 int gnutls_srtp_get_profile_id (const char *name,
139 gnutls_srtp_profile_t *profile)
141 *profile = find_profile (name, NULL);
142 if (*profile == 0)
144 return GNUTLS_E_ILLEGAL_PARAMETER;
146 return 0;
149 #define MAX_PROFILES_IN_SRTP_EXTENSION 256
152 * gnutls_srtp_get_profile_name
153 * @profile: The profile to look up a string for
155 * This function allows you to get the corresponding name for a
156 * SRTP protection profile.
158 * Returns: On success, the name of a SRTP profile as a string,
159 * otherwise NULL.
161 * Since 3.1.4
163 const char *gnutls_srtp_get_profile_name (gnutls_srtp_profile_t profile)
165 const srtp_profile_st *p = get_profile(profile);
167 if (p != NULL)
168 return p->name;
170 return NULL;
173 static int
174 _gnutls_srtp_recv_params (gnutls_session_t session,
175 const uint8_t *data, size_t _data_size)
177 unsigned int i;
178 int ret;
179 const uint8_t *p = data;
180 int len;
181 ssize_t data_size = _data_size;
182 srtp_ext_st *priv;
183 extension_priv_data_t epriv;
184 uint16_t profile;
186 ret =
187 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
188 &epriv);
189 if (ret < 0)
190 return 0;
192 priv = epriv.ptr;
194 DECR_LENGTH_RET (data_size, 2, 0);
195 len = _gnutls_read_uint16 (p);
196 p += 2;
198 if (len+1 > data_size)
199 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
201 if (session->security_parameters.entity == GNUTLS_SERVER)
203 if (len > MAX_PROFILES_IN_SRTP_EXTENSION*2)
204 return 0;
206 else
208 if (len != 2)
209 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
212 while (len > 0)
214 DECR_LEN (data_size, 2);
215 profile = _gnutls_read_uint16 (p);
217 for (i = 0; i < priv->profiles_size;i++)
219 if (priv->profiles[i] == profile)
221 priv->selected_profile = profile;
222 break;
225 p += 2;
226 len -= 2;
229 DECR_LEN (data_size, 1);
230 priv->mki_size = *p;
231 p++;
233 if (priv->mki_size > 0)
235 DECR_LEN (data_size, priv->mki_size);
236 memcpy(priv->mki, p, priv->mki_size);
237 priv->mki_received = 1;
240 return 0;
243 static int
244 _gnutls_srtp_send_params (gnutls_session_t session,
245 gnutls_buffer_st* extdata)
247 unsigned i;
248 int total_size = 0, ret;
249 srtp_ext_st *priv;
250 extension_priv_data_t epriv;
252 ret =
253 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
254 &epriv);
255 if (ret < 0)
256 return 0;
258 priv = epriv.ptr;
260 if (priv->profiles_size == 0)
261 return 0;
263 if (session->security_parameters.entity == GNUTLS_SERVER)
265 /* Don't send anything if no matching profile was found */
266 if (priv->selected_profile == 0)
267 return 0;
269 ret = _gnutls_buffer_append_prefix(extdata, 16, 2);
270 if (ret < 0)
271 return gnutls_assert_val(ret);
272 ret = _gnutls_buffer_append_prefix(extdata, 16, priv->selected_profile);
273 if (ret < 0)
274 return gnutls_assert_val(ret);
275 total_size = 4;
277 else
279 ret = _gnutls_buffer_append_prefix(extdata, 16, 2 * priv->profiles_size);
280 if (ret < 0)
281 return gnutls_assert_val(ret);
283 for (i = 0; i < priv->profiles_size; i++)
285 ret = _gnutls_buffer_append_prefix(extdata, 16, priv->profiles[i]);
286 if (ret < 0)
287 return gnutls_assert_val(ret);
289 total_size = 2 + 2 * priv->profiles_size;
292 /* use_mki */
293 ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki, priv->mki_size);
294 if (ret < 0)
295 return gnutls_assert_val(ret);
297 return total_size + 1;
301 * gnutls_srtp_get_selected_profile:
302 * @session: is a #gnutls_session_t structure.
303 * @profile: will hold the profile
305 * This function allows you to get the negotiated SRTP profile.
307 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
308 * otherwise a negative error code is returned.
310 * Since 3.1.4
313 gnutls_srtp_get_selected_profile (gnutls_session_t session,
314 gnutls_srtp_profile_t *profile)
316 srtp_ext_st *priv;
317 int ret;
318 extension_priv_data_t epriv;
320 ret =
321 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
322 &epriv);
323 if (ret < 0)
325 gnutls_assert ();
326 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
329 priv = epriv.ptr;
331 if (priv->selected_profile == 0)
333 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
336 *profile = priv->selected_profile;
338 return 0;
342 * gnutls_srtp_get_mki:
343 * @session: is a #gnutls_session_t structure.
344 * @mki: will hold the MKI
346 * This function exports the negotiated Master Key Identifier,
347 * received by the peer if any. The returned value in @mki should be
348 * treated as constant and valid only during the session's lifetime.
350 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
351 * otherwise a negative error code is returned.
353 * Since 3.1.4
356 gnutls_srtp_get_mki (gnutls_session_t session,
357 gnutls_datum_t *mki)
359 srtp_ext_st *priv;
360 int ret;
361 extension_priv_data_t epriv;
363 ret =
364 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
365 &epriv);
366 if (ret < 0)
367 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
369 priv = epriv.ptr;
371 if (priv->mki_received == 0)
372 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
374 mki->data = priv->mki;
375 mki->size = priv->mki_size;
377 return 0;
381 * gnutls_srtp_set_mki:
382 * @session: is a #gnutls_session_t structure.
383 * @mki: holds the MKI
385 * This function sets the Master Key Identifier, to be
386 * used by this session (if any).
388 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
389 * otherwise a negative error code is returned.
391 * Since 3.1.4
394 gnutls_srtp_set_mki (gnutls_session_t session,
395 const gnutls_datum_t *mki)
397 int ret;
398 srtp_ext_st *priv;
399 extension_priv_data_t epriv;
401 ret =
402 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
403 &epriv);
404 if (ret < 0)
406 priv = gnutls_calloc (1, sizeof (*priv));
407 if (priv == NULL)
409 gnutls_assert ();
410 return GNUTLS_E_MEMORY_ERROR;
412 epriv.ptr = priv;
413 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
414 epriv);
416 else
417 priv = epriv.ptr;
419 if (mki->size > 0 && mki->size <= sizeof(priv->mki))
421 priv->mki_size = mki->size;
422 memcpy(priv->mki, mki->data, mki->size);
424 else
425 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
427 return 0;
431 * gnutls_srtp_set_profile:
432 * @session: is a #gnutls_session_t structure.
433 * @profile: is the profile id to add.
435 * This function is to be used by both clients and servers, to declare
436 * what SRTP profiles they support, to negotiate with the peer.
438 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
439 * otherwise a negative error code is returned.
441 * Since 3.1.4
444 gnutls_srtp_set_profile (gnutls_session_t session,
445 gnutls_srtp_profile_t profile)
447 int ret;
448 srtp_ext_st *priv;
449 extension_priv_data_t epriv;
451 ret =
452 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
453 &epriv);
454 if (ret < 0)
456 priv = gnutls_calloc (1, sizeof (*priv));
457 if (priv == NULL)
459 gnutls_assert ();
460 return GNUTLS_E_MEMORY_ERROR;
462 epriv.ptr = priv;
463 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
464 epriv);
466 else
467 priv = epriv.ptr;
469 if (priv->profiles_size < MAX_SRTP_PROFILES)
470 priv->profiles_size++;
471 priv->profiles[priv->profiles_size - 1] = profile;
473 return 0;
477 * gnutls_srtp_set_profile_direct:
478 * @session: is a #gnutls_session_t structure.
479 * @profiles: is a string that contains the supported SRTP profiles,
480 * separated by colons.
481 * @err_pos: In case of an error this will have the position in the string the error occured, may be NULL.
483 * This function is to be used by both clients and servers, to declare
484 * what SRTP profiles they support, to negotiate with the peer.
486 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
487 * %GNUTLS_E_SUCCESS on success, or an error code.
489 * Since 3.1.4
492 gnutls_srtp_set_profile_direct (gnutls_session_t session,
493 const char *profiles, const char **err_pos)
495 int ret;
496 srtp_ext_st *priv;
497 extension_priv_data_t epriv;
498 int set = 0;
499 const char *col;
500 gnutls_srtp_profile_t id;
502 ret =
503 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRTP,
504 &epriv);
505 if (ret < 0)
507 set = 1;
508 priv = gnutls_calloc (1, sizeof (*priv));
509 if (priv == NULL)
511 if (err_pos != NULL)
512 *err_pos = profiles;
513 gnutls_assert ();
514 return GNUTLS_E_MEMORY_ERROR;
516 epriv.ptr = priv;
518 else
519 priv = epriv.ptr;
523 col = strchr (profiles, ':');
524 id = find_profile (profiles, col);
525 if (id == 0)
527 if (set != 0)
528 gnutls_free (priv);
529 if (err_pos != NULL)
530 *err_pos = profiles;
531 return GNUTLS_E_INVALID_REQUEST;
534 if (priv->profiles_size < MAX_SRTP_PROFILES)
536 priv->profiles_size++;
538 priv->profiles[priv->profiles_size - 1] = id;
539 profiles = col + 1;
540 } while (col != NULL);
542 if (set != 0)
543 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRTP,
544 epriv);
546 return 0;
550 * gnutls_srtp_get_keys:
551 * @session: is a #gnutls_session_t structure.
552 * @key_material: Space to hold the generated key material
553 * @key_material_size: The maximum size of the key material
554 * @client_key: The master client write key, pointing inside the key material
555 * @server_key: The master server write key, pointing inside the key material
556 * @client_salt: The master client write salt, pointing inside the key material
557 * @server_salt: The master server write salt, pointing inside the key material
559 * This is a helper function to generate the keying material for SRTP.
560 * It requires the space of the key material to be pre-allocated (should be at least
561 * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key
562 * and @server_salt are convenience datums that point inside the key material. They may
563 * be %NULL.
565 * Returns: On success the size of the key material is returned,
566 * otherwise, %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
567 * sufficient, or a negative error code.
569 * Since 3.1.4
572 gnutls_srtp_get_keys (gnutls_session_t session,
573 void *key_material,
574 unsigned int key_material_size,
575 gnutls_datum_t *client_key,
576 gnutls_datum_t *client_salt,
577 gnutls_datum_t *server_key,
578 gnutls_datum_t *server_salt)
580 int ret;
581 const srtp_profile_st *p;
582 gnutls_srtp_profile_t profile;
583 unsigned int msize;
584 uint8_t *km = key_material;
586 ret = gnutls_srtp_get_selected_profile (session, &profile);
587 if (ret < 0)
588 return gnutls_assert_val(ret);
590 p = get_profile(profile);
591 if (p == NULL)
592 return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
594 msize = 2*(p->key_length+p->salt_length);
595 if (msize > key_material_size)
596 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
598 if (msize == 0)
599 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
601 ret = gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp")-1, "EXTRACTOR-dtls_srtp", 0, 0,
602 NULL, msize, key_material);
603 if (ret < 0)
604 return gnutls_assert_val(ret);
606 if (client_key)
608 client_key->data = km;
609 client_key->size = p->key_length;
612 if (server_key)
614 server_key->data = km + p->key_length;
615 server_key->size = p->key_length;
618 if (client_salt)
620 client_salt->data = km + 2*p->key_length;
621 client_salt->size = p->salt_length;
624 if (server_salt)
626 server_salt->data = km + 2*p->key_length + p->salt_length;
627 server_salt->size = p->salt_length;
630 return msize;
633 static void
634 _gnutls_srtp_deinit_data (extension_priv_data_t priv)
636 gnutls_free (priv.ptr);
639 static int
640 _gnutls_srtp_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
642 srtp_ext_st *priv = epriv.ptr;
643 unsigned int i;
644 int ret;
646 BUFFER_APPEND_NUM (ps, priv->profiles_size);
647 for (i = 0; i < priv->profiles_size; i++)
649 BUFFER_APPEND_NUM (ps, priv->profiles[i]);
652 BUFFER_APPEND_NUM (ps, priv->mki_received);
653 if (priv->mki_received)
655 BUFFER_APPEND_NUM (ps, priv->selected_profile);
656 BUFFER_APPEND_PFX4 (ps, priv->mki, priv->mki_size);
658 return 0;
661 static int
662 _gnutls_srtp_unpack (gnutls_buffer_st * ps,
663 extension_priv_data_t * _priv)
665 srtp_ext_st *priv;
666 unsigned int i;
667 int ret;
668 extension_priv_data_t epriv;
670 priv = gnutls_calloc (1, sizeof (*priv));
671 if (priv == NULL)
673 gnutls_assert ();
674 return GNUTLS_E_MEMORY_ERROR;
677 BUFFER_POP_NUM (ps, priv->profiles_size);
678 for (i = 0; i < priv->profiles_size; i++)
680 BUFFER_POP_NUM (ps, priv->profiles[i]);
682 BUFFER_POP_NUM (ps, priv->selected_profile);
684 BUFFER_POP_NUM (ps, priv->mki_received);
685 if (priv->mki_received)
687 BUFFER_POP_NUM (ps, priv->mki_size);
688 BUFFER_POP (ps, priv->mki, priv->mki_size);
691 epriv.ptr = priv;
692 *_priv = epriv;
694 return 0;
696 error:
697 gnutls_free (priv);
698 return ret;