Implement support for some SDES session parameters

Supports: UNENCRYPTED_SRTCP, UNENCRYPTED_SRTP and UNAUTHENTICATED_SRTP

Usermode only
pull/110/head
Richard Fuchs 10 years ago
parent fd426457d7
commit 96e3b91859

@ -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:

@ -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 {

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

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

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

@ -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];
}
}

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

Loading…
Cancel
Save