From 349954d2bce50522b87fe5b6f138f5b6e256348f Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 7 Mar 2019 15:38:43 -0500 Subject: [PATCH] TT#50652 handle SRTP output for media playback Change-Id: Ie83c9c01c4c17e14d30aa14272b86af9ea38e1fb --- daemon/media_player.c | 3 ++ include/media_player.h | 1 + t/auto-daemon-tests.pl | 93 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/daemon/media_player.c b/daemon/media_player.c index 9b89cdf43..798056bdd 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -343,6 +343,8 @@ static void media_player_read_packet(struct media_player *mp) { } } + media_packet_encrypt(mp->crypt_handler->out->rtp_crypt, mp->sink, &packet); + mutex_lock(&mp->sink->out_lock); if (media_socket_dequeue(&packet, mp->sink)) ilog(LOG_ERR, "Error sending playback media to RTP sink"); @@ -380,6 +382,7 @@ found: } mp->media = media; mp->sink = media->streams.head->data; + mp->crypt_handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], media->protocol, 1); return 0; } diff --git a/include/media_player.h b/include/media_player.h index 57a1934dc..6ec4e7673 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -29,6 +29,7 @@ struct media_player { struct call_monologue *ml; struct call_media *media; struct packet_stream *sink; + const struct streamhandler *crypt_handler; struct timeval next_run; diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 126c9804e..634b1c65d 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -3,6 +3,7 @@ use strict; use warnings; use NGCP::Rtpengine::Test; +use NGCP::Rtpclient::SRTP; use Test::More; use File::Temp; use IPC::Open3; @@ -115,13 +116,16 @@ sub rtp { return pack('CCnNN a*', 0x80, $pt, $seq, $ts, $ssrc, $payload); } sub rcv { - my ($sock, $port, $match) = @_; + my ($sock, $port, $match, $cb, $cb_arg) = @_; my $p = ''; alarm(1); my $addr = $sock->recv($p, 65535, 0) or die; alarm(0); my ($hdr_mark, $pt, $seq, $ts, $ssrc, $payload) = unpack('CCnNN a*', $p); print("rtp recv $pt $seq $ts $ssrc\n"); + if ($cb) { + $p = $cb->($hdr_mark, $pt, $seq, $ts, $ssrc, $payload, $p, $cb_arg); + } like $p, $match, 'received packet matches'; my @matches = $p =~ $match; for my $m (@matches) { @@ -134,6 +138,21 @@ sub rcv { } return @matches; } +sub srtp_rcv { + my ($sock, $port, $match, $srtp_ctx) = @_; + return rcv($sock, $port, $match, \&srtp_dec, $srtp_ctx); +} +sub srtp_dec { + my ($hdr_mark, $pt, $seq, $ts, $ssrc, $payload, $pack, $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 ($dec, $out_roc, $tag, $hmac) = NGCP::Rtpclient::SRTP::decrypt_rtp(@$srtp_ctx{qw(cs skey ssalt sauth roc)}, $pack); + $srtp_ctx->{roc} = $out_roc; + is $tag, substr($hmac, 0, length($tag)), 'SRTP auth tag matches'; + return $dec; +} sub escape { return "\Q$_[0]\E"; } @@ -1545,6 +1564,78 @@ rcv($sock_b, -1, rtpm(8, $seq + 9, $ts + 160 * 4, $ssrc, $pcma_5)); +($sock_a, $sock_b) = new_call([qw(198.51.100.1 2050)], [qw(198.51.100.3 2052)]); + +offer('media playback, SRTP', { ICE => 'remove', replace => ['origin'], DTLS => 'off' }, < ['origin'] }, < $ft, blob => $wav_file }); +is $resp->{duration}, 100, 'media duration'; + +my $srtp_ctx = { + cs => $NGCP::Rtpclient::SRTP::crypto_suites{AES_CM_128_HMAC_SHA1_80}, + key => 'DVM+BTeYX2UI1LaA9bgXrcBEDBxoItA9/39fSoRF', +}; +($seq, $ts, $ssrc) = srtp_rcv($sock_a, -1, rtpm(8 | 0x80, -1, -1, -1, $pcma_1), $srtp_ctx); +srtp_rcv($sock_a, -1, rtpm(8, $seq + 1, $ts + 160 * 1, $ssrc, $pcma_2), $srtp_ctx); +srtp_rcv($sock_a, -1, rtpm(8, $seq + 2, $ts + 160 * 2, $ssrc, $pcma_3), $srtp_ctx); +srtp_rcv($sock_a, -1, rtpm(8, $seq + 3, $ts + 160 * 3, $ssrc, $pcma_4), $srtp_ctx); +srtp_rcv($sock_a, -1, rtpm(8, $seq + 4, $ts + 160 * 4, $ssrc, $pcma_5), $srtp_ctx); + + + + END { if ($rtpe_pid) { kill('INT', $rtpe_pid) or die;