From fbc8f77e3ab217adc9826afec8b7b50ed2db0884 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 21 May 2014 13:10:34 +0200 Subject: [PATCH] allow crypto lines to be configured from linphonerc, and improve code handling SRTP crypto lines --- coreapi/bellesip_sal/sal_impl.c | 1 + coreapi/bellesip_sal/sal_sdp.c | 82 ++++++++++++--------------------- coreapi/linphonecall.c | 41 +++++++++++++---- coreapi/linphonecore.c | 1 + coreapi/misc.c | 49 ++++++++++++++++++++ coreapi/offeranswer.c | 5 +- coreapi/private.h | 2 + include/sal/sal.h | 2 +- mediastreamer2 | 2 +- oRTP | 2 +- 10 files changed, 118 insertions(+), 69 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index a35d85822..0212c8a39 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -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); } + diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 50e3504a5..23d0d8be4 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -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; jcrypto[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) { diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 27ce04a3a..b91bf71c2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -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 && jstreams[i].crypto[j],suites[j],j+1); + } } } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 157ce6acf..a9e472388 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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) diff --git a/coreapi/misc.c b/coreapi/misc.c index 56383fa58..c27147107 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -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; +} + diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index db2a28b76..fd99f421c 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -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; } } diff --git a/coreapi/private.h b/coreapi/private.h index 08db6a40d..d43f6454f 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -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 */ diff --git a/include/sal/sal.h b/include/sal/sal.h index 55c5ebf20..fbeaf2e14 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -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; diff --git a/mediastreamer2 b/mediastreamer2 index ad376cf21..b6ad773d4 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit ad376cf215143507c1f8e297084e210939e7f31b +Subproject commit b6ad773d4896b36fd707b6fc4f743b6b7df7325a diff --git a/oRTP b/oRTP index 73317c9bf..e4f28d143 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 73317c9bf59700b44f85008f6e254476bbe756eb +Subproject commit e4f28d1434b8f18061fb6a45a80649c4bc13cf9a