From 96e3b91859724512641def19e06e7c3ee8df283b Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 19 Mar 2015 15:39:15 -0400 Subject: [PATCH] Implement support for some SDES session parameters Supports: UNENCRYPTED_SRTCP, UNENCRYPTED_SRTP and UNAUTHENTICATED_SRTP Usermode only --- daemon/call.c | 3 +++ daemon/crypto.h | 3 +++ daemon/rtcp.c | 4 ++-- daemon/rtp.c | 9 ++++---- daemon/sdp.c | 23 ++++++++++++++++++- tests/simulator-ng.pl | 51 +++++++++++++++++++++++++++++-------------- utils/SRTP.pm | 6 ++--- 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index d9b2d7c16..82637327d 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2182,6 +2182,9 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi cp->crypto_suite->master_key_len); random_string((unsigned char *) cp->master_salt, cp->crypto_suite->master_salt_len); + cp->unencrypted_srtp = cp_in->unencrypted_srtp; + cp->unencrypted_srtcp = cp_in->unencrypted_srtcp; + cp->unauthenticated_srtp = cp_in->unauthenticated_srtp; /* mki = mki_len = 0 */ skip_sdes: diff --git a/daemon/crypto.h b/daemon/crypto.h index ea27dc006..120a87a69 100644 --- a/daemon/crypto.h +++ b/daemon/crypto.h @@ -64,6 +64,9 @@ struct crypto_params { unsigned char master_salt[SRTP_MAX_MASTER_SALT_LEN]; unsigned char *mki; unsigned int mki_len; + int unencrypted_srtcp:1, + unencrypted_srtp:1, + unauthenticated_srtp:1; }; struct crypto_context { diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 793bc39c5..741d86230 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -401,11 +401,11 @@ int rtcp_avp2savp(str *s, struct crypto_context *c) { if (check_session_keys(c)) return -1; - if (crypto_encrypt_rtcp(c, rtcp, &payload, c->last_index)) + if (!c->params.unencrypted_srtcp && crypto_encrypt_rtcp(c, rtcp, &payload, c->last_index)) return -1; idx = (void *) s->s + s->len; - *idx = htonl(0x80000000ULL | c->last_index++); + *idx = htonl((c->params.unencrypted_srtcp ? 0ULL : 0x80000000ULL) | c->last_index++); s->len += sizeof(*idx); to_auth = *s; diff --git a/daemon/rtp.c b/daemon/rtp.c index 8fb624030..9713bcb09 100644 --- a/daemon/rtp.c +++ b/daemon/rtp.c @@ -201,14 +201,14 @@ int rtp_avp2savp(str *s, struct crypto_context *c) { /* rfc 3711 section 3.1 */ - if (crypto_encrypt_rtp(c, rtp, &payload, index)) + if (!c->params.unencrypted_srtp && crypto_encrypt_rtp(c, rtp, &payload, index)) return -1; to_auth = *s; rtp_append_mki(s, c); - if (c->params.crypto_suite->srtp_auth_tag) { + if (!c->params.unauthenticated_srtp && c->params.crypto_suite->srtp_auth_tag) { c->params.crypto_suite->hash_rtp(c, s->s + s->len, &to_auth, index); s->len += c->params.crypto_suite->srtp_auth_tag; } @@ -230,7 +230,8 @@ int rtp_savp2avp(str *s, struct crypto_context *c) { index = packet_index(c, rtp); if (srtp_payloads(&to_auth, &to_decrypt, &auth_tag, NULL, - c->params.crypto_suite->srtp_auth_tag, c->params.mki_len, + c->params.unauthenticated_srtp ? 0 : c->params.crypto_suite->srtp_auth_tag, + c->params.mki_len, s, &payload)) return -1; @@ -265,7 +266,7 @@ int rtp_savp2avp(str *s, struct crypto_context *c) { decrypt_idx: c->last_index = index; decrypt: - if (crypto_decrypt_rtp(c, rtp, &to_decrypt, index)) + if (!c->params.unencrypted_srtp && crypto_decrypt_rtp(c, rtp, &to_decrypt, index)) return -1; *s = to_auth; diff --git a/daemon/sdp.c b/daemon/sdp.c index b15b28966..874199523 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -97,13 +97,13 @@ struct attribute_crypto { str tag_str; str crypto_suite_str; str key_params_str; - /* str session_params; */ str key_base64_str; str lifetime_str; str mki_str; unsigned int tag; + /* XXX use struct crypto_params for these below? */ const struct crypto_suite *crypto_suite; str master_key; str salt; @@ -111,6 +111,9 @@ struct attribute_crypto { u_int64_t lifetime; unsigned char mki[256]; unsigned int mki_len; + int unencrypted_srtcp:1, + unencrypted_srtp:1, + unauthenticated_srtp:1; }; struct attribute_ssrc { @@ -542,6 +545,15 @@ static int parse_attribute_crypto(struct sdp_attribute *output) { memcpy(c->mki + (c->mki_len - sizeof(u32)), &u32, sizeof(u32)); } + while (extract_token(&start, end, &s) == 0) { + if (!str_cmp(&s, "UNENCRYPTED_SRTCP")) + c->unencrypted_srtcp = 1; + else if (!str_cmp(&s, "UNENCRYPTED_SRTP")) + c->unencrypted_srtp = 1; + else if (!str_cmp(&s, "UNAUTHENTICATED_SRTP")) + c->unauthenticated_srtp = 1; + } + return 0; error: @@ -1233,6 +1245,9 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl attr->u.crypto.master_key.len); memcpy(sp->crypto.master_salt, attr->u.crypto.salt.s, attr->u.crypto.salt.len); + sp->crypto.unencrypted_srtp = attr->u.crypto.unencrypted_srtp; + sp->crypto.unencrypted_srtcp = attr->u.crypto.unencrypted_srtcp; + sp->crypto.unauthenticated_srtp = attr->u.crypto.unauthenticated_srtp; } /* a=sendrecv/sendonly/recvonly/inactive */ @@ -1863,6 +1878,12 @@ static void insert_crypto(struct call_media *media, struct sdp_chopper *chop) { ull |= cp->mki[cp->mki_len - i - 1] << (i * 8); chopper_append_printf(chop, "|%llu:%u", ull, cp->mki_len); } + if (cp->unencrypted_srtp) + chopper_append_c(chop, " UNENCRYPTED_SRTP"); + if (cp->unencrypted_srtcp) + chopper_append_c(chop, " UNENCRYPTED_SRTCP"); + if (cp->unauthenticated_srtp) + chopper_append_c(chop, " UNAUTHENTICATED_SRTP"); chopper_append_c(chop, "\r\n"); } diff --git a/tests/simulator-ng.pl b/tests/simulator-ng.pl index 3c2e98cb9..526430172 100755 --- a/tests/simulator-ng.pl +++ b/tests/simulator-ng.pl @@ -120,10 +120,11 @@ sub rtcp_encrypt { my $iv = $$dctx{crypto_suite}{iv_rtcp}->($dctx, $r); my ($hdr, $to_enc) = unpack('a8a*', $r); - my $enc = $$dctx{crypto_suite}{enc_func}->($to_enc, $$dctx{rtcp_session_key}, + my $enc = $$dctx{unenc_srtcp} ? $to_enc : + $$dctx{crypto_suite}{enc_func}->($to_enc, $$dctx{rtcp_session_key}, $iv, $$dctx{rtcp_session_salt}); my $pkt = $hdr . $enc; - $pkt .= pack("N", (($$dctx{rtcp_index} || 0) | 0x80000000)); + $pkt .= pack("N", (($$dctx{rtcp_index} || 0) | ($$dctx{unenc_srtcp} ? 0 : 0x80000000))); my $hmac = hmac_sha1($pkt, $$dctx{rtcp_session_auth_key}); @@ -152,7 +153,7 @@ sub rtp_encrypt { ($NOENC && $NOENC{rtp_packet}) and return $NOENC{rtp_packet}; my ($pkt, $roc) = SRTP::encrypt_rtp(@$dctx{qw(crypto_suite rtp_session_key rtp_session_salt - rtp_session_auth_key rtp_roc rtp_mki rtp_mki_len)}, $r); + rtp_session_auth_key rtp_roc rtp_mki rtp_mki_len unenc_srtp unauth_srtp)}, $r); $$dctx{rtp_roc} = $roc; $NOENC{rtp_packet} = $pkt; @@ -166,8 +167,20 @@ sub savp_sdp { my ($ctx, $ctx_o) = @_; if (!$$ctx{out}{crypto_suite}) { - $$ctx{out}{crypto_suite} = $$ctx_o{in}{crypto_suite} ? $$ctx_o{in}{crypto_suite} - : $SRTP::crypto_suites[rand(@SRTP::crypto_suites)]; + if ($$ctx{in}{crypto_suite}) { + $$ctx{out}{crypto_suite} = $$ctx{in}{crypto_suite}; + $$ctx{out}{crypto_tag} = $$ctx{in}{crypto_tag}; + $$ctx{out}{unenc_srtp} = $$ctx{in}{unenc_srtp}; + $$ctx{out}{unenc_srtcp} = $$ctx{in}{unenc_srtcp}; + $$ctx{out}{unauth_srtp} = $$ctx{in}{unauth_srtp}; + } + else { + $$ctx{out}{crypto_suite} = $SRTP::crypto_suites[rand(@SRTP::crypto_suites)]; + $$ctx{out}{crypto_tag} = int(rand(100)); + $$ctx{out}{unenc_srtp} = rand() < .5 ? 0 : 1; + $$ctx{out}{unenc_srtcp} = rand() < .5 ? 0 : 1; + $$ctx{out}{unauth_srtp} = rand() < .5 ? 0 : 1; + } $$ctx{out}{rtp_mki_len} = 0; if (rand() > .5) { @@ -193,10 +206,12 @@ sub savp_sdp { $NOENC{rtp_master_salt} = $$ctx{out}{rtp_master_salt}; } - my $ret = "a=crypto:0 $$ctx{out}{crypto_suite}{str} inline:" . encode_base64($$ctx{out}{rtp_master_key} . $$ctx{out}{rtp_master_salt}, ''); - if ($$ctx{out}{rtp_mki_len}) { - $ret .= "|$$ctx{out}{rtp_mki}:$$ctx{out}{rtp_mki_len}"; - } + my $ret = "a=crypto:$$ctx{out}{crypto_tag} $$ctx{out}{crypto_suite}{str} inline:" . encode_base64($$ctx{out}{rtp_master_key} . $$ctx{out}{rtp_master_salt}, ''); + $$ctx{out}{rtp_mki_len} and $ret .= "|$$ctx{out}{rtp_mki}:$$ctx{out}{rtp_mki_len}"; + + $$ctx{out}{unenc_srtp} and $ret .= " UNENCRYPTED_SRTP"; + $$ctx{out}{unenc_srtcp} and $ret .= " UNENCRYPTED_SRTCP"; + $$ctx{out}{unauth_srtp} and $ret .= " UNAUTHENTICATED_SRTP"; $ret .= "\n"; return $ret; @@ -290,20 +305,24 @@ sub rtp_savp { sub savp_crypto { my ($sdp, $ctx, $ctx_o) = @_; - my @a = $sdp =~ /[\r\n]a=crypto:\d+ (\w+) inline:([\w\/+]{40})(?:\|(?:2\^(\d+)|(\d+)))?(?:\|(\d+):(\d+))?[\r\n]/sig; + my @a = $sdp =~ /[\r\n]a=crypto:(\d+) (\w+) inline:([\w\/+]{40})(?:\|(?:2\^(\d+)|(\d+)))?(?:\|(\d+):(\d+))?(?: (.*?))?[\r\n]/sig; @a or die; my $i = 0; - while (@a >= 6) { - $$ctx[$i]{in}{crypto_suite} = $SRTP::crypto_suites{$a[0]} or die; + while (@a >= 8) { + $$ctx[$i]{in}{crypto_suite} = $SRTP::crypto_suites{$a[1]} or die; + $$ctx[$i]{in}{crypto_tag} = $a[0]; ($$ctx[$i]{in}{rtp_master_key}, $$ctx[$i]{in}{rtp_master_salt}) - = SRTP::decode_inline_base64($a[1]); - $$ctx[$i]{in}{rtp_mki} = $a[4]; - $$ctx[$i]{in}{rtp_mki_len} = $a[5]; + = SRTP::decode_inline_base64($a[2]); + $$ctx[$i]{in}{rtp_mki} = $a[5]; + $$ctx[$i]{in}{rtp_mki_len} = $a[6]; undef($$ctx[$i]{in}{rtp_session_key}); undef($$ctx[$i]{in}{rtcp_session_key}); + ($a[7] || '') =~ /UNENCRYPTED_SRTP/ and $$ctx[$i]{in}{unenc_srtp} = 1; + ($a[7] || '') =~ /UNENCRYPTED_SRTCP/ and $$ctx[$i]{in}{unenc_srtcp} = 1; + ($a[7] || '') =~ /UNAUTHENTICATED_SRTP/ and $$ctx[$i]{in}{unauth_srtp} = 1; $i++; - @a = @a[6 .. $#a]; + @a = @a[8 .. $#a]; } } diff --git a/utils/SRTP.pm b/utils/SRTP.pm index 83e19edd0..dfdf48ecf 100644 --- a/utils/SRTP.pm +++ b/utils/SRTP.pm @@ -215,14 +215,14 @@ sub decode_inline_base64 { } sub encrypt_rtp { - my ($suite, $skey, $ssalt, $sauth, $roc, $mki, $mki_len, $packet) = @_; + my ($suite, $skey, $ssalt, $sauth, $roc, $mki, $mki_len, $unenc_srtp, $unauth_srtp, $packet) = @_; my ($hdr, $seq, $h2, $to_enc) = unpack('a2na8a*', $packet); $roc = $roc || 0; $seq == 0 and $roc++; my $iv = $$suite{iv_rtp}->($packet, $ssalt, $roc); - my $enc = $$suite{enc_func}->($to_enc, $skey, + my $enc = $unenc_srtp ? $to_enc : $$suite{enc_func}->($to_enc, $skey, $iv, $ssalt); my $pkt = pack('a*na*a*', $hdr, $seq, $h2, $enc); @@ -232,7 +232,7 @@ sub encrypt_rtp { append_mki(\$pkt, $mki_len, $mki); #$pkt .= pack("N", 1); # mki - $pkt .= substr($hmac, 0, $$suite{auth_tag}); + $pkt .= substr($hmac, 0, $unauth_srtp ? 0 : $$suite{auth_tag}); return ($pkt, $roc); }