@ -1014,9 +1014,13 @@ static int __init_stream(struct packet_stream *ps) {
if ( MEDIA_ISSET ( media , SDES ) ) {
for ( GList * l = ps - > sfds . head ; l ; l = l - > next ) {
struct stream_fd * sfd = l - > data ;
crypto_init ( & sfd - > crypto , & media - > sdes_in . params ) ;
struct crypto_params_sdes * cps = media - > sdes_in . head
? media - > sdes_in . head - > data : NULL ;
crypto_init ( & sfd - > crypto , cps ? & cps - > params : NULL ) ;
}
crypto_init ( & ps - > crypto , & media - > sdes_out . params ) ;
struct crypto_params_sdes * cps = media - > sdes_out . head
? media - > sdes_out . head - > data : NULL ;
crypto_init ( & ps - > crypto , cps ? & cps - > params : NULL ) ;
}
if ( MEDIA_ISSET ( media , DTLS ) & & ! PS_ISSET ( ps , FALLBACK_RTCP ) ) {
@ -1214,14 +1218,17 @@ static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *thi
static void __generate_crypto ( const struct sdp_ng_flags * flags , struct call_media * this ,
struct call_media * other )
{
struct crypto_params * cp = & this - > sdes_out . params ,
* cp_in = & this - > sdes_in . params ;
//struct crypto_params *cp = &this->sdes_out.params,
//*cp_in = &this->sdes_in.params;
GQueue * cpq = & this - > sdes_out ;
GQueue * cpq_in = & this - > sdes_in ;
GQueue * offered_cpq = & other - > sdes_in ;
if ( ! flags )
return ;
if ( ! this - > protocol | | ! this - > protocol - > srtp | | MEDIA_ISSET ( this , PASSTHRU ) ) {
cp - > crypto_suite = NULL ;
crypto_params_sdes_queue_clear ( cpq ) ;
/* clear crypto for the this leg b/c we are in passthrough mode */
MEDIA_CLEAR ( this , DTLS ) ;
MEDIA_CLEAR ( this , SDES ) ;
@ -1279,43 +1286,136 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
/* SDES parameters below */
/* for answer case, otherwise we default to one */
this - > sdes_out . tag = cp_in - > crypto_suite ? this - > sdes_in . tag : 1 ;
if ( other - > sdes_in . params . crypto_suite ) {
/* SRTP <> SRTP case, copy from other stream */
cp - > session_params = cp_in - > session_params ;
crypto_params_copy ( cp , & other - > sdes_in . params , ( flags - > opmode = = OP_OFFER ) ? 1 : 0 ) ;
}
if ( cp - > crypto_suite )
goto apply_sdes_flags ;
cp - > crypto_suite = cp_in - > crypto_suite ;
if ( ! cp - > crypto_suite )
cp - > crypto_suite = & crypto_suites [ 0 ] ;
random_string ( ( unsigned char * ) cp - > master_key ,
cp - > crypto_suite - > master_key_len ) ;
random_string ( ( unsigned char * ) cp - > master_salt ,
cp - > crypto_suite - > master_salt_len ) ;
/* mki = mki_len = 0 */
cp - > session_params . unencrypted_srtp = cp_in - > session_params . unencrypted_srtp ;
cp - > session_params . unencrypted_srtcp = cp_in - > session_params . unencrypted_srtcp ;
cp - > session_params . unauthenticated_srtp = cp_in - > session_params . unauthenticated_srtp ;
apply_sdes_flags :
if ( flags - > sdes_unencrypted_srtp & & flags - > opmode = = OP_OFFER )
cp_in - > session_params . unencrypted_srtp = cp - > session_params . unencrypted_srtp = 1 ;
else if ( flags - > sdes_encrypted_srtp )
cp_in - > session_params . unencrypted_srtp = cp - > session_params . unencrypted_srtp = 0 ;
if ( flags - > sdes_unencrypted_srtcp & & flags - > opmode = = OP_OFFER )
cp_in - > session_params . unencrypted_srtcp = cp - > session_params . unencrypted_srtcp = 1 ;
else if ( flags - > sdes_encrypted_srtcp )
cp_in - > session_params . unencrypted_srtcp = cp - > session_params . unencrypted_srtcp = 0 ;
if ( flags - > sdes_unauthenticated_srtp & & flags - > opmode = = OP_OFFER )
cp_in - > session_params . unauthenticated_srtp = cp - > session_params . unauthenticated_srtp = 1 ;
else if ( flags - > sdes_authenticated_srtp )
cp_in - > session_params . unauthenticated_srtp = cp - > session_params . unauthenticated_srtp = 0 ;
// XXX tests:
// generate all offers
// copy offered suites
// amend offered suites
// ignore suites not supported
// params copy on answer
if ( flags - > opmode = = OP_OFFER ) {
if ( ! cpq - > head ) {
// generate a new set of params
// if we were offered some crypto suites, copy those first into our offer
unsigned int c_tag = 1 ; // tag for next crypto suite generated by us
unsigned long types_offered = 0 ;
// make sure our bit field is large enough
assert ( num_crypto_suites < = sizeof ( types_offered ) * 8 ) ;
for ( GList * l = offered_cpq - > head ; l ; l = l - > next ) {
struct crypto_params_sdes * offered_cps = l - > data ;
struct crypto_params_sdes * cps = g_slice_alloc0 ( sizeof ( * cps ) ) ;
g_queue_push_tail ( cpq , cps ) ;
cps - > tag = offered_cps - > tag ;
// our own offered tags will be higher than the ones we received
if ( cps - > tag > = c_tag )
c_tag = cps - > tag + 1 ;
crypto_params_copy ( & cps - > params , & offered_cps - > params , 1 ) ;
// we use a bit field to keep track of which types we've seen here
types_offered | = 1 < < cps - > params . crypto_suite - > idx ;
}
// generate crypto suite offers for any types that we haven't seen above
for ( unsigned int i = 0 ; i < num_crypto_suites ; i + + ) {
if ( ( types_offered & ( 1 < < i ) ) )
continue ;
struct crypto_params_sdes * cps = g_slice_alloc0 ( sizeof ( * cps ) ) ;
g_queue_push_tail ( cpq , cps ) ;
cps - > tag = c_tag + + ;
cps - > params . crypto_suite = & crypto_suites [ i ] ;
random_string ( ( unsigned char * ) cps - > params . master_key ,
cps - > params . crypto_suite - > master_key_len ) ;
random_string ( ( unsigned char * ) cps - > params . master_salt ,
cps - > params . crypto_suite - > master_salt_len ) ;
/* mki = mki_len = 0 */
// XXX cps->params.session_params.unencrypted_srtp
// XXX = cp_in->session_params.unencrypted_srtp;
// XXX cps->params.session_params.unencrypted_srtcp
// XXX = cp_in->session_params.unencrypted_srtcp;
// XXX cps->params.session_params.unauthenticated_srtp
// XXX = cp_in->session_params.unauthenticated_srtp;
}
}
}
else {
// we pick the first supported crypto suite
struct crypto_params_sdes * cps = cpq - > head ? cpq - > head - > data : NULL ;
struct crypto_params_sdes * cps_in = cpq_in - > head ? cpq_in - > head - > data : NULL ;
struct crypto_params_sdes * offered_cps = offered_cpq - > head ? offered_cpq - > head - > data : NULL ;
if ( offered_cps ) {
// check if we can do SRTP<>SRTP passthrough. the crypto suite that was accepted
// must have been present in what was offered to us
for ( GList * l = cpq_in - > head ; l ; l = l - > next ) {
struct crypto_params_sdes * check_cps = l - > data ;
if ( check_cps - > params . crypto_suite = = offered_cps - > params . crypto_suite ) {
cps_in = check_cps ;
break ;
}
}
}
if ( cps_in & & ( ! cps | | cps - > params . crypto_suite ! = cps_in - > params . crypto_suite ) ) {
crypto_params_sdes_queue_clear ( cpq ) ;
cps = g_slice_alloc0 ( sizeof ( * cps ) ) ;
g_queue_push_tail ( cpq , cps ) ;
cps - > tag = cps_in - > tag ;
cps - > params . crypto_suite = cps_in - > params . crypto_suite ;
if ( offered_cps & & offered_cps - > params . crypto_suite = = cps - > params . crypto_suite ) {
// SRTP<>SRTP passthrough
cps - > params . session_params = cps_in - > params . session_params ; // XXX verify
crypto_params_copy ( & cps - > params , & offered_cps - > params , 1 ) ;
}
else {
random_string ( ( unsigned char * ) cps - > params . master_key ,
cps - > params . crypto_suite - > master_key_len ) ;
random_string ( ( unsigned char * ) cps - > params . master_salt ,
cps - > params . crypto_suite - > master_salt_len ) ;
/* mki = mki_len = 0 */
cps - > params . session_params = cps_in - > params . session_params ;
// XXX cps->params.session_params.unencrypted_srtp
// XXX = cp_in->session_params.unencrypted_srtp;
// XXX cps->params.session_params.unencrypted_srtcp
// XXX = cp_in->session_params.unencrypted_srtcp;
// XXX cps->params.session_params.unauthenticated_srtp
// XXX = cp_in->session_params.unauthenticated_srtp;
}
}
}
// XXX if (cp->crypto_suite)
// XXX goto apply_sdes_flags; // XXX ?
// cp->crypto_suite = cp_in->crypto_suite;
// if (!cp->crypto_suite)
// cp->crypto_suite = &crypto_suites[0];
// random_string((unsigned char *) cp->master_key,
// cp->crypto_suite->master_key_len);
// random_string((unsigned char *) cp->master_salt,
// cp->crypto_suite->master_salt_len);
// /* mki = mki_len = 0 */
// cp->session_params.unencrypted_srtp = cp_in->session_params.unencrypted_srtp;
// cp->session_params.unencrypted_srtcp = cp_in->session_params.unencrypted_srtcp;
// cp->session_params.unauthenticated_srtp = cp_in->session_params.unauthenticated_srtp;
// XXXapply_sdes_flags:
// XXX if (flags->sdes_unencrypted_srtp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 1;
// XXX else if (flags->sdes_encrypted_srtp)
// XXX cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 0;
// XXX if (flags->sdes_unencrypted_srtcp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 1;
// XXX else if (flags->sdes_encrypted_srtcp)
// XXX cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 0;
// XXX if (flags->sdes_unauthenticated_srtp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 1;
// XXX else if (flags->sdes_authenticated_srtp)
// XXX cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 0;
skip_sdes :
;
@ -1637,9 +1737,12 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
SHARED_FLAG_RTCP_MUX | SHARED_FLAG_ASYMMETRIC | SHARED_FLAG_UNIDIRECTIONAL |
SHARED_FLAG_ICE | SHARED_FLAG_TRICKLE_ICE | SHARED_FLAG_ICE_LITE ) ;
crypto_params_copy ( & other_media - > sdes_in . params , & sp - > crypto , 1 ) ;
other_media - > sdes_in . tag = sp - > sdes_tag ;
if ( other_media - > sdes_in . params . crypto_suite )
// steal the entire queue of offered crypto params
crypto_params_sdes_queue_clear ( & other_media - > sdes_in ) ;
other_media - > sdes_in = sp - > sdes_params ;
g_queue_init ( & sp - > sdes_params ) ;
if ( other_media - > sdes_in . length )
MEDIA_SET ( other_media , SDES ) ;
}
@ -2053,8 +2156,8 @@ static void __call_free(void *p) {
while ( c - > medias . head ) {
md = g_queue_pop_head ( & c - > medias ) ;
crypto_params_ cleanup ( & md - > sdes_in . params ) ;
crypto_params_ cleanup ( & md - > sdes_out . params ) ;
crypto_params_ sdes_queue_clear ( & md - > sdes_in ) ;
crypto_params_ sdes_queue_clear ( & md - > sdes_out ) ;
g_queue_clear ( & md - > streams ) ;
g_queue_clear ( & md - > endpoint_maps ) ;
g_hash_table_destroy ( md - > codecs_recv ) ;