FrameEncryption Video End To End Testcase.
There was a suggestion in a previous CL to add an end to end test case to prevent future regressions. I have enabled this by adding two fakes that perform fake encryption and enabling an end to end test with VP8 and the GenericDescriptor. Bug: webrtc:9927 Change-Id: Icf96eeed541ada1e0579eb81b6f87a46d1c43d96 Reviewed-on: https://webrtc-review.googlesource.com/c/108020 Commit-Queue: Benjamin Wright <benwright@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25399}
This commit is contained in:
parent
c462a6ef9b
commit
150a907403
@ -25,19 +25,20 @@ int FakeFrameDecryptor::Decrypt(cricket::MediaType media_type,
|
||||
rtc::ArrayView<uint8_t> frame,
|
||||
size_t* bytes_written) {
|
||||
if (fail_decryption_) {
|
||||
return 1;
|
||||
return static_cast<int>(FakeDecryptStatus::FORCED_FAILURE);
|
||||
}
|
||||
|
||||
RTC_CHECK_EQ(frame.size() + 1, encrypted_frame.size());
|
||||
for (size_t i = 0; i < frame.size(); i++) {
|
||||
frame[i] ^= fake_key_;
|
||||
frame[i] = encrypted_frame[i] ^ fake_key_;
|
||||
}
|
||||
|
||||
if (encrypted_frame[frame.size()] != expected_postfix_byte_) {
|
||||
return 1;
|
||||
return static_cast<int>(FakeDecryptStatus::INVALID_POSTFIX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
*bytes_written = frame.size();
|
||||
return static_cast<int>(FakeDecryptStatus::OK);
|
||||
}
|
||||
|
||||
size_t FakeFrameDecryptor::GetMaxPlaintextByteSize(
|
||||
|
||||
@ -22,34 +22,40 @@ namespace webrtc {
|
||||
// FrameDecryptorInterface. It is constructed with a simple single digit key and
|
||||
// a fixed postfix byte. This is just to validate that the core code works
|
||||
// as expected.
|
||||
class FakeFrameDecryptor
|
||||
class FakeFrameDecryptor final
|
||||
: public rtc::RefCountedObject<FrameDecryptorInterface> {
|
||||
public:
|
||||
// Provide a key (0,255) and some postfix byte (0,255) this should match the
|
||||
// byte you expect from the FakeFrameEncryptor.
|
||||
explicit FakeFrameDecryptor(uint8_t fake_key = 1,
|
||||
explicit FakeFrameDecryptor(uint8_t fake_key = 0xAA,
|
||||
uint8_t expected_postfix_byte = 255);
|
||||
|
||||
// FrameDecryptorInterface implementation
|
||||
// Fake decryption that just xors the payload with the 1 byte key and checks
|
||||
// the postfix byte. This will always fail if fail_decryption_ is set to true.
|
||||
int Decrypt(cricket::MediaType media_type,
|
||||
const std::vector<uint32_t>& csrcs,
|
||||
rtc::ArrayView<const uint8_t> additional_data,
|
||||
rtc::ArrayView<const uint8_t> encrypted_frame,
|
||||
rtc::ArrayView<uint8_t> frame,
|
||||
size_t* bytes_written) override;
|
||||
|
||||
// Always returns 1 less than the size of the encrypted frame.
|
||||
size_t GetMaxPlaintextByteSize(cricket::MediaType media_type,
|
||||
size_t encrypted_frame_size) override;
|
||||
|
||||
// Sets the fake key to use for encryption.
|
||||
void SetFakeKey(uint8_t fake_key);
|
||||
|
||||
// Returns the fake key used for encryption.
|
||||
uint8_t GetFakeKey() const;
|
||||
|
||||
// Set the Postfix byte that is expected in the encrypted payload.
|
||||
void SetExpectedPostfixByte(uint8_t expected_postfix_byte);
|
||||
|
||||
// Returns the postfix byte that will be checked for in the encrypted payload.
|
||||
uint8_t GetExpectedPostfixByte() const;
|
||||
|
||||
// If set to true will force all encryption to fail.
|
||||
void SetFailDecryption(bool fail_decryption);
|
||||
// Simple error codes for tests to validate against.
|
||||
enum class FakeDecryptStatus : int {
|
||||
OK = 0,
|
||||
FORCED_FAILURE = 1,
|
||||
INVALID_POSTFIX = 2
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t fake_key_ = 0;
|
||||
|
||||
@ -22,18 +22,18 @@ int FakeFrameEncryptor::Encrypt(cricket::MediaType media_type,
|
||||
rtc::ArrayView<const uint8_t> frame,
|
||||
rtc::ArrayView<uint8_t> encrypted_frame,
|
||||
size_t* bytes_written) {
|
||||
// Useful if you want to test failure cases.
|
||||
if (fail_encryption_) {
|
||||
return 1;
|
||||
return static_cast<int>(FakeEncryptionStatus::FORCED_FAILURE);
|
||||
}
|
||||
|
||||
RTC_CHECK_EQ(frame.size() + 1, encrypted_frame.size());
|
||||
for (size_t i = 0; i < frame.size(); i++) {
|
||||
encrypted_frame[i] ^= fake_key_;
|
||||
encrypted_frame[i] = frame[i] ^ fake_key_;
|
||||
}
|
||||
|
||||
encrypted_frame[frame.size()] = postfix_byte_;
|
||||
*bytes_written = encrypted_frame.size();
|
||||
return 0;
|
||||
return static_cast<int>(FakeEncryptionStatus::OK);
|
||||
}
|
||||
|
||||
size_t FakeFrameEncryptor::GetMaxCiphertextByteSize(
|
||||
|
||||
@ -24,29 +24,35 @@ class FakeFrameEncryptor
|
||||
: public rtc::RefCountedObject<FrameEncryptorInterface> {
|
||||
public:
|
||||
// Provide a key (0,255) and some postfix byte (0,255).
|
||||
explicit FakeFrameEncryptor(uint8_t fake_key = 1, uint8_t postfix_byte = 255);
|
||||
|
||||
// FrameEncryptorInterface implementation
|
||||
explicit FakeFrameEncryptor(uint8_t fake_key = 0xAA,
|
||||
uint8_t postfix_byte = 255);
|
||||
// Simply xors each payload with the provided fake key and adds the postfix
|
||||
// bit to the end. This will always fail if fail_encryption_ is set to true.
|
||||
int Encrypt(cricket::MediaType media_type,
|
||||
uint32_t ssrc,
|
||||
rtc::ArrayView<const uint8_t> additional_data,
|
||||
rtc::ArrayView<const uint8_t> frame,
|
||||
rtc::ArrayView<uint8_t> encrypted_frame,
|
||||
size_t* bytes_written) override;
|
||||
|
||||
// Always returns 1 more than the size of the frame.
|
||||
size_t GetMaxCiphertextByteSize(cricket::MediaType media_type,
|
||||
size_t frame_size) override;
|
||||
|
||||
// Sets the fake key to use during encryption.
|
||||
void SetFakeKey(uint8_t fake_key);
|
||||
|
||||
// Returns the fake key used during encryption.
|
||||
uint8_t GetFakeKey() const;
|
||||
|
||||
// Set the postfix byte to use.
|
||||
void SetPostfixByte(uint8_t expected_postfix_byte);
|
||||
|
||||
// Return a postfix byte added to each outgoing payload.
|
||||
uint8_t GetPostfixByte() const;
|
||||
|
||||
// Force all encryptions to fail.
|
||||
void SetFailEncryption(bool fail_encryption);
|
||||
|
||||
enum class FakeEncryptionStatus : int {
|
||||
OK = 0,
|
||||
FORCED_FAILURE = 1,
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t fake_key_ = 0;
|
||||
uint8_t postfix_byte_ = 0;
|
||||
|
||||
@ -394,6 +394,7 @@ if (rtc_include_tests) {
|
||||
"end_to_end_tests/config_tests.cc",
|
||||
"end_to_end_tests/extended_reports_tests.cc",
|
||||
"end_to_end_tests/fec_tests.cc",
|
||||
"end_to_end_tests/frame_encryption_tests.cc",
|
||||
"end_to_end_tests/histogram_tests.cc",
|
||||
"end_to_end_tests/multi_codec_receive_tests.cc",
|
||||
"end_to_end_tests/multi_stream_tester.cc",
|
||||
@ -426,6 +427,8 @@ if (rtc_include_tests) {
|
||||
":video",
|
||||
":video_mocks",
|
||||
":video_stream_encoder_impl",
|
||||
"../api:fake_frame_decryptor",
|
||||
"../api:fake_frame_encryptor",
|
||||
"../api:simulated_network_api",
|
||||
"../api/test/video:function_video_factory",
|
||||
"../api/video:encoded_image",
|
||||
|
||||
81
video/end_to_end_tests/frame_encryption_tests.cc
Normal file
81
video/end_to_end_tests/frame_encryption_tests.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2018 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 "api/test/fake_frame_decryptor.h"
|
||||
#include "api/test/fake_frame_encryptor.h"
|
||||
#include "media/engine/internaldecoderfactory.h"
|
||||
#include "modules/video_coding/codecs/vp8/include/vp8.h"
|
||||
#include "test/call_test.h"
|
||||
#include "test/field_trial.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FrameEncryptionEndToEndTest : public test::CallTest {
|
||||
public:
|
||||
FrameEncryptionEndToEndTest() = default;
|
||||
|
||||
private:
|
||||
// GenericDescriptor is required for FrameEncryption to work.
|
||||
test::ScopedFieldTrials field_trials_{"WebRTC-GenericDescriptor/Enabled/"};
|
||||
};
|
||||
|
||||
// Validates that payloads cannot be sent without a frame encryptor and frame
|
||||
// decryptor attached.
|
||||
TEST_F(FrameEncryptionEndToEndTest, RequireFrameEncryptionEnforced) {
|
||||
class DecryptedFrameObserver : public test::EndToEndTest,
|
||||
public rtc::VideoSinkInterface<VideoFrame> {
|
||||
public:
|
||||
DecryptedFrameObserver()
|
||||
: EndToEndTest(kDefaultTimeoutMs),
|
||||
encoder_factory_([]() { return VP8Encoder::Create(); }) {}
|
||||
|
||||
private:
|
||||
void ModifyVideoConfigs(
|
||||
VideoSendStream::Config* send_config,
|
||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||
VideoEncoderConfig* encoder_config) override {
|
||||
// Use VP8 instead of FAKE.
|
||||
send_config->encoder_settings.encoder_factory = &encoder_factory_;
|
||||
send_config->rtp.payload_name = "VP8";
|
||||
send_config->rtp.payload_type = kVideoSendPayloadType;
|
||||
send_config->frame_encryptor = new FakeFrameEncryptor();
|
||||
send_config->crypto_options.sframe.require_frame_encryption = true;
|
||||
encoder_config->codec_type = kVideoCodecVP8;
|
||||
VideoReceiveStream::Decoder decoder =
|
||||
test::CreateMatchingDecoder(*send_config);
|
||||
decoder.decoder_factory = &decoder_factory_;
|
||||
for (auto& recv_config : *receive_configs) {
|
||||
recv_config.decoders.clear();
|
||||
recv_config.decoders.push_back(decoder);
|
||||
recv_config.renderer = this;
|
||||
recv_config.frame_decryptor = new FakeFrameDecryptor();
|
||||
recv_config.crypto_options.sframe.require_frame_encryption = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that rotation is preserved.
|
||||
void OnFrame(const VideoFrame& video_frame) override {
|
||||
observation_complete_.Set();
|
||||
}
|
||||
|
||||
void PerformTest() override {
|
||||
EXPECT_TRUE(Wait())
|
||||
<< "Timed out waiting for decrypted frames to be rendered.";
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoEncoder> encoder_;
|
||||
test::FunctionVideoEncoderFactory encoder_factory_;
|
||||
InternalDecoderFactory decoder_factory_;
|
||||
} test;
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user