Commit fbc8f77e authored by Simon Morlat's avatar Simon Morlat

allow crypto lines to be configured from linphonerc, and improve code handling SRTP crypto lines

parent cc5570ca
......@@ -999,3 +999,4 @@ void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer) {
belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
belle_sip_main_loop_remove_source(ml, timer);
}
......@@ -146,36 +146,15 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
if ( stream->proto == SalProtoRtpSavp ) {
/* add crypto lines */
for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) {
const char *enc_name=NULL;
switch ( stream->crypto[j].algo ) {
case MS_AES_128_SHA1_80:
enc_name="AES_CM_128_HMAC_SHA1_80";
break;
case MS_AES_128_SHA1_32:
enc_name="AES_CM_128_HMAC_SHA1_32";
break;
case MS_AES_256_SHA1_32:
enc_name="AES_CM_256_HMAC_SHA1_32";
break;
case MS_AES_256_SHA1_80:
enc_name="AES_CM_256_HMAC_SHA1_32";
break;
case MS_AES_128_NO_AUTH:
ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" );
break;
case MS_NO_CIPHER_SHA1_80:
ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" );
break;
default:
j = SAL_CRYPTO_ALGO_MAX;
/* no break */
}
if (enc_name){
snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s",
stream->crypto[j].tag, enc_name, stream->crypto[j].master_key );
belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) );
}
MSCryptoSuiteNameParams desc;
if (ms_crypto_suite_to_name_params(stream->crypto[j].algo,&desc)==0){
if (desc.params)
snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s %s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key,desc.params);
else
snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key );
belle_sdp_media_description_add_attribute( media_desc,belle_sdp_attribute_create ("crypto", buffer));
}else break;
}
}
switch ( stream->dir ) {
......@@ -330,7 +309,7 @@ static void sdp_parse_payload_types(belle_sdp_media_description_t *media_desc, S
static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
belle_sip_list_t *attribute_it;
belle_sdp_attribute_t *attribute;
char tmp[256], tmp2[256];
char tmp[256], tmp2[256], parameters[256]={0};
int valid_count = 0;
int nb;
......@@ -341,42 +320,39 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med
attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );
if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s",
nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s %256s",
&stream->crypto[valid_count].tag,
tmp,
tmp2 );
ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
stream->crypto[valid_count].tag,
tmp,
tmp2 );
if ( nb == 3 ) {
if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 ){
stream->crypto[valid_count].algo = MS_AES_128_SHA1_80;
}else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 ){
stream->crypto[valid_count].algo = MS_AES_128_SHA1_32;
}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_32",tmp ) == 0 ){
stream->crypto[valid_count].algo = MS_AES_256_SHA1_32;
}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_80",tmp ) == 0 ){
stream->crypto[valid_count].algo = MS_AES_256_SHA1_80;
}else {
tmp2, parameters );
if ( nb >= 3 ) {
MSCryptoSuite cs;
MSCryptoSuiteNameParams np;
np.name=tmp;
np.params=parameters[0]!='\0' ? parameters : NULL;
cs=ms_crypto_suite_build_from_name_params(&np);
if (cs==MS_CRYPTO_SUITE_INVALID){
ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
stream->crypto[valid_count].algo = 0;
}
if ( stream->crypto[valid_count].algo ) {
strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 );
stream->crypto[valid_count].master_key[40] = '\0';
}else{
char *sep;
strncpy ( stream->crypto[valid_count].master_key, tmp2, sizeof(stream->crypto[valid_count].master_key)-1 );
sep=strchr(stream->crypto[valid_count].master_key,'|');
if (sep) *sep='\0';
stream->crypto[valid_count].algo = cs;
ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
stream->crypto[valid_count].tag,
tmp,
stream->crypto[valid_count].master_key );
valid_count++;
}
} else {
}else{
ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
}
}
}
ms_message ( "Found: %d valid crypto lines", valid_count );
ms_message("Found: %d valid crypto lines", valid_count );
}
static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
......
......@@ -232,9 +232,35 @@ static void update_media_description_from_stun(SalMediaDescription *md, const St
}
}
static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){
int keylen=0;
crypto->tag=tag;
crypto->algo=suite;
switch(suite){
case MS_AES_128_SHA1_80:
case MS_AES_128_SHA1_32:
case MS_AES_128_NO_AUTH:
case MS_NO_CIPHER_SHA1_80: /*not sure for this one*/
keylen=30;
break;
case MS_AES_256_SHA1_80:
case MS_AES_256_SHA1_32:
keylen=46;
break;
case MS_CRYPTO_SUITE_INVALID:
break;
}
if (keylen==0 || !generate_b64_crypto_key(30, crypto->master_key, SAL_SRTP_KEY_SIZE)){
ms_error("Could not generate SRTP key.");
crypto->algo = 0;
return -1;
}
return 0;
}
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
LinphoneCore *lc=call->core;
int i;
int i,j;
SalMediaDescription *old_md=call->localdesc;
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
......@@ -247,15 +273,10 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
}
}else{
md->streams[i].crypto[0].tag = 1;
md->streams[i].crypto[0].algo = MS_AES_128_SHA1_80;
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE))
md->streams[i].crypto[0].algo = 0;
md->streams[i].crypto[1].tag = 2;
md->streams[i].crypto[1].algo = MS_AES_128_SHA1_32;
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE))
md->streams[i].crypto[1].algo = 0;
md->streams[i].crypto[2].algo = 0;
const MSCryptoSuite *suites=linphone_core_get_srtp_crypto_suites(lc);
for(j=0;suites!=NULL && suites[j]!=MS_CRYPTO_SUITE_INVALID && j<SAL_CRYPTO_ALGO_MAX;++j){
setup_encryption_key(&md->streams[i].crypto[j],suites[j],j+1);
}
}
}
}
......
......@@ -5738,6 +5738,7 @@ void rtp_config_uninit(LinphoneCore *lc)
lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
lp_config_set_int(lc->config,"rtp","audio_adaptive_jitt_comp_enabled",config->audio_adaptive_jitt_comp_enabled);
lp_config_set_int(lc->config,"rtp","video_adaptive_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
ms_free(config->srtp_suites);
}
static void sound_config_uninit(LinphoneCore *lc)
......
......@@ -1471,3 +1471,52 @@ void linphone_core_set_tone(LinphoneCore *lc, LinphoneToneID id, const char *aud
_linphone_core_set_tone(lc, LinphoneReasonNone, id, audiofile);
}
const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc){
const char *config=lp_config_get_string(lc->config,"sip","srtp_crypto_suites","AES_CM_128_HMAC_SHA1_80, AES_CM_128_HMAC_SHA1_32");
char *tmp=ms_strdup(config);
char *sep;
char *pos;
char *nextpos;
char *params;
int found=0;
MSCryptoSuite *result=NULL;
pos=tmp;
do{
sep=strchr(pos,',');
if (!sep) {
sep=pos+strlen(pos);
nextpos=NULL;
}else {
*sep='\0';
nextpos=sep+1;
}
while(*pos==' ') ++pos; /*strip leading spaces*/
params=strchr(pos,' '); /*look for params that arrive after crypto suite name*/
if (params){
while(*params==' ') ++params; /*strip parameters leading space*/
}
if (sep-pos>0){
MSCryptoSuiteNameParams np;
MSCryptoSuite suite;
np.name=pos;
np.params=params;
suite=ms_crypto_suite_build_from_name_params(&np);
if (suite!=MS_CRYPTO_SUITE_INVALID){
result=ms_realloc(result,found+1+1);
result[found]=suite;
result[found+1]=MS_CRYPTO_SUITE_INVALID;
found++;
ms_message("Configured srtp crypto suite: %s %s",np.name,np.params ? np.params : "");
}
}
pos=nextpos;
}while(pos);
ms_free(tmp);
if (lc->rtp_conf.srtp_suites){
ms_free(lc->rtp_conf.srtp_suites);
lc->rtp_conf.srtp_suites=NULL;
}
lc->rtp_conf.srtp_suites=result;
return result;
}
......@@ -156,17 +156,16 @@ static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCry
result->algo = remote[i].algo;
/* We're answering an SDP offer. Supply our master key, associated with the remote supplied tag */
if (use_local_key) {
strncpy(result->master_key, local[j].master_key, 41);
strncpy(result->master_key, local[j].master_key, sizeof(result->master_key) );
result->tag = remote[i].tag;
*choosen_local_tag = local[j].tag;
}
/* We received an answer to our SDP crypto proposal. Copy matching algo remote master key to result, and memorize local tag */
else {
strncpy(result->master_key, remote[i].master_key, 41);
strncpy(result->master_key, remote[i].master_key, sizeof(result->master_key));
result->tag = local[j].tag;
*choosen_local_tag = local[j].tag;
}
result->master_key[40] = '\0';
return TRUE;
}
}
......
......@@ -519,6 +519,7 @@ typedef struct rtp_config
int video_jitt_comp; /*jitter compensation*/
int nortp_timeout;
int disable_upnp;
MSCryptoSuite *srtp_suites;
bool_t rtp_no_xmit_on_audio_mute;
/* stop rtp xmit when audio muted */
bool_t audio_adaptive_jitt_comp_enabled;
......@@ -886,6 +887,7 @@ static inline const LinphoneErrorInfo *linphone_error_info_from_sal_op(const Sal
return (const LinphoneErrorInfo*)sal_op_get_error_info(op);
}
const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc);
/** Belle Sip-based objects need unique ids
*/
......
......@@ -166,7 +166,7 @@ typedef struct SalIceRemoteCandidate {
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN 256
/*sufficient for 256bit keys encoded in base 64*/
#define SAL_SRTP_KEY_SIZE 64
#define SAL_SRTP_KEY_SIZE 128
typedef struct SalSrtpCryptoAlgo {
unsigned int tag;
......
mediastreamer2 @ b6ad773d
Subproject commit ad376cf215143507c1f8e297084e210939e7f31b
Subproject commit b6ad773d4896b36fd707b6fc4f743b6b7df7325a
oRTP @ e4f28d14
Subproject commit 73317c9bf59700b44f85008f6e254476bbe756eb
Subproject commit e4f28d1434b8f18061fb6a45a80649c4bc13cf9a
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment