1 /*
2 * Copyright (C) 2012 Free Software Foundation
3 *
4 * Author: Martin Storsjo
5 *
6 * This file is part of GnuTLS.
7 *
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 2.1 of
11 * the License, or (at your option) any later version.
12 *
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.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 #include "gnutls_int.h"
24 #include "auth.h"
25 #include "errors.h"
26 #include "num.h"
27 #include <ext/srtp.h>
28
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);
34
35 static int _gnutls_srtp_unpack(gnutls_buffer_st * ps,
36 gnutls_ext_priv_data_t * _priv);
37 static int _gnutls_srtp_pack(gnutls_ext_priv_data_t _priv,
38 gnutls_buffer_st * ps);
39 static void _gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv);
40
41
42 const hello_ext_entry_st ext_mod_srtp = {
43 .name = "SRTP",
44 .tls_id = 14,
45 .gid = GNUTLS_EXTENSION_SRTP,
46 .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
47 GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
48 .client_parse_point = GNUTLS_EXT_APPLICATION,
49 .server_parse_point = GNUTLS_EXT_APPLICATION,
50 .recv_func = _gnutls_srtp_recv_params,
51 .send_func = _gnutls_srtp_send_params,
52 .pack_func = _gnutls_srtp_pack,
53 .unpack_func = _gnutls_srtp_unpack,
54 .deinit_func = _gnutls_srtp_deinit_data,
55 .cannot_be_overriden = 1
56 };
57
58 typedef struct {
59 const char *name;
60 gnutls_srtp_profile_t id;
61 unsigned int key_length;
62 unsigned int salt_length;
63 } srtp_profile_st;
64
65 static const srtp_profile_st profile_names[] = {
66 {
67 "SRTP_AES128_CM_HMAC_SHA1_80",
68 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_80,
69 16, 14},
70 {
71 "SRTP_AES128_CM_HMAC_SHA1_32",
72 GNUTLS_SRTP_AES128_CM_HMAC_SHA1_32,
73 16, 14},
74 {
75 "SRTP_NULL_HMAC_SHA1_80",
76 GNUTLS_SRTP_NULL_HMAC_SHA1_80,
77 16, 14},
78 {
79 "SRTP_NULL_SHA1_32",
80 GNUTLS_SRTP_NULL_HMAC_SHA1_32,
81 16, 14},
82 {
83 NULL,
84 0, 0, 0}
85 };
86
get_profile(gnutls_srtp_profile_t profile)87 static const srtp_profile_st *get_profile(gnutls_srtp_profile_t profile)
88 {
89 const srtp_profile_st *p = profile_names;
90 while (p->name != NULL) {
91 if (p->id == profile)
92 return p;
93 p++;
94 }
95 return NULL;
96 }
97
find_profile(const char * str,const char * end)98 static gnutls_srtp_profile_t find_profile(const char *str, const char *end)
99 {
100 const srtp_profile_st *prof = profile_names;
101 unsigned int len;
102 if (end != NULL) {
103 len = end - str;
104 } else {
105 len = strlen(str);
106 }
107
108 while (prof->name != NULL) {
109 if (strlen(prof->name) == len
110 && !strncmp(str, prof->name, len)) {
111 return prof->id;
112 }
113 prof++;
114 }
115 return 0;
116 }
117
118 /**
119 * gnutls_srtp_get_profile_id
120 * @name: The name of the profile to look up
121 * @profile: Will hold the profile id
122 *
123 * This function allows you to look up a profile based on a string.
124 *
125 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
126 * otherwise a negative error code is returned.
127 *
128 * Since 3.1.4
129 **/
gnutls_srtp_get_profile_id(const char * name,gnutls_srtp_profile_t * profile)130 int gnutls_srtp_get_profile_id(const char *name,
131 gnutls_srtp_profile_t * profile)
132 {
133 *profile = find_profile(name, NULL);
134 if (*profile == 0) {
135 return GNUTLS_E_ILLEGAL_PARAMETER;
136 }
137 return 0;
138 }
139
140 #define MAX_PROFILES_IN_SRTP_EXTENSION 256
141
142 /**
143 * gnutls_srtp_get_profile_name
144 * @profile: The profile to look up a string for
145 *
146 * This function allows you to get the corresponding name for a
147 * SRTP protection profile.
148 *
149 * Returns: On success, the name of a SRTP profile as a string,
150 * otherwise NULL.
151 *
152 * Since 3.1.4
153 **/
gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile)154 const char *gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile)
155 {
156 const srtp_profile_st *p = get_profile(profile);
157
158 if (p != NULL)
159 return p->name;
160
161 return NULL;
162 }
163
164 static int
_gnutls_srtp_recv_params(gnutls_session_t session,const uint8_t * data,size_t data_size)165 _gnutls_srtp_recv_params(gnutls_session_t session,
166 const uint8_t * data, size_t data_size)
167 {
168 unsigned int i;
169 int ret;
170 const uint8_t *p = data;
171 size_t len;
172 srtp_ext_st *priv;
173 gnutls_ext_priv_data_t epriv;
174 uint16_t profile;
175
176 ret =
177 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
178 &epriv);
179 if (ret < 0)
180 return 0;
181
182 priv = epriv;
183
184 DECR_LENGTH_RET(data_size, 2, 0);
185 len = _gnutls_read_uint16(p);
186 p += 2;
187
188 if (len + 1 > data_size)
189 return
190 gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
191
192 if (session->security_parameters.entity == GNUTLS_SERVER) {
193 if (len > MAX_PROFILES_IN_SRTP_EXTENSION * 2)
194 return 0;
195 } else {
196 if (len != 2)
197 return
198 gnutls_assert_val
199 (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
200 }
201
202 priv->selected_profile = 0;
203
204 while (len > 0) {
205 DECR_LEN(data_size, 2);
206 profile = _gnutls_read_uint16(p);
207
208 for (i = 0;
209 i < priv->profiles_size
210 && priv->selected_profile == 0; i++) {
211 if (priv->profiles[i] == profile) {
212 priv->selected_profile = profile;
213 break;
214 }
215 }
216 p += 2;
217 len -= 2;
218 }
219
220 DECR_LEN(data_size, 1);
221 priv->mki_size = *p;
222 p++;
223
224 if (priv->mki_size > 0) {
225 DECR_LEN(data_size, priv->mki_size);
226 memcpy(priv->mki, p, priv->mki_size);
227 priv->mki_received = 1;
228 }
229
230 return 0;
231 }
232
233 static int
_gnutls_srtp_send_params(gnutls_session_t session,gnutls_buffer_st * extdata)234 _gnutls_srtp_send_params(gnutls_session_t session,
235 gnutls_buffer_st * extdata)
236 {
237 unsigned i;
238 int total_size = 0, ret;
239 srtp_ext_st *priv;
240 gnutls_ext_priv_data_t epriv;
241
242 ret =
243 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
244 &epriv);
245 if (ret < 0)
246 return 0;
247
248 priv = epriv;
249
250 if (priv->profiles_size == 0)
251 return 0;
252
253 if (session->security_parameters.entity == GNUTLS_SERVER) {
254 /* Don't send anything if no matching profile was found */
255 if (priv->selected_profile == 0)
256 return 0;
257
258 ret = _gnutls_buffer_append_prefix(extdata, 16, 2);
259 if (ret < 0)
260 return gnutls_assert_val(ret);
261 ret =
262 _gnutls_buffer_append_prefix(extdata, 16,
263 priv->selected_profile);
264 if (ret < 0)
265 return gnutls_assert_val(ret);
266 total_size = 4;
267 } else {
268 ret =
269 _gnutls_buffer_append_prefix(extdata, 16,
270 2 * priv->profiles_size);
271 if (ret < 0)
272 return gnutls_assert_val(ret);
273
274 for (i = 0; i < priv->profiles_size; i++) {
275 ret =
276 _gnutls_buffer_append_prefix(extdata, 16,
277 priv->
278 profiles[i]);
279 if (ret < 0)
280 return gnutls_assert_val(ret);
281 }
282 total_size = 2 + 2 * priv->profiles_size;
283 }
284
285 /* use_mki */
286 ret =
287 _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki,
288 priv->mki_size);
289 if (ret < 0)
290 return gnutls_assert_val(ret);
291 total_size += 1 + priv->mki_size;
292
293 return total_size;
294 }
295
296 /**
297 * gnutls_srtp_get_selected_profile:
298 * @session: is a #gnutls_session_t type.
299 * @profile: will hold the profile
300 *
301 * This function allows you to get the negotiated SRTP profile.
302 *
303 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
304 * otherwise a negative error code is returned.
305 *
306 * Since 3.1.4
307 **/
308 int
gnutls_srtp_get_selected_profile(gnutls_session_t session,gnutls_srtp_profile_t * profile)309 gnutls_srtp_get_selected_profile(gnutls_session_t session,
310 gnutls_srtp_profile_t * profile)
311 {
312 srtp_ext_st *priv;
313 int ret;
314 gnutls_ext_priv_data_t epriv;
315
316 ret =
317 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
318 &epriv);
319 if (ret < 0) {
320 gnutls_assert();
321 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
322 }
323
324 priv = epriv;
325
326 if (priv->selected_profile == 0) {
327 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
328 }
329
330 *profile = priv->selected_profile;
331
332 return 0;
333 }
334
335 /**
336 * gnutls_srtp_get_mki:
337 * @session: is a #gnutls_session_t type.
338 * @mki: will hold the MKI
339 *
340 * This function exports the negotiated Master Key Identifier,
341 * received by the peer if any. The returned value in @mki should be
342 * treated as constant and valid only during the session's lifetime.
343 *
344 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
345 * otherwise a negative error code is returned.
346 *
347 * Since 3.1.4
348 **/
gnutls_srtp_get_mki(gnutls_session_t session,gnutls_datum_t * mki)349 int gnutls_srtp_get_mki(gnutls_session_t session, gnutls_datum_t * mki)
350 {
351 srtp_ext_st *priv;
352 int ret;
353 gnutls_ext_priv_data_t epriv;
354
355 ret =
356 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
357 &epriv);
358 if (ret < 0)
359 return
360 gnutls_assert_val
361 (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
362
363 priv = epriv;
364
365 if (priv->mki_received == 0)
366 return
367 gnutls_assert_val
368 (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
369
370 mki->data = priv->mki;
371 mki->size = priv->mki_size;
372
373 return 0;
374 }
375
376 /**
377 * gnutls_srtp_set_mki:
378 * @session: is a #gnutls_session_t type.
379 * @mki: holds the MKI
380 *
381 * This function sets the Master Key Identifier, to be
382 * used by this session (if any).
383 *
384 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
385 * otherwise a negative error code is returned.
386 *
387 * Since 3.1.4
388 **/
389 int
gnutls_srtp_set_mki(gnutls_session_t session,const gnutls_datum_t * mki)390 gnutls_srtp_set_mki(gnutls_session_t session, const gnutls_datum_t * mki)
391 {
392 int ret;
393 srtp_ext_st *priv;
394 gnutls_ext_priv_data_t epriv;
395
396 ret =
397 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
398 &epriv);
399 if (ret < 0) {
400 priv = gnutls_calloc(1, sizeof(*priv));
401 if (priv == NULL) {
402 gnutls_assert();
403 return GNUTLS_E_MEMORY_ERROR;
404 }
405 epriv = priv;
406 _gnutls_hello_ext_set_priv(session,
407 GNUTLS_EXTENSION_SRTP, epriv);
408 } else
409 priv = epriv;
410
411 if (mki->size > 0 && mki->size <= sizeof(priv->mki)) {
412 priv->mki_size = mki->size;
413 memcpy(priv->mki, mki->data, mki->size);
414 } else
415 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
416
417 return 0;
418 }
419
420 /**
421 * gnutls_srtp_set_profile:
422 * @session: is a #gnutls_session_t type.
423 * @profile: is the profile id to add.
424 *
425 * This function is to be used by both clients and servers, to declare
426 * what SRTP profiles they support, to negotiate with the peer.
427 *
428 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
429 * otherwise a negative error code is returned.
430 *
431 * Since 3.1.4
432 **/
433 int
gnutls_srtp_set_profile(gnutls_session_t session,gnutls_srtp_profile_t profile)434 gnutls_srtp_set_profile(gnutls_session_t session,
435 gnutls_srtp_profile_t profile)
436 {
437 int ret;
438 srtp_ext_st *priv;
439 gnutls_ext_priv_data_t epriv;
440
441 ret =
442 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
443 &epriv);
444 if (ret < 0) {
445 priv = gnutls_calloc(1, sizeof(*priv));
446 if (priv == NULL) {
447 gnutls_assert();
448 return GNUTLS_E_MEMORY_ERROR;
449 }
450 epriv = priv;
451 _gnutls_hello_ext_set_priv(session,
452 GNUTLS_EXTENSION_SRTP, epriv);
453 } else
454 priv = epriv;
455
456 if (priv->profiles_size < MAX_SRTP_PROFILES)
457 priv->profiles_size++;
458 priv->profiles[priv->profiles_size - 1] = profile;
459
460 return 0;
461 }
462
463 /**
464 * gnutls_srtp_set_profile_direct:
465 * @session: is a #gnutls_session_t type.
466 * @profiles: is a string that contains the supported SRTP profiles,
467 * separated by colons.
468 * @err_pos: In case of an error this will have the position in the string the error occurred, may be NULL.
469 *
470 * This function is to be used by both clients and servers, to declare
471 * what SRTP profiles they support, to negotiate with the peer.
472 *
473 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
474 * %GNUTLS_E_SUCCESS on success, or an error code.
475 *
476 * Since 3.1.4
477 **/
478 int
gnutls_srtp_set_profile_direct(gnutls_session_t session,const char * profiles,const char ** err_pos)479 gnutls_srtp_set_profile_direct(gnutls_session_t session,
480 const char *profiles, const char **err_pos)
481 {
482 int ret;
483 srtp_ext_st *priv;
484 gnutls_ext_priv_data_t epriv;
485 int set = 0;
486 const char *col;
487 gnutls_srtp_profile_t id;
488
489 ret =
490 _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP,
491 &epriv);
492 if (ret < 0) {
493 set = 1;
494 priv = gnutls_calloc(1, sizeof(*priv));
495 if (priv == NULL) {
496 if (err_pos != NULL)
497 *err_pos = profiles;
498 gnutls_assert();
499 return GNUTLS_E_MEMORY_ERROR;
500 }
501 epriv = priv;
502 } else
503 priv = epriv;
504
505 do {
506 col = strchr(profiles, ':');
507 id = find_profile(profiles, col);
508 if (id == 0) {
509 if (set != 0)
510 gnutls_free(priv);
511 if (err_pos != NULL)
512 *err_pos = profiles;
513 return GNUTLS_E_INVALID_REQUEST;
514 }
515
516 if (priv->profiles_size < MAX_SRTP_PROFILES) {
517 priv->profiles_size++;
518 }
519 priv->profiles[priv->profiles_size - 1] = id;
520 profiles = col + 1;
521 } while (col != NULL);
522
523 if (set != 0)
524 _gnutls_hello_ext_set_priv(session,
525 GNUTLS_EXTENSION_SRTP, epriv);
526
527 return 0;
528 }
529
530 /**
531 * gnutls_srtp_get_keys:
532 * @session: is a #gnutls_session_t type.
533 * @key_material: Space to hold the generated key material
534 * @key_material_size: The maximum size of the key material
535 * @client_key: The master client write key, pointing inside the key material
536 * @server_key: The master server write key, pointing inside the key material
537 * @client_salt: The master client write salt, pointing inside the key material
538 * @server_salt: The master server write salt, pointing inside the key material
539 *
540 * This is a helper function to generate the keying material for SRTP.
541 * It requires the space of the key material to be pre-allocated (should be at least
542 * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key
543 * and @server_salt are convenience datums that point inside the key material. They may
544 * be %NULL.
545 *
546 * Returns: On success the size of the key material is returned,
547 * otherwise, %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
548 * sufficient, or a negative error code.
549 *
550 * Since 3.1.4
551 **/
552 int
gnutls_srtp_get_keys(gnutls_session_t session,void * key_material,unsigned int key_material_size,gnutls_datum_t * client_key,gnutls_datum_t * client_salt,gnutls_datum_t * server_key,gnutls_datum_t * server_salt)553 gnutls_srtp_get_keys(gnutls_session_t session,
554 void *key_material,
555 unsigned int key_material_size,
556 gnutls_datum_t * client_key,
557 gnutls_datum_t * client_salt,
558 gnutls_datum_t * server_key,
559 gnutls_datum_t * server_salt)
560 {
561 int ret;
562 const srtp_profile_st *p;
563 gnutls_srtp_profile_t profile;
564 unsigned int msize;
565 uint8_t *km = key_material;
566
567 ret = gnutls_srtp_get_selected_profile(session, &profile);
568 if (ret < 0)
569 return gnutls_assert_val(ret);
570
571 p = get_profile(profile);
572 if (p == NULL)
573 return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
574
575 msize = 2 * (p->key_length + p->salt_length);
576 if (msize > key_material_size)
577 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
578
579 if (msize == 0)
580 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
581
582 ret =
583 gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp") - 1,
584 "EXTRACTOR-dtls_srtp", 0, 0, NULL, msize,
585 key_material);
586 if (ret < 0)
587 return gnutls_assert_val(ret);
588
589 if (client_key) {
590 client_key->data = km;
591 client_key->size = p->key_length;
592 }
593
594 if (server_key) {
595 server_key->data = km + p->key_length;
596 server_key->size = p->key_length;
597 }
598
599 if (client_salt) {
600 client_salt->data = km + 2 * p->key_length;
601 client_salt->size = p->salt_length;
602 }
603
604 if (server_salt) {
605 server_salt->data =
606 km + 2 * p->key_length + p->salt_length;
607 server_salt->size = p->salt_length;
608 }
609
610 return msize;
611 }
612
_gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv)613 static void _gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv)
614 {
615 gnutls_free(priv);
616 }
617
618 static int
_gnutls_srtp_pack(gnutls_ext_priv_data_t epriv,gnutls_buffer_st * ps)619 _gnutls_srtp_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps)
620 {
621 srtp_ext_st *priv = epriv;
622 unsigned int i;
623 int ret;
624
625 BUFFER_APPEND_NUM(ps, priv->profiles_size);
626 for (i = 0; i < priv->profiles_size; i++) {
627 BUFFER_APPEND_NUM(ps, priv->profiles[i]);
628 }
629
630 BUFFER_APPEND_NUM(ps, priv->mki_received);
631 if (priv->mki_received) {
632 BUFFER_APPEND_NUM(ps, priv->selected_profile);
633 BUFFER_APPEND_PFX4(ps, priv->mki, priv->mki_size);
634 }
635 return 0;
636 }
637
638 static int
_gnutls_srtp_unpack(gnutls_buffer_st * ps,gnutls_ext_priv_data_t * _priv)639 _gnutls_srtp_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv)
640 {
641 srtp_ext_st *priv;
642 unsigned int i;
643 int ret;
644 gnutls_ext_priv_data_t epriv;
645
646 priv = gnutls_calloc(1, sizeof(*priv));
647 if (priv == NULL) {
648 gnutls_assert();
649 return GNUTLS_E_MEMORY_ERROR;
650 }
651
652 BUFFER_POP_NUM(ps, priv->profiles_size);
653 for (i = 0; i < priv->profiles_size; i++) {
654 BUFFER_POP_NUM(ps, priv->profiles[i]);
655 }
656 BUFFER_POP_NUM(ps, priv->selected_profile);
657
658 BUFFER_POP_NUM(ps, priv->mki_received);
659 if (priv->mki_received) {
660 BUFFER_POP_NUM(ps, priv->mki_size);
661 BUFFER_POP(ps, priv->mki, priv->mki_size);
662 }
663
664 epriv = priv;
665 *_priv = epriv;
666
667 return 0;
668
669 error:
670 gnutls_free(priv);
671 return ret;
672 }
673