Browse Source

TT#65800 fix SDES negotiation bug

If B accepts a crypto suite that was not listed as the first, in order
to support SRTP passthrough, we correctly answer to A with only that one
crypto suite. But we must also remove all other crypto suites from our
list of supported crypto suites internally, because we use the first one
to init our crypto contexts.

fixes #829

Change-Id: Id07343d7b24648208e3a4b4e0b246949dce0385e
changes/89/32789/1
Richard Fuchs 6 years ago
parent
commit
3466700149
2 changed files with 179 additions and 1 deletions
  1. +15
    -0
      daemon/call.c
  2. +164
    -1
      t/auto-daemon-tests.pl

+ 15
- 0
daemon/call.c View File

@ -1373,11 +1373,15 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
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) {
ilog(LOG_DEBUG, "Looking for matching crypto suite to offered %u:%s", offered_cps->tag,
offered_cps->params.crypto_suite->name);
// 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) {
ilog(LOG_DEBUG, "Found matching crypto suite %u:%s", check_cps->tag,
check_cps->params.crypto_suite->name);
cps_in = check_cps;
break;
}
@ -1394,6 +1398,8 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
// SRTP<>SRTP passthrough
cps->params.session_params = cps_in->params.session_params; // XXX verify
crypto_params_copy(&cps->params, &offered_cps->params, 1);
ilog(LOG_DEBUG, "Copied crypto params from %i:%s for SRTP passthrough",
cps_in->tag, cps_in->params.crypto_suite->name);
}
else {
random_string((unsigned char *) cps->params.master_key,
@ -1402,7 +1408,16 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
cps->params.crypto_suite->master_salt_len);
/* mki = mki_len = 0 */
cps->params.session_params = cps_in->params.session_params;
ilog(LOG_DEBUG, "Creating new SRTP crypto params for %i:%s",
cps->tag, cps->params.crypto_suite->name);
}
// flush out crypto suites we ended up not using - leave only one
if (!g_queue_remove(cpq_in, cps_in))
ilog(LOG_ERR, "BUG: incoming crypto suite not found in queue");
crypto_params_sdes_queue_clear(cpq_in);
g_queue_push_tail(cpq_in, cps_in);
__sdes_flags(cps, flags);
__sdes_flags(cps_in, flags);
}


+ 164
- 1
t/auto-daemon-tests.pl View File

@ -112,6 +112,17 @@ sub snd {
my ($sock, $dest, $packet) = @_;
$sock->send($packet, 0, pack_sockaddr_in($dest, inet_aton('203.0.113.1'))) or die;
}
sub srtp_snd {
my ($sock, $dest, $packet, $srtp_ctx) = @_;
if (!$srtp_ctx->{skey}) {
my ($key, $salt) = NGCP::Rtpclient::SRTP::decode_inline_base64($srtp_ctx->{key}, $srtp_ctx->{cs});
@$srtp_ctx{qw(skey sauth ssalt)} = NGCP::Rtpclient::SRTP::gen_rtp_session_keys($key, $salt);
}
my ($enc, $out_roc) = NGCP::Rtpclient::SRTP::encrypt_rtp(@$srtp_ctx{qw(cs skey ssalt sauth roc)},
'', 0, 0, 0, $packet);
$srtp_ctx->{roc} = $out_roc;
$sock->send($enc, 0, pack_sockaddr_in($dest, inet_aton('203.0.113.1'))) or die;
}
sub rtp {
my ($pt, $seq, $ts, $ssrc, $payload) = @_;
print("rtp in $pt $seq $ts $ssrc\n");
@ -180,7 +191,159 @@ sub rtpm {
my ($sock_a, $sock_b, $port_a, $port_b, $ssrc, $resp);
my ($sock_a, $sock_b, $port_a, $port_b, $ssrc, $resp, $srtp_ctx_a, $srtp_ctx_b);
# github issue 829
($sock_a, $sock_b) = new_call([qw(198.51.100.1 7316)], [qw(198.51.100.3 7318)]);
($port_a) = offer('gh829 control',
{ ICE => 'remove', replace => ['origin'], flags => ['pad crypto'], DTLS => 'off' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 7316 RTP/SAVP 0
c=IN IP4 198.51.100.1
a=sendrecv
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa
a=crypto:4 AES_CM_128_HMAC_SHA1_32 inline:Kl3GFJ5Gqz5x07xYkoyHODkVkSpiplZnXsQIw+Q7
----------------------------------
v=0
o=- 1545997027 1 IN IP4 203.0.113.1
s=tester
t=0 0
m=audio PORT RTP/SAVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa
a=crypto:4 AES_CM_128_HMAC_SHA1_32 inline:Kl3GFJ5Gqz5x07xYkoyHODkVkSpiplZnXsQIw+Q7
a=crypto:5 AES_192_CM_HMAC_SHA1_80 inline:CRYPTO192=
a=crypto:6 AES_192_CM_HMAC_SHA1_32 inline:CRYPTO192=
a=crypto:7 AES_256_CM_HMAC_SHA1_80 inline:CRYPTO256==
a=crypto:8 AES_256_CM_HMAC_SHA1_32 inline:CRYPTO256==
a=crypto:9 F8_128_HMAC_SHA1_80 inline:CRYPTO128
a=crypto:10 F8_128_HMAC_SHA1_32 inline:CRYPTO128
a=crypto:11 NULL_HMAC_SHA1_80 inline:CRYPTO128
a=crypto:12 NULL_HMAC_SHA1_32 inline:CRYPTO128
SDP
($port_b) = answer('gh829 control',
{ ICE => 'remove', replace => ['origin'], flags => ['pad crypto'], DTLS => 'off' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 7318 RTP/SAVP 0
c=IN IP4 198.51.100.3
a=sendrecv
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 203.0.113.1
s=tester
t=0 0
m=audio PORT RTP/SAVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1
SDP
$srtp_ctx_a = {
cs => $NGCP::Rtpclient::SRTP::crypto_suites{AES_CM_128_HMAC_SHA1_80},
key => 'IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1',
};
$srtp_ctx_b = {
cs => $NGCP::Rtpclient::SRTP::crypto_suites{AES_CM_128_HMAC_SHA1_80},
key => 'Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa',
};
srtp_snd($sock_a, $port_b, rtp(0, 1000, 3000, 0x1234, "\x00" x 160), $srtp_ctx_a);
srtp_rcv($sock_b, $port_a, rtpm(0, 1000, 3000, 0x1234, "\x00" x 160), $srtp_ctx_a);
srtp_snd($sock_b, $port_a, rtp(0, 2000, 4000, 0x3456, "\x00" x 160), $srtp_ctx_b);
srtp_rcv($sock_a, $port_b, rtpm(0, 2000, 4000, 0x3456, "\x00" x 160), $srtp_ctx_b);
($sock_a, $sock_b) = new_call([qw(198.51.100.1 7310)], [qw(198.51.100.3 7312)]);
($port_a) = offer('gh829',
{ ICE => 'remove', replace => ['origin'], flags => ['pad crypto'], DTLS => 'off' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 7310 RTP/SAVP 0
c=IN IP4 198.51.100.1
a=sendrecv
a=crypto:1 AES_256_CM_HMAC_SHA1_80 inline:EPm8bCW0w2BvozGK++QzjF4m6ARVCpXrn8GAMAoIiDW8BQRDZ+fFRwDjLFALJQ==
a=crypto:2 AES_256_CM_HMAC_SHA1_32 inline:7Io806fF2XLWT782TTPsrSQTptu9HPGRnJ3Y5QDwk9HbhRi+nNwJ/nqNQP+tDg==
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa
a=crypto:4 AES_CM_128_HMAC_SHA1_32 inline:Kl3GFJ5Gqz5x07xYkoyHODkVkSpiplZnXsQIw+Q7
----------------------------------
v=0
o=- 1545997027 1 IN IP4 203.0.113.1
s=tester
t=0 0
m=audio PORT RTP/SAVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
a=crypto:1 AES_256_CM_HMAC_SHA1_80 inline:EPm8bCW0w2BvozGK++QzjF4m6ARVCpXrn8GAMAoIiDW8BQRDZ+fFRwDjLFALJQ==
a=crypto:2 AES_256_CM_HMAC_SHA1_32 inline:7Io806fF2XLWT782TTPsrSQTptu9HPGRnJ3Y5QDwk9HbhRi+nNwJ/nqNQP+tDg==
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa
a=crypto:4 AES_CM_128_HMAC_SHA1_32 inline:Kl3GFJ5Gqz5x07xYkoyHODkVkSpiplZnXsQIw+Q7
a=crypto:5 AES_192_CM_HMAC_SHA1_80 inline:CRYPTO192=
a=crypto:6 AES_192_CM_HMAC_SHA1_32 inline:CRYPTO192=
a=crypto:7 F8_128_HMAC_SHA1_80 inline:CRYPTO128
a=crypto:8 F8_128_HMAC_SHA1_32 inline:CRYPTO128
a=crypto:9 NULL_HMAC_SHA1_80 inline:CRYPTO128
a=crypto:10 NULL_HMAC_SHA1_32 inline:CRYPTO128
SDP
($port_b) = answer('gh829',
{ ICE => 'remove', replace => ['origin'], flags => ['pad crypto'], DTLS => 'off' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 7312 RTP/SAVP 0
c=IN IP4 198.51.100.3
a=sendrecv
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 203.0.113.1
s=tester
t=0 0
m=audio PORT RTP/SAVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1
SDP
$srtp_ctx_a = {
cs => $NGCP::Rtpclient::SRTP::crypto_suites{AES_CM_128_HMAC_SHA1_80},
key => 'IDdiM2QzOWYzMjA2YzkwZWIxY2NmOWVhOTc4MjE1',
};
$srtp_ctx_b = {
cs => $NGCP::Rtpclient::SRTP::crypto_suites{AES_CM_128_HMAC_SHA1_80},
key => 'Qk0TvVeyfqfjFd/YebnyyklqSEhJntpVKV1KAhHa',
};
srtp_snd($sock_a, $port_b, rtp(0, 1000, 3000, 0x1234, "\x00" x 160), $srtp_ctx_a);
srtp_rcv($sock_b, $port_a, rtpm(0, 1000, 3000, 0x1234, "\x00" x 160), $srtp_ctx_a);
srtp_snd($sock_b, $port_a, rtp(0, 2000, 4000, 0x3456, "\x00" x 160), $srtp_ctx_b);
srtp_rcv($sock_a, $port_b, rtpm(0, 2000, 4000, 0x3456, "\x00" x 160), $srtp_ctx_b);
# DTMF injection


Loading…
Cancel
Save