@ -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 ) ;