- Timestamp:
- Jan 18, 2008 8:42:15 PM (17 years ago)
- Location:
- pjproject/branches/users/nanang/pjmedia
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_srtp.h
r1702 r1711 54 54 55 55 /** Crypto name. */ 56 pj_str_t crypto;56 pj_str_t name; 57 57 58 58 /* Flags, bitmask from #pjmedia_srtp_crypto_option */ … … 169 169 */ 170 170 PJ_DECL(pj_status_t) pjmedia_transport_srtp_start( 171 pjmedia_transport * srtp,171 pjmedia_transport *tp, 172 172 const pjmedia_srtp_crypto *tx, 173 173 const pjmedia_srtp_crypto *rx); … … 182 182 * @see #pjmedia_transport_srtp_start() 183 183 */ 184 PJ_DECL(pj_status_t) pjmedia_transport_srtp_stop(pjmedia_transport * srtp);184 PJ_DECL(pj_status_t) pjmedia_transport_srtp_stop(pjmedia_transport *tp); 185 185 186 186 … … 193 193 */ 194 194 PJ_DECL(pjmedia_transport*) pjmedia_transport_srtp_get_member( 195 pjmedia_transport * srtp);195 pjmedia_transport *tp); 196 196 197 197 -
pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c
r1702 r1711 33 33 #define MAX_BUFFER_LEN 1500 34 34 #define MAX_KEY_LEN 32 35 #define SRTP_ERROR(e) -1 36 37 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 35 #define DEACTIVATE_MEDIA(pool, m) {\ 36 attr = pjmedia_sdp_attr_create(pool, ID_INACTIVE.ptr, NULL); \ 37 m->attr[m->attr_count++] = attr; \ 38 m->desc.port = 0; \ 39 } 40 41 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 38 42 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 43 static const pj_str_t ID_INACTIVE = { "inactive", 8 }; 39 44 40 45 typedef struct crypto_suite … … 76 81 char tx_buffer[MAX_BUFFER_LEN]; 77 82 char rx_buffer[MAX_BUFFER_LEN]; 78 unsigned options; /**< Transport options. */79 83 80 84 pjmedia_srtp_setting setting; … … 82 86 pj_bool_t session_inited; 83 87 pj_bool_t offerer_side; 88 pj_bool_t bypass_srtp; 84 89 char tx_key[MAX_KEY_LEN]; 85 90 char rx_key[MAX_KEY_LEN]; 86 pjmedia_srtp_ stream_cryptotx_policy;87 pjmedia_srtp_ stream_cryptorx_policy;91 pjmedia_srtp_crypto tx_policy; 92 pjmedia_srtp_crypto rx_policy; 88 93 89 94 /* libSRTP contexts */ … … 144 149 pj_pool_t *pool, 145 150 pjmedia_sdp_session *sdp_local, 146 const pjmedia_sdp_session *sdp_remote); 151 const pjmedia_sdp_session *sdp_remote, 152 unsigned media_index); 147 153 static pj_status_t transport_media_start (pjmedia_transport *tp, 148 154 pj_pool_t *pool, … … 174 180 char * octet_string_hex_string(const void *s, int length); 175 181 182 183 pj_str_t srtp_transport_getliberrstr(int err) 184 { 185 pj_str_t msg = {NULL, 0}; 186 187 #if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0) 188 static char *liberr[] = { 189 "nothing to report ", /* err_status_ok = 0, */ 190 "unspecified failure ", /* err_status_fail = 1, */ 191 "unsupported parameter ", /* err_status_bad_param = 2, */ 192 "couldn't allocate memory ", /* err_status_alloc_fail = 3, */ 193 "couldn't deallocate properly ", /* err_status_dealloc_fail = 4, */ 194 "couldn't initialize ", /* err_status_init_fail = 5, */ 195 "can't process as much data as requested ", /* err_status_terminus = 6, */ 196 "authentication failure ", /* err_status_auth_fail = 7, */ 197 "cipher failure ", /* err_status_cipher_fail = 8, */ 198 "replay check failed (bad index) ", /* err_status_replay_fail = 9, */ 199 "replay check failed (index too old) ", /* err_status_replay_old = 10, */ 200 "algorithm failed test routine ", /* err_status_algo_fail = 11, */ 201 "unsupported operation ", /* err_status_no_such_op = 12, */ 202 "no appropriate context found ", /* err_status_no_ctx = 13, */ 203 "unable to perform desired validation ", /* err_status_cant_check = 14, */ 204 "can't use key any more ", /* err_status_key_expired = 15, */ 205 "error in use of socket ", /* err_status_socket_err = 16, */ 206 "error in use POSIX signals ", /* err_status_signal_err = 17, */ 207 "nonce check failed ", /* err_status_nonce_bad = 18, */ 208 "couldn't read data ", /* err_status_read_fail = 19, */ 209 "couldn't write data ", /* err_status_write_fail = 20, */ 210 "error pasring data ", /* err_status_parse_err = 21, */ 211 "error encoding data ", /* err_status_encode_err = 22, */ 212 "error while using semaphores ", /* err_status_semaphore_err = 23, */ 213 "error while using pfkey " /* err_status_pfkey_err = 24, */ 214 }; 215 if (err >= 0 && err <= 24) { 216 msg.ptr = liberr[err]; 217 msg.slen = 40; 218 } 219 #endif 220 221 return msg; 222 } 223 176 224 static pj_status_t pjmedia_srtp_init_lib(void) 177 225 { … … 183 231 if (err != err_status_ok) { 184 232 PJ_LOG(4, (THIS_FILE, "Failed to init libsrtp.")); 185 return SRTP_ERROR(err);233 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 186 234 } 187 235 … … 192 240 193 241 return PJ_SUCCESS; 242 } 243 244 static int get_crypto_idx(const pj_str_t* crypto_name) 245 { 246 int i; 247 int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]); 248 249 for (i=0; i<cs_cnt; ++i) { 250 if (!pj_stricmp2(crypto_name, crypto_suites[i].name)) 251 return i; 252 } 253 254 return -1; 255 } 256 257 PJ_DEF(void) pjmedia_srtp_setting_default(pjmedia_srtp_setting *opt) 258 { 259 int i; 260 261 pj_bzero(opt, sizeof(pjmedia_srtp_setting)); 262 opt->close_member_tp = PJ_TRUE; 263 opt->use = PJMEDIA_SRTP_OPTIONAL; 264 opt->crypto_count = sizeof(crypto_suites)/sizeof(crypto_suites[0]); 265 for (i=0; i<opt->crypto_count; ++i) 266 opt->crypto[i].name = pj_str(crypto_suites[i].name); 194 267 } 195 268 … … 198 271 * Create an SRTP media transport. 199 272 */ 200 PJ_DEF(pj_status_t) pjmedia_transport_srtp_create( pjmedia_endpt *endpt, 201 pjmedia_transport *tp, 202 unsigned options, 203 pjmedia_transport **p_srtp) 273 PJ_DEF(pj_status_t) pjmedia_transport_srtp_create( 274 pjmedia_endpt *endpt, 275 pjmedia_transport *tp, 276 const pjmedia_srtp_setting *opt, 277 pjmedia_transport **p_tp) 204 278 { 205 279 pj_pool_t *pool; 206 280 transport_srtp *srtp; 207 281 pj_status_t status; 208 209 PJ_ASSERT_RETURN(endpt && p_srtp, PJ_EINVAL); 282 int i; 283 284 PJ_ASSERT_RETURN(endpt && p_tp, PJ_EINVAL); 210 285 211 286 /* Init libsrtp. */ … … 219 294 srtp->pool = pool; 220 295 srtp->session_inited = PJ_FALSE; 221 srtp->offerer_side = PJ_TRUE; 222 srtp->options = options; 296 srtp->bypass_srtp = PJ_TRUE; 297 298 if (opt) { 299 srtp->setting = *opt; 300 for (i=0; i < opt->crypto_count; ++i) { 301 int cs_idx = get_crypto_idx(&opt->crypto[i].name); 302 if (cs_idx == -1) 303 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 304 305 srtp->setting.crypto[i].name = pj_str(crypto_suites[cs_idx].name); 306 pj_strdup(pool, &srtp->setting.crypto[i].key, &opt->crypto[i].key); 307 } 308 } else { 309 pjmedia_srtp_setting_default(&srtp->setting); 310 } 311 312 if (srtp->setting.crypto_count==0 && 313 srtp->setting.use == PJMEDIA_SRTP_MANDATORY) 314 return PJMEDIA_SRTP_ESDPREQCRYPTO; 223 315 224 316 status = pj_lock_create_null_mutex(pool, pool->obj_name, &srtp->mutex); … … 237 329 238 330 /* Done */ 239 *p_ srtp = &srtp->base;331 *p_tp = &srtp->base; 240 332 241 333 return PJ_SUCCESS; … … 247 339 */ 248 340 PJ_DEF(pj_status_t) pjmedia_transport_srtp_start( 249 pjmedia_transport * srtp,250 const pjmedia_srtp_ stream_crypto *policy_tx,251 const pjmedia_srtp_ stream_crypto *policy_rx)252 { 253 transport_srtp * p_srtp = (transport_srtp*) srtp;254 srtp_policy_t policy_tx_;255 srtp_policy_t policy_rx_;341 pjmedia_transport *tp, 342 const pjmedia_srtp_crypto *tx, 343 const pjmedia_srtp_crypto *rx) 344 { 345 transport_srtp *srtp = (transport_srtp*) tp; 346 srtp_policy_t tx_; 347 srtp_policy_t rx_; 256 348 err_status_t err; 257 int i; 258 int cs_tx_idx = -1; 259 int cs_rx_idx = -1; 349 int cr_tx_idx = 0; 350 int au_tx_idx = 0; 351 int cr_rx_idx = 0; 352 int au_rx_idx = 0; 260 353 int crypto_suites_cnt; 261 354 262 if ( p_srtp->session_inited) {355 if (srtp->session_inited) { 263 356 PJ_LOG(4, (THIS_FILE, "SRTP could not be re-init'd before deinit'd")); 264 357 return PJ_EINVALIDOP; … … 268 361 269 362 /* Check whether the crypto-suite requested is supported */ 270 for (i=0; i<crypto_suites_cnt; ++i) { 271 if ((cs_rx_idx == -1) && 272 !pj_stricmp2(&policy_rx->crypto_suite, crypto_suites[i].name)) 273 cs_rx_idx = i; 274 275 if ((cs_tx_idx == -1) && 276 !pj_stricmp2(&policy_tx->crypto_suite, crypto_suites[i].name)) 277 cs_tx_idx = i; 278 } 279 280 if ((cs_tx_idx == -1) || (cs_rx_idx == -1)) { 281 PJ_LOG(4, (THIS_FILE, "Crypto-suite specified is not supported.")); 282 return PJ_ENOTSUP; 283 } 363 cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name); 364 if (tx->flags && PJMEDIA_SRTP_NO_ENCRYPTION) 365 cr_tx_idx = 0; 366 if (tx->flags && PJMEDIA_SRTP_NO_AUTHENTICATION) 367 au_tx_idx = 0; 368 369 /* Check whether the crypto-suite requested is supported */ 370 cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name); 371 if (rx->flags && PJMEDIA_SRTP_NO_ENCRYPTION) 372 cr_rx_idx = 0; 373 if (rx->flags && PJMEDIA_SRTP_NO_AUTHENTICATION) 374 au_rx_idx = 0; 375 376 if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || au_rx_idx == -1) 377 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 284 378 285 379 /* Init transmit direction */ 286 pj_bzero(& policy_tx_, sizeof(srtp_policy_t));287 pj_memmove( p_srtp->tx_key, policy_tx->key.ptr, policy_tx->key.slen);288 policy_tx_.key = (uint8_t*)p_srtp->tx_key;289 policy_tx_.ssrc.type= ssrc_any_outbound;290 policy_tx_.ssrc.value= 0;291 policy_tx_.rtp.sec_serv = crypto_suites[cs_tx_idx].service;292 policy_tx_.rtp.cipher_type = crypto_suites[cs_tx_idx].cipher_type;293 policy_tx_.rtp.cipher_key_len = crypto_suites[cs_tx_idx].cipher_key_len;294 policy_tx_.rtp.auth_type = crypto_suites[cs_tx_idx].auth_type;295 policy_tx_.rtp.auth_key_len = crypto_suites[cs_tx_idx].auth_key_len;296 policy_tx_.rtp.auth_tag_len = crypto_suites[cs_tx_idx].srtp_auth_tag_len;297 policy_tx_.rtcp = policy_tx_.rtp;298 policy_tx_.rtcp.auth_tag_len = crypto_suites[cs_tx_idx].srtcp_auth_tag_len;299 policy_tx_.next= NULL;300 err = srtp_create(& p_srtp->srtp_tx_ctx, &policy_tx_);380 pj_bzero(&tx_, sizeof(srtp_policy_t)); 381 pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen); 382 tx_.key = (uint8_t*)srtp->tx_key; 383 tx_.ssrc.type = ssrc_any_outbound; 384 tx_.ssrc.value = 0; 385 tx_.rtp.sec_serv = crypto_suites[cr_tx_idx].service; 386 tx_.rtp.cipher_type = crypto_suites[cr_tx_idx].cipher_type; 387 tx_.rtp.cipher_key_len = crypto_suites[cr_tx_idx].cipher_key_len; 388 tx_.rtp.auth_type = crypto_suites[au_tx_idx].auth_type; 389 tx_.rtp.auth_key_len = crypto_suites[au_tx_idx].auth_key_len; 390 tx_.rtp.auth_tag_len = crypto_suites[au_tx_idx].srtp_auth_tag_len; 391 tx_.rtcp = tx_.rtp; 392 tx_.rtcp.auth_tag_len = crypto_suites[au_tx_idx].srtcp_auth_tag_len; 393 tx_.next = NULL; 394 err = srtp_create(&srtp->srtp_tx_ctx, &tx_); 301 395 if (err != err_status_ok) { 302 return SRTP_ERROR(err); 303 } 304 305 pj_strset(&p_srtp->tx_policy.key, p_srtp->tx_key, policy_tx->key.slen); 306 p_srtp->tx_policy.crypto_suite = pj_str(crypto_suites[cs_tx_idx].name); 396 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 397 } 398 srtp->tx_policy = *tx; 399 pj_strset(&srtp->tx_policy.key, srtp->tx_key, tx->key.slen); 400 srtp->tx_policy.name = 401 pj_str(crypto_suites[get_crypto_idx(&tx->name)].name); 307 402 308 403 309 404 /* Init receive direction */ 310 pj_bzero(& policy_rx_, sizeof(srtp_policy_t));311 pj_memmove( p_srtp->rx_key, policy_rx->key.ptr, policy_rx->key.slen);312 policy_rx_.key = (uint8_t*)p_srtp->rx_key;313 policy_rx_.ssrc.type= ssrc_any_inbound;314 policy_rx_.ssrc.value= 0;315 policy_rx_.rtp.sec_serv = crypto_suites[cs_rx_idx].service;316 policy_rx_.rtp.cipher_type = crypto_suites[cs_rx_idx].cipher_type;317 policy_rx_.rtp.cipher_key_len = crypto_suites[cs_rx_idx].cipher_key_len;318 policy_rx_.rtp.auth_type = crypto_suites[cs_rx_idx].auth_type;319 policy_rx_.rtp.auth_key_len = crypto_suites[cs_rx_idx].auth_key_len;320 policy_rx_.rtp.auth_tag_len = crypto_suites[cs_rx_idx].srtp_auth_tag_len;321 policy_rx_.rtcp = policy_rx_.rtp;322 policy_rx_.rtcp.auth_tag_len = crypto_suites[cs_rx_idx].srtcp_auth_tag_len;323 policy_rx_.next= NULL;324 err = srtp_create(& p_srtp->srtp_rx_ctx, &policy_rx_);405 pj_bzero(&rx_, sizeof(srtp_policy_t)); 406 pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen); 407 rx_.key = (uint8_t*)srtp->rx_key; 408 rx_.ssrc.type = ssrc_any_inbound; 409 rx_.ssrc.value = 0; 410 rx_.rtp.sec_serv = crypto_suites[cr_rx_idx].service; 411 rx_.rtp.cipher_type = crypto_suites[cr_rx_idx].cipher_type; 412 rx_.rtp.cipher_key_len = crypto_suites[cr_rx_idx].cipher_key_len; 413 rx_.rtp.auth_type = crypto_suites[au_rx_idx].auth_type; 414 rx_.rtp.auth_key_len = crypto_suites[au_rx_idx].auth_key_len; 415 rx_.rtp.auth_tag_len = crypto_suites[au_rx_idx].srtp_auth_tag_len; 416 rx_.rtcp = rx_.rtp; 417 rx_.rtcp.auth_tag_len = crypto_suites[au_rx_idx].srtcp_auth_tag_len; 418 rx_.next = NULL; 419 err = srtp_create(&srtp->srtp_rx_ctx, &rx_); 325 420 if (err != err_status_ok) { 326 srtp_dealloc(p_srtp->srtp_tx_ctx); 327 return SRTP_ERROR(err); 328 } 329 330 pj_strset(&p_srtp->rx_policy.key, p_srtp->rx_key, policy_rx->key.slen); 331 p_srtp->rx_policy.crypto_suite = pj_str(crypto_suites[i].name); 421 srtp_dealloc(srtp->srtp_tx_ctx); 422 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 423 } 424 srtp->rx_policy = *rx; 425 pj_strset(&srtp->rx_policy.key, srtp->rx_key, rx->key.slen); 426 srtp->rx_policy.name = 427 pj_str(crypto_suites[get_crypto_idx(&rx->name)].name); 332 428 333 429 /* Declare SRTP session initialized */ 334 p_srtp->session_inited = PJ_TRUE; 335 336 PJ_LOG(5, (THIS_FILE, "TX %s key=%s", crypto_suites[cs_tx_idx].name, 337 octet_string_hex_string(policy_tx->key.ptr, policy_tx->key.slen))); 338 PJ_LOG(5, (THIS_FILE, "RX %s key=%s", crypto_suites[cs_rx_idx].name, 339 octet_string_hex_string(policy_rx->key.ptr, policy_rx->key.slen))); 430 srtp->session_inited = PJ_TRUE; 431 srtp->bypass_srtp = PJ_FALSE; 432 433 PJ_LOG(5, (THIS_FILE, "TX: %s key=%s", srtp->tx_policy.name.ptr, 434 octet_string_hex_string(tx->key.ptr, tx->key.slen))); 435 if (srtp->tx_policy.flags) { 436 PJ_LOG(5, (THIS_FILE, "TX: disable%s%s", (cr_tx_idx?"":" enc"), 437 (au_tx_idx?"":" auth"))); 438 } 439 440 PJ_LOG(5, (THIS_FILE, "RX: %s key=%s", srtp->rx_policy.name.ptr, 441 octet_string_hex_string(rx->key.ptr, rx->key.slen))); 442 if (srtp->rx_policy.flags) { 443 PJ_LOG(5, (THIS_FILE, "RX: disable%s%s", (cr_rx_idx?"":" enc"), 444 (au_rx_idx?"":" auth"))); 445 } 340 446 341 447 return PJ_SUCCESS; … … 438 544 err_status_t err; 439 545 546 if (srtp->bypass_srtp) 547 return pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len); 548 440 549 if (!srtp->session_inited) 441 550 return PJ_SUCCESS; 442 551 443 PJ_ASSERT_RETURN(size < sizeof(srtp->tx_buffer), PJ_ETOOBIG); 552 if (size > sizeof(srtp->tx_buffer)) 553 return PJ_ETOOBIG; 444 554 445 555 pj_lock_acquire(srtp->mutex); … … 450 560 status = pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len); 451 561 } else { 452 status = SRTP_ERROR(err);562 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err); 453 563 } 454 564 … … 467 577 err_status_t err; 468 578 579 if (srtp->bypass_srtp) 580 return pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len); 581 469 582 if (!srtp->session_inited) 470 583 return PJ_SUCCESS; 471 584 472 PJ_ASSERT_RETURN((size) < sizeof(srtp->tx_buffer), PJ_ETOOBIG); 585 if (size > sizeof(srtp->tx_buffer)) 586 return PJ_ETOOBIG; 473 587 474 588 pj_lock_acquire(srtp->mutex); … … 478 592 479 593 if (err == err_status_ok) { 480 status = pjmedia_transport_send_rtcp(srtp->real_tp, srtp->tx_buffer, len); 594 status = pjmedia_transport_send_rtcp(srtp->real_tp, srtp->tx_buffer, 595 len); 481 596 } else { 482 status = SRTP_ERROR(err);597 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err); 483 598 } 484 599 … … 525 640 int len = size; 526 641 err_status_t err; 642 643 if (srtp->bypass_srtp) { 644 srtp->rtp_cb(srtp->user_data, srtp->rx_buffer, len); 645 return; 646 } 527 647 528 648 if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) { … … 553 673 err_status_t err; 554 674 675 if (srtp->bypass_srtp) { 676 srtp->rtcp_cb(srtp->user_data, srtp->rx_buffer, len); 677 return; 678 } 679 555 680 if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) { 556 681 return; … … 575 700 * and set buffer_len = 0. 576 701 */ 577 static pj_status_t generate_crypto_attr_value(char *buffer, int *buffer_len, 578 int cs_idx, int cs_tag) 579 { 580 pj_uint8_t key[MAX_KEY_LEN]; 702 static pj_status_t generate_crypto_attr_value(pj_pool_t *pool, 703 char *buffer, int *buffer_len, 704 pjmedia_srtp_crypto *crypto, 705 int tag) 706 { 707 pj_status_t status; 708 int cs_idx = get_crypto_idx(&crypto->name); 581 709 char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1]; 582 710 int b64_key_len = sizeof(b64_key); 583 err_status_t err; 584 pj_status_t status; 585 pj_bool_t key_ok; 586 587 PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len, 588 PJ_ETOOSMALL); 711 712 if (cs_idx == -1) 713 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 589 714 590 715 /* Crypto-suite NULL. */ … … 594 719 } 595 720 596 /* Generate key. */ 597 do { 598 unsigned i; 599 key_ok = PJ_TRUE; 600 601 err = crypto_get_random(key, crypto_suites[cs_idx].cipher_key_len); 602 if (err != err_status_ok) { 603 PJ_LOG(5,(THIS_FILE, "Failed generating random key")); 604 return SRTP_ERROR(err); 605 } 606 for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i) 607 if (key[i] == 0) key_ok = PJ_FALSE; 608 609 } while (!key_ok); 721 /* Generate key if not specified. */ 722 if (crypto->key.slen == 0) { 723 pj_bool_t key_ok; 724 char key[MAX_KEY_LEN]; 725 err_status_t err; 726 int i; 727 728 PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len, 729 PJ_ETOOSMALL); 730 731 do { 732 key_ok = PJ_TRUE; 733 734 err = crypto_get_random((unsigned char*)key, 735 crypto_suites[cs_idx].cipher_key_len); 736 if (err != err_status_ok) { 737 PJ_LOG(5,(THIS_FILE, "Failed generating random key")); 738 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 739 } 740 for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i) 741 if (key[i] == 0) key_ok = PJ_FALSE; 742 743 } while (!key_ok); 744 key[crypto_suites[cs_idx].cipher_key_len] = '\0'; 745 pj_strdup2(pool, &crypto->key, key); 746 } 747 748 if ((unsigned)crypto->key.slen != crypto_suites[cs_idx].cipher_key_len) 749 return PJMEDIA_SRTP_EINKEYLEN; 610 750 611 751 /* Key transmitted via SDP should be base64 encoded. */ 612 status = pj_base64_encode( key, crypto_suites[cs_idx].cipher_key_len,752 status = pj_base64_encode((pj_uint8_t*)crypto->key.ptr, crypto->key.slen, 613 753 b64_key, &b64_key_len); 614 754 if (status != PJ_SUCCESS) { … … 618 758 619 759 b64_key[b64_key_len] = '\0'; 620 621 760 622 PJ_ASSERT_RETURN((unsigned)*buffer_len >= 623 (pj_ansi_strlen(crypto_suites[cs_idx].name) + 761 PJ_ASSERT_RETURN((unsigned)*buffer_len >= (crypto->name.slen + \ 624 762 b64_key_len + 16), PJ_ETOOSMALL); 625 763 626 764 /* Print the crypto attribute value. */ 627 765 *buffer_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s", 628 cs_tag,766 tag, 629 767 crypto_suites[cs_idx].name, 630 768 b64_key); 631 769 632 770 return PJ_SUCCESS; 633 }634 635 static pj_status_t transport_media_create(pjmedia_transport *tp,636 pj_pool_t *pool,637 pjmedia_sdp_session *sdp_local,638 const pjmedia_sdp_session *sdp_remote)639 {640 struct transport_srtp *srtp = (struct transport_srtp*) tp;641 enum { MAXLEN = 512 };642 char buffer[MAXLEN];643 pj_status_t status;644 unsigned i, j;645 unsigned cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);646 647 /* If we are the answerer side, skip generating crypto-suites offer */648 if (sdp_remote) {649 srtp->offerer_side = PJ_FALSE;650 return PJ_SUCCESS;651 }652 653 srtp->offerer_side = PJ_TRUE;654 655 for (i=0; i<sdp_local->media_count; ++i) {656 /* Change "RTP/AVP" transport to "RTP/SAVP" */657 if (pj_stricmp(&sdp_local->media[i]->desc.transport, &ID_RTP_AVP) == 0) {658 sdp_local->media[i]->desc.transport = ID_RTP_SAVP;659 660 /* Skip media transport that is not appropriate for SRTP */661 } else if (pj_stricmp(&sdp_local->media[i]->desc.transport,662 &ID_RTP_SAVP) != 0)663 {664 continue;665 }666 667 /* Generate "crypto" attribute(s) */668 for (j=1; j<cs_cnt; ++j) {669 /* Offer all our crypto-suites. */670 pj_str_t attr_value;671 int buffer_len = MAXLEN;672 pjmedia_sdp_attr *attr;673 674 status = generate_crypto_attr_value(buffer, &buffer_len, j, j);675 if (status != PJ_SUCCESS)676 return status;677 678 /* If buffer_len==0, just skip the crypto attribute. */679 if (buffer_len) {680 pj_strset(&attr_value, buffer, buffer_len);681 attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);682 sdp_local->media[i]->attr[sdp_local->media[i]->attr_count++] = attr;683 }684 }685 }686 687 return pjmedia_transport_media_create(srtp->real_tp, pool, sdp_local,688 sdp_remote);689 771 } 690 772 … … 692 774 static pj_status_t parse_attr_crypto(pj_pool_t *pool, 693 775 const pjmedia_sdp_attr *attr, 694 pjmedia_srtp_ stream_crypto *policy,776 pjmedia_srtp_crypto *crypto, 695 777 int *tag) 696 778 { 697 779 pj_str_t input; 698 780 char *token; 699 700 pj_bzero(policy, sizeof(*policy)); 781 pj_str_t tmp; 782 pj_status_t status; 783 int itmp; 784 785 pj_bzero(crypto, sizeof(*crypto)); 701 786 pj_strdup_with_null(pool, &input, &attr->value); 702 787 … … 708 793 } 709 794 *tag = atoi(token); 795 if (*tag == 0) 796 return PJMEDIA_SDP_EINATTR; 710 797 711 798 /* Crypto-suite */ … … 715 802 return PJMEDIA_SDP_EINATTR; 716 803 } 717 policy->crypto_suite = pj_str(token);804 crypto->name = pj_str(token); 718 805 719 806 /* Key method */ … … 734 821 return PJMEDIA_SDP_EINATTR; 735 822 } 736 policy->key = pj_str(token); 823 tmp = pj_str(token); 824 crypto->key.ptr = pj_pool_zalloc(pool, MAX_KEY_LEN); 825 826 /* Decode key */ 827 itmp = MAX_KEY_LEN; 828 status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr, 829 &itmp); 830 if (status != PJ_SUCCESS) { 831 PJ_LOG(5,(THIS_FILE, "Failed decoding key from base64")); 832 return status; 833 } 834 crypto->key.slen = itmp; 737 835 738 836 return PJ_SUCCESS; 739 837 } 838 839 static pj_status_t transport_media_create(pjmedia_transport *tp, 840 pj_pool_t *pool, 841 pjmedia_sdp_session *sdp_local, 842 const pjmedia_sdp_session *sdp_remote, 843 unsigned media_index) 844 { 845 struct transport_srtp *srtp = (struct transport_srtp*) tp; 846 pjmedia_sdp_media *m_rem, *m_loc; 847 enum { MAXLEN = 512 }; 848 char buffer[MAXLEN]; 849 int buffer_len = MAXLEN; 850 pj_status_t status; 851 pjmedia_sdp_attr *attr; 852 pj_str_t attr_value; 853 int i, j; 854 855 PJ_ASSERT_RETURN(tp && pool && sdp_local, PJ_EINVAL); 856 857 pj_bzero(&srtp->rx_policy, sizeof(srtp->rx_policy)); 858 pj_bzero(&srtp->tx_policy, sizeof(srtp->rx_policy)); 859 860 m_rem = sdp_remote ? sdp_remote->media[media_index] : NULL; 861 m_loc = sdp_local->media[media_index]; 862 863 /* bypass if media transport is not RTP/AVP or RTP/SAVP */ 864 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 && 865 pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0) 866 goto PROPAGATE_MEDIA_CREATE; 867 868 /* If the media is inactive, do nothing. */ 869 if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) || 870 (m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))) 871 { 872 goto PROPAGATE_MEDIA_CREATE; 873 } 874 875 srtp->offerer_side = !sdp_remote; 876 877 /* Check remote media transport & set local media transport 878 * based on SRTP usage option. 879 */ 880 if (srtp->offerer_side) { 881 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 882 goto PROPAGATE_MEDIA_CREATE; 883 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 884 m_loc->desc.transport = ID_RTP_AVP; 885 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 886 m_loc->desc.transport = ID_RTP_SAVP; 887 } 888 } else { 889 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 890 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) { 891 DEACTIVATE_MEDIA(pool, m_loc); 892 return PJMEDIA_SRTP_ESDPINTRANSPORT; 893 } 894 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 895 m_loc->desc.transport = m_rem->desc.transport; 896 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 897 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) { 898 DEACTIVATE_MEDIA(pool, m_loc); 899 return PJMEDIA_SRTP_ESDPINTRANSPORT; 900 } 901 } 902 } 903 904 /* Generate crypto attribute */ 905 if (srtp->offerer_side) { 906 for (i=0; i<srtp->setting.crypto_count; ++i) { 907 /* Offer crypto-suites based on setting. */ 908 status = generate_crypto_attr_value(pool, buffer, &buffer_len, 909 &srtp->setting.crypto[i], 910 i+1); 911 if (status != PJ_SUCCESS) 912 return status; 913 914 /* If buffer_len==0, just skip the crypto attribute. */ 915 if (buffer_len) { 916 pj_strset(&attr_value, buffer, buffer_len); 917 attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value); 918 m_loc->attr[m_loc->attr_count++] = attr; 919 } 920 } 921 } else { 922 /* find supported crypto-suite, get the tag, and assign policy_local */ 923 pjmedia_srtp_crypto tmp_rx_crypto; 924 pj_bool_t has_crypto_attr = PJ_FALSE; 925 pj_bool_t has_match = PJ_FALSE; 926 int chosen_tag = 0; 927 int tags[8]; 928 int cr_count = 0; 929 int k; 930 931 for (i=0; i<m_rem->attr_count; ++i) { 932 if (pj_stricmp2(&m_rem->attr[i]->name, "crypto") != 0) 933 continue; 934 935 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 936 DEACTIVATE_MEDIA(pool, m_loc); 937 return PJMEDIA_SRTP_ESDPINTRANSPORT; 938 } 939 940 has_crypto_attr = PJ_TRUE; 941 942 status = parse_attr_crypto(pool, m_rem->attr[i], 943 &tmp_rx_crypto, &tags[cr_count]); 944 if (status != PJ_SUCCESS) 945 return status; 946 947 /* Check duplicated tag */ 948 for (k=0; k<cr_count; ++k) { 949 if (tags[k] == tags[cr_count]) { 950 DEACTIVATE_MEDIA(pool, m_loc); 951 return PJMEDIA_SRTP_ESDPDUPCRYPTOTAG; 952 } 953 } 954 955 if (!has_match) { 956 /* lets see if the crypto-suite offered is supported */ 957 for (j=0; j<srtp->setting.crypto_count; ++j) 958 if (pj_stricmp(&tmp_rx_crypto.name, 959 &srtp->setting.crypto[j].name) == 0) 960 { 961 srtp->tx_policy = srtp->setting.crypto[j]; 962 srtp->rx_policy = tmp_rx_crypto; 963 chosen_tag = tags[cr_count]; 964 has_match = PJ_TRUE; 965 break; 966 } 967 } 968 cr_count++; 969 } 970 971 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 972 /* At this point, it is ensured remote has no crypto attr */ 973 goto PROPAGATE_MEDIA_CREATE; 974 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 975 if (!has_crypto_attr) 976 goto PROPAGATE_MEDIA_CREATE;; 977 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 978 if (!has_crypto_attr) { 979 DEACTIVATE_MEDIA(pool, m_loc); 980 return PJMEDIA_SRTP_ESDPREQCRYPTO; 981 } 982 } 983 984 /* No crypto match? */ 985 if (!has_match) { 986 DEACTIVATE_MEDIA(pool, m_loc); 987 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 988 } 989 990 /* we have to generate crypto answer, 991 * with srtp->tx_policy matched the offer 992 * and rem_tag contains matched offer tag. 993 */ 994 status = generate_crypto_attr_value(pool, buffer, &buffer_len, 995 &srtp->tx_policy, 996 chosen_tag); 997 if (status != PJ_SUCCESS) 998 return status; 999 1000 /* If buffer_len==0, just skip the crypto attribute. */ 1001 if (buffer_len) { 1002 pj_strset(&attr_value, buffer, buffer_len); 1003 attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value); 1004 m_loc->attr[m_loc->attr_count++] = attr; 1005 } 1006 1007 /* At this point, 1008 * we should have valid rx_policy & tx_policy. 1009 */ 1010 } 1011 1012 PROPAGATE_MEDIA_CREATE: 1013 return pjmedia_transport_media_create(srtp->real_tp, pool, sdp_local, 1014 sdp_remote, media_index); 1015 } 1016 1017 740 1018 741 1019 static pj_status_t transport_media_start(pjmedia_transport *tp, … … 746 1024 { 747 1025 struct transport_srtp *srtp = (struct transport_srtp*) tp; 748 pjmedia_sdp_media *m edia_remote = sdp_remote->media[media_index];749 pj media_sdp_media *media_local = sdp_local->media[media_index];1026 pjmedia_sdp_media *m_rem, *m_loc; 1027 pj_status_t status; 750 1028 pjmedia_sdp_attr *attr; 751 pjmedia_srtp_stream_crypto policy_remote; 752 pjmedia_srtp_stream_crypto policy_local; 753 pj_status_t status; 754 unsigned cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]); 755 int cs_tag = -1; 756 unsigned i, j; 1029 int i; 1030 1031 PJ_ASSERT_RETURN(tp && pool && sdp_local && sdp_remote, PJ_EINVAL); 1032 1033 m_rem = sdp_remote->media[media_index]; 1034 m_loc = sdp_local->media[media_index]; 1035 1036 /* bypass if media transport is not RTP/AVP or RTP/SAVP */ 1037 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 && 1038 pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0) 1039 goto PROPAGATE_MEDIA_START; 757 1040 758 1041 /* If the media is inactive, do nothing. */ 759 if (pjmedia_sdp_media_find_attr 2(media_remote, "inactive", NULL) ||760 pjmedia_sdp_media_find_attr2(media_local, "inactive", NULL))1042 if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) || 1043 (m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))) 761 1044 { 762 return PJ_SUCCESS; 763 } 764 765 /* default crypto-suite = crypto 'NULL' */ 766 pj_bzero(&policy_remote, sizeof(policy_remote)); 767 policy_remote.crypto_suite = pj_str(crypto_suites[0].name); 768 pj_bzero(&policy_local, sizeof(policy_local)); 769 policy_remote.crypto_suite = pj_str(crypto_suites[0].name); 770 771 /* If the media transport is not RTP/SAVP, just apply crypto default */ 772 if (pj_stricmp(&media_local->desc.transport, &ID_RTP_SAVP) || 773 pj_stricmp(&media_remote->desc.transport, &ID_RTP_SAVP)) 774 { 775 return PJMEDIA_SRTP_ESDPREQSECTP; 776 } 777 778 /* 779 * In this stage, we need to make sure the crypto-suite negotiation 780 * is completed, and also parse the key from SDP. 1045 goto PROPAGATE_MEDIA_START; 1046 } 1047 1048 /* For answerer side, this function will just have to start SRTP */ 1049 1050 /* Check remote media transport & set local media transport 1051 * based on SRTP usage option. 781 1052 */ 782 1053 if (srtp->offerer_side) { 783 /* If we are at the offerer side: 784 * 1. Get what crypto-suite selected by remote, we use the same one. 785 * 2. Get what key we offered in the offering stage for 786 * the selected crypto-suite. 787 * 3. If no crypto-suite answered, assume the answerer want plain RTP. 788 * (perhaps this will abuse RFC 4568) 789 */ 790 791 /* Make sure only thera is ONLY ONE crypto attribute in the answer. */ 792 attr = NULL; 793 for (i=0; i<media_remote->attr_count; ++i) { 794 if (!pj_stricmp2(&media_local->attr[i]->name, "crypto")) { 795 if (attr) { 796 PJ_LOG(5,(THIS_FILE, "More than one crypto attr in " \ 797 "the SDP answer.")); 798 return PJMEDIA_SRTP_ESDPAMBIGUEANS; 799 } 800 801 attr = media_local->attr[i]; 802 } 803 } 804 if (!attr) { 805 /* the answer got no crypto-suite attribute, huh! */ 806 PJ_LOG(5,(THIS_FILE, "Crypto attribute cannot be found in" \ 807 "remote SDP, using NULL crypto.")); 808 } else { 809 810 /* get policy_remote */ 811 status = parse_attr_crypto(pool, attr, &policy_remote, &cs_tag); 1054 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 1055 if (pjmedia_sdp_media_find_attr2(m_rem, "crypto", NULL)) { 1056 DEACTIVATE_MEDIA(pool, m_loc); 1057 return PJMEDIA_SRTP_ESDPINCRYPTO; 1058 } 1059 goto PROPAGATE_MEDIA_START;; 1060 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 1061 if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) { 1062 DEACTIVATE_MEDIA(pool, m_loc); 1063 return PJMEDIA_SDP_EINPROTO; 1064 } 1065 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 1066 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) { 1067 DEACTIVATE_MEDIA(pool, m_loc); 1068 return PJMEDIA_SDP_EINPROTO; 1069 } 1070 } 1071 } 1072 1073 if (srtp->offerer_side) { 1074 /* find supported crypto-suite, get the tag, and assign policy_local */ 1075 pj_bool_t has_crypto_attr = PJ_FALSE; 1076 int rem_tag; 1077 1078 for (i=0; i<m_rem->attr_count; ++i) { 1079 if (pj_stricmp2(&m_rem->attr[i]->name, "crypto") != 0) 1080 continue; 1081 1082 /* more than one crypto attribute in media answer */ 1083 if (has_crypto_attr) { 1084 DEACTIVATE_MEDIA(pool, m_loc); 1085 return PJMEDIA_SRTP_ESDPAMBIGUEANS; 1086 } 1087 1088 has_crypto_attr = PJ_TRUE; 1089 1090 status = parse_attr_crypto(pool, m_rem->attr[i], 1091 &srtp->rx_policy, &rem_tag); 812 1092 if (status != PJ_SUCCESS) 813 1093 return status; 814 1094 815 /* lets see what crypto-suite chosen, we will use the same one */ 816 for (i=1; i<cs_cnt; ++i) { 817 if (!pj_stricmp2(&policy_remote.crypto_suite, 818 crypto_suites[i].name)) 819 break; 820 } 821 822 /* The crypto-suite answered is not supported, 823 * this SHOULD NEVER happen, since we only offer what we support, 824 * except the answerer is trying to force us use his crypto-suite! 825 * Let's return non-PJ_SUCCESS and cancel the call. 826 */ 827 if (i == cs_cnt) { 828 return PJ_ENOTSUP; 829 } 830 831 /* check whether the answer is match to our offers, 832 * then get our own offered key along with the crypto-suite 833 * and put it in policy_local. 834 */ 835 for (i=0; i<media_local->attr_count; ++i) { 836 int tmp_cs_tag; 837 838 if (pj_stricmp2(&media_local->attr[i]->name, "crypto")) 839 continue; 840 841 status = parse_attr_crypto(pool, media_local->attr[i], 842 &policy_local, &tmp_cs_tag); 843 if (status != PJ_SUCCESS) 844 return status; 845 846 /* Selected crypto-suite is marked by same crypto attr tag */ 847 if (tmp_cs_tag == cs_tag) 848 break; 849 } 850 /* This SHOULD NEVER happen. */ 851 if (i == media_local->attr_count) { 852 return PJMEDIA_SDPNEG_ENOMEDIA; 853 } 854 855 /* Check if crypto-suite name match, crypto tag was ensured same */ 856 if (pj_stricmp(&policy_local.crypto_suite, 857 &policy_remote.crypto_suite)) 1095 1096 /* our offer tag is always ordered by setting */ 1097 if (rem_tag<1 || rem_tag>srtp->setting.crypto_count) { 1098 DEACTIVATE_MEDIA(pool, m_loc); 1099 return PJMEDIA_SRTP_ESDPINCRYPTOTAG; 1100 } 1101 1102 /* match the crypto name */ 1103 if (pj_stricmp(&srtp->rx_policy.name, 1104 &srtp->setting.crypto[rem_tag-1].name) != 0) 858 1105 { 859 return PJMEDIA_ERROR; 860 } 861 } 862 } else { 863 /* If we are at the answerer side: 864 * 1. Negotiate: check if any offered crypto-suite matches 865 * our capability. 866 * 2. If there is one, generate key and media attribute. 867 * 3. If there isn't, return error. 868 * 4. If no crypto-suite offered, apply NULL crypto-suite. 869 * (perhaps this will abuse RFC 4568) 870 * 871 * Please note that we need to consider the existance of other media, 872 * so instead of returning non-PJ_SUCCESS on failed negotiation, 873 * which will cancel the call, perhaps it is wiser to mark the media 874 * as inactive. 1106 DEACTIVATE_MEDIA(pool, m_loc); 1107 return PJMEDIA_SRTP_ECRYPTONOTMATCH; 1108 } 1109 1110 srtp->tx_policy = srtp->setting.crypto[rem_tag-1]; 1111 } 1112 1113 if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 1114 /* should never reach here */ 1115 goto PROPAGATE_MEDIA_START; 1116 } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 1117 if (!has_crypto_attr) 1118 goto PROPAGATE_MEDIA_START; 1119 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 1120 if (!has_crypto_attr) { 1121 DEACTIVATE_MEDIA(pool, m_loc); 1122 return PJMEDIA_SRTP_ESDPREQCRYPTO; 1123 } 1124 } 1125 1126 /* At this point, 1127 * we should have valid rx_policy & tx_policy. 875 1128 */ 876 877 enum { MAXLEN = 512 };878 char buffer[MAXLEN];879 int buffer_len = MAXLEN;880 pj_str_t attr_value;881 pj_bool_t no_crypto_attr = PJ_TRUE;882 int cs_idx = -1;883 884 /* find supported crypto-suite, get the tag, and assign policy_local */885 for (i=0; (i<media_remote->attr_count) && (cs_idx == -1); ++i) {886 if (pj_stricmp2(&media_remote->attr[i]->name, "crypto"))887 continue;888 889 no_crypto_attr = PJ_FALSE;890 891 status = parse_attr_crypto(pool, media_remote->attr[i],892 &policy_remote, &cs_tag);893 if (status != PJ_SUCCESS)894 return status;895 896 /* lets see if the crypto-suite offered is supported */897 for (j=1; j<cs_cnt; ++j) {898 if (!pj_stricmp2(&policy_remote.crypto_suite,899 crypto_suites[j].name))900 {901 cs_idx = j;902 break;903 }904 }905 }906 907 if (!no_crypto_attr) {908 /* No crypto-suites offered is supported by us.909 * What should we do?910 * By now, let's just deactivate the media.911 */912 if (i == media_remote->attr_count) {913 attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);914 media_local->attr[media_local->attr_count++] = attr;915 media_local->desc.port = 0;916 917 return PJ_SUCCESS;918 }919 920 /* there is crypto-suite supported921 * let's generate crypto attribute and also the key,922 * dont forget to use offerer cs_tag.923 */924 status = generate_crypto_attr_value(buffer, &buffer_len, cs_idx, cs_tag);925 if (status != PJ_SUCCESS)926 return status;927 928 /* If buffer_len==0, just skip the crypto attribute. */929 if (buffer_len) {930 pj_strset(&attr_value, buffer, buffer_len);931 attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);932 media_local->attr[media_local->attr_count++] = attr;933 934 /* put our key & crypto-suite name to policy_local */935 status = parse_attr_crypto(pool, attr, &policy_local, &cs_tag);936 if (status != PJ_SUCCESS)937 return status;938 }939 }940 }941 942 /* in the SDP, all keys are in base64, they have to be decoded back943 * to base256 before used.944 */945 if (policy_local.key.slen) {946 char key[MAX_KEY_LEN];947 int key_len = MAX_KEY_LEN;948 949 status = pj_base64_decode(&policy_local.key,950 (pj_uint8_t*)key, &key_len);951 if (status != PJ_SUCCESS)952 return status;953 954 pj_memcpy(policy_local.key.ptr, key, key_len);955 policy_local.key.slen = key_len;956 }957 958 if (policy_remote.key.slen) {959 char key[MAX_KEY_LEN];960 int key_len = MAX_KEY_LEN;961 962 status = pj_base64_decode(&policy_remote.key,963 (pj_uint8_t*)key, &key_len);964 if (status != PJ_SUCCESS)965 return status;966 967 pj_memcpy(policy_remote.key.ptr, key, key_len);968 policy_remote.key.slen = key_len;969 1129 } 970 1130 971 1131 /* Got policy_local & policy_remote, let's initalize the SRTP */ 972 status = pjmedia_transport_srtp_start(tp, & policy_local, &policy_remote);1132 status = pjmedia_transport_srtp_start(tp, &srtp->tx_policy, &srtp->rx_policy); 973 1133 if (status != PJ_SUCCESS) 974 1134 return status; 975 1135 1136 PROPAGATE_MEDIA_START: 976 1137 return pjmedia_transport_media_start(srtp->real_tp, pool, 977 1138 sdp_local, sdp_remote,
Note: See TracChangeset
for help on using the changeset viewer.