From 3dad15f9380c924f3818e7719545d46a32020977 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 28 Feb 2014 02:03:48 +0500 Subject: [PATCH] FS-5755 part 2 rtp_secure_media=true --inbound: Accept the srongest supported offered crypto suite, MUST result in a negotiated crypto or aborts. --outbound: offer all supported crypto suites, MUST result in a negotiated crypto or aborts. rtp_secure_media=optional --inbound: Accept the srongest supported offered crypto suite, fall back to no crypto if no valid ones accepted. --outbound: offer all supported crypto suites, OPTIONAL result in a negotiated crypto falls back to no crypto. rtp_secure_media=, --inbound: same behaviour as rtp_secure_media=true with smaller set of acceptable suites. --outbound: offer supplied crypto suites, same behaviour as rtp_secure_media=true with smaller set of suites. --- src/include/switch_types.h | 1 - src/switch_core_media.c | 371 +++++++++++++++++++++++-------------- 2 files changed, 233 insertions(+), 139 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 65b395959c..fb7a0510fb 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -2329,7 +2329,6 @@ typedef enum { AES_CM_192_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_32, AES_CM_128_NULL_AUTH, - NO_CRYPTO, CRYPTO_INVALID } switch_rtp_crypto_key_type_t; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 3a7207be1d..458b418d7f 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -60,8 +60,6 @@ typedef struct secure_settings_s { int crypto_tag; unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]; unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]; - switch_rtp_crypto_key_type_t crypto_send_type; - switch_rtp_crypto_key_type_t crypto_recv_type; switch_rtp_crypto_key_type_t crypto_type; char *local_crypto_key; char *remote_crypto_key; @@ -78,7 +76,9 @@ struct media_helper { typedef struct switch_rtp_engine_s { - switch_secure_settings_t ssec; + switch_secure_settings_t ssec[CRYPTO_INVALID+1]; + switch_rtp_crypto_key_type_t crypto_type; + switch_media_type_t type; switch_rtp_t *rtp_session; @@ -146,7 +146,7 @@ typedef struct switch_rtp_engine_s { uint8_t fir; uint8_t pli; - + uint8_t no_crypto; } switch_rtp_engine_t; @@ -193,8 +193,7 @@ static switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID] = { { "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46}, { "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38}, { "AES_CM_128_HMAC_SHA1_32", AES_CM_128_HMAC_SHA1_32, 30}, - { "AES_CM_128_NULL_AUTH", AES_CM_128_NULL_AUTH, 30}, - { "NULL", NO_CRYPTO, 0 } + { "AES_CM_128_NULL_AUTH", AES_CM_128_NULL_AUTH, 30} }; SWITCH_DECLARE(switch_rtp_crypto_key_type_t) switch_core_media_crypto_str2type(const char *str) @@ -709,8 +708,10 @@ SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *ses const char *vars[] = { "rtp_last_audio_local_crypto_key", "srtp_remote_audio_crypto_key", "srtp_remote_audio_crypto_tag", + "srtp_remote_audio_crypto_type", "srtp_remote_video_crypto_key", "srtp_remote_video_crypto_tag", + "srtp_remote_video_crypto_type", "rtp_secure_media", NULL}; @@ -721,9 +722,10 @@ SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *ses if (!(smh = session->media_handle)) { return; } - - memset(&smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec)); - memset(&smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec)); + for (i = 0; i < CRYPTO_INVALID; i++) { + memset(&smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec[i], 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec[i])); + memset(&smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec[i], 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec[i])); + } } @@ -733,7 +735,7 @@ SWITCH_DECLARE(const char *) switch_core_session_local_crypto_key(switch_core_se return NULL; } - return session->media_handle->engines[type].ssec.local_crypto_key; + return session->media_handle->engines[type].ssec[session->media_handle->engines[type].crypto_type].local_crypto_key; } @@ -859,7 +861,7 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh engine = &smh->engines[type]; - if (!force && engine->ssec.local_raw_key[0]) { + if (!force && engine->ssec[ctype].local_raw_key[0]) { return SWITCH_STATUS_SUCCESS; } @@ -869,18 +871,18 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh #ifdef SAME_KEY if (switch_channel_test_flag(channel, CF_WEBRTC) && type == SWITCH_MEDIA_TYPE_VIDEO) { if (direction == SWITCH_RTP_CRYPTO_SEND) { - memcpy(engine->ssec.local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keylen); - key = engine->ssec.local_raw_key; + memcpy(engine->ssec[ctype].local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keylen); + key = engine->ssec[ctype].local_raw_key; } else { - memcpy(engine->ssec.remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keylen); - key = engine->ssec.remote_raw_key; + memcpy(engine->ssec[ctype].remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keylen); + key = engine->ssec[ctype].remote_raw_key; } } else { #endif if (direction == SWITCH_RTP_CRYPTO_SEND) { - key = engine->ssec.local_raw_key; + key = engine->ssec[ctype].local_raw_key; } else { - key = engine->ssec.remote_raw_key; + key = engine->ssec[ctype].remote_raw_key; } switch_rtp_get_random(key, SUITES[ctype].keylen); @@ -895,17 +897,21 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh *p-- = '\0'; } - engine->ssec.local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, SUITES[ctype].name, b64_key); - switch_channel_set_variable_name_printf(smh->session->channel, engine->ssec.local_crypto_key, "rtp_last_%s_local_crypto_key", type2str(type)); + if (!index) index = ctype + 1; + + engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, SUITES[ctype].name, b64_key); + switch_channel_set_variable_name_printf(smh->session->channel, engine->ssec[ctype].local_crypto_key, "rtp_last_%s_local_crypto_key", type2str(type)); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", engine->ssec.local_crypto_key); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local %s crypto Key [%s]\n", + type2str(type), + engine->ssec[ctype].local_crypto_key); if (!(smh->mparams->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) && !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) { - engine->ssec.crypto_type = ctype; + engine->ssec[ctype].crypto_type = ctype; } else { - engine->ssec.crypto_type = AES_CM_128_NULL_AUTH; + engine->ssec[ctype].crypto_type = AES_CM_128_NULL_AUTH; } return SWITCH_STATUS_SUCCESS; @@ -946,10 +952,8 @@ switch_status_t switch_core_media_add_crypto(switch_secure_settings_t *ssec, con switch_b64_decode(p, (char *) key, sizeof(key)); if (direction == SWITCH_RTP_CRYPTO_SEND) { - ssec->crypto_send_type = type; memcpy(ssec->local_raw_key, key, SUITES[type].keylen); } else { - ssec->crypto_recv_type = type; memcpy(ssec->remote_raw_key, key, SUITES[type].keylen); } return SWITCH_STATUS_SUCCESS; @@ -978,7 +982,7 @@ static void switch_core_session_get_recovery_crypto_key(switch_core_session_t *s { const char *tmp; switch_rtp_engine_t *engine; - char *keyvar, *tagvar; + char *keyvar, *tagvar, *ctypevar; if (!session->media_handle) return; engine = &session->media_handle->engines[type]; @@ -986,20 +990,25 @@ static void switch_core_session_get_recovery_crypto_key(switch_core_session_t *s if (type == SWITCH_MEDIA_TYPE_AUDIO) { keyvar = "srtp_remote_audio_crypto_key"; tagvar = "srtp_remote_audio_crypto_tag"; + ctypevar = "srtp_remote_audio_crypto_type"; } else { keyvar = "srtp_remote_video_crypto_key"; tagvar = "srtp_remote_video_crypto_tag"; + ctypevar = "srtp_remote_video_crypto_type"; } - if ((tmp = switch_channel_get_variable(session->channel, keyvar))) { - engine->ssec.remote_crypto_key = switch_core_session_strdup(session, tmp); + if ((tmp = switch_channel_get_variable(session->channel, ctypevar))) { + engine->crypto_type = switch_core_media_crypto_str2type(tmp); + } + + engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, tmp); if ((tmp = switch_channel_get_variable(session->channel, tagvar))) { int tv = atoi(tmp); - engine->ssec.crypto_tag = tv; + engine->ssec[engine->crypto_type].crypto_tag = tv; } else { - engine->ssec.crypto_tag = 1; + engine->ssec[engine->crypto_type].crypto_tag = 1; } switch_channel_set_flag(session->channel, CF_SECURE); @@ -1025,15 +1034,20 @@ static void switch_core_session_apply_crypto(switch_core_session_t *session, swi return; } - if (engine->ssec.remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) { - switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); + if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) { + switch_core_media_add_crypto(&engine->ssec[engine->crypto_type], engine->ssec[engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1, - engine->ssec.crypto_type, engine->ssec.local_raw_key, SUITES[engine->ssec.crypto_type].keylen); + engine->ssec[engine->crypto_type].crypto_type, + engine->ssec[engine->crypto_type].local_raw_key, + SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen); - switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec.crypto_tag, - engine->ssec.crypto_type, engine->ssec.remote_raw_key, SUITES[engine->ssec.crypto_type].keylen); + switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, + engine->ssec[engine->crypto_type].crypto_tag, + engine->ssec[engine->crypto_type].crypto_type, + engine->ssec[engine->crypto_type].remote_raw_key, + SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen); switch_channel_set_variable(session->channel, varname, "true"); } @@ -1056,6 +1070,10 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio engine = &session->media_handle->engines[type]; + if (suite && !strcasecmp(suite, "optional")) { + suite = "true"; + } + if (zstr(suite) || (!switch_true(suite) && switch_core_media_crypto_str2type(suite) == CRYPTO_INVALID)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto suite: [%s] not valid in this context.\n", crypto); goto end; @@ -1073,40 +1091,53 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio } } - if (engine->ssec.remote_crypto_key && switch_rtp_ready(engine->rtp_session)) { + if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_rtp_ready(engine->rtp_session)) { /* Compare all the key. The tag may remain the same even if key changed */ - if (crypto && !strcmp(crypto, engine->ssec.remote_crypto_key)) { + if (crypto && engine->crypto_type != CRYPTO_INVALID && !strcmp(crypto, engine->ssec[engine->crypto_type].remote_crypto_key)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n"); got_crypto = 1; } else { - const char *a = switch_stristr("AE", engine->ssec.remote_crypto_key); + const char *a = switch_stristr("AE", engine->ssec[engine->crypto_type].remote_crypto_key); const char *b = switch_stristr("AE", crypto); if (sdp_type == SDP_TYPE_REQUEST) { if (!vval) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unsupported Crypto [%s]\n", crypto); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto); goto end; } switch_channel_set_variable(session->channel, varname, vval); switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1); - switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec.crypto_type, - engine->ssec.local_raw_key, SUITES[ctype].keylen); + switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec[engine->crypto_type].crypto_type, + engine->ssec[engine->crypto_type].local_raw_key, SUITES[ctype].keylen); } if (a && b && !strncasecmp(a, b, 23)) { + engine->crypto_type = ctype; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto); - engine->ssec.remote_crypto_key = switch_core_session_strdup(session, crypto); - switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto); - switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_tag", "%d", crypto_tag); - engine->ssec.crypto_tag = crypto_tag; + engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto); + + if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) { + switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto); + switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_tag", "%d", crypto_tag); + switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype)); + } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) { + switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto); + switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_tag", "%d", crypto_tag); + switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype)); + } + + engine->ssec[engine->crypto_type].crypto_tag = crypto_tag; + if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE)) { - switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); - switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec.crypto_tag, - engine->ssec.crypto_type, engine->ssec.remote_raw_key, SUITES[engine->ssec.crypto_type].keylen); + switch_core_media_add_crypto(&engine->ssec[engine->crypto_type], engine->ssec[engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); + switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec[engine->crypto_type].crypto_tag, + engine->ssec[engine->crypto_type].crypto_type, engine->ssec[engine->crypto_type].remote_raw_key, SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen); } got_crypto++; + } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n"); } @@ -1114,17 +1145,26 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio } else if (!switch_rtp_ready(engine->rtp_session)) { if (!vval) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unsupported Crypto [%s]\n", crypto); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto); goto end; } - engine->ssec.remote_crypto_key = switch_core_session_strdup(session, crypto); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", engine->ssec.remote_crypto_key); - switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto); - engine->ssec.crypto_tag = crypto_tag; + engine->crypto_type = ctype; + engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", engine->ssec[engine->crypto_type].remote_crypto_key); + if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) { + switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto); + switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype)); + } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) { + switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto); + switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype)); + } + + engine->ssec[engine->crypto_type].crypto_tag = crypto_tag; got_crypto++; - if (zstr(engine->ssec.local_crypto_key)) { + + if (zstr(engine->ssec[engine->crypto_type].local_crypto_key)) { switch_channel_set_variable(session->channel, varname, vval); switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1); } @@ -1143,36 +1183,28 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_session_t *session, const char *sec_var) { switch_channel_t *channel = switch_core_session_get_channel(session); - const char *var; if (!switch_core_session_media_handle_ready(session) == SWITCH_STATUS_SUCCESS) { return; } - if ((var = switch_channel_get_variable(channel, sec_var)) && !zstr(var)) { + if (!zstr(sec_var)) { int i; - switch_rtp_crypto_key_type_t ctype = CRYPTO_INVALID; - - if (switch_true(var)) { - ctype = AES_CM_128_HMAC_SHA1_32; - } else { - for (i = 0; i < CRYPTO_INVALID; i++) { - if (!strcasecmp(var, SUITES[i].name)) { - ctype = SUITES[i].type; - break; - } + int all = switch_true(sec_var) || !strcasecmp(sec_var, "optional"); + + for (i = 0; i < CRYPTO_INVALID; i++) { + if (all || switch_stristr(SUITES[i].name, sec_var)) { + + switch_channel_set_flag(channel, CF_SECURE); + + switch_core_media_build_crypto(session->media_handle, + SWITCH_MEDIA_TYPE_AUDIO, 0, SUITES[i].type, SWITCH_RTP_CRYPTO_SEND, 0); + + switch_core_media_build_crypto(session->media_handle, + SWITCH_MEDIA_TYPE_VIDEO, 0, SUITES[i].type, SWITCH_RTP_CRYPTO_SEND, 0); } } - - if (ctype != CRYPTO_INVALID) { - switch_channel_set_flag(channel, CF_SECURE); - switch_core_media_build_crypto(session->media_handle, - SWITCH_MEDIA_TYPE_AUDIO, 1, ctype, SWITCH_RTP_CRYPTO_SEND, 0); - switch_core_media_build_crypto(session->media_handle, - SWITCH_MEDIA_TYPE_VIDEO, 1, ctype, SWITCH_RTP_CRYPTO_SEND, 0); - } } - } #define add_stat(_i, _s) \ @@ -1286,6 +1318,8 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t { switch_status_t status = SWITCH_STATUS_FALSE; switch_media_handle_t *smh = NULL; + int i; + *smhp = NULL; if (zstr(params->sdp_username)) { @@ -1302,10 +1336,21 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t session->media_handle->media_flags[SCMF_RUNNING] = 1; session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN; session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].type = SWITCH_MEDIA_TYPE_AUDIO; + session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].crypto_type = CRYPTO_INVALID; + for (i = 0; i < CRYPTO_INVALID; i++) { + session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec[i].crypto_type = i; + } + + session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN; session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].type = SWITCH_MEDIA_TYPE_VIDEO; - session->media_handle->mparams = params; + session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].crypto_type = CRYPTO_INVALID; + for (i = 0; i < CRYPTO_INVALID; i++) { + session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec[i].crypto_type = i; + } + session->media_handle->mparams = params; + switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); @@ -2770,8 +2815,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s const char *tmp; int m_idx = 0; int nm_idx = 0; + int needs_crypto = 0; const char *var; - + switch_assert(session); if (!(smh = session->media_handle)) { @@ -2793,9 +2839,17 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s return 0; } - if (sdp_type == SDP_TYPE_REQUEST && (var = switch_channel_get_variable(session->channel, "rtp_secure_media"))) { - if (!switch_true(var) && switch_core_media_crypto_str2type(var) == CRYPTO_INVALID) { - got_crypto = -1; + if (!switch_channel_test_flag(session->channel, CF_DTLS) && (var = switch_channel_get_variable(session->channel, "rtp_secure_media"))) { + if (strcasecmp(var, "optional")) { + needs_crypto = 1; + + switch_channel_set_variable(session->channel, "rtp_crypto_mandatory", "true"); + + if (sdp_type == SDP_TYPE_REQUEST) { + if (!switch_true(var) && switch_core_media_crypto_str2type(var) == CRYPTO_INVALID) { + got_crypto = -1; + } + } } } @@ -2808,7 +2862,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s clear_pmaps(a_engine); clear_pmaps(v_engine); - if (proceed) *proceed = 1; greedy = !!switch_media_handle_test_media_flag(smh, SCMF_CODEC_GREEDY); @@ -3114,11 +3167,14 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) { switch_channel_set_variable(session->channel, "rtp_remote_audio_rtcp_port", attr->a_value); a_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value); + if (!smh->mparams->rtcp_audio_interval_msec) { + smh->mparams->rtcp_audio_interval_msec = "5000"; + } } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) { ptime = atoi(attr->a_value); } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) { maxptime = atoi(attr->a_value); - } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { //&& + } else if (got_crypto < 1 && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { //&& //(!switch_channel_test_flag(session->channel, CF_WEBRTC) || switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, attr->a_value))) { int crypto_tag; @@ -3139,11 +3195,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } } - if (got_crypto > 0 && !got_avp) { - switch_channel_set_variable(session->channel, "rtp_crypto_mandatory", "true"); - //switch_channel_set_variable(session->channel, "rtp_secure_media", "true"); - } - if (got_crypto == -1 && got_savp && !got_avp && !got_webrtc) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Declining invite with only SAVP because secure media is administratively disabled\n"); match = 0; @@ -3322,6 +3373,13 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } } + if (needs_crypto && got_crypto < 1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n"); + match = 0; + m_idx = nm_idx = 0; + } + + if (!m_idx && nm_idx) { int j; @@ -3563,6 +3621,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } else if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !strcmp(attr->a_value, "1")) { switch_channel_set_variable(session->channel, "rtp_remote_video_rtcp_port", attr->a_value); v_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value); + if (!smh->mparams->rtcp_video_interval_msec) { + smh->mparams->rtcp_video_interval_msec = "5000"; + } } else if (!got_video_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { int crypto_tag; @@ -3585,11 +3646,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } } - if (got_video_crypto && !got_video_avp) { - switch_channel_set_variable(session->channel, "rtp_crypto_mandatory", "true"); - //switch_channel_set_variable(session->channel, "rtp_secure_media", "true"); - } - if (!(rm_encoding = map->rm_encoding)) { rm_encoding = ""; } @@ -3628,6 +3684,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } } + if (needs_crypto && got_video_crypto < 1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n"); + vmatch = 0; + m_idx = 0; + } + if (m_idx) { char tmp[50]; //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload"); @@ -4607,7 +4669,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_rtp_reset_media_timer(a_engine->rtp_session); } - if ((var = switch_channel_get_variable(session->channel, "rtp_secure_media")) && (switch_true(var) || switch_core_media_crypto_str2type(var) != CRYPTO_INVALID)) { + if (!switch_channel_test_flag(session->channel, CF_SECURE) && (var = switch_channel_get_variable(session->channel, "rtp_secure_media")) && + (switch_true(var) || switch_core_media_crypto_str2type(var) != CRYPTO_INVALID)) { switch_channel_set_flag(session->channel, CF_SECURE); } @@ -4947,11 +5010,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi xtype = DTLS_TYPE_RTP; - if (a_engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP; + if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP; switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype); - if (a_engine->rtcp_mux < 1) { + if (a_engine->rtcp_mux < 1 && smh->mparams->rtcp_audio_interval_msec) { xtype = DTLS_TYPE_RTCP; switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype); } @@ -5367,11 +5430,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi dtls_type_t xtype, dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER; xtype = DTLS_TYPE_RTP; - if (v_engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP; + if (v_engine->rtcp_mux > 0 && smh->mparams->rtcp_video_interval_msec) xtype |= DTLS_TYPE_RTCP; switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype); - if (v_engine->rtcp_mux < 1) { + if (v_engine->rtcp_mux < 1 && smh->mparams->rtcp_video_interval_msec) { xtype = DTLS_TYPE_RTCP; switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype); } @@ -5464,7 +5527,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, int rate; int already_did[128] = { 0 }; int ptime = 0, noptime = 0; - const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); + //const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); const char *local_sdp_audio_zrtp_hash; switch_media_handle_t *smh; switch_rtp_engine_t *a_engine; @@ -5480,7 +5543,10 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP%s", //port, secure ? "S" : "", switch_channel_test_flag(session->channel, CF_WEBRTC) ? "F" : ""); - switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d %s", port, get_media_profile_name(session, secure)); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d %s", port, + get_media_profile_name(session, + (secure && switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) || + a_engine->crypto_type != CRYPTO_INVALID)); for (i = 0; i < smh->mparams->num_codecs; i++) { @@ -5698,8 +5764,14 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, } - if (secure && !zstr(local_audio_crypto_key)) { - switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key); + if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) { + int i; + + for (i = 0; i < CRYPTO_INVALID; i++) { + if ((a_engine->crypto_type == i || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[i].local_crypto_key)) { + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", a_engine->ssec[i].local_crypto_key); + } + } //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n"); } @@ -5857,7 +5929,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess const char *fmtp_out_var = switch_channel_get_variable(session->channel, "rtp_force_audio_fmtp"); switch_event_t *map = NULL, *ptmap = NULL; //const char *b_sdp = NULL; - const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); + //const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); const char *local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE); const char *local_sdp_video_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_TRUE); const char *tmp; @@ -5867,6 +5939,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess int vp8 = 0; int red = 0; payload_map_t *pmap; + int is_outbound = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND; + const char *secure_media_var = switch_channel_get_variable(session->channel, "rtp_secure_media"); + int secure_only = 0; + + + if (!zstr(secure_media_var) && is_outbound && strcasecmp(secure_media_var, "optional")) { + secure_only = 0; + } switch_assert(session); @@ -5877,12 +5957,25 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO]; + if (switch_true(switch_channel_get_variable(session->channel, "rtcp_mux"))) { + a_engine->rtcp_mux = 1; + v_engine->rtcp_mux = 1; + } + + if (!smh->mparams->rtcp_audio_interval_msec) { + smh->mparams->rtcp_audio_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec"); + } + + if (!smh->mparams->rtcp_video_interval_msec) { + smh->mparams->rtcp_video_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_video_interval_msec"); + } + if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) { switch_channel_clear_flag(smh->session->channel, CF_DTLS_OK); switch_channel_clear_flag(smh->session->channel, CF_DTLS); } - if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_channel_test_flag(session->channel, CF_RECOVERING)) { + if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) { if (!switch_channel_test_flag(session->channel, CF_WEBRTC) && switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) { switch_channel_set_flag(session->channel, CF_WEBRTC); @@ -5900,12 +5993,11 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } } - switch_core_session_check_outgoing_crypto(session, "rtp_secure_media"); - local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); + switch_core_session_check_outgoing_crypto(session, secure_media_var); } else { if (switch_channel_test_flag(smh->session->channel, CF_DTLS)) { - local_audio_crypto_key = NULL; + a_engine->no_crypto = 1; } } @@ -6083,18 +6175,12 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess if (a_engine->codec_negotiated) { - /* - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP%s", - port, ((!zstr(local_audio_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) && - switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "", - switch_channel_test_flag(session->channel, CF_WEBRTC) ? "F" : ""); - */ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d %s", port, get_media_profile_name(session, - ((!zstr(local_audio_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) && - switch_channel_test_flag(session->channel, CF_SECURE)) - )); + ((!a_engine->no_crypto || switch_channel_test_flag(session->channel, CF_DTLS)) && + a_engine->crypto_type != CRYPTO_INVALID + ))); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->cur_payload_map->pt); @@ -6258,7 +6344,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } - if (a_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || + if (a_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", @@ -6289,9 +6375,11 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess - if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) { - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key); - //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n"); + if (a_engine->crypto_type != CRYPTO_INVALID && !switch_channel_test_flag(session->channel, CF_DTLS) && + !zstr(a_engine->ssec[a_engine->crypto_type].local_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) { + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", a_engine->ssec[a_engine->crypto_type].local_crypto_key); + //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n"); } } else if (smh->mparams->num_codecs) { @@ -6314,7 +6402,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess char *bp = buf; int both = switch_channel_test_flag(session->channel, CF_WEBRTC) ? 0 : 1; - if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || + if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) || switch_channel_test_flag(session->channel, CF_DTLS)) { generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1, sdp_type); bp = (buf + strlen(buf)); @@ -6326,7 +6414,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } - if (both) { + if (both && !secure_only) { generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0, sdp_type); } @@ -6351,7 +6439,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess cur_ptime = this_ptime; - if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || + if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) || switch_channel_test_flag(session->channel, CF_DTLS)) { generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1, sdp_type); bp = (buf + strlen(buf)); @@ -6366,7 +6454,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess both = 0; } - if (both) { + if (both && !secure_only) { generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0, sdp_type); } } @@ -6377,11 +6465,9 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) { - const char *local_video_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_VIDEO); - if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) { if (switch_channel_test_flag(smh->session->channel, CF_DTLS)) { - local_video_crypto_key = NULL; + v_engine->no_crypto = 1; } } @@ -6408,8 +6494,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d %s", v_port, get_media_profile_name(session, - (!zstr(local_video_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) - && switch_channel_test_flag(session->channel, CF_SECURE))); + (!v_engine->no_crypto || switch_channel_test_flag(session->channel, CF_DTLS)) + && v_engine->crypto_type != CRYPTO_INVALID)); @@ -6595,7 +6681,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } - if ((switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_channel_test_flag(session->channel, CF_RECOVERING)) + if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) && switch_channel_test_flag(smh->session->channel, CF_DTLS)) { generate_local_fingerprint(smh, SWITCH_MEDIA_TYPE_VIDEO); } @@ -6689,7 +6775,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } - if (v_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || + if (v_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", @@ -6720,8 +6806,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess - if (switch_channel_test_flag(session->channel, CF_SECURE) && !zstr(local_video_crypto_key)){ - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key); + if (switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS) && + v_engine->crypto_type != CRYPTO_INVALID && + !zstr(v_engine->ssec[v_engine->crypto_type].local_crypto_key)) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", v_engine->ssec[v_engine->crypto_type].local_crypto_key); //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n"); } @@ -6747,6 +6835,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_safe_free(buf); } + + //? SWITCH_DECLARE(void) switch_core_media_absorb_sdp(switch_core_session_t *session) { @@ -8490,19 +8580,24 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s switch_core_session_get_recovery_crypto_key(session, SWITCH_MEDIA_TYPE_VIDEO); - if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec.remote_crypto_key) { + if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec[a_engine->crypto_type].remote_crypto_key) { int idx = atoi(tmp); - a_engine->ssec.local_crypto_key = switch_core_session_strdup(session, tmp); - switch_core_media_add_crypto(&a_engine->ssec, a_engine->ssec.local_crypto_key, SWITCH_RTP_CRYPTO_SEND); - switch_core_media_add_crypto(&a_engine->ssec, a_engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); + a_engine->ssec[a_engine->crypto_type].local_crypto_key = switch_core_session_strdup(session, tmp); + switch_core_media_add_crypto(&a_engine->ssec[a_engine->crypto_type], a_engine->ssec[a_engine->crypto_type].local_crypto_key, SWITCH_RTP_CRYPTO_SEND); + switch_core_media_add_crypto(&a_engine->ssec[a_engine->crypto_type], a_engine->ssec[a_engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV); switch_channel_set_flag(smh->session->channel, CF_SECURE); switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, idx, - a_engine->ssec.crypto_send_type, a_engine->ssec.local_raw_key, SUITES[a_engine->ssec.crypto_send_type].keylen); + a_engine->crypto_type, + a_engine->ssec[a_engine->crypto_type].local_raw_key, + SUITES[a_engine->crypto_type].keylen); - switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, a_engine->ssec.crypto_tag, - a_engine->ssec.crypto_recv_type, a_engine->ssec.remote_raw_key, SUITES[a_engine->ssec.crypto_recv_type].keylen); + switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, + a_engine->ssec[a_engine->crypto_type].crypto_tag, + a_engine->crypto_type, + a_engine->ssec[a_engine->crypto_type].remote_raw_key, + SUITES[a_engine->crypto_type].keylen); }