Fix reINVITE issues when SRTP mode is mandatory

This commit is contained in:
bossiel 2015-06-09 00:58:22 +00:00
parent 493815f88e
commit 9f4760fe25
4 changed files with 305 additions and 291 deletions

View File

@ -1107,6 +1107,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
tsk_bool_t is_ice_enabled[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_ice_restart[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_dtls_fingerprint_changed[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_sdes_crypto_changed[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tmedia_type_t media_types[TMEDIA_SESSION_MAX_LINES] = { tmedia_none };
tsk_bool_t is_media_type_changed = tsk_false;
tsk_bool_t is_ro_media_lines_changed = tsk_false;
@ -1189,12 +1190,13 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
while ((M0 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(self->sdp.ro, tsdp_htype_M, index))){
++m_lines_count;
if (m_lines_count >= TMEDIA_SESSION_MAX_LINES) {
TSK_DEBUG_ERROR("Too many m-lines %d>%d", m_lines_count, TMEDIA_SESSION_MAX_LINES);
TSK_DEBUG_ERROR("Too many m-lines %u>%u", (unsigned)m_lines_count, (unsigned)TMEDIA_SESSION_MAX_LINES);
ret = -2;
goto bail;
}
M1 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index);
// media-level diffs
if ((ret = tsdp_header_M_diff(M0, M1, &med_level_diff)) != 0) {
goto bail;
}
@ -1205,8 +1207,8 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_enabled)) is_ice_enabled[index] = tsk_true;
if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_restart)) is_ice_restart[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_dtls_fingerprint) is_dtls_fingerprint_changed[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_sdes_crypto);
if (med_level_diff & tsdp_header_M_diff_media_type);
if (med_level_diff & tsdp_header_M_diff_sdes_crypto) is_sdes_crypto_changed[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_media_type); // cannot happen as media must keep same index
// dtls fingerprint (session-level)
if (!is_dtls_fingerprint_changed[index]) {
@ -1225,6 +1227,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
}
}
}
// TODO: sdes crypo lines (session-level)
// media type
media_types[index] = tmedia_type_from_sdp_headerM(M1);
@ -1313,6 +1316,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
TSK_DEBUG_INFO(
"m_lines_count=%u,\n"
"is_dtls_fingerprint_changed=%u,\n"
"is_sdes_crypto_changed=%u,\n"
"is_ice_enabled=%u,\n"
"is_ice_restart=%u,\n"
"is_ro_hold_resume_changed=%u,\n"
@ -1325,6 +1329,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
"is_local_encoder_still_ok=%u\n",
(unsigned)m_lines_count,
(unsigned)__flags_sum((const tsk_bool_t*)&is_dtls_fingerprint_changed, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_sdes_crypto_changed, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ice_enabled, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ice_restart, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ro_hold_resume_changed, m_lines_count),
@ -1348,7 +1353,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
*/
if (self->started) {
for (index = 0; index < m_lines_count; ++index) {
if (/* && (!is_ro_loopback_address[index]) && */ ((is_ro_codecs_changed[index] && !is_local_encoder_still_ok[index]) || is_ro_network_info_changed[index] || is_dtls_fingerprint_changed[index])) {
if (/* && (!is_ro_loopback_address[index]) && */ ((is_ro_codecs_changed[index] && !is_local_encoder_still_ok[index]) || is_ro_network_info_changed[index] || is_dtls_fingerprint_changed[index] || is_sdes_crypto_changed[index])) {
TSK_DEBUG_INFO("Stop media index %d to reconf", (int)index);
stopped_to_reconf[index] = tsk_true;
tmedia_session_mgr_set(self,
@ -1518,7 +1523,7 @@ end_of_sessions_update:
for (index = 0; index < m_lines_count; ++index) {
if (stopped_to_reconf[index] && !is_ice_enabled[index]) {
if ((ret = _tmedia_session_mgr_start(self, (int)index))) {
TSK_DEBUG_ERROR("Failed to re-start session at index = %d", index);
TSK_DEBUG_ERROR("Failed to re-start session at index = %d", (int)index);
goto bail;
}
}
@ -2365,7 +2370,7 @@ static int _tmedia_session_mgr_start(tmedia_session_mgr_t* self, int session_ind
}
}
}
if (session_index) {
if (session_index == kSessionIndexAll) {
self->started = tsk_true;
}

View File

@ -91,6 +91,7 @@ typedef struct trtp_srtp_ctx_internal_xs
trtp_srtp_crypto_type_t crypto_type;
char key_str[SRTP_MAX_KEY_LEN];
char key_bin[SRTP_MASTER_KEY_LEN];
tsk_bool_t have_valid_key;
srtp_t session;
srtp_policy_t policy;

View File

@ -1,23 +1,23 @@
/*
* Copyright (C) 2012 Mamadou Diop
* Copyright (C) 2012-2013 Doubango Telecom <http://www.doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
* Copyright (C) 2012 Mamadou Diop
* Copyright (C) 2012-2013 Doubango Telecom <http://www.doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file trtp_srtp.c
*/
#include "tinyrtp/trtp_srtp.h"
@ -30,297 +30,303 @@ crypto_get_random(unsigned char *buffer, unsigned int length);
int trtp_srtp_ctx_internal_init(struct trtp_srtp_ctx_internal_xs* ctx, int32_t tag, trtp_srtp_crypto_type_t type, uint32_t ssrc)
{
char* key_str = ctx->key_str;
err_status_t srtp_err;
tsk_size_t size;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(ctx->initialized){
trtp_srtp_ctx_internal_deinit(ctx);
}
ctx->tag = tag;
ctx->crypto_type = type;
if((srtp_err = crypto_get_random((unsigned char*)ctx->key_bin, sizeof(ctx->key_bin))) != err_status_ok){
TSK_DEBUG_ERROR("crypto_get_random() failed");
return -2;
}
size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str);
key_str[size] = '\0';
switch(ctx->crypto_type){
case HMAC_SHA1_80:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp);
break;
}
case HMAC_SHA1_32:
default:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); // RTCP always 80
break;
}
}
ctx->policy.key = (unsigned char*)ctx->key_bin;
ctx->policy.ssrc.type = ssrc_any_outbound;
ctx->policy.ssrc.value = ssrc;
ctx->policy.window_size = 2048;
ctx->policy.allow_repeat_tx = 1;
if((srtp_err = srtp_create(&ctx->session, &ctx->policy)) != err_status_ok){
TSK_DEBUG_ERROR("srtp_create() failed");
return -3;
}
ctx->initialized = tsk_true;
return 0;
char* key_str = ctx->key_str;
err_status_t srtp_err;
tsk_size_t size;
if (!ctx) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (ctx->initialized) {
trtp_srtp_ctx_internal_deinit(ctx);
}
ctx->tag = tag;
ctx->crypto_type = type;
if (!ctx->have_valid_key) { // use same key to avoid unseless SRTP re-negs (also fix interop-issues against buggy clients -reINVITEs-)
if ((srtp_err = crypto_get_random((unsigned char*)ctx->key_bin, sizeof(ctx->key_bin))) != err_status_ok) {
TSK_DEBUG_ERROR("crypto_get_random() failed");
return -2;
}
size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str);
key_str[size] = '\0';
ctx->have_valid_key = tsk_true;
}
switch(ctx->crypto_type){
case HMAC_SHA1_80:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp);
break;
}
case HMAC_SHA1_32:
default:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); // RTCP always 80
break;
}
}
ctx->policy.key = (unsigned char*)ctx->key_bin;
ctx->policy.ssrc.type = ssrc_any_outbound;
ctx->policy.ssrc.value = ssrc;
ctx->policy.window_size = 2048;
ctx->policy.allow_repeat_tx = 1;
if ((srtp_err = srtp_create(&ctx->session, &ctx->policy)) != err_status_ok) {
TSK_DEBUG_ERROR("srtp_create() failed");
return -3;
}
ctx->initialized = tsk_true;
return 0;
}
int trtp_srtp_ctx_internal_deinit(struct trtp_srtp_ctx_internal_xs* ctx)
{
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(ctx->initialized){
/*err_status_t srtp_err =*/ srtp_dealloc(ctx->session);
memset(&ctx->policy, 0, sizeof(ctx->policy));
ctx->initialized = tsk_false;
}
return 0;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(ctx->initialized){
/*err_status_t srtp_err =*/ srtp_dealloc(ctx->session);
memset(&ctx->policy, 0, sizeof(ctx->policy));
ctx->initialized = tsk_false;
}
return 0;
}
int trtp_srtp_ctx_init(trtp_srtp_ctx_xt* ctx, int32_t tag, trtp_srtp_crypto_type_t type, uint32_t ssrc)
{
int ret;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if((ret = trtp_srtp_ctx_internal_init(&ctx->rtp, tag, type, ssrc))){
return ret;
}
return trtp_srtp_ctx_internal_init(&ctx->rtcp, tag, type, ssrc);
int ret;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if((ret = trtp_srtp_ctx_internal_init(&ctx->rtp, tag, type, ssrc))){
return ret;
}
return trtp_srtp_ctx_internal_init(&ctx->rtcp, tag, type, ssrc);
}
int trtp_srtp_ctx_deinit(trtp_srtp_ctx_xt* ctx)
{
int ret;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if((ret = trtp_srtp_ctx_internal_deinit(&ctx->rtp))){
return ret;
}
return trtp_srtp_ctx_internal_deinit(&ctx->rtcp);
{
int ret;
if(!ctx){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if((ret = trtp_srtp_ctx_internal_deinit(&ctx->rtp))){
return ret;
}
return trtp_srtp_ctx_internal_deinit(&ctx->rtcp);
}
int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_type, char* key, tsk_size_t key_size)
{
char* saveptr;
char* v = tsk_strtok_r((char*)crypto_line, " :|;", &saveptr);
int32_t k = 0;
while(v){
switch(k){
case 0:
{
if(tag){
*tag = atoi(v);
}
break;
}
case 1:
{
if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_80)){
if(crypto_type){
*crypto_type = HMAC_SHA1_80;
}
}
else if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32)){
if(crypto_type){
*crypto_type = HMAC_SHA1_32;
}
}
else {
return -0xFF;
}
break;
}
case 2:
{
if(!tsk_striequals(v, "inline")){
return -0xFF;
}
break;
}
case 3:
{
if(key && key_size){
memset(key, 0, key_size);
memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v)));
}
return 0;
}
}
++k;
v = tsk_strtok_r(tsk_null, " :|;", &saveptr);
}
return -0xF0;
char* copyptr = tsk_strdup(crypto_line); // "strtok_r" will insert "\0" and modify the string
char* saveptr = tsk_null;
char* v = tsk_strtok_r(copyptr, " :|;", &saveptr);
int32_t k = 0;
int ret = -0xF0;
while(v){
switch(k){
case 0:
{
if(tag){
*tag = atoi(v);
}
break;
}
case 1:
{
if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_80)){
if(crypto_type){
*crypto_type = HMAC_SHA1_80;
}
}
else if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32)){
if(crypto_type){
*crypto_type = HMAC_SHA1_32;
}
}
else {
ret = -0xFF; goto bail;
}
break;
}
case 2:
{
if(!tsk_striequals(v, "inline")){
ret = -0xFF; goto bail;
}
break;
}
case 3:
{
if(key && key_size){
memset(key, 0, key_size);
memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v)));
}
ret = 0; goto bail;
}
}
++k;
v = tsk_strtok_r(tsk_null, " :|;", &saveptr);
}
bail:
TSK_FREE(copyptr);
return ret;
}
tsk_size_t trtp_srtp_get_local_contexts(trtp_manager_t* rtp_mgr, const struct trtp_srtp_ctx_xs ** contexts, tsk_size_t contexts_count)
{
tsk_size_t ret = 0;
if(!rtp_mgr || !contexts){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if(contexts_count > ret && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.initialized){
contexts[ret++] = &rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80];
}
if(contexts_count > ret && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.initialized){
contexts[ret++] = &rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32];
}
return ret;
tsk_size_t ret = 0;
if(!rtp_mgr || !contexts){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if (contexts_count > ret && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.initialized) {
contexts[ret++] = &rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80];
}
if (contexts_count > ret && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.initialized) {
contexts[ret++] = &rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32];
}
return ret;
}
int trtp_srtp_set_crypto(struct trtp_manager_s* rtp_mgr, const char* crypto_line, int32_t idx)
{
//e.g. 2 F8_128_HMAC_SHA1_80 inline:MTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5QUJjZGVm|2^20|1:4;inline:QUJjZGVmMTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5|2^20|2:4"
trtp_srtp_ctx_xt* srtp_ctx;
int ret;
uint8_t *key_bin;
err_status_t srtp_err;
int32_t tag, crypto_type;
char key_str[SRTP_MAX_KEY_LEN + 1];
memset(key_str, 0, sizeof(key_str));
if((ret = trtp_srtp_match_line(crypto_line, &tag, &crypto_type, key_str, sizeof(key_str) - 1))){
return ret;
}
srtp_ctx = &rtp_mgr->srtp_contexts[idx][crypto_type];
ret = trtp_srtp_ctx_deinit(srtp_ctx);
srtp_ctx->rtp.tag = tag;
srtp_ctx->rtp.crypto_type = (trtp_srtp_crypto_type_t)crypto_type;
memcpy(srtp_ctx->rtp.key_str, key_str, sizeof(srtp_ctx->rtp.key_str));
switch(srtp_ctx->rtp.crypto_type){
case HMAC_SHA1_80:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp);
if(idx == TRTP_SRTP_LINE_IDX_REMOTE){
trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32]);
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.tag =
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtcp.tag = srtp_ctx->rtp.tag;
}
break;
}
case HMAC_SHA1_32:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->rtp.policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); // RTCP always 80
if(idx == TRTP_SRTP_LINE_IDX_REMOTE){
trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]);
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.tag =
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtcp.tag = srtp_ctx->rtp.tag;
}
break;
}
//e.g. 2 F8_128_HMAC_SHA1_80 inline:MTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5QUJjZGVm|2^20|1:4;inline:QUJjZGVmMTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5|2^20|2:4"
trtp_srtp_ctx_xt* srtp_ctx;
int ret;
uint8_t *key_bin;
err_status_t srtp_err;
int32_t tag, crypto_type;
char key_str[SRTP_MAX_KEY_LEN + 1];
memset(key_str, 0, sizeof(key_str));
if ((ret = trtp_srtp_match_line(crypto_line, &tag, &crypto_type, key_str, sizeof(key_str) - 1))) {
return ret;
}
srtp_ctx = &rtp_mgr->srtp_contexts[idx][crypto_type];
ret = trtp_srtp_ctx_deinit(srtp_ctx);
srtp_ctx->rtp.tag = tag;
srtp_ctx->rtp.crypto_type = (trtp_srtp_crypto_type_t)crypto_type;
memcpy(srtp_ctx->rtp.key_str, key_str, sizeof(srtp_ctx->rtp.key_str));
switch(srtp_ctx->rtp.crypto_type){
case HMAC_SHA1_80:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp);
if (idx == TRTP_SRTP_LINE_IDX_REMOTE) {
trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32]);
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.tag =
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtcp.tag = srtp_ctx->rtp.tag;
}
break;
}
case HMAC_SHA1_32:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->rtp.policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); // RTCP always 80
if (idx == TRTP_SRTP_LINE_IDX_REMOTE) {
trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]);
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.tag =
rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtcp.tag = srtp_ctx->rtp.tag;
}
break;
}
default: break;
}
key_bin = (unsigned char*)srtp_ctx->rtp.key_bin;
tsk_base64_decode((const uint8_t*)srtp_ctx->rtp.key_str, tsk_strlen(srtp_ctx->rtp.key_str), (char**)&key_bin);
srtp_ctx->rtp.policy.key = key_bin;
srtp_ctx->rtp.policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
srtp_ctx->rtp.policy.window_size = 2048;
srtp_ctx->rtp.policy.allow_repeat_tx = 1;
if((srtp_err = srtp_create(&srtp_ctx->rtp.session, &srtp_ctx->rtp.policy)) != err_status_ok){
TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
return -3;
}
srtp_ctx->rtp.initialized = tsk_true;
return 0;
}
key_bin = (unsigned char*)srtp_ctx->rtp.key_bin;
tsk_base64_decode((const uint8_t*)srtp_ctx->rtp.key_str, (tsk_size_t)tsk_strlen(srtp_ctx->rtp.key_str), (char**)&key_bin);
srtp_ctx->rtp.policy.key = key_bin;
srtp_ctx->rtp.policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
srtp_ctx->rtp.policy.window_size = 2048;
srtp_ctx->rtp.policy.allow_repeat_tx = 1;
if ((srtp_err = srtp_create(&srtp_ctx->rtp.session, &srtp_ctx->rtp.policy)) != err_status_ok) {
TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
return -3;
}
srtp_ctx->rtp.initialized = tsk_true;
return 0;
}
int trtp_srtp_set_key_and_salt(trtp_manager_t* rtp_mgr, trtp_srtp_crypto_type_t crypto_type, const void* key, tsk_size_t key_size, const void* salt, tsk_size_t salt_size, int32_t idx, tsk_bool_t is_rtp)
{
int ret;
trtp_srtp_ctx_internal_xt* srtp_ctx;
err_status_t srtp_err;
if(!rtp_mgr || !key || !key_size || !salt || !salt_size){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
srtp_ctx = is_rtp ? &rtp_mgr->srtp_contexts[idx][crypto_type].rtp : &rtp_mgr->srtp_contexts[idx][crypto_type].rtcp;
if((ret = trtp_srtp_ctx_internal_deinit(srtp_ctx))){
return ret;
}
switch((srtp_ctx->crypto_type = crypto_type)){
case HMAC_SHA1_80:
default:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp);
break;
}
case HMAC_SHA1_32:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // always 80
break;
}
}
memcpy(srtp_ctx->key_bin, key, key_size);
int ret;
trtp_srtp_ctx_internal_xt* srtp_ctx;
err_status_t srtp_err;
if (!rtp_mgr || !key || !key_size || !salt || !salt_size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
srtp_ctx = is_rtp ? &rtp_mgr->srtp_contexts[idx][crypto_type].rtp : &rtp_mgr->srtp_contexts[idx][crypto_type].rtcp;
if ((ret = trtp_srtp_ctx_internal_deinit(srtp_ctx))) {
return ret;
}
switch ((srtp_ctx->crypto_type = crypto_type)) {
case HMAC_SHA1_80:
default:
{
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp);
break;
}
case HMAC_SHA1_32:
{
crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // always 80
break;
}
}
memcpy(srtp_ctx->key_bin, key, key_size);
#if HAVE_APPEND_SALT_TO_KEY
append_salt_to_key(srtp_ctx->key_bin, key_size, (void*)salt, salt_size);
append_salt_to_key(srtp_ctx->key_bin, key_size, (void*)salt, salt_size);
#else
memcpy(&srtp_ctx->key_bin[key_size], salt, salt_size);
memcpy(&srtp_ctx->key_bin[key_size], salt, salt_size);
#endif
srtp_ctx->policy.key = (unsigned char *)srtp_ctx->key_bin;
srtp_ctx->policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
srtp_ctx->policy.window_size = 2048;
srtp_ctx->policy.allow_repeat_tx = 1;
if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok){
TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
return -3;
}
srtp_ctx->initialized = tsk_true;
return 0;
srtp_ctx->policy.key = (unsigned char *)srtp_ctx->key_bin;
srtp_ctx->policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
srtp_ctx->policy.window_size = 2048;
srtp_ctx->policy.allow_repeat_tx = 1;
if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok){
TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
return -3;
}
srtp_ctx->initialized = tsk_true;
return 0;
}
tsk_bool_t trtp_srtp_is_initialized(trtp_manager_t* rtp_mgr)
{
if(!rtp_mgr){
return tsk_false;
}
return ((rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0].rtp.initialized || rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1].rtp.initialized)
&& rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][0].rtp.initialized);
if (!rtp_mgr) {
return tsk_false;
}
return ((rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0].rtp.initialized || rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1].rtp.initialized)
&& rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][0].rtp.initialized);
}
tsk_bool_t trtp_srtp_is_started(trtp_manager_t* rtp_mgr)
{
if(!rtp_mgr){
TSK_DEBUG_ERROR("Invalid argument");
return tsk_false;
}
return (rtp_mgr ->srtp_ctx_neg_remote && rtp_mgr ->srtp_ctx_neg_local);
if (!rtp_mgr) {
TSK_DEBUG_ERROR("Invalid argument");
return tsk_false;
}
return (rtp_mgr ->srtp_ctx_neg_remote && rtp_mgr ->srtp_ctx_neg_local);
}
#endif /* HAVE_SRTP */

View File

@ -818,13 +818,13 @@ tsk_bool_t tsdp_header_M_is_ice_enabled(const tsdp_header_M_t* self)
const tsdp_header_A_t *A;
tsk_bool_t have_ufrag = tsk_false, have_pwd = tsk_false, have_candidates = tsk_false;
if ((A = tsdp_header_M_findA(self, "ice-ufrag"))) {
have_ufrag = tsk_true;
}
if ((A = tsdp_header_M_findA(self, "ice-pwd"))) {
have_pwd = tsk_true;
}
have_candidates = (tsdp_header_M_findA_at(self, "candidate", 0) != tsk_null);
if ((A = tsdp_header_M_findA(self, "ice-ufrag"))) {
have_ufrag = tsk_true;
}
if ((A = tsdp_header_M_findA(self, "ice-pwd"))) {
have_pwd = tsk_true;
}
have_candidates = (tsdp_header_M_findA_at(self, "candidate", 0) != tsk_null);
return have_ufrag && have_pwd && have_candidates;
}
return tsk_false;
@ -873,14 +873,16 @@ int tsdp_header_M_diff(const tsdp_header_M_t* M_old, const tsdp_header_M_t* M_ne
do {
A0 = tsdp_header_M_findA_at(M_old, "crypto", index);
A1 = M_new ? tsdp_header_M_findA_at(M_new, "crypto", index) : tsk_null;
if (A0 && A1 && !tsk_striequals(A0->value, A1->value)) {
diff |= tsdp_header_M_diff_dtls_fingerprint;
}
else if ((A0 && !A1) || (!A0 && A1)) {
diff |= tsdp_header_M_diff_dtls_fingerprint;
}
if (A0 && A1) {
if (!tsk_striequals(A0->value, A1->value)) {
diff |= tsdp_header_M_diff_sdes_crypto;
}
}
else if (index == 0) { // (A1 && !AO) means "more" crypto lines, otherwise "less". In all cases if the first matched we're ok
diff |= tsdp_header_M_diff_sdes_crypto;
}
++index;
} while (A0 && A1);
} while ((A0 && A1) && ((diff & tsdp_header_M_diff_sdes_crypto) != tsdp_header_M_diff_sdes_crypto));
// media lines
if ((diff & tsdp_header_M_diff_index) != tsdp_header_M_diff_index) {