blob: 85b432829f727cf88b20ad1a978066c59c3f1930 [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <pjmedia/transport_srtp.h>
22#include <pjmedia/endpoint.h>
23#include <pjlib-util/base64.h>
24#include <pj/assert.h>
25#include <pj/ctype.h>
26#include <pj/lock.h>
27#include <pj/log.h>
28#include <pj/os.h>
29#include <pj/pool.h>
30
31#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
32
33#include <srtp.h>
34
35#define THIS_FILE "transport_srtp.c"
36
37/* Maximum size of outgoing packet */
38#define MAX_RTP_BUFFER_LEN PJMEDIA_MAX_MTU
39#define MAX_RTCP_BUFFER_LEN PJMEDIA_MAX_MTU
40
41/* Maximum SRTP crypto key length */
42#define MAX_KEY_LEN 128
43
44/* Initial value of probation counter. When probation counter > 0,
45 * it means SRTP is in probation state, and it may restart when
46 * srtp_unprotect() returns err_status_replay_*
47 */
48#define PROBATION_CNT_INIT 100
49
50#define DEACTIVATE_MEDIA(pool, m) pjmedia_sdp_media_deactivate(pool, m)
51
52static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
53static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
54static const pj_str_t ID_INACTIVE = { "inactive", 8 };
55static const pj_str_t ID_CRYPTO = { "crypto", 6 };
56
57typedef struct crypto_suite
58{
59 char *name;
60 cipher_type_id_t cipher_type;
61 unsigned cipher_key_len;
62 auth_type_id_t auth_type;
63 unsigned auth_key_len;
64 unsigned srtp_auth_tag_len;
65 unsigned srtcp_auth_tag_len;
66 sec_serv_t service;
67} crypto_suite;
68
69/* Crypto suites as defined on RFC 4568 */
70static crypto_suite crypto_suites[] = {
71 /* plain RTP/RTCP (no cipher & no auth) */
72 {"NULL", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none},
73
74 /* cipher AES_CM, auth HMAC_SHA1, auth tag len = 10 octets */
75 {"AES_CM_128_HMAC_SHA1_80", AES_128_ICM, 30, HMAC_SHA1, 20, 10, 10,
76 sec_serv_conf_and_auth},
77
78 /* cipher AES_CM, auth HMAC_SHA1, auth tag len = 4 octets */
79 {"AES_CM_128_HMAC_SHA1_32", AES_128_ICM, 30, HMAC_SHA1, 20, 4, 10,
80 sec_serv_conf_and_auth},
81
82 /*
83 * F8_128_HMAC_SHA1_8 not supported by libsrtp?
84 * {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none}
85 */
86};
87
88typedef struct transport_srtp
89{
90 pjmedia_transport base; /**< Base transport interface. */
91 pj_pool_t *pool; /**< Pool for transport SRTP. */
92 pj_lock_t *mutex; /**< Mutex for libsrtp contexts.*/
93 char rtp_tx_buffer[MAX_RTP_BUFFER_LEN];
94 char rtcp_tx_buffer[MAX_RTCP_BUFFER_LEN];
95 pjmedia_srtp_setting setting;
96 unsigned media_option;
97
98 /* SRTP policy */
99 pj_bool_t session_inited;
100 pj_bool_t offerer_side;
101 pj_bool_t bypass_srtp;
102 char tx_key[MAX_KEY_LEN];
103 char rx_key[MAX_KEY_LEN];
104 pjmedia_srtp_crypto tx_policy;
105 pjmedia_srtp_crypto rx_policy;
106
107 /* Temporary policy for negotiation */
108 pjmedia_srtp_crypto tx_policy_neg;
109 pjmedia_srtp_crypto rx_policy_neg;
110
111 /* libSRTP contexts */
112 srtp_t srtp_tx_ctx;
113 srtp_t srtp_rx_ctx;
114
115 /* Stream information */
116 void *user_data;
117 void (*rtp_cb)( void *user_data,
118 void *pkt,
119 pj_ssize_t size);
120 void (*rtcp_cb)(void *user_data,
121 void *pkt,
122 pj_ssize_t size);
123
124 /* Transport information */
125 pjmedia_transport *member_tp; /**< Underlying transport. */
126
127 /* SRTP usage policy of peer. This field is updated when media is starting.
128 * This is useful when SRTP is in optional mode and peer is using mandatory
129 * mode, so when local is about to reinvite/update, it should offer
130 * RTP/SAVP instead of offering RTP/AVP.
131 */
132 pjmedia_srtp_use peer_use;
133
134 /* When probation counter > 0, it means SRTP is in probation state,
135 * and it may restart when srtp_unprotect() returns err_status_replay_*
136 */
137 unsigned probation_cnt;
138} transport_srtp;
139
140
141/*
142 * This callback is called by transport when incoming rtp is received
143 */
144static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size);
145
146/*
147 * This callback is called by transport when incoming rtcp is received
148 */
149static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size);
150
151
152/*
153 * These are media transport operations.
154 */
155static pj_status_t transport_get_info (pjmedia_transport *tp,
156 pjmedia_transport_info *info);
157static pj_status_t transport_attach (pjmedia_transport *tp,
158 void *user_data,
159 const pj_sockaddr_t *rem_addr,
160 const pj_sockaddr_t *rem_rtcp,
161 unsigned addr_len,
162 void (*rtp_cb)(void*,
163 void*,
164 pj_ssize_t),
165 void (*rtcp_cb)(void*,
166 void*,
167 pj_ssize_t));
168static void transport_detach (pjmedia_transport *tp,
169 void *strm);
170static pj_status_t transport_send_rtp( pjmedia_transport *tp,
171 const void *pkt,
172 pj_size_t size);
173static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
174 const void *pkt,
175 pj_size_t size);
176static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
177 const pj_sockaddr_t *addr,
178 unsigned addr_len,
179 const void *pkt,
180 pj_size_t size);
181static pj_status_t transport_media_create(pjmedia_transport *tp,
182 pj_pool_t *sdp_pool,
183 unsigned options,
184 const pjmedia_sdp_session *sdp_remote,
185 unsigned media_index);
186static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
187 pj_pool_t *sdp_pool,
188 pjmedia_sdp_session *sdp_local,
189 const pjmedia_sdp_session *sdp_remote,
190 unsigned media_index);
191static pj_status_t transport_media_start (pjmedia_transport *tp,
192 pj_pool_t *pool,
193 const pjmedia_sdp_session *sdp_local,
194 const pjmedia_sdp_session *sdp_remote,
195 unsigned media_index);
196static pj_status_t transport_media_stop(pjmedia_transport *tp);
197static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
198 pjmedia_dir dir,
199 unsigned pct_lost);
200static pj_status_t transport_destroy (pjmedia_transport *tp);
201
202
203
204static pjmedia_transport_op transport_srtp_op =
205{
206 &transport_get_info,
207 &transport_attach,
208 &transport_detach,
209 &transport_send_rtp,
210 &transport_send_rtcp,
211 &transport_send_rtcp2,
212 &transport_media_create,
213 &transport_encode_sdp,
214 &transport_media_start,
215 &transport_media_stop,
216 &transport_simulate_lost,
217 &transport_destroy
218};
219
220/* This function may also be used by other module, e.g: pjmedia/errno.c,
221 * it should have C compatible declaration.
222 */
223PJ_BEGIN_DECL
224 const char* get_libsrtp_errstr(int err);
225PJ_END_DECL
226
227const char* get_libsrtp_errstr(int err)
228{
229#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
230 static char *liberr[] = {
231 "ok", /* err_status_ok = 0 */
232 "unspecified failure", /* err_status_fail = 1 */
233 "unsupported parameter", /* err_status_bad_param = 2 */
234 "couldn't allocate memory", /* err_status_alloc_fail = 3 */
235 "couldn't deallocate properly", /* err_status_dealloc_fail = 4 */
236 "couldn't initialize", /* err_status_init_fail = 5 */
237 "can't process as much data as requested",
238 /* err_status_terminus = 6 */
239 "authentication failure", /* err_status_auth_fail = 7 */
240 "cipher failure", /* err_status_cipher_fail = 8 */
241 "replay check failed (bad index)", /* err_status_replay_fail = 9 */
242 "replay check failed (index too old)",
243 /* err_status_replay_old = 10 */
244 "algorithm failed test routine", /* err_status_algo_fail = 11 */
245 "unsupported operation", /* err_status_no_such_op = 12 */
246 "no appropriate context found", /* err_status_no_ctx = 13 */
247 "unable to perform desired validation",
248 /* err_status_cant_check = 14 */
249 "can't use key any more", /* err_status_key_expired = 15 */
250 "error in use of socket", /* err_status_socket_err = 16 */
251 "error in use POSIX signals", /* err_status_signal_err = 17 */
252 "nonce check failed", /* err_status_nonce_bad = 18 */
253 "couldn't read data", /* err_status_read_fail = 19 */
254 "couldn't write data", /* err_status_write_fail = 20 */
255 "error pasring data", /* err_status_parse_err = 21 */
256 "error encoding data", /* err_status_encode_err = 22 */
257 "error while using semaphores", /* err_status_semaphore_err = 23 */
258 "error while using pfkey" /* err_status_pfkey_err = 24 */
259 };
260 if (err >= 0 && err < (int)PJ_ARRAY_SIZE(liberr)) {
261 return liberr[err];
262 } else {
263 static char msg[32];
264 pj_ansi_snprintf(msg, sizeof(msg), "Unknown libsrtp error %d", err);
265 return msg;
266 }
267#else
268 static char msg[32];
269 pj_ansi_snprintf(msg, sizeof(msg), "libsrtp error %d", err);
270 return msg;
271#endif
272}
273
274static pj_bool_t libsrtp_initialized;
275static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt);
276
277PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt)
278{
279 if (libsrtp_initialized == PJ_FALSE) {
280 err_status_t err;
281
282 err = srtp_init();
283 if (err != err_status_ok) {
284 PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s",
285 get_libsrtp_errstr(err)));
286 return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
287 }
288
289 if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS)
290 {
291 /* There will be memory leak when it fails to schedule libsrtp
292 * deinitialization, however the memory leak could be harmless,
293 * since in modern OS's memory used by an application is released
294 * when the application terminates.
295 */
296 PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit."));
297 }
298
299 libsrtp_initialized = PJ_TRUE;
300 }
301
302 return PJ_SUCCESS;
303}
304
305static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt)
306{
307 err_status_t err;
308
309 /* Note that currently this SRTP init/deinit is not equipped with
310 * reference counter, it should be safe as normally there is only
311 * one single instance of media endpoint and even if it isn't, the
312 * pjmedia_transport_srtp_create() will invoke SRTP init (the only
313 * drawback should be the delay described by #788).
314 */
315
316 PJ_UNUSED_ARG(endpt);
317
318 err = srtp_deinit();
319 if (err != err_status_ok) {
320 PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s",
321 get_libsrtp_errstr(err)));
322 }
323
324 libsrtp_initialized = PJ_FALSE;
325}
326
327
328static int get_crypto_idx(const pj_str_t* crypto_name)
329{
330 int i;
331 int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
332
333 /* treat unspecified crypto_name as crypto 'NULL' */
334 if (crypto_name->slen == 0)
335 return 0;
336
337 for (i=0; i<cs_cnt; ++i) {
338 if (!pj_stricmp2(crypto_name, crypto_suites[i].name))
339 return i;
340 }
341
342 return -1;
343}
344
345
346static int srtp_crypto_cmp(const pjmedia_srtp_crypto* c1,
347 const pjmedia_srtp_crypto* c2)
348{
349 int r;
350
351 r = pj_strcmp(&c1->key, &c2->key);
352 if (r != 0)
353 return r;
354
355 r = pj_stricmp(&c1->name, &c2->name);
356 if (r != 0)
357 return r;
358
359 return (c1->flags != c2->flags);
360}
361
362
363static pj_bool_t srtp_crypto_empty(const pjmedia_srtp_crypto* c)
364{
365 return (c->name.slen==0 || c->key.slen==0);
366}
367
368
369PJ_DEF(void) pjmedia_srtp_setting_default(pjmedia_srtp_setting *opt)
370{
371 unsigned i;
372
373 pj_assert(opt);
374
375 pj_bzero(opt, sizeof(pjmedia_srtp_setting));
376 opt->close_member_tp = PJ_TRUE;
377 opt->use = PJMEDIA_SRTP_OPTIONAL;
378
379 /* Copy default crypto-suites, but skip crypto 'NULL' */
380 opt->crypto_count = sizeof(crypto_suites)/sizeof(crypto_suites[0]) - 1;
381 for (i=0; i<opt->crypto_count; ++i)
382 opt->crypto[i].name = pj_str(crypto_suites[i+1].name);
383}
384
385
386/*
387 * Create an SRTP media transport.
388 */
389PJ_DEF(pj_status_t) pjmedia_transport_srtp_create(
390 pjmedia_endpt *endpt,
391 pjmedia_transport *tp,
392 const pjmedia_srtp_setting *opt,
393 pjmedia_transport **p_tp)
394{
395 pj_pool_t *pool;
396 transport_srtp *srtp;
397 pj_status_t status;
398 unsigned i;
399
400 PJ_ASSERT_RETURN(endpt && tp && p_tp, PJ_EINVAL);
401
402 /* Check crypto availability */
403 if (opt && opt->crypto_count == 0 &&
404 opt->use == PJMEDIA_SRTP_MANDATORY)
405 return PJMEDIA_SRTP_ESDPREQCRYPTO;
406
407 /* Check crypto */
408 if (opt && opt->use != PJMEDIA_SRTP_DISABLED) {
409 for (i=0; i < opt->crypto_count; ++i) {
410 int cs_idx = get_crypto_idx(&opt->crypto[i].name);
411
412 /* check crypto name */
413 if (cs_idx == -1)
414 return PJMEDIA_SRTP_ENOTSUPCRYPTO;
415
416 /* check key length */
417 if (opt->crypto[i].key.slen &&
418 opt->crypto[i].key.slen <
419 (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
420 return PJMEDIA_SRTP_EINKEYLEN;
421 }
422 }
423
424 /* Init libsrtp. */
425 status = pjmedia_srtp_init_lib(endpt);
426 if (status != PJ_SUCCESS)
427 return status;
428
429 pool = pjmedia_endpt_create_pool(endpt, "srtp%p", 1000, 1000);
430 srtp = PJ_POOL_ZALLOC_T(pool, transport_srtp);
431
432 srtp->pool = pool;
433 srtp->session_inited = PJ_FALSE;
434 srtp->bypass_srtp = PJ_FALSE;
435 srtp->probation_cnt = PROBATION_CNT_INIT;
436
437 if (opt) {
438 srtp->setting = *opt;
439 if (opt->use == PJMEDIA_SRTP_DISABLED)
440 srtp->setting.crypto_count = 0;
441
442 for (i=0; i < srtp->setting.crypto_count; ++i) {
443 int cs_idx = get_crypto_idx(&opt->crypto[i].name);
444 pj_str_t tmp_key = opt->crypto[i].key;
445
446 /* re-set crypto */
447 srtp->setting.crypto[i].name = pj_str(crypto_suites[cs_idx].name);
448 /* cut key length */
449 if (tmp_key.slen)
450 tmp_key.slen = crypto_suites[cs_idx].cipher_key_len;
451 pj_strdup(pool, &srtp->setting.crypto[i].key, &tmp_key);
452 }
453 } else {
454 pjmedia_srtp_setting_default(&srtp->setting);
455 }
456
457 status = pj_lock_create_recursive_mutex(pool, pool->obj_name, &srtp->mutex);
458 if (status != PJ_SUCCESS) {
459 pj_pool_release(pool);
460 return status;
461 }
462
463 /* Initialize base pjmedia_transport */
464 pj_memcpy(srtp->base.name, pool->obj_name, PJ_MAX_OBJ_NAME);
465 if (tp)
466 srtp->base.type = tp->type;
467 else
468 srtp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
469 srtp->base.op = &transport_srtp_op;
470
471 /* Set underlying transport */
472 srtp->member_tp = tp;
473
474 /* Initialize peer's SRTP usage mode. */
475 srtp->peer_use = srtp->setting.use;
476
477 /* Done */
478 *p_tp = &srtp->base;
479
480 return PJ_SUCCESS;
481}
482
483
484/*
485 * Initialize and start SRTP session with the given parameters.
486 */
487PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
488 pjmedia_transport *tp,
489 const pjmedia_srtp_crypto *tx,
490 const pjmedia_srtp_crypto *rx)
491{
492 transport_srtp *srtp = (transport_srtp*) tp;
493 srtp_policy_t tx_;
494 srtp_policy_t rx_;
495 err_status_t err;
496 int cr_tx_idx = 0;
497 int au_tx_idx = 0;
498 int cr_rx_idx = 0;
499 int au_rx_idx = 0;
500 int crypto_suites_cnt;
501 pj_status_t status = PJ_SUCCESS;
502
503 PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL);
504
505 pj_lock_acquire(srtp->mutex);
506
507 if (srtp->session_inited) {
508 pjmedia_transport_srtp_stop(tp);
509 }
510
511 crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
512
513 /* Get encryption and authentication method */
514 cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
515 if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
516 cr_tx_idx = 0;
517 if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
518 au_tx_idx = 0;
519
520 cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
521 if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
522 cr_rx_idx = 0;
523 if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
524 au_rx_idx = 0;
525
526 /* Check whether the crypto-suite requested is supported */
527 if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 ||
528 au_rx_idx == -1)
529 {
530 status = PJMEDIA_SRTP_ENOTSUPCRYPTO;
531 goto on_return;
532 }
533
534 /* If all options points to 'NULL' method, just bypass SRTP */
535 if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
536 srtp->bypass_srtp = PJ_TRUE;
537 goto on_return;
538 }
539
540 /* Check key length */
541 if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
542 rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
543 {
544 status = PJMEDIA_SRTP_EINKEYLEN;
545 goto on_return;
546 }
547
548 /* Init transmit direction */
549 pj_bzero(&tx_, sizeof(srtp_policy_t));
550 pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
551 if (cr_tx_idx && au_tx_idx)
552 tx_.rtp.sec_serv = sec_serv_conf_and_auth;
553 else if (cr_tx_idx)
554 tx_.rtp.sec_serv = sec_serv_conf;
555 else if (au_tx_idx)
556 tx_.rtp.sec_serv = sec_serv_auth;
557 else
558 tx_.rtp.sec_serv = sec_serv_none;
559 tx_.key = (uint8_t*)srtp->tx_key;
560 tx_.ssrc.type = ssrc_any_outbound;
561 tx_.ssrc.value = 0;
562 tx_.rtp.cipher_type = crypto_suites[cr_tx_idx].cipher_type;
563 tx_.rtp.cipher_key_len = crypto_suites[cr_tx_idx].cipher_key_len;
564 tx_.rtp.auth_type = crypto_suites[au_tx_idx].auth_type;
565 tx_.rtp.auth_key_len = crypto_suites[au_tx_idx].auth_key_len;
566 tx_.rtp.auth_tag_len = crypto_suites[au_tx_idx].srtp_auth_tag_len;
567 tx_.rtcp = tx_.rtp;
568 tx_.rtcp.auth_tag_len = crypto_suites[au_tx_idx].srtcp_auth_tag_len;
569 tx_.next = NULL;
570 err = srtp_create(&srtp->srtp_tx_ctx, &tx_);
571 if (err != err_status_ok) {
572 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
573 goto on_return;
574 }
575 srtp->tx_policy = *tx;
576 pj_strset(&srtp->tx_policy.key, srtp->tx_key, tx->key.slen);
577 srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name);
578
579
580 /* Init receive direction */
581 pj_bzero(&rx_, sizeof(srtp_policy_t));
582 pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
583 if (cr_rx_idx && au_rx_idx)
584 rx_.rtp.sec_serv = sec_serv_conf_and_auth;
585 else if (cr_rx_idx)
586 rx_.rtp.sec_serv = sec_serv_conf;
587 else if (au_rx_idx)
588 rx_.rtp.sec_serv = sec_serv_auth;
589 else
590 rx_.rtp.sec_serv = sec_serv_none;
591 rx_.key = (uint8_t*)srtp->rx_key;
592 rx_.ssrc.type = ssrc_any_inbound;
593 rx_.ssrc.value = 0;
594 rx_.rtp.sec_serv = crypto_suites[cr_rx_idx].service;
595 rx_.rtp.cipher_type = crypto_suites[cr_rx_idx].cipher_type;
596 rx_.rtp.cipher_key_len = crypto_suites[cr_rx_idx].cipher_key_len;
597 rx_.rtp.auth_type = crypto_suites[au_rx_idx].auth_type;
598 rx_.rtp.auth_key_len = crypto_suites[au_rx_idx].auth_key_len;
599 rx_.rtp.auth_tag_len = crypto_suites[au_rx_idx].srtp_auth_tag_len;
600 rx_.rtcp = rx_.rtp;
601 rx_.rtcp.auth_tag_len = crypto_suites[au_rx_idx].srtcp_auth_tag_len;
602 rx_.next = NULL;
603 err = srtp_create(&srtp->srtp_rx_ctx, &rx_);
604 if (err != err_status_ok) {
605 srtp_dealloc(srtp->srtp_tx_ctx);
606 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
607 goto on_return;
608 }
609 srtp->rx_policy = *rx;
610 pj_strset(&srtp->rx_policy.key, srtp->rx_key, rx->key.slen);
611 srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name);
612
613 /* Declare SRTP session initialized */
614 srtp->session_inited = PJ_TRUE;
615
616 /* Logging stuffs */
617#if PJ_LOG_MAX_LEVEL >= 5
618 {
619 char b64[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)];
620 int b64_len;
621
622 /* TX crypto and key */
623 b64_len = sizeof(b64);
624 status = pj_base64_encode((pj_uint8_t*)tx->key.ptr, tx->key.slen,
625 b64, &b64_len);
626 if (status != PJ_SUCCESS)
627 b64_len = pj_ansi_sprintf(b64, "--key too long--");
628 else
629 b64[b64_len] = '\0';
630
631 PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s",
632 srtp->tx_policy.name.ptr, b64));
633 if (srtp->tx_policy.flags) {
634 PJ_LOG(5,(srtp->pool->obj_name, "TX: disable%s%s",
635 (cr_tx_idx?"":" enc"),
636 (au_tx_idx?"":" auth")));
637 }
638
639 /* RX crypto and key */
640 b64_len = sizeof(b64);
641 status = pj_base64_encode((pj_uint8_t*)rx->key.ptr, rx->key.slen,
642 b64, &b64_len);
643 if (status != PJ_SUCCESS)
644 b64_len = pj_ansi_sprintf(b64, "--key too long--");
645 else
646 b64[b64_len] = '\0';
647
648 PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s",
649 srtp->rx_policy.name.ptr, b64));
650 if (srtp->rx_policy.flags) {
651 PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s",
652 (cr_rx_idx?"":" enc"),
653 (au_rx_idx?"":" auth")));
654 }
655 }
656#endif
657
658on_return:
659 pj_lock_release(srtp->mutex);
660 return status;
661}
662
663/*
664 * Stop SRTP session.
665 */
666PJ_DEF(pj_status_t) pjmedia_transport_srtp_stop(pjmedia_transport *srtp)
667{
668 transport_srtp *p_srtp = (transport_srtp*) srtp;
669 err_status_t err;
670
671 PJ_ASSERT_RETURN(srtp, PJ_EINVAL);
672
673 pj_lock_acquire(p_srtp->mutex);
674
675 if (!p_srtp->session_inited) {
676 pj_lock_release(p_srtp->mutex);
677 return PJ_SUCCESS;
678 }
679
680 err = srtp_dealloc(p_srtp->srtp_rx_ctx);
681 if (err != err_status_ok) {
682 PJ_LOG(4, (p_srtp->pool->obj_name,
683 "Failed to dealloc RX SRTP context: %s",
684 get_libsrtp_errstr(err)));
685 }
686 err = srtp_dealloc(p_srtp->srtp_tx_ctx);
687 if (err != err_status_ok) {
688 PJ_LOG(4, (p_srtp->pool->obj_name,
689 "Failed to dealloc TX SRTP context: %s",
690 get_libsrtp_errstr(err)));
691 }
692
693 p_srtp->session_inited = PJ_FALSE;
694 pj_bzero(&p_srtp->rx_policy, sizeof(p_srtp->rx_policy));
695 pj_bzero(&p_srtp->tx_policy, sizeof(p_srtp->tx_policy));
696
697 pj_lock_release(p_srtp->mutex);
698
699 return PJ_SUCCESS;
700}
701
702PJ_DEF(pjmedia_transport *) pjmedia_transport_srtp_get_member(
703 pjmedia_transport *tp)
704{
705 transport_srtp *srtp = (transport_srtp*) tp;
706
707 PJ_ASSERT_RETURN(tp, NULL);
708
709 return srtp->member_tp;
710}
711
712
713static pj_status_t transport_get_info(pjmedia_transport *tp,
714 pjmedia_transport_info *info)
715{
716 transport_srtp *srtp = (transport_srtp*) tp;
717 pjmedia_srtp_info srtp_info;
718 int spc_info_idx;
719
720 PJ_ASSERT_RETURN(tp && info, PJ_EINVAL);
721 PJ_ASSERT_RETURN(info->specific_info_cnt <
722 PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT, PJ_ETOOMANY);
723 PJ_ASSERT_RETURN(sizeof(pjmedia_srtp_info) <=
724 PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE, PJ_ENOMEM);
725
726 srtp_info.active = srtp->session_inited;
727 srtp_info.rx_policy = srtp->rx_policy;
728 srtp_info.tx_policy = srtp->tx_policy;
729 srtp_info.use = srtp->setting.use;
730 srtp_info.peer_use = srtp->peer_use;
731
732 spc_info_idx = info->specific_info_cnt++;
733 info->spc_info[spc_info_idx].type = PJMEDIA_TRANSPORT_TYPE_SRTP;
734 info->spc_info[spc_info_idx].cbsize = sizeof(srtp_info);
735 pj_memcpy(&info->spc_info[spc_info_idx].buffer, &srtp_info,
736 sizeof(srtp_info));
737
738 return pjmedia_transport_get_info(srtp->member_tp, info);
739}
740
741static pj_status_t transport_attach(pjmedia_transport *tp,
742 void *user_data,
743 const pj_sockaddr_t *rem_addr,
744 const pj_sockaddr_t *rem_rtcp,
745 unsigned addr_len,
746 void (*rtp_cb) (void*, void*,
747 pj_ssize_t),
748 void (*rtcp_cb)(void*, void*,
749 pj_ssize_t))
750{
751 transport_srtp *srtp = (transport_srtp*) tp;
752 pj_status_t status;
753
754 PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL);
755
756 /* Save the callbacks */
757 pj_lock_acquire(srtp->mutex);
758 srtp->rtp_cb = rtp_cb;
759 srtp->rtcp_cb = rtcp_cb;
760 srtp->user_data = user_data;
761 pj_lock_release(srtp->mutex);
762
763 /* Attach itself to transport */
764 status = pjmedia_transport_attach(srtp->member_tp, srtp, rem_addr,
765 rem_rtcp, addr_len, &srtp_rtp_cb,
766 &srtp_rtcp_cb);
767 if (status != PJ_SUCCESS) {
768 pj_lock_acquire(srtp->mutex);
769 srtp->rtp_cb = NULL;
770 srtp->rtcp_cb = NULL;
771 srtp->user_data = NULL;
772 pj_lock_release(srtp->mutex);
773 return status;
774 }
775
776 return PJ_SUCCESS;
777}
778
779static void transport_detach(pjmedia_transport *tp, void *strm)
780{
781 transport_srtp *srtp = (transport_srtp*) tp;
782
783 PJ_UNUSED_ARG(strm);
784 PJ_ASSERT_ON_FAIL(tp, return);
785
786 if (srtp->member_tp) {
787 pjmedia_transport_detach(srtp->member_tp, srtp);
788 }
789
790 /* Clear up application infos from transport */
791 pj_lock_acquire(srtp->mutex);
792 srtp->rtp_cb = NULL;
793 srtp->rtcp_cb = NULL;
794 srtp->user_data = NULL;
795 pj_lock_release(srtp->mutex);
796}
797
798static pj_status_t transport_send_rtp( pjmedia_transport *tp,
799 const void *pkt,
800 pj_size_t size)
801{
802 pj_status_t status;
803 transport_srtp *srtp = (transport_srtp*) tp;
804 int len = (int)size;
805 err_status_t err;
806
807 if (srtp->bypass_srtp)
808 return pjmedia_transport_send_rtp(srtp->member_tp, pkt, size);
809
810 if (size > sizeof(srtp->rtp_tx_buffer) - 10)
811 return PJ_ETOOBIG;
812
813 pj_memcpy(srtp->rtp_tx_buffer, pkt, size);
814
815 pj_lock_acquire(srtp->mutex);
816 if (!srtp->session_inited) {
817 pj_lock_release(srtp->mutex);
818 return PJ_EINVALIDOP;
819 }
820 err = srtp_protect(srtp->srtp_tx_ctx, srtp->rtp_tx_buffer, &len);
821 pj_lock_release(srtp->mutex);
822
823 if (err == err_status_ok) {
824 status = pjmedia_transport_send_rtp(srtp->member_tp,
825 srtp->rtp_tx_buffer, len);
826 } else {
827 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
828 }
829
830 return status;
831}
832
833static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
834 const void *pkt,
835 pj_size_t size)
836{
837 return transport_send_rtcp2(tp, NULL, 0, pkt, size);
838}
839
840static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
841 const pj_sockaddr_t *addr,
842 unsigned addr_len,
843 const void *pkt,
844 pj_size_t size)
845{
846 pj_status_t status;
847 transport_srtp *srtp = (transport_srtp*) tp;
848 int len = (int)size;
849 err_status_t err;
850
851 if (srtp->bypass_srtp) {
852 return pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len,
853 pkt, size);
854 }
855
856 if (size > sizeof(srtp->rtcp_tx_buffer) - 10)
857 return PJ_ETOOBIG;
858
859 pj_memcpy(srtp->rtcp_tx_buffer, pkt, size);
860
861 pj_lock_acquire(srtp->mutex);
862 if (!srtp->session_inited) {
863 pj_lock_release(srtp->mutex);
864 return PJ_EINVALIDOP;
865 }
866 err = srtp_protect_rtcp(srtp->srtp_tx_ctx, srtp->rtcp_tx_buffer, &len);
867 pj_lock_release(srtp->mutex);
868
869 if (err == err_status_ok) {
870 status = pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len,
871 srtp->rtcp_tx_buffer, len);
872 } else {
873 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
874 }
875
876 return status;
877}
878
879
880static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
881 pjmedia_dir dir,
882 unsigned pct_lost)
883{
884 transport_srtp *srtp = (transport_srtp *) tp;
885
886 PJ_ASSERT_RETURN(tp, PJ_EINVAL);
887
888 return pjmedia_transport_simulate_lost(srtp->member_tp, dir, pct_lost);
889}
890
891static pj_status_t transport_destroy (pjmedia_transport *tp)
892{
893 transport_srtp *srtp = (transport_srtp *) tp;
894 pj_status_t status;
895
896 PJ_ASSERT_RETURN(tp, PJ_EINVAL);
897
898 if (srtp->setting.close_member_tp && srtp->member_tp) {
899 pjmedia_transport_close(srtp->member_tp);
900 }
901
902 status = pjmedia_transport_srtp_stop(tp);
903
904 /* In case mutex is being acquired by other thread */
905 pj_lock_acquire(srtp->mutex);
906 pj_lock_release(srtp->mutex);
907
908 pj_lock_destroy(srtp->mutex);
909 pj_pool_release(srtp->pool);
910
911 return status;
912}
913
914/*
915 * This callback is called by transport when incoming rtp is received
916 */
917static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
918{
919 transport_srtp *srtp = (transport_srtp *) user_data;
920 int len = size;
921 err_status_t err;
922 void (*cb)(void*, void*, pj_ssize_t) = NULL;
923 void *cb_data = NULL;
924
925 if (srtp->bypass_srtp) {
926 srtp->rtp_cb(srtp->user_data, pkt, size);
927 return;
928 }
929
930 if (size < 0) {
931 return;
932 }
933
934 /* Make sure buffer is 32bit aligned */
935 PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );
936
937 if (srtp->probation_cnt > 0)
938 --srtp->probation_cnt;
939
940 pj_lock_acquire(srtp->mutex);
941
942 if (!srtp->session_inited) {
943 pj_lock_release(srtp->mutex);
944 return;
945 }
946 err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
947 if (srtp->probation_cnt > 0 &&
948 (err == err_status_replay_old || err == err_status_replay_fail))
949 {
950 /* Handle such condition that stream is updated (RTP seq is reinited
951 * & SRTP is restarted), but some old packets are still coming
952 * so SRTP is learning wrong RTP seq. While the newly inited RTP seq
953 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
954 * will return err_status_replay_*. Restarting SRTP can resolve this.
955 */
956 pjmedia_srtp_crypto tx, rx;
957 pj_status_t status;
958
959 tx = srtp->tx_policy;
960 rx = srtp->rx_policy;
961 status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
962 &tx, &rx);
963 if (status != PJ_SUCCESS) {
964 PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
965 get_libsrtp_errstr(err)));
966 } else if (!srtp->bypass_srtp) {
967 err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
968 }
969 }
970
971 if (err != err_status_ok) {
972 PJ_LOG(5,(srtp->pool->obj_name,
973 "Failed to unprotect SRTP, pkt size=%d, err=%s",
974 size, get_libsrtp_errstr(err)));
975 } else {
976 cb = srtp->rtp_cb;
977 cb_data = srtp->user_data;
978 }
979
980 pj_lock_release(srtp->mutex);
981
982 if (cb) {
983 (*cb)(cb_data, pkt, len);
984 }
985}
986
987/*
988 * This callback is called by transport when incoming rtcp is received
989 */
990static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size)
991{
992 transport_srtp *srtp = (transport_srtp *) user_data;
993 int len = size;
994 err_status_t err;
995 void (*cb)(void*, void*, pj_ssize_t) = NULL;
996 void *cb_data = NULL;
997
998 if (srtp->bypass_srtp) {
999 srtp->rtcp_cb(srtp->user_data, pkt, size);
1000 return;
1001 }
1002
1003 if (size < 0) {
1004 return;
1005 }
1006
1007 /* Make sure buffer is 32bit aligned */
1008 PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );
1009
1010 pj_lock_acquire(srtp->mutex);
1011
1012 if (!srtp->session_inited) {
1013 pj_lock_release(srtp->mutex);
1014 return;
1015 }
1016 err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
1017 if (err != err_status_ok) {
1018 PJ_LOG(5,(srtp->pool->obj_name,
1019 "Failed to unprotect SRTCP, pkt size=%d, err=%s",
1020 size, get_libsrtp_errstr(err)));
1021 } else {
1022 cb = srtp->rtcp_cb;
1023 cb_data = srtp->user_data;
1024 }
1025
1026 pj_lock_release(srtp->mutex);
1027
1028 if (cb) {
1029 (*cb)(cb_data, pkt, len);
1030 }
1031}
1032
1033/* Generate crypto attribute, including crypto key.
1034 * If crypto-suite chosen is crypto NULL, just return PJ_SUCCESS,
1035 * and set buffer_len = 0.
1036 */
1037static pj_status_t generate_crypto_attr_value(pj_pool_t *pool,
1038 char *buffer, int *buffer_len,
1039 pjmedia_srtp_crypto *crypto,
1040 int tag)
1041{
1042 pj_status_t status;
1043 int cs_idx = get_crypto_idx(&crypto->name);
1044 char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1];
1045 int b64_key_len = sizeof(b64_key);
1046 int print_len;
1047
1048 if (cs_idx == -1)
1049 return PJMEDIA_SRTP_ENOTSUPCRYPTO;
1050
1051 /* Crypto-suite NULL. */
1052 if (cs_idx == 0) {
1053 *buffer_len = 0;
1054 return PJ_SUCCESS;
1055 }
1056
1057 /* Generate key if not specified. */
1058 if (crypto->key.slen == 0) {
1059 pj_bool_t key_ok;
1060 char key[MAX_KEY_LEN];
1061 err_status_t err;
1062 unsigned i;
1063
1064 PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len,
1065 PJ_ETOOSMALL);
1066
1067 do {
1068 key_ok = PJ_TRUE;
1069
1070 err = crypto_get_random((unsigned char*)key,
1071 crypto_suites[cs_idx].cipher_key_len);
1072 if (err != err_status_ok) {
1073 PJ_LOG(5,(THIS_FILE, "Failed generating random key: %s",
1074 get_libsrtp_errstr(err)));
1075 return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
1076 }
1077 for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i)
1078 if (key[i] == 0) key_ok = PJ_FALSE;
1079
1080 } while (!key_ok);
1081 crypto->key.ptr = (char*)
1082 pj_pool_zalloc(pool,
1083 crypto_suites[cs_idx].cipher_key_len);
1084 pj_memcpy(crypto->key.ptr, key, crypto_suites[cs_idx].cipher_key_len);
1085 crypto->key.slen = crypto_suites[cs_idx].cipher_key_len;
1086 }
1087
1088 if (crypto->key.slen != (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
1089 return PJMEDIA_SRTP_EINKEYLEN;
1090
1091 /* Key transmitted via SDP should be base64 encoded. */
1092 status = pj_base64_encode((pj_uint8_t*)crypto->key.ptr, crypto->key.slen,
1093 b64_key, &b64_key_len);
1094 if (status != PJ_SUCCESS) {
1095 PJ_LOG(5,(THIS_FILE, "Failed encoding plain key to base64"));
1096 return status;
1097 }
1098
1099 b64_key[b64_key_len] = '\0';
1100
1101 PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \
1102 b64_key_len + 16), PJ_ETOOSMALL);
1103
1104 /* Print the crypto attribute value. */
1105 print_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s",
1106 tag,
1107 crypto_suites[cs_idx].name,
1108 b64_key);
1109 if (print_len < 1 || print_len >= *buffer_len)
1110 return PJ_ETOOSMALL;
1111
1112 *buffer_len = print_len;
1113
1114 return PJ_SUCCESS;
1115}
1116
1117/* Parse crypto attribute line */
1118static pj_status_t parse_attr_crypto(pj_pool_t *pool,
1119 const pjmedia_sdp_attr *attr,
1120 pjmedia_srtp_crypto *crypto,
1121 int *tag)
1122{
1123 pj_str_t input;
1124 char *token;
1125 pj_size_t token_len;
1126 pj_str_t tmp;
1127 pj_status_t status;
1128 int itmp;
1129
1130 pj_bzero(crypto, sizeof(*crypto));
1131 pj_strdup_with_null(pool, &input, &attr->value);
1132
1133 /* Tag */
1134 token = strtok(input.ptr, " ");
1135 if (!token) {
1136 PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag"));
1137 return PJMEDIA_SDP_EINATTR;
1138 }
1139 token_len = pj_ansi_strlen(token);
1140
1141 /* Tag must not use leading zeroes. */
1142 if (token_len > 1 && *token == '0')
1143 return PJMEDIA_SDP_EINATTR;
1144
1145 /* Tag must be decimal, i.e: contains only digit '0'-'9'. */
1146 for (itmp = 0; itmp < token_len; ++itmp)
1147 if (!pj_isdigit(token[itmp]))
1148 return PJMEDIA_SDP_EINATTR;
1149
1150 /* Get tag value. */
1151 *tag = atoi(token);
1152
1153 /* Crypto-suite */
1154 token = strtok(NULL, " ");
1155 if (!token) {
1156 PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite"));
1157 return PJMEDIA_SDP_EINATTR;
1158 }
1159 crypto->name = pj_str(token);
1160
1161 /* Key method */
1162 token = strtok(NULL, ":");
1163 if (!token) {
1164 PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method"));
1165 return PJMEDIA_SDP_EINATTR;
1166 }
1167 if (pj_ansi_stricmp(token, "inline")) {
1168 PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%s' not supported!",
1169 token));
1170 return PJMEDIA_SDP_EINATTR;
1171 }
1172
1173 /* Key */
1174 token = strtok(NULL, "| ");
1175 if (!token) {
1176 PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key"));
1177 return PJMEDIA_SDP_EINATTR;
1178 }
1179 tmp = pj_str(token);
1180 if (PJ_BASE64_TO_BASE256_LEN(tmp.slen) > MAX_KEY_LEN) {
1181 PJ_LOG(4,(THIS_FILE, "Key too long"));
1182 return PJMEDIA_SRTP_EINKEYLEN;
1183 }
1184
1185 /* Decode key */
1186 crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN);
1187 itmp = MAX_KEY_LEN;
1188 status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr,
1189 &itmp);
1190 if (status != PJ_SUCCESS) {
1191 PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64"));
1192 return status;
1193 }
1194 crypto->key.slen = itmp;
1195
1196 return PJ_SUCCESS;
1197}
1198
1199static pj_status_t transport_media_create(pjmedia_transport *tp,
1200 pj_pool_t *sdp_pool,
1201 unsigned options,
1202 const pjmedia_sdp_session *sdp_remote,
1203 unsigned media_index)
1204{
1205 struct transport_srtp *srtp = (struct transport_srtp*) tp;
1206 unsigned member_tp_option;
1207
1208 PJ_ASSERT_RETURN(tp, PJ_EINVAL);
1209
1210 pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg));
1211 pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg));
1212
1213 srtp->media_option = options;
1214 member_tp_option = options | PJMEDIA_TPMED_NO_TRANSPORT_CHECKING;
1215
1216 srtp->offerer_side = sdp_remote == NULL;
1217
1218 /* Validations */
1219 if (srtp->offerer_side) {
1220
1221 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED)
1222 goto BYPASS_SRTP;
1223
1224 } else {
1225
1226 pjmedia_sdp_media *m_rem;
1227
1228 m_rem = sdp_remote->media[media_index];
1229
1230 /* Nothing to do on inactive media stream */
1231 if (pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))
1232 goto BYPASS_SRTP;
1233
1234 /* Validate remote media transport based on SRTP usage option.
1235 */
1236 switch (srtp->setting.use) {
1237 case PJMEDIA_SRTP_DISABLED:
1238 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1239 return PJMEDIA_SRTP_ESDPINTRANSPORT;
1240 goto BYPASS_SRTP;
1241 case PJMEDIA_SRTP_OPTIONAL:
1242 break;
1243 case PJMEDIA_SRTP_MANDATORY:
1244 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)
1245 return PJMEDIA_SRTP_ESDPINTRANSPORT;
1246 break;
1247 }
1248
1249 }
1250 goto PROPAGATE_MEDIA_CREATE;
1251
1252BYPASS_SRTP:
1253 srtp->bypass_srtp = PJ_TRUE;
1254 member_tp_option &= ~PJMEDIA_TPMED_NO_TRANSPORT_CHECKING;
1255
1256PROPAGATE_MEDIA_CREATE:
1257 return pjmedia_transport_media_create(srtp->member_tp, sdp_pool,
1258 member_tp_option, sdp_remote,
1259 media_index);
1260}
1261
1262static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
1263 pj_pool_t *sdp_pool,
1264 pjmedia_sdp_session *sdp_local,
1265 const pjmedia_sdp_session *sdp_remote,
1266 unsigned media_index)
1267{
1268 struct transport_srtp *srtp = (struct transport_srtp*) tp;
1269 pjmedia_sdp_media *m_rem, *m_loc;
1270 enum { MAXLEN = 512 };
1271 char buffer[MAXLEN];
1272 int buffer_len;
1273 pj_status_t status;
1274 pjmedia_sdp_attr *attr;
1275 pj_str_t attr_value;
1276 unsigned i, j;
1277
1278 PJ_ASSERT_RETURN(tp && sdp_pool && sdp_local, PJ_EINVAL);
1279
1280 pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg));
1281 pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg));
1282
1283 srtp->offerer_side = sdp_remote == NULL;
1284
1285 m_rem = sdp_remote ? sdp_remote->media[media_index] : NULL;
1286 m_loc = sdp_local->media[media_index];
1287
1288 /* Bypass if media transport is not RTP/AVP or RTP/SAVP */
1289 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 &&
1290 pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0)
1291 goto BYPASS_SRTP;
1292
1293 /* If the media is inactive, do nothing. */
1294 /* No, we still need to process SRTP offer/answer even if the media is
1295 * marked as inactive, because the transport is still alive in this
1296 * case (e.g. for keep-alive). See:
1297 * http://trac.pjsip.org/repos/ticket/1079
1298 */
1299 /*
1300 if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) ||
1301 (m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL)))
1302 goto BYPASS_SRTP;
1303 */
1304
1305 /* Check remote media transport & set local media transport
1306 * based on SRTP usage option.
1307 */
1308 if (srtp->offerer_side) {
1309
1310 /* Generate transport */
1311 switch (srtp->setting.use) {
1312 case PJMEDIA_SRTP_DISABLED:
1313 goto BYPASS_SRTP;
1314 case PJMEDIA_SRTP_OPTIONAL:
1315 m_loc->desc.transport =
1316 (srtp->peer_use == PJMEDIA_SRTP_MANDATORY)?
1317 ID_RTP_SAVP : ID_RTP_AVP;
1318 break;
1319 case PJMEDIA_SRTP_MANDATORY:
1320 m_loc->desc.transport = ID_RTP_SAVP;
1321 break;
1322 }
1323
1324 /* Generate crypto attribute if not yet */
1325 if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) {
1326 for (i=0; i<srtp->setting.crypto_count; ++i) {
1327 /* Offer crypto-suites based on setting. */
1328 buffer_len = MAXLEN;
1329 status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len,
1330 &srtp->setting.crypto[i],
1331 i+1);
1332 if (status != PJ_SUCCESS)
1333 return status;
1334
1335 /* If buffer_len==0, just skip the crypto attribute. */
1336 if (buffer_len) {
1337 pj_strset(&attr_value, buffer, buffer_len);
1338 attr = pjmedia_sdp_attr_create(srtp->pool, ID_CRYPTO.ptr,
1339 &attr_value);
1340 m_loc->attr[m_loc->attr_count++] = attr;
1341 }
1342 }
1343 }
1344
1345 } else {
1346 /* Answerer side */
1347
1348 pj_assert(sdp_remote && m_rem);
1349
1350 /* Generate transport */
1351 switch (srtp->setting.use) {
1352 case PJMEDIA_SRTP_DISABLED:
1353 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1354 return PJMEDIA_SRTP_ESDPINTRANSPORT;
1355 goto BYPASS_SRTP;
1356 case PJMEDIA_SRTP_OPTIONAL:
1357 m_loc->desc.transport = m_rem->desc.transport;
1358 break;
1359 case PJMEDIA_SRTP_MANDATORY:
1360 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)
1361 return PJMEDIA_SRTP_ESDPINTRANSPORT;
1362 m_loc->desc.transport = ID_RTP_SAVP;
1363 break;
1364 }
1365
1366 /* Generate crypto attribute if not yet */
1367 if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) {
1368
1369 pjmedia_srtp_crypto tmp_rx_crypto;
1370 pj_bool_t has_crypto_attr = PJ_FALSE;
1371 int matched_idx = -1;
1372 int chosen_tag = 0;
1373 int tags[64]; /* assume no more than 64 crypto attrs in a media */
1374 unsigned cr_attr_count = 0;
1375
1376 /* Find supported crypto-suite, get the tag, and assign policy_local */
1377 for (i=0; i<m_rem->attr_count; ++i) {
1378 if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
1379 continue;
1380
1381 has_crypto_attr = PJ_TRUE;
1382
1383 status = parse_attr_crypto(srtp->pool, m_rem->attr[i],
1384 &tmp_rx_crypto, &tags[cr_attr_count]);
1385 if (status != PJ_SUCCESS)
1386 return status;
1387
1388 /* Check duplicated tag */
1389 for (j=0; j<cr_attr_count; ++j) {
1390 if (tags[j] == tags[cr_attr_count]) {
1391 DEACTIVATE_MEDIA(sdp_pool, m_loc);
1392 return PJMEDIA_SRTP_ESDPDUPCRYPTOTAG;
1393 }
1394 }
1395
1396 if (matched_idx == -1) {
1397 /* lets see if the crypto-suite offered is supported */
1398 for (j=0; j<srtp->setting.crypto_count; ++j)
1399 if (pj_stricmp(&tmp_rx_crypto.name,
1400 &srtp->setting.crypto[j].name) == 0)
1401 {
1402 int cs_idx = get_crypto_idx(&tmp_rx_crypto.name);
1403
1404 /* Force to use test key */
1405 /* bad keys for snom: */
1406 //char *hex_test_key = "58b29c5c8f42308120ce857e439f2d"
1407 // "7810a8b10ad0b1446be5470faea496";
1408 //char *hex_test_key = "20a26aac7ba062d356ff52b61e3993"
1409 // "ccb78078f12c64db94b9c294927fd0";
1410 //pj_str_t *test_key = &srtp->setting.crypto[j].key;
1411 //char *raw_test_key = pj_pool_zalloc(srtp->pool, 64);
1412 //hex_string_to_octet_string(
1413 // raw_test_key,
1414 // hex_test_key,
1415 // strlen(hex_test_key));
1416 //pj_strset(test_key, raw_test_key,
1417 // crypto_suites[cs_idx].cipher_key_len);
1418 /* EO Force to use test key */
1419
1420 if (tmp_rx_crypto.key.slen !=
1421 (int)crypto_suites[cs_idx].cipher_key_len)
1422 return PJMEDIA_SRTP_EINKEYLEN;
1423
1424 srtp->rx_policy_neg = tmp_rx_crypto;
1425 chosen_tag = tags[cr_attr_count];
1426 matched_idx = j;
1427 break;
1428 }
1429 }
1430 cr_attr_count++;
1431 }
1432
1433 /* Check crypto negotiation result */
1434 switch (srtp->setting.use) {
1435 case PJMEDIA_SRTP_DISABLED:
1436 pj_assert(!"Should never reach here");
1437 break;
1438
1439 case PJMEDIA_SRTP_OPTIONAL:
1440 /* bypass SRTP when no crypto-attr and remote uses RTP/AVP */
1441 if (!has_crypto_attr &&
1442 pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0)
1443 goto BYPASS_SRTP;
1444 /* bypass SRTP when nothing match and remote uses RTP/AVP */
1445 else if (matched_idx == -1 &&
1446 pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0)
1447 goto BYPASS_SRTP;
1448 break;
1449
1450 case PJMEDIA_SRTP_MANDATORY:
1451 /* Do nothing, intentional */
1452 break;
1453 }
1454
1455 /* No crypto attr */
1456 if (!has_crypto_attr) {
1457 DEACTIVATE_MEDIA(sdp_pool, m_loc);
1458 return PJMEDIA_SRTP_ESDPREQCRYPTO;
1459 }
1460
1461 /* No crypto match */
1462 if (matched_idx == -1) {
1463 DEACTIVATE_MEDIA(sdp_pool, m_loc);
1464 return PJMEDIA_SRTP_ENOTSUPCRYPTO;
1465 }
1466
1467 /* we have to generate crypto answer,
1468 * with srtp->tx_policy_neg matched the offer
1469 * and rem_tag contains matched offer tag.
1470 */
1471 buffer_len = MAXLEN;
1472 status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len,
1473 &srtp->setting.crypto[matched_idx],
1474 chosen_tag);
1475 if (status != PJ_SUCCESS)
1476 return status;
1477
1478 srtp->tx_policy_neg = srtp->setting.crypto[matched_idx];
1479
1480 /* If buffer_len==0, just skip the crypto attribute. */
1481 if (buffer_len) {
1482 pj_strset(&attr_value, buffer, buffer_len);
1483 attr = pjmedia_sdp_attr_create(sdp_pool, ID_CRYPTO.ptr,
1484 &attr_value);
1485 m_loc->attr[m_loc->attr_count++] = attr;
1486 }
1487
1488 /* At this point, we get valid rx_policy_neg & tx_policy_neg. */
1489 }
1490
1491 }
1492 goto PROPAGATE_MEDIA_CREATE;
1493
1494BYPASS_SRTP:
1495 /* Do not update this flag here as actually the media session hasn't been
1496 * updated.
1497 */
1498 //srtp->bypass_srtp = PJ_TRUE;
1499
1500PROPAGATE_MEDIA_CREATE:
1501 return pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool,
1502 sdp_local, sdp_remote, media_index);
1503}
1504
1505
1506
1507static pj_status_t transport_media_start(pjmedia_transport *tp,
1508 pj_pool_t *pool,
1509 const pjmedia_sdp_session *sdp_local,
1510 const pjmedia_sdp_session *sdp_remote,
1511 unsigned media_index)
1512{
1513 struct transport_srtp *srtp = (struct transport_srtp*) tp;
1514 pjmedia_sdp_media *m_rem, *m_loc;
1515 pj_status_t status;
1516 unsigned i;
1517
1518 PJ_ASSERT_RETURN(tp && pool && sdp_local && sdp_remote, PJ_EINVAL);
1519
1520 m_rem = sdp_remote->media[media_index];
1521 m_loc = sdp_local->media[media_index];
1522
1523 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1524 srtp->peer_use = PJMEDIA_SRTP_MANDATORY;
1525 else
1526 srtp->peer_use = PJMEDIA_SRTP_OPTIONAL;
1527
1528 /* For answerer side, this function will just have to start SRTP */
1529
1530 /* Check remote media transport & set local media transport
1531 * based on SRTP usage option.
1532 */
1533 if (srtp->offerer_side) {
1534 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
1535 if (pjmedia_sdp_media_find_attr(m_rem, &ID_CRYPTO, NULL)) {
1536 DEACTIVATE_MEDIA(pool, m_loc);
1537 return PJMEDIA_SRTP_ESDPINCRYPTO;
1538 }
1539 goto BYPASS_SRTP;
1540 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
1541 // Regardless the answer's transport type (RTP/AVP or RTP/SAVP),
1542 // the answer must be processed through in optional mode.
1543 // Please note that at this point transport type is ensured to be
1544 // RTP/AVP or RTP/SAVP, see transport_media_create()
1545 //if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) {
1546 //DEACTIVATE_MEDIA(pool, m_loc);
1547 //return PJMEDIA_SDP_EINPROTO;
1548 //}
1549 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
1550 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) {
1551 DEACTIVATE_MEDIA(pool, m_loc);
1552 return PJMEDIA_SDP_EINPROTO;
1553 }
1554 }
1555 }
1556
1557 if (srtp->offerer_side) {
1558 /* find supported crypto-suite, get the tag, and assign policy_local */
1559 pjmedia_srtp_crypto tmp_tx_crypto;
1560 pj_bool_t has_crypto_attr = PJ_FALSE;
1561 int rem_tag;
1562
1563 for (i=0; i<m_rem->attr_count; ++i) {
1564 if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
1565 continue;
1566
1567 /* more than one crypto attribute in media answer */
1568 if (has_crypto_attr) {
1569 DEACTIVATE_MEDIA(pool, m_loc);
1570 return PJMEDIA_SRTP_ESDPAMBIGUEANS;
1571 }
1572
1573 has_crypto_attr = PJ_TRUE;
1574
1575 status = parse_attr_crypto(srtp->pool, m_rem->attr[i],
1576 &tmp_tx_crypto, &rem_tag);
1577 if (status != PJ_SUCCESS)
1578 return status;
1579
1580
1581 /* our offer tag is always ordered by setting */
1582 if (rem_tag < 1 || rem_tag > (int)srtp->setting.crypto_count) {
1583 DEACTIVATE_MEDIA(pool, m_loc);
1584 return PJMEDIA_SRTP_ESDPINCRYPTOTAG;
1585 }
1586
1587 /* match the crypto name */
1588 if (pj_stricmp(&tmp_tx_crypto.name,
1589 &srtp->setting.crypto[rem_tag-1].name) != 0)
1590 {
1591 DEACTIVATE_MEDIA(pool, m_loc);
1592 return PJMEDIA_SRTP_ECRYPTONOTMATCH;
1593 }
1594
1595 srtp->tx_policy_neg = srtp->setting.crypto[rem_tag-1];
1596 srtp->rx_policy_neg = tmp_tx_crypto;
1597 }
1598
1599 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
1600 /* should never reach here */
1601 goto BYPASS_SRTP;
1602 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
1603 if (!has_crypto_attr)
1604 goto BYPASS_SRTP;
1605 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
1606 if (!has_crypto_attr) {
1607 DEACTIVATE_MEDIA(pool, m_loc);
1608 return PJMEDIA_SRTP_ESDPREQCRYPTO;
1609 }
1610 }
1611
1612 /* At this point, we get valid rx_policy_neg & tx_policy_neg. */
1613 }
1614
1615 /* Make sure we have the SRTP policies */
1616 if (srtp_crypto_empty(&srtp->tx_policy_neg) ||
1617 srtp_crypto_empty(&srtp->rx_policy_neg))
1618 {
1619 goto BYPASS_SRTP;
1620 }
1621
1622 /* Reset probation counts */
1623 srtp->probation_cnt = PROBATION_CNT_INIT;
1624
1625 /* Got policy_local & policy_remote, let's initalize the SRTP */
1626
1627 /* Ticket #1075: media_start() is called whenever media description
1628 * gets updated, e.g: call hold, however we should restart SRTP only
1629 * when the SRTP policy settings are updated.
1630 */
1631 if (srtp_crypto_cmp(&srtp->tx_policy_neg, &srtp->tx_policy) ||
1632 srtp_crypto_cmp(&srtp->rx_policy_neg, &srtp->rx_policy))
1633 {
1634 status = pjmedia_transport_srtp_start(tp,
1635 &srtp->tx_policy_neg,
1636 &srtp->rx_policy_neg);
1637 if (status != PJ_SUCCESS)
1638 return status;
1639 }
1640
1641 srtp->bypass_srtp = PJ_FALSE;
1642
1643 goto PROPAGATE_MEDIA_START;
1644
1645BYPASS_SRTP:
1646 srtp->bypass_srtp = PJ_TRUE;
1647 srtp->peer_use = PJMEDIA_SRTP_DISABLED;
1648 if (srtp->session_inited) {
1649 pjmedia_transport_srtp_stop(tp);
1650 }
1651
1652PROPAGATE_MEDIA_START:
1653 return pjmedia_transport_media_start(srtp->member_tp, pool,
1654 sdp_local, sdp_remote,
1655 media_index);
1656}
1657
1658static pj_status_t transport_media_stop(pjmedia_transport *tp)
1659{
1660 struct transport_srtp *srtp = (struct transport_srtp*) tp;
1661 pj_status_t status;
1662
1663 PJ_ASSERT_RETURN(tp, PJ_EINVAL);
1664
1665 status = pjmedia_transport_media_stop(srtp->member_tp);
1666 if (status != PJ_SUCCESS)
1667 PJ_LOG(4, (srtp->pool->obj_name,
1668 "SRTP failed stop underlying media transport."));
1669
1670 return pjmedia_transport_srtp_stop(tp);
1671}
1672
1673/* Utility */
1674PJ_DEF(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
1675 pj_bool_t is_rtp,
1676 void *pkt,
1677 int *pkt_len)
1678{
1679 transport_srtp *srtp = (transport_srtp *)tp;
1680 err_status_t err;
1681
1682 if (srtp->bypass_srtp)
1683 return PJ_SUCCESS;
1684
1685 PJ_ASSERT_RETURN(tp && pkt && (*pkt_len>0), PJ_EINVAL);
1686 PJ_ASSERT_RETURN(srtp->session_inited, PJ_EINVALIDOP);
1687
1688 /* Make sure buffer is 32bit aligned */
1689 PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return PJ_EINVAL);
1690
1691 pj_lock_acquire(srtp->mutex);
1692
1693 if (!srtp->session_inited) {
1694 pj_lock_release(srtp->mutex);
1695 return PJ_EINVALIDOP;
1696 }
1697
1698 if (is_rtp)
1699 err = srtp_unprotect(srtp->srtp_rx_ctx, pkt, pkt_len);
1700 else
1701 err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len);
1702
1703 if (err != err_status_ok) {
1704 PJ_LOG(5,(srtp->pool->obj_name,
1705 "Failed to unprotect SRTP, pkt size=%d, err=%s",
1706 *pkt_len, get_libsrtp_errstr(err)));
1707 }
1708
1709 pj_lock_release(srtp->mutex);
1710
1711 return (err==err_status_ok) ? PJ_SUCCESS : PJMEDIA_ERRNO_FROM_LIBSRTP(err);
1712}
1713
1714#endif
1715
1716