1
/* $Id: transport_srtp.c 2891 2009-08-17 15:17:36Z bennylp $ */
3
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
* Additional permission under GNU GPL version 3 section 7:
22
* If you modify this program, or any covered work, by linking or
23
* combining it with the OpenSSL project's OpenSSL library (or a
24
* modified version of that library), containing parts covered by the
25
* terms of the OpenSSL or SSLeay licenses, Teluu Inc. (http://www.teluu.com)
26
* grants you additional permission to convey the resulting work.
27
* Corresponding Source for a non-source form of such a combination
28
* shall include the source code for the parts of OpenSSL used as well
29
* as that of the covered work.
32
#include <pjmedia/transport_srtp.h>
33
#include <pjmedia/endpoint.h>
34
#include <pjlib-util/base64.h>
35
#include <pj/assert.h>
42
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
46
#define THIS_FILE "transport_srtp.c"
48
/* Maximum size of packet */
49
#define MAX_RTP_BUFFER_LEN 1500
50
#define MAX_RTCP_BUFFER_LEN 1500
51
#define MAX_KEY_LEN 32
53
/* Initial value of probation counter. When probation counter > 0,
54
* it means SRTP is in probation state, and it may restart when
55
* srtp_unprotect() returns err_status_replay_*
57
#define PROBATION_CNT_INIT 100
59
#define DEACTIVATE_MEDIA(pool, m) pjmedia_sdp_media_deactivate(pool, m)
61
static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
62
static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
63
static const pj_str_t ID_INACTIVE = { "inactive", 8 };
64
static const pj_str_t ID_CRYPTO = { "crypto", 6 };
66
typedef struct crypto_suite
69
cipher_type_id_t cipher_type;
70
unsigned cipher_key_len;
71
auth_type_id_t auth_type;
72
unsigned auth_key_len;
73
unsigned srtp_auth_tag_len;
74
unsigned srtcp_auth_tag_len;
78
/* Crypto suites as defined on RFC 4568 */
79
static crypto_suite crypto_suites[] = {
80
/* plain RTP/RTCP (no cipher & no auth) */
81
{"NULL", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none},
83
/* cipher AES_CM, auth HMAC_SHA1, auth tag len = 10 octets */
84
{"AES_CM_128_HMAC_SHA1_80", AES_128_ICM, 30, HMAC_SHA1, 20, 10, 10,
85
sec_serv_conf_and_auth},
87
/* cipher AES_CM, auth HMAC_SHA1, auth tag len = 4 octets */
88
{"AES_CM_128_HMAC_SHA1_32", AES_128_ICM, 30, HMAC_SHA1, 20, 4, 10,
89
sec_serv_conf_and_auth},
92
* F8_128_HMAC_SHA1_8 not supported by libsrtp?
93
* {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none}
97
typedef struct transport_srtp
99
pjmedia_transport base; /**< Base transport interface. */
100
pj_pool_t *pool; /**< Pool for transport SRTP. */
101
pj_lock_t *mutex; /**< Mutex for libsrtp contexts.*/
102
char rtp_tx_buffer[MAX_RTP_BUFFER_LEN];
103
char rtcp_tx_buffer[MAX_RTCP_BUFFER_LEN];
104
pjmedia_srtp_setting setting;
105
unsigned media_option;
108
pj_bool_t session_inited;
109
pj_bool_t offerer_side;
110
pj_bool_t bypass_srtp;
111
char tx_key[MAX_KEY_LEN];
112
char rx_key[MAX_KEY_LEN];
113
pjmedia_srtp_crypto tx_policy;
114
pjmedia_srtp_crypto rx_policy;
116
/* Temporary policy for negotiation */
117
pjmedia_srtp_crypto tx_policy_neg;
118
pjmedia_srtp_crypto rx_policy_neg;
120
/* libSRTP contexts */
124
/* Stream information */
126
void (*rtp_cb)( void *user_data,
129
void (*rtcp_cb)(void *user_data,
133
/* Transport information */
134
pjmedia_transport *member_tp; /**< Underlying transport. */
136
/* SRTP usage policy of peer. This field is updated when media is starting.
137
* This is useful when SRTP is in optional mode and peer is using mandatory
138
* mode, so when local is about to reinvite/update, it should offer
139
* RTP/SAVP instead of offering RTP/AVP.
141
pjmedia_srtp_use peer_use;
143
/* When probation counter > 0, it means SRTP is in probation state,
144
* and it may restart when srtp_unprotect() returns err_status_replay_*
146
unsigned probation_cnt;
151
* This callback is called by transport when incoming rtp is received
153
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size);
156
* This callback is called by transport when incoming rtcp is received
158
static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size);
162
* These are media transport operations.
164
static pj_status_t transport_get_info (pjmedia_transport *tp,
165
pjmedia_transport_info *info);
166
static pj_status_t transport_attach (pjmedia_transport *tp,
168
const pj_sockaddr_t *rem_addr,
169
const pj_sockaddr_t *rem_rtcp,
171
void (*rtp_cb)(void*,
174
void (*rtcp_cb)(void*,
177
static void transport_detach (pjmedia_transport *tp,
179
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
182
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
185
static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
186
const pj_sockaddr_t *addr,
190
static pj_status_t transport_media_create(pjmedia_transport *tp,
193
const pjmedia_sdp_session *sdp_remote,
194
unsigned media_index);
195
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
197
pjmedia_sdp_session *sdp_local,
198
const pjmedia_sdp_session *sdp_remote,
199
unsigned media_index);
200
static pj_status_t transport_media_start (pjmedia_transport *tp,
202
const pjmedia_sdp_session *sdp_local,
203
const pjmedia_sdp_session *sdp_remote,
204
unsigned media_index);
205
static pj_status_t transport_media_stop(pjmedia_transport *tp);
206
static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
209
static pj_status_t transport_destroy (pjmedia_transport *tp);
213
static pjmedia_transport_op transport_srtp_op =
219
&transport_send_rtcp,
220
&transport_send_rtcp2,
221
&transport_media_create,
222
&transport_encode_sdp,
223
&transport_media_start,
224
&transport_media_stop,
225
&transport_simulate_lost,
229
/* This function may also be used by other module, e.g: pjmedia/errno.c,
230
* it should have C compatible declaration.
233
const char* get_libsrtp_errstr(int err);
236
const char* get_libsrtp_errstr(int err)
238
#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
239
static char *liberr[] = {
240
"ok", /* err_status_ok = 0 */
241
"unspecified failure", /* err_status_fail = 1 */
242
"unsupported parameter", /* err_status_bad_param = 2 */
243
"couldn't allocate memory", /* err_status_alloc_fail = 3 */
244
"couldn't deallocate properly", /* err_status_dealloc_fail = 4 */
245
"couldn't initialize", /* err_status_init_fail = 5 */
246
"can't process as much data as requested",
247
/* err_status_terminus = 6 */
248
"authentication failure", /* err_status_auth_fail = 7 */
249
"cipher failure", /* err_status_cipher_fail = 8 */
250
"replay check failed (bad index)", /* err_status_replay_fail = 9 */
251
"replay check failed (index too old)",
252
/* err_status_replay_old = 10 */
253
"algorithm failed test routine", /* err_status_algo_fail = 11 */
254
"unsupported operation", /* err_status_no_such_op = 12 */
255
"no appropriate context found", /* err_status_no_ctx = 13 */
256
"unable to perform desired validation",
257
/* err_status_cant_check = 14 */
258
"can't use key any more", /* err_status_key_expired = 15 */
259
"error in use of socket", /* err_status_socket_err = 16 */
260
"error in use POSIX signals", /* err_status_signal_err = 17 */
261
"nonce check failed", /* err_status_nonce_bad = 18 */
262
"couldn't read data", /* err_status_read_fail = 19 */
263
"couldn't write data", /* err_status_write_fail = 20 */
264
"error pasring data", /* err_status_parse_err = 21 */
265
"error encoding data", /* err_status_encode_err = 22 */
266
"error while using semaphores", /* err_status_semaphore_err = 23 */
267
"error while using pfkey" /* err_status_pfkey_err = 24 */
269
if (err >= 0 && err < (int)PJ_ARRAY_SIZE(liberr)) {
273
pj_ansi_snprintf(msg, sizeof(msg), "Unknown libsrtp error %d", err);
278
pj_ansi_snprintf(msg, sizeof(msg), "libsrtp error %d", err);
283
static pj_bool_t libsrtp_initialized;
284
static void pjmedia_srtp_deinit_lib(void);
286
PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
288
if (libsrtp_initialized == PJ_FALSE) {
292
if (err != err_status_ok) {
293
PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s",
294
get_libsrtp_errstr(err)));
295
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
298
if (pj_atexit(pjmedia_srtp_deinit_lib) != PJ_SUCCESS) {
299
/* There will be memory leak when it fails to schedule libsrtp
300
* deinitialization, however the memory leak could be harmless,
301
* since in modern OS's memory used by an application is released
302
* when the application terminates.
304
PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit."));
307
libsrtp_initialized = PJ_TRUE;
313
static void pjmedia_srtp_deinit_lib(void)
318
if (err != err_status_ok) {
319
PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s",
320
get_libsrtp_errstr(err)));
323
libsrtp_initialized = PJ_FALSE;
326
static int get_crypto_idx(const pj_str_t* crypto_name)
329
int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
331
/* treat unspecified crypto_name as crypto 'NULL' */
332
if (crypto_name->slen == 0)
335
for (i=0; i<cs_cnt; ++i) {
336
if (!pj_stricmp2(crypto_name, crypto_suites[i].name))
343
PJ_DEF(void) pjmedia_srtp_setting_default(pjmedia_srtp_setting *opt)
349
pj_bzero(opt, sizeof(pjmedia_srtp_setting));
350
opt->close_member_tp = PJ_TRUE;
351
opt->use = PJMEDIA_SRTP_OPTIONAL;
353
/* Copy default crypto-suites, but skip crypto 'NULL' */
354
opt->crypto_count = sizeof(crypto_suites)/sizeof(crypto_suites[0]) - 1;
355
for (i=0; i<opt->crypto_count; ++i)
356
opt->crypto[i].name = pj_str(crypto_suites[i+1].name);
361
* Create an SRTP media transport.
363
PJ_DEF(pj_status_t) pjmedia_transport_srtp_create(
364
pjmedia_endpt *endpt,
365
pjmedia_transport *tp,
366
const pjmedia_srtp_setting *opt,
367
pjmedia_transport **p_tp)
370
transport_srtp *srtp;
374
PJ_ASSERT_RETURN(endpt && tp && p_tp, PJ_EINVAL);
376
/* Check crypto availability */
377
if (opt && opt->crypto_count == 0 &&
378
opt->use == PJMEDIA_SRTP_MANDATORY)
379
return PJMEDIA_SRTP_ESDPREQCRYPTO;
382
if (opt && opt->use != PJMEDIA_SRTP_DISABLED) {
383
for (i=0; i < opt->crypto_count; ++i) {
384
int cs_idx = get_crypto_idx(&opt->crypto[i].name);
386
/* check crypto name */
388
return PJMEDIA_SRTP_ENOTSUPCRYPTO;
390
/* check key length */
391
if (opt->crypto[i].key.slen &&
392
opt->crypto[i].key.slen <
393
(pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
394
return PJMEDIA_SRTP_EINKEYLEN;
399
status = pjmedia_srtp_init_lib();
400
if (status != PJ_SUCCESS)
403
pool = pjmedia_endpt_create_pool(endpt, "srtp%p", 1000, 1000);
404
srtp = PJ_POOL_ZALLOC_T(pool, transport_srtp);
407
srtp->session_inited = PJ_FALSE;
408
srtp->bypass_srtp = PJ_FALSE;
409
srtp->probation_cnt = PROBATION_CNT_INIT;
412
srtp->setting = *opt;
413
if (opt->use == PJMEDIA_SRTP_DISABLED)
414
srtp->setting.crypto_count = 0;
416
for (i=0; i < srtp->setting.crypto_count; ++i) {
417
int cs_idx = get_crypto_idx(&opt->crypto[i].name);
418
pj_str_t tmp_key = opt->crypto[i].key;
421
srtp->setting.crypto[i].name = pj_str(crypto_suites[cs_idx].name);
424
tmp_key.slen = crypto_suites[cs_idx].cipher_key_len;
425
pj_strdup(pool, &srtp->setting.crypto[i].key, &tmp_key);
428
pjmedia_srtp_setting_default(&srtp->setting);
431
status = pj_lock_create_recursive_mutex(pool, pool->obj_name, &srtp->mutex);
432
if (status != PJ_SUCCESS) {
433
pj_pool_release(pool);
437
/* Initialize base pjmedia_transport */
438
pj_memcpy(srtp->base.name, pool->obj_name, PJ_MAX_OBJ_NAME);
440
srtp->base.type = tp->type;
442
srtp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
443
srtp->base.op = &transport_srtp_op;
445
/* Set underlying transport */
446
srtp->member_tp = tp;
448
/* Initialize peer's SRTP usage mode. */
449
srtp->peer_use = srtp->setting.use;
459
* Initialize and start SRTP session with the given parameters.
461
PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
462
pjmedia_transport *tp,
463
const pjmedia_srtp_crypto *tx,
464
const pjmedia_srtp_crypto *rx)
466
transport_srtp *srtp = (transport_srtp*) tp;
474
int crypto_suites_cnt;
476
PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL);
478
if (srtp->session_inited) {
479
pjmedia_transport_srtp_stop(tp);
482
crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
484
/* Get encryption and authentication method */
485
cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
486
if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
488
if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
491
cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
492
if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
494
if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
497
/* Check whether the crypto-suite requested is supported */
498
if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 ||
500
return PJMEDIA_SRTP_ENOTSUPCRYPTO;
502
/* If all options points to 'NULL' method, just bypass SRTP */
503
if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
504
srtp->bypass_srtp = PJ_TRUE;
508
/* Check key length */
509
if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
510
rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
511
return PJMEDIA_SRTP_EINKEYLEN;
513
/* Init transmit direction */
514
pj_bzero(&tx_, sizeof(srtp_policy_t));
515
pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
516
if (cr_tx_idx && au_tx_idx)
517
tx_.rtp.sec_serv = sec_serv_conf_and_auth;
519
tx_.rtp.sec_serv = sec_serv_conf;
521
tx_.rtp.sec_serv = sec_serv_auth;
523
tx_.rtp.sec_serv = sec_serv_none;
524
tx_.key = (uint8_t*)srtp->tx_key;
525
tx_.ssrc.type = ssrc_any_outbound;
527
tx_.rtp.cipher_type = crypto_suites[cr_tx_idx].cipher_type;
528
tx_.rtp.cipher_key_len = crypto_suites[cr_tx_idx].cipher_key_len;
529
tx_.rtp.auth_type = crypto_suites[au_tx_idx].auth_type;
530
tx_.rtp.auth_key_len = crypto_suites[au_tx_idx].auth_key_len;
531
tx_.rtp.auth_tag_len = crypto_suites[au_tx_idx].srtp_auth_tag_len;
533
tx_.rtcp.auth_tag_len = crypto_suites[au_tx_idx].srtcp_auth_tag_len;
535
err = srtp_create(&srtp->srtp_tx_ctx, &tx_);
536
if (err != err_status_ok) {
537
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
539
srtp->tx_policy = *tx;
540
pj_strset(&srtp->tx_policy.key, srtp->tx_key, tx->key.slen);
541
srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name);
544
/* Init receive direction */
545
pj_bzero(&rx_, sizeof(srtp_policy_t));
546
pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
547
if (cr_rx_idx && au_rx_idx)
548
rx_.rtp.sec_serv = sec_serv_conf_and_auth;
550
rx_.rtp.sec_serv = sec_serv_conf;
552
rx_.rtp.sec_serv = sec_serv_auth;
554
rx_.rtp.sec_serv = sec_serv_none;
555
rx_.key = (uint8_t*)srtp->rx_key;
556
rx_.ssrc.type = ssrc_any_inbound;
558
rx_.rtp.sec_serv = crypto_suites[cr_rx_idx].service;
559
rx_.rtp.cipher_type = crypto_suites[cr_rx_idx].cipher_type;
560
rx_.rtp.cipher_key_len = crypto_suites[cr_rx_idx].cipher_key_len;
561
rx_.rtp.auth_type = crypto_suites[au_rx_idx].auth_type;
562
rx_.rtp.auth_key_len = crypto_suites[au_rx_idx].auth_key_len;
563
rx_.rtp.auth_tag_len = crypto_suites[au_rx_idx].srtp_auth_tag_len;
565
rx_.rtcp.auth_tag_len = crypto_suites[au_rx_idx].srtcp_auth_tag_len;
567
err = srtp_create(&srtp->srtp_rx_ctx, &rx_);
568
if (err != err_status_ok) {
569
srtp_dealloc(srtp->srtp_tx_ctx);
570
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
572
srtp->rx_policy = *rx;
573
pj_strset(&srtp->rx_policy.key, srtp->rx_key, rx->key.slen);
574
srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name);
576
/* Declare SRTP session initialized */
577
srtp->session_inited = PJ_TRUE;
579
PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", srtp->tx_policy.name.ptr,
580
octet_string_hex_string(tx->key.ptr, tx->key.slen)));
581
if (srtp->tx_policy.flags) {
582
PJ_LOG(5,(srtp->pool->obj_name,"TX: disable%s%s", (cr_tx_idx?"":" enc"),
583
(au_tx_idx?"":" auth")));
586
PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s", srtp->rx_policy.name.ptr,
587
octet_string_hex_string(rx->key.ptr, rx->key.slen)));
588
if (srtp->rx_policy.flags) {
589
PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s", (cr_rx_idx?"":" enc"),
590
(au_rx_idx?"":" auth")));
599
PJ_DEF(pj_status_t) pjmedia_transport_srtp_stop(pjmedia_transport *srtp)
601
transport_srtp *p_srtp = (transport_srtp*) srtp;
604
PJ_ASSERT_RETURN(srtp, PJ_EINVAL);
606
if (!p_srtp->session_inited)
609
err = srtp_dealloc(p_srtp->srtp_rx_ctx);
610
if (err != err_status_ok) {
611
PJ_LOG(4, (p_srtp->pool->obj_name,
612
"Failed to dealloc RX SRTP context: %s",
613
get_libsrtp_errstr(err)));
615
err = srtp_dealloc(p_srtp->srtp_tx_ctx);
616
if (err != err_status_ok) {
617
PJ_LOG(4, (p_srtp->pool->obj_name,
618
"Failed to dealloc TX SRTP context: %s",
619
get_libsrtp_errstr(err)));
622
p_srtp->session_inited = PJ_FALSE;
627
PJ_DEF(pjmedia_transport *) pjmedia_transport_srtp_get_member(
628
pjmedia_transport *tp)
630
transport_srtp *srtp = (transport_srtp*) tp;
632
PJ_ASSERT_RETURN(tp, NULL);
634
return srtp->member_tp;
638
static pj_status_t transport_get_info(pjmedia_transport *tp,
639
pjmedia_transport_info *info)
641
transport_srtp *srtp = (transport_srtp*) tp;
642
pjmedia_srtp_info srtp_info;
645
PJ_ASSERT_RETURN(tp && info, PJ_EINVAL);
646
PJ_ASSERT_RETURN(info->specific_info_cnt <
647
PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT, PJ_ETOOMANY);
648
PJ_ASSERT_RETURN(sizeof(pjmedia_srtp_info) <=
649
PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE, PJ_ENOMEM);
651
srtp_info.active = srtp->session_inited;
652
srtp_info.rx_policy = srtp->rx_policy;
653
srtp_info.tx_policy = srtp->tx_policy;
654
srtp_info.use = srtp->setting.use;
655
srtp_info.peer_use = srtp->peer_use;
657
spc_info_idx = info->specific_info_cnt++;
658
info->spc_info[spc_info_idx].type = PJMEDIA_TRANSPORT_TYPE_SRTP;
659
info->spc_info[spc_info_idx].cbsize = sizeof(srtp_info);
660
pj_memcpy(&info->spc_info[spc_info_idx].buffer, &srtp_info,
663
return pjmedia_transport_get_info(srtp->member_tp, info);
666
static pj_status_t transport_attach(pjmedia_transport *tp,
668
const pj_sockaddr_t *rem_addr,
669
const pj_sockaddr_t *rem_rtcp,
671
void (*rtp_cb) (void*, void*,
673
void (*rtcp_cb)(void*, void*,
676
transport_srtp *srtp = (transport_srtp*) tp;
679
PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL);
681
/* Save the callbacks */
682
srtp->rtp_cb = rtp_cb;
683
srtp->rtcp_cb = rtcp_cb;
684
srtp->user_data = user_data;
686
/* Attach itself to transport */
687
status = pjmedia_transport_attach(srtp->member_tp, srtp, rem_addr,
688
rem_rtcp, addr_len, &srtp_rtp_cb,
690
if (status != PJ_SUCCESS) {
692
srtp->rtcp_cb = NULL;
693
srtp->user_data = NULL;
700
static void transport_detach(pjmedia_transport *tp, void *strm)
702
transport_srtp *srtp = (transport_srtp*) tp;
705
PJ_ASSERT_ON_FAIL(tp, return);
707
if (srtp->member_tp) {
708
pjmedia_transport_detach(srtp->member_tp, srtp);
711
/* Clear up application infos from transport */
713
srtp->rtcp_cb = NULL;
714
srtp->user_data = NULL;
717
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
722
transport_srtp *srtp = (transport_srtp*) tp;
726
if (srtp->bypass_srtp)
727
return pjmedia_transport_send_rtp(srtp->member_tp, pkt, size);
729
if (!srtp->session_inited)
732
if (size > sizeof(srtp->rtp_tx_buffer))
735
pj_memcpy(srtp->rtp_tx_buffer, pkt, size);
737
pj_lock_acquire(srtp->mutex);
738
err = srtp_protect(srtp->srtp_tx_ctx, srtp->rtp_tx_buffer, &len);
739
pj_lock_release(srtp->mutex);
741
if (err == err_status_ok) {
742
status = pjmedia_transport_send_rtp(srtp->member_tp, srtp->rtp_tx_buffer, len);
744
status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
750
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
754
return transport_send_rtcp2(tp, NULL, 0, pkt, size);
757
static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
758
const pj_sockaddr_t *addr,
764
transport_srtp *srtp = (transport_srtp*) tp;
768
if (srtp->bypass_srtp) {
769
return pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len,
773
if (!srtp->session_inited)
776
if (size > sizeof(srtp->rtcp_tx_buffer))
779
pj_memcpy(srtp->rtcp_tx_buffer, pkt, size);
781
pj_lock_acquire(srtp->mutex);
782
err = srtp_protect_rtcp(srtp->srtp_tx_ctx, srtp->rtcp_tx_buffer, &len);
783
pj_lock_release(srtp->mutex);
785
if (err == err_status_ok) {
786
status = pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len,
787
srtp->rtcp_tx_buffer, len);
789
status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
796
static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
800
transport_srtp *srtp = (transport_srtp *) tp;
802
PJ_ASSERT_RETURN(tp, PJ_EINVAL);
804
return pjmedia_transport_simulate_lost(srtp->member_tp, dir, pct_lost);
807
static pj_status_t transport_destroy (pjmedia_transport *tp)
809
transport_srtp *srtp = (transport_srtp *) tp;
812
PJ_ASSERT_RETURN(tp, PJ_EINVAL);
814
pj_lock_acquire(srtp->mutex);
816
if (srtp->setting.close_member_tp && srtp->member_tp) {
817
pjmedia_transport_close(srtp->member_tp);
820
status = pjmedia_transport_srtp_stop(tp);
822
pj_lock_release(srtp->mutex);
824
pj_lock_destroy(srtp->mutex);
825
pj_pool_release(srtp->pool);
831
* This callback is called by transport when incoming rtp is received
833
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
835
transport_srtp *srtp = (transport_srtp *) user_data;
839
if (srtp->bypass_srtp) {
840
srtp->rtp_cb(srtp->user_data, pkt, size);
844
if (size < 0 || !srtp->session_inited) {
848
/* Make sure buffer is 32bit aligned */
849
PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return );
851
if (srtp->probation_cnt > 0)
852
--srtp->probation_cnt;
854
pj_lock_acquire(srtp->mutex);
856
err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
858
if (srtp->probation_cnt > 0 &&
859
(err == err_status_replay_old || err == err_status_replay_fail))
861
/* Handle such condition that stream is updated (RTP seq is reinited
862
* & SRTP is restarted), but some old packets are still coming
863
* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
864
* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
865
* will returning err_status_replay_*. Restarting SRTP can resolve
868
if (pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
869
&srtp->tx_policy, &srtp->rx_policy)
872
PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
873
get_libsrtp_errstr(err)));
875
err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
879
if (err == err_status_ok) {
880
srtp->rtp_cb(srtp->user_data, pkt, len);
882
PJ_LOG(5,(srtp->pool->obj_name,
883
"Failed to unprotect SRTP, pkt size=%d, err=%s",
884
size, get_libsrtp_errstr(err)));
887
pj_lock_release(srtp->mutex);
891
* This callback is called by transport when incoming rtcp is received
893
static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size)
895
transport_srtp *srtp = (transport_srtp *) user_data;
899
if (srtp->bypass_srtp) {
900
srtp->rtcp_cb(srtp->user_data, pkt, size);
904
if (size < 0 || !srtp->session_inited) {
908
/* Make sure buffer is 32bit aligned */
909
PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return );
911
pj_lock_acquire(srtp->mutex);
913
err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
915
if (err == err_status_ok) {
916
srtp->rtcp_cb(srtp->user_data, pkt, len);
918
PJ_LOG(5,(srtp->pool->obj_name,
919
"Failed to unprotect SRTCP, pkt size=%d, err=%s",
920
size, get_libsrtp_errstr(err)));
923
pj_lock_release(srtp->mutex);
926
/* Generate crypto attribute, including crypto key.
927
* If crypto-suite chosen is crypto NULL, just return PJ_SUCCESS,
928
* and set buffer_len = 0.
930
static pj_status_t generate_crypto_attr_value(pj_pool_t *pool,
931
char *buffer, int *buffer_len,
932
pjmedia_srtp_crypto *crypto,
936
int cs_idx = get_crypto_idx(&crypto->name);
937
char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1];
938
int b64_key_len = sizeof(b64_key);
941
return PJMEDIA_SRTP_ENOTSUPCRYPTO;
943
/* Crypto-suite NULL. */
949
/* Generate key if not specified. */
950
if (crypto->key.slen == 0) {
952
char key[MAX_KEY_LEN];
956
PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len,
962
err = crypto_get_random((unsigned char*)key,
963
crypto_suites[cs_idx].cipher_key_len);
964
if (err != err_status_ok) {
965
PJ_LOG(5,(THIS_FILE, "Failed generating random key: %s",
966
get_libsrtp_errstr(err)));
967
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
969
for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i)
970
if (key[i] == 0) key_ok = PJ_FALSE;
973
crypto->key.ptr = (char*)
975
crypto_suites[cs_idx].cipher_key_len);
976
pj_memcpy(crypto->key.ptr, key, crypto_suites[cs_idx].cipher_key_len);
977
crypto->key.slen = crypto_suites[cs_idx].cipher_key_len;
980
if (crypto->key.slen != (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
981
return PJMEDIA_SRTP_EINKEYLEN;
983
/* Key transmitted via SDP should be base64 encoded. */
984
status = pj_base64_encode((pj_uint8_t*)crypto->key.ptr, crypto->key.slen,
985
b64_key, &b64_key_len);
986
if (status != PJ_SUCCESS) {
987
PJ_LOG(5,(THIS_FILE, "Failed encoding plain key to base64"));
991
b64_key[b64_key_len] = '\0';
993
PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \
994
b64_key_len + 16), PJ_ETOOSMALL);
996
/* Print the crypto attribute value. */
997
*buffer_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s",
999
crypto_suites[cs_idx].name,
1005
/* Parse crypto attribute line */
1006
static pj_status_t parse_attr_crypto(pj_pool_t *pool,
1007
const pjmedia_sdp_attr *attr,
1008
pjmedia_srtp_crypto *crypto,
1018
pj_bzero(crypto, sizeof(*crypto));
1019
pj_strdup_with_null(pool, &input, &attr->value);
1022
token = strtok(input.ptr, " ");
1024
PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag"));
1025
return PJMEDIA_SDP_EINATTR;
1027
token_len = pj_ansi_strlen(token);
1029
/* Tag must not use leading zeroes. */
1030
if (token_len > 1 && *token == '0')
1031
return PJMEDIA_SDP_EINATTR;
1033
/* Tag must be decimal, i.e: contains only digit '0'-'9'. */
1034
for (itmp = 0; itmp < token_len; ++itmp)
1035
if (!pj_isdigit(token[itmp]))
1036
return PJMEDIA_SDP_EINATTR;
1038
/* Get tag value. */
1042
token = strtok(NULL, " ");
1044
PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite"));
1045
return PJMEDIA_SDP_EINATTR;
1047
crypto->name = pj_str(token);
1050
token = strtok(NULL, ":");
1052
PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method"));
1053
return PJMEDIA_SDP_EINATTR;
1055
if (pj_ansi_stricmp(token, "inline")) {
1056
PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%s' not supported!",
1058
return PJMEDIA_SDP_EINATTR;
1062
token = strtok(NULL, "| ");
1064
PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key"));
1065
return PJMEDIA_SDP_EINATTR;
1067
tmp = pj_str(token);
1068
crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN);
1072
status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr,
1074
if (status != PJ_SUCCESS) {
1075
PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64"));
1078
crypto->key.slen = itmp;
1083
static pj_status_t transport_media_create(pjmedia_transport *tp,
1084
pj_pool_t *sdp_pool,
1086
const pjmedia_sdp_session *sdp_remote,
1087
unsigned media_index)
1089
struct transport_srtp *srtp = (struct transport_srtp*) tp;
1090
unsigned member_tp_option;
1092
PJ_ASSERT_RETURN(tp, PJ_EINVAL);
1094
pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg));
1095
pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg));
1097
srtp->media_option = options;
1098
member_tp_option = options | PJMEDIA_TPMED_NO_TRANSPORT_CHECKING;
1100
srtp->offerer_side = sdp_remote == NULL;
1103
if (srtp->offerer_side) {
1105
if (srtp->setting.use == PJMEDIA_SRTP_DISABLED)
1110
pjmedia_sdp_media *m_rem;
1112
m_rem = sdp_remote->media[media_index];
1114
/* Nothing to do on inactive media stream */
1115
if (pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))
1118
/* Validate remote media transport based on SRTP usage option.
1120
switch (srtp->setting.use) {
1121
case PJMEDIA_SRTP_DISABLED:
1122
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1123
return PJMEDIA_SRTP_ESDPINTRANSPORT;
1125
case PJMEDIA_SRTP_OPTIONAL:
1127
case PJMEDIA_SRTP_MANDATORY:
1128
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)
1129
return PJMEDIA_SRTP_ESDPINTRANSPORT;
1134
goto PROPAGATE_MEDIA_CREATE;
1137
srtp->bypass_srtp = PJ_TRUE;
1138
member_tp_option &= ~PJMEDIA_TPMED_NO_TRANSPORT_CHECKING;
1140
PROPAGATE_MEDIA_CREATE:
1141
return pjmedia_transport_media_create(srtp->member_tp, sdp_pool,
1142
member_tp_option, sdp_remote,
1146
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
1147
pj_pool_t *sdp_pool,
1148
pjmedia_sdp_session *sdp_local,
1149
const pjmedia_sdp_session *sdp_remote,
1150
unsigned media_index)
1152
struct transport_srtp *srtp = (struct transport_srtp*) tp;
1153
pjmedia_sdp_media *m_rem, *m_loc;
1154
enum { MAXLEN = 512 };
1155
char buffer[MAXLEN];
1158
pjmedia_sdp_attr *attr;
1159
pj_str_t attr_value;
1162
PJ_ASSERT_RETURN(tp && sdp_pool && sdp_local, PJ_EINVAL);
1164
srtp->offerer_side = sdp_remote == NULL;
1166
m_rem = sdp_remote ? sdp_remote->media[media_index] : NULL;
1167
m_loc = sdp_local->media[media_index];
1169
/* Bypass if media transport is not RTP/AVP or RTP/SAVP */
1170
if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 &&
1171
pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0)
1174
/* If the media is inactive, do nothing. */
1175
if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) ||
1176
(m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL)))
1179
/* Check remote media transport & set local media transport
1180
* based on SRTP usage option.
1182
if (srtp->offerer_side) {
1184
/* Generate transport */
1185
switch (srtp->setting.use) {
1186
case PJMEDIA_SRTP_DISABLED:
1188
case PJMEDIA_SRTP_OPTIONAL:
1189
m_loc->desc.transport =
1190
(srtp->peer_use == PJMEDIA_SRTP_MANDATORY)?
1191
ID_RTP_SAVP : ID_RTP_AVP;
1193
case PJMEDIA_SRTP_MANDATORY:
1194
m_loc->desc.transport = ID_RTP_SAVP;
1198
/* Generate crypto attribute if not yet */
1199
if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) {
1200
for (i=0; i<srtp->setting.crypto_count; ++i) {
1201
/* Offer crypto-suites based on setting. */
1202
buffer_len = MAXLEN;
1203
status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len,
1204
&srtp->setting.crypto[i],
1206
if (status != PJ_SUCCESS)
1209
/* If buffer_len==0, just skip the crypto attribute. */
1211
pj_strset(&attr_value, buffer, buffer_len);
1212
attr = pjmedia_sdp_attr_create(srtp->pool, ID_CRYPTO.ptr,
1214
m_loc->attr[m_loc->attr_count++] = attr;
1222
pj_assert(sdp_remote && m_rem);
1224
/* Generate transport */
1225
switch (srtp->setting.use) {
1226
case PJMEDIA_SRTP_DISABLED:
1227
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1228
return PJMEDIA_SRTP_ESDPINTRANSPORT;
1230
case PJMEDIA_SRTP_OPTIONAL:
1231
m_loc->desc.transport = m_rem->desc.transport;
1233
case PJMEDIA_SRTP_MANDATORY:
1234
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)
1235
return PJMEDIA_SRTP_ESDPINTRANSPORT;
1236
m_loc->desc.transport = ID_RTP_SAVP;
1240
/* Generate crypto attribute if not yet */
1241
if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) {
1243
pjmedia_srtp_crypto tmp_rx_crypto;
1244
pj_bool_t has_crypto_attr = PJ_FALSE;
1245
int matched_idx = -1;
1247
int tags[64]; /* assume no more than 64 crypto attrs in a media */
1248
unsigned cr_attr_count = 0;
1250
/* Find supported crypto-suite, get the tag, and assign policy_local */
1251
for (i=0; i<m_rem->attr_count; ++i) {
1252
if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
1255
has_crypto_attr = PJ_TRUE;
1257
status = parse_attr_crypto(srtp->pool, m_rem->attr[i],
1258
&tmp_rx_crypto, &tags[cr_attr_count]);
1259
if (status != PJ_SUCCESS)
1262
/* Check duplicated tag */
1263
for (j=0; j<cr_attr_count; ++j) {
1264
if (tags[j] == tags[cr_attr_count]) {
1265
DEACTIVATE_MEDIA(sdp_pool, m_loc);
1266
return PJMEDIA_SRTP_ESDPDUPCRYPTOTAG;
1270
if (matched_idx == -1) {
1271
/* lets see if the crypto-suite offered is supported */
1272
for (j=0; j<srtp->setting.crypto_count; ++j)
1273
if (pj_stricmp(&tmp_rx_crypto.name,
1274
&srtp->setting.crypto[j].name) == 0)
1276
int cs_idx = get_crypto_idx(&tmp_rx_crypto.name);
1278
/* Force to use test key */
1279
/* bad keys for snom: */
1280
//char *hex_test_key = "58b29c5c8f42308120ce857e439f2d"
1281
// "7810a8b10ad0b1446be5470faea496";
1282
//char *hex_test_key = "20a26aac7ba062d356ff52b61e3993"
1283
// "ccb78078f12c64db94b9c294927fd0";
1284
//pj_str_t *test_key = &srtp->setting.crypto[j].key;
1285
//char *raw_test_key = pj_pool_zalloc(srtp->pool, 64);
1286
//hex_string_to_octet_string(
1289
// strlen(hex_test_key));
1290
//pj_strset(test_key, raw_test_key,
1291
// crypto_suites[cs_idx].cipher_key_len);
1292
/* EO Force to use test key */
1294
if (tmp_rx_crypto.key.slen !=
1295
(int)crypto_suites[cs_idx].cipher_key_len)
1296
return PJMEDIA_SRTP_EINKEYLEN;
1298
srtp->rx_policy_neg = tmp_rx_crypto;
1299
chosen_tag = tags[cr_attr_count];
1307
/* Check crypto negotiation result */
1308
switch (srtp->setting.use) {
1309
case PJMEDIA_SRTP_DISABLED:
1310
pj_assert(!"Should never reach here");
1313
case PJMEDIA_SRTP_OPTIONAL:
1314
/* bypass SRTP when no crypto-attr and remote uses RTP/AVP */
1315
if (!has_crypto_attr &&
1316
pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0)
1318
/* bypass SRTP when nothing match and remote uses RTP/AVP */
1319
else if (matched_idx == -1 &&
1320
pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0)
1324
case PJMEDIA_SRTP_MANDATORY:
1325
/* Do nothing, intentional */
1329
/* No crypto attr */
1330
if (!has_crypto_attr) {
1331
DEACTIVATE_MEDIA(sdp_pool, m_loc);
1332
return PJMEDIA_SRTP_ESDPREQCRYPTO;
1335
/* No crypto match */
1336
if (matched_idx == -1) {
1337
DEACTIVATE_MEDIA(sdp_pool, m_loc);
1338
return PJMEDIA_SRTP_ENOTSUPCRYPTO;
1341
/* we have to generate crypto answer,
1342
* with srtp->tx_policy_neg matched the offer
1343
* and rem_tag contains matched offer tag.
1345
buffer_len = MAXLEN;
1346
status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len,
1347
&srtp->setting.crypto[matched_idx],
1349
if (status != PJ_SUCCESS)
1352
srtp->tx_policy_neg = srtp->setting.crypto[matched_idx];
1354
/* If buffer_len==0, just skip the crypto attribute. */
1356
pj_strset(&attr_value, buffer, buffer_len);
1357
attr = pjmedia_sdp_attr_create(sdp_pool, ID_CRYPTO.ptr,
1359
m_loc->attr[m_loc->attr_count++] = attr;
1362
/* At this point, we get valid rx_policy_neg & tx_policy_neg. */
1366
goto PROPAGATE_MEDIA_CREATE;
1369
srtp->bypass_srtp = PJ_TRUE;
1371
PROPAGATE_MEDIA_CREATE:
1372
return pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool,
1373
sdp_local, sdp_remote, media_index);
1378
static pj_status_t transport_media_start(pjmedia_transport *tp,
1380
const pjmedia_sdp_session *sdp_local,
1381
const pjmedia_sdp_session *sdp_remote,
1382
unsigned media_index)
1384
struct transport_srtp *srtp = (struct transport_srtp*) tp;
1385
pjmedia_sdp_media *m_rem, *m_loc;
1389
PJ_ASSERT_RETURN(tp && pool && sdp_local && sdp_remote, PJ_EINVAL);
1391
if (srtp->bypass_srtp)
1394
m_rem = sdp_remote->media[media_index];
1395
m_loc = sdp_local->media[media_index];
1397
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)
1398
srtp->peer_use = PJMEDIA_SRTP_MANDATORY;
1400
srtp->peer_use = PJMEDIA_SRTP_OPTIONAL;
1402
/* For answerer side, this function will just have to start SRTP */
1404
/* Check remote media transport & set local media transport
1405
* based on SRTP usage option.
1407
if (srtp->offerer_side) {
1408
if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
1409
if (pjmedia_sdp_media_find_attr(m_rem, &ID_CRYPTO, NULL)) {
1410
DEACTIVATE_MEDIA(pool, m_loc);
1411
return PJMEDIA_SRTP_ESDPINCRYPTO;
1414
} else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
1415
// Regardless the answer's transport type (RTP/AVP or RTP/SAVP),
1416
// the answer must be processed through in optional mode.
1417
// Please note that at this point transport type is ensured to be
1418
// RTP/AVP or RTP/SAVP, see transport_media_create()
1419
//if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) {
1420
//DEACTIVATE_MEDIA(pool, m_loc);
1421
//return PJMEDIA_SDP_EINPROTO;
1423
} else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
1424
if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) {
1425
DEACTIVATE_MEDIA(pool, m_loc);
1426
return PJMEDIA_SDP_EINPROTO;
1431
if (srtp->offerer_side) {
1432
/* find supported crypto-suite, get the tag, and assign policy_local */
1433
pjmedia_srtp_crypto tmp_tx_crypto;
1434
pj_bool_t has_crypto_attr = PJ_FALSE;
1437
for (i=0; i<m_rem->attr_count; ++i) {
1438
if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
1441
/* more than one crypto attribute in media answer */
1442
if (has_crypto_attr) {
1443
DEACTIVATE_MEDIA(pool, m_loc);
1444
return PJMEDIA_SRTP_ESDPAMBIGUEANS;
1447
has_crypto_attr = PJ_TRUE;
1449
status = parse_attr_crypto(srtp->pool, m_rem->attr[i],
1450
&tmp_tx_crypto, &rem_tag);
1451
if (status != PJ_SUCCESS)
1455
/* our offer tag is always ordered by setting */
1456
if (rem_tag < 1 || rem_tag > (int)srtp->setting.crypto_count) {
1457
DEACTIVATE_MEDIA(pool, m_loc);
1458
return PJMEDIA_SRTP_ESDPINCRYPTOTAG;
1461
/* match the crypto name */
1462
if (pj_stricmp(&tmp_tx_crypto.name,
1463
&srtp->setting.crypto[rem_tag-1].name) != 0)
1465
DEACTIVATE_MEDIA(pool, m_loc);
1466
return PJMEDIA_SRTP_ECRYPTONOTMATCH;
1469
srtp->tx_policy_neg = srtp->setting.crypto[rem_tag-1];
1470
srtp->rx_policy_neg = tmp_tx_crypto;
1473
if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
1474
/* should never reach here */
1476
} else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
1477
if (!has_crypto_attr)
1479
} else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
1480
if (!has_crypto_attr) {
1481
DEACTIVATE_MEDIA(pool, m_loc);
1482
return PJMEDIA_SRTP_ESDPREQCRYPTO;
1486
/* At this point, we get valid rx_policy_neg & tx_policy_neg. */
1489
/* Reset probation counts */
1490
srtp->probation_cnt = PROBATION_CNT_INIT;
1492
/* Got policy_local & policy_remote, let's initalize the SRTP */
1493
status = pjmedia_transport_srtp_start(tp, &srtp->tx_policy_neg, &srtp->rx_policy_neg);
1494
if (status != PJ_SUCCESS)
1497
goto PROPAGATE_MEDIA_START;
1500
srtp->bypass_srtp = PJ_TRUE;
1501
srtp->peer_use = PJMEDIA_SRTP_DISABLED;
1503
PROPAGATE_MEDIA_START:
1504
return pjmedia_transport_media_start(srtp->member_tp, pool,
1505
sdp_local, sdp_remote,
1509
static pj_status_t transport_media_stop(pjmedia_transport *tp)
1511
struct transport_srtp *srtp = (struct transport_srtp*) tp;
1514
PJ_ASSERT_RETURN(tp, PJ_EINVAL);
1516
status = pjmedia_transport_media_stop(srtp->member_tp);
1517
if (status != PJ_SUCCESS)
1518
PJ_LOG(4, (srtp->pool->obj_name,
1519
"SRTP failed stop underlying media transport."));
1521
return pjmedia_transport_srtp_stop(tp);
1525
PJ_DEF(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
1530
transport_srtp *srtp = (transport_srtp *)tp;
1533
if (srtp->bypass_srtp)
1536
PJ_ASSERT_RETURN(tp && pkt && (*pkt_len>0), PJ_EINVAL);
1537
PJ_ASSERT_RETURN(srtp->session_inited, PJ_EINVALIDOP);
1539
/* Make sure buffer is 32bit aligned */
1540
PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return PJ_EINVAL);
1542
pj_lock_acquire(srtp->mutex);
1545
err = srtp_unprotect(srtp->srtp_rx_ctx, pkt, pkt_len);
1547
err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len);
1549
if (err != err_status_ok) {
1550
PJ_LOG(5,(srtp->pool->obj_name,
1551
"Failed to unprotect SRTP, pkt size=%d, err=%s",
1552
*pkt_len, get_libsrtp_errstr(err)));
1555
pj_lock_release(srtp->mutex);
1557
return (err==err_status_ok) ? PJ_SUCCESS : PJMEDIA_ERRNO_FROM_LIBSRTP(err);