mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-19 00:27:51 +01:00

The SrtpTransport takes the SRTP responsibilities from the BaseChannel and SrtpFilter. SrtpTransport is now responsible for setting the crypto keys, protecting and unprotecting the packets. SrtpTransport doesn't know if the keys are from SDES or DTLS handshake. BaseChannel is now only responsible setting the offer/answer for SDES or extracting the key from DtlsTransport and configuring the SrtpTransport. SrtpFilter is used by BaseChannel as a helper for SDES negotiation. BUG=webrtc:7013 Change-Id: If61489dfbdf23481a1f1831ad181fbf45eaadb3e Reviewed-on: https://webrtc-review.googlesource.com/2560 Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Commit-Queue: Zhi Huang <zhihuang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19977}
464 lines
19 KiB
C++
464 lines
19 KiB
C++
/*
|
|
* Copyright 2004 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
#include "pc/srtpfilter.h"
|
|
|
|
#include "media/base/cryptoparams.h"
|
|
#include "rtc_base/gunit.h"
|
|
|
|
using cricket::CryptoParams;
|
|
using cricket::CS_LOCAL;
|
|
using cricket::CS_REMOTE;
|
|
|
|
namespace rtc {
|
|
|
|
static const std::string kTestKeyParams1 =
|
|
"inline:WVNfX19zZW1jdGwgKCkgewkyMjA7fQp9CnVubGVz";
|
|
static const std::string kTestKeyParams2 =
|
|
"inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
|
|
static const std::string kTestKeyParams3 =
|
|
"inline:1234X19zZW1jdGwgKCkgewkyMjA7fQp9CnVubGVz";
|
|
static const std::string kTestKeyParams4 =
|
|
"inline:4567QCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
|
|
static const std::string kTestKeyParamsGcm1 =
|
|
"inline:e166KFlKzJsGW0d5apX+rrI05vxbrvMJEzFI14aTDCa63IRTlLK4iH66uOI=";
|
|
static const std::string kTestKeyParamsGcm2 =
|
|
"inline:6X0oCd55zfz4VgtOwsuqcFq61275PDYN5uwuu3p7ZUHbfUY2FMpdP4m2PEo=";
|
|
static const std::string kTestKeyParamsGcm3 =
|
|
"inline:YKlABGZWMgX32xuMotrG0v0T7G83veegaVzubQ==";
|
|
static const std::string kTestKeyParamsGcm4 =
|
|
"inline:gJ6tWoUym2v+/F6xjr7xaxiS3QbJJozl3ZD/0A==";
|
|
static const cricket::CryptoParams kTestCryptoParams1(
|
|
1, "AES_CM_128_HMAC_SHA1_80", kTestKeyParams1, "");
|
|
static const cricket::CryptoParams kTestCryptoParams2(
|
|
1, "AES_CM_128_HMAC_SHA1_80", kTestKeyParams2, "");
|
|
static const cricket::CryptoParams kTestCryptoParamsGcm1(
|
|
1, "AEAD_AES_256_GCM", kTestKeyParamsGcm1, "");
|
|
static const cricket::CryptoParams kTestCryptoParamsGcm2(
|
|
1, "AEAD_AES_256_GCM", kTestKeyParamsGcm2, "");
|
|
static const cricket::CryptoParams kTestCryptoParamsGcm3(
|
|
1, "AEAD_AES_128_GCM", kTestKeyParamsGcm3, "");
|
|
static const cricket::CryptoParams kTestCryptoParamsGcm4(
|
|
1, "AEAD_AES_128_GCM", kTestKeyParamsGcm4, "");
|
|
|
|
class SrtpFilterTest : public testing::Test {
|
|
protected:
|
|
SrtpFilterTest() {}
|
|
static std::vector<CryptoParams> MakeVector(const CryptoParams& params) {
|
|
std::vector<CryptoParams> vec;
|
|
vec.push_back(params);
|
|
return vec;
|
|
}
|
|
|
|
void TestSetParams(const std::vector<CryptoParams>& params1,
|
|
const std::vector<CryptoParams>& params2) {
|
|
EXPECT_TRUE(f1_.SetOffer(params1, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(params1, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetAnswer(params2, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(params2, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
}
|
|
|
|
void VerifyCryptoParamsMatch(const std::string& cs1, const std::string& cs2) {
|
|
EXPECT_EQ(rtc::SrtpCryptoSuiteFromName(cs1), f1_.send_cipher_suite());
|
|
EXPECT_EQ(rtc::SrtpCryptoSuiteFromName(cs2), f2_.send_cipher_suite());
|
|
EXPECT_TRUE(f1_.send_key() == f2_.recv_key());
|
|
EXPECT_TRUE(f2_.send_key() == f1_.recv_key());
|
|
}
|
|
|
|
cricket::SrtpFilter f1_;
|
|
cricket::SrtpFilter f2_;
|
|
};
|
|
|
|
// Test that we can set up the session and keys properly.
|
|
TEST_F(SrtpFilterTest, TestGoodSetupOneCipherSuite) {
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
}
|
|
|
|
TEST_F(SrtpFilterTest, TestGoodSetupOneCipherSuiteGcm) {
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParamsGcm1), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParamsGcm2), CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we can set up things with multiple params.
|
|
TEST_F(SrtpFilterTest, TestGoodSetupMultipleCipherSuites) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
offer.push_back(kTestCryptoParams1);
|
|
offer[1].tag = 2;
|
|
offer[1].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
answer[0].tag = 2;
|
|
answer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
}
|
|
|
|
TEST_F(SrtpFilterTest, TestGoodSetupMultipleCipherSuitesGcm) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParamsGcm1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParamsGcm3));
|
|
offer.push_back(kTestCryptoParamsGcm4);
|
|
offer[1].tag = 2;
|
|
answer[0].tag = 2;
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we handle the cases where crypto is not desired.
|
|
TEST_F(SrtpFilterTest, TestGoodSetupNoCipherSuites) {
|
|
std::vector<CryptoParams> offer, answer;
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we handle the cases where crypto is not desired by the remote side.
|
|
TEST_F(SrtpFilterTest, TestGoodSetupNoAnswerCipherSuites) {
|
|
std::vector<CryptoParams> answer;
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail if we call the functions the wrong way.
|
|
TEST_F(SrtpFilterTest, TestBadSetup) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we can set offer multiple times from the same source.
|
|
TEST_F(SrtpFilterTest, TestGoodSetupMultipleOffers) {
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
}
|
|
// Test that we can't set offer multiple times from different sources.
|
|
TEST_F(SrtpFilterTest, TestBadSetupMultipleOffers) {
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams1), CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
|
|
EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_FALSE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_FALSE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
|
|
}
|
|
|
|
// Test that we fail if we have params in the answer when none were offered.
|
|
TEST_F(SrtpFilterTest, TestNoAnswerCipherSuites) {
|
|
std::vector<CryptoParams> offer;
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail if we have too many params in our answer.
|
|
TEST_F(SrtpFilterTest, TestMultipleAnswerCipherSuites) {
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer.push_back(kTestCryptoParams2);
|
|
answer[1].tag = 2;
|
|
answer[1].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail if we don't support the cipher-suite.
|
|
TEST_F(SrtpFilterTest, TestInvalidCipherSuite) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
offer[0].cipher_suite = answer[0].cipher_suite = "FOO";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail if we can't agree on a tag.
|
|
TEST_F(SrtpFilterTest, TestNoMatchingTag) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].tag = 99;
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail if we can't agree on a cipher-suite.
|
|
TEST_F(SrtpFilterTest, TestNoMatchingCipherSuite) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].tag = 2;
|
|
answer[0].cipher_suite = "FOO";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail keys with bad base64 content.
|
|
TEST_F(SrtpFilterTest, TestInvalidKeyData) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].key_params = "inline:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail keys with the wrong key-method.
|
|
TEST_F(SrtpFilterTest, TestWrongKeyMethod) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].key_params = "outline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail keys of the wrong length.
|
|
TEST_F(SrtpFilterTest, TestKeyTooShort) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].key_params = "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtx";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail keys of the wrong length.
|
|
TEST_F(SrtpFilterTest, TestKeyTooLong) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].key_params = "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBRABCD";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we fail keys with lifetime or MKI set (since we don't support)
|
|
TEST_F(SrtpFilterTest, TestUnsupportedOptions) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
answer[0].key_params =
|
|
"inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:4";
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
}
|
|
|
|
// Test that we can encrypt/decrypt after negotiating AES_CM_128_HMAC_SHA1_80.
|
|
TEST_F(SrtpFilterTest, TestProtect_AES_CM_128_HMAC_SHA1_80) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
offer.push_back(kTestCryptoParams1);
|
|
offer[1].tag = 2;
|
|
offer[1].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
TestSetParams(offer, answer);
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
}
|
|
|
|
// Test that we can encrypt/decrypt after negotiating AES_CM_128_HMAC_SHA1_32.
|
|
TEST_F(SrtpFilterTest, TestProtect_AES_CM_128_HMAC_SHA1_32) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
offer.push_back(kTestCryptoParams1);
|
|
offer[1].tag = 2;
|
|
offer[1].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
answer[0].tag = 2;
|
|
answer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
TestSetParams(offer, answer);
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_32,
|
|
CS_AES_CM_128_HMAC_SHA1_32);
|
|
}
|
|
|
|
// Test that we can change encryption parameters.
|
|
TEST_F(SrtpFilterTest, TestChangeParameters) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
|
|
TestSetParams(offer, answer);
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
|
|
// Change the key parameters and cipher_suite.
|
|
offer[0].key_params = kTestKeyParams3;
|
|
offer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
answer[0].key_params = kTestKeyParams4;
|
|
answer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
|
|
// Test that the old keys are valid until the negotiation is complete.
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
|
|
// Complete the negotiation and test that we can still understand each other.
|
|
EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_32,
|
|
CS_AES_CM_128_HMAC_SHA1_32);
|
|
}
|
|
|
|
// Test that we can send and receive provisional answers with crypto enabled.
|
|
// Also test that we can change the crypto.
|
|
TEST_F(SrtpFilterTest, TestProvisionalAnswer) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
offer.push_back(kTestCryptoParams1);
|
|
offer[1].tag = 2;
|
|
offer[1].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
|
|
answer[0].key_params = kTestKeyParams4;
|
|
answer[0].tag = 2;
|
|
answer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
|
|
EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_32,
|
|
CS_AES_CM_128_HMAC_SHA1_32);
|
|
}
|
|
|
|
// Test that a provisional answer doesn't need to contain a crypto.
|
|
TEST_F(SrtpFilterTest, TestProvisionalAnswerWithoutCrypto) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer;
|
|
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
|
|
answer.push_back(kTestCryptoParams2);
|
|
EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
}
|
|
|
|
// Test that if we get a new local offer after a provisional answer
|
|
// with no crypto, that we are in an inactive state.
|
|
TEST_F(SrtpFilterTest, TestLocalOfferAfterProvisionalAnswerWithoutCrypto) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer;
|
|
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
// The calls to set an offer after a provisional answer fail, so the
|
|
// state doesn't change.
|
|
EXPECT_FALSE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_FALSE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
|
|
answer.push_back(kTestCryptoParams2);
|
|
EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
}
|
|
|
|
// Test that we can disable encryption.
|
|
TEST_F(SrtpFilterTest, TestDisableEncryption) {
|
|
std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
|
|
std::vector<CryptoParams> answer(MakeVector(kTestCryptoParams2));
|
|
|
|
TestSetParams(offer, answer);
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
|
|
offer.clear();
|
|
answer.clear();
|
|
EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
|
|
EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
|
|
EXPECT_TRUE(f1_.IsActive());
|
|
EXPECT_TRUE(f2_.IsActive());
|
|
|
|
// Test that the old keys are valid until the negotiation is complete.
|
|
VerifyCryptoParamsMatch(CS_AES_CM_128_HMAC_SHA1_80,
|
|
CS_AES_CM_128_HMAC_SHA1_80);
|
|
|
|
// Complete the negotiation.
|
|
EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
|
|
EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
|
|
|
|
EXPECT_FALSE(f1_.IsActive());
|
|
EXPECT_FALSE(f2_.IsActive());
|
|
}
|
|
|
|
} // namespace rtc
|