Implemented bit flipping fuzz test.

Moved random encryption to its own file.

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/392017

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1771 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
phoglund@webrtc.org 2012-02-27 15:29:52 +00:00
parent b4556cd29a
commit 52b59d095e
6 changed files with 296 additions and 77 deletions

View File

@ -8,129 +8,141 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "gtest/gtest.h"
#include "gflags/gflags.h"
#include "video_engine/include/vie_encryption.h"
#include "video_engine/test/auto_test/automated/two_windows_fixture.h"
#include "video_engine/test/auto_test/helpers/bit_flip_encryption.h"
#include "video_engine/test/auto_test/helpers/random_encryption.h"
#include "video_engine/test/auto_test/helpers/vie_window_creator.h"
#include "video_engine/test/auto_test/interface/tb_capture_device.h"
#include "video_engine/test/auto_test/interface/tb_interfaces.h"
#include "video_engine/test/auto_test/interface/tb_video_channel.h"
#include "video_engine/test/auto_test/interface/vie_autotest_window_manager_interface.h"
#include "video_engine/test/auto_test/primitives/general_primitives.h"
#include "video_engine/vie_defines.h"
namespace {
DEFINE_int32(rtp_fuzz_test_rand_seed, 0, "The rand seed to use for "
"the RTP fuzz test. Defaults to time(). 0 cannot be specified.");
"the RTP fuzz test. Defaults to time(). 0 cannot be specified.");
class ViERtpFuzzTest : public TwoWindowsFixture {
protected:
TbVideoChannel* video_channel_;
TbInterfaces* video_engine_;
TbCaptureDevice* capture_device_;
void SetUp() {
video_engine_ = new TbInterfaces(
"ViERtpTryInjectingRandomPacketsIntoRtpStream");
video_channel_ = new TbVideoChannel(
*video_engine_, webrtc::kVideoCodecVP8);
capture_device_ = new TbCaptureDevice(*video_engine_);
capture_device_->ConnectTo(video_channel_->videoChannel);
// Enable PLI RTCP, which will allow the video engine to recover better.
video_engine_->rtp_rtcp->SetKeyFrameRequestMethod(
video_channel_->videoChannel, webrtc::kViEKeyFrameRequestPliRtcp);
video_channel_->StartReceive();
video_channel_->StartSend();
RenderInWindow(
video_engine_->render, capture_device_->captureId, window_1_, 0);
RenderInWindow(
video_engine_->render, video_channel_->videoChannel, window_2_, 1);
}
void TearDown() {
delete capture_device_;
delete video_channel_;
delete video_engine_;
}
unsigned int FetchRandSeed() {
if (FLAGS_rtp_fuzz_test_rand_seed != 0) {
return FLAGS_rtp_fuzz_test_rand_seed;
}
return std::time(NULL);
}
// Pass in a number [0, 1] which will be the bit flip probability per byte.
void BitFlipFuzzTest(float flip_probability) {
unsigned int rand_seed = FetchRandSeed();
ViETest::Log("Running test with rand seed %d.", rand_seed);
ViETest::Log("Running as usual. You should see video output.");
AutoTestSleep(2000);
ViETest::Log("Starting to flip bits in packets (%f%% chance per byte).",
flip_probability * 100);
BitFlipEncryption bit_flip_encryption(rand_seed, flip_probability);
video_engine_->encryption->RegisterExternalEncryption(
video_channel_->videoChannel, bit_flip_encryption);
AutoTestSleep(5000);
ViETest::Log("Back to normal. Flipped %d bits.",
bit_flip_encryption.flip_count());
video_engine_->encryption->DeregisterExternalEncryption(
video_channel_->videoChannel);
AutoTestSleep(5000);
}
};
static int Saturate(int value, int min, int max) {
return std::min(std::max(value, min), max);
TEST_F(ViERtpFuzzTest, VideoEngineDealsWithASmallNumberOfTamperedPackets) {
// Try 0.005% bit flip chance per byte.
BitFlipFuzzTest(0.00005);
}
// These algorithms attempt to create an uncrackable encryption
// scheme by completely disregarding the input data.
class RandomEncryption : public webrtc::Encryption {
public:
RandomEncryption(unsigned int rand_seed) {
srand(rand_seed);
}
TEST_F(ViERtpFuzzTest, VideoEngineDealsWithAMediumNumberOfTamperedPackets) {
// Try 0.05% bit flip chance per byte.
BitFlipFuzzTest(0.0005);
}
virtual void encrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
TEST_F(ViERtpFuzzTest, VideoEngineDealsWithALargeNumberOfTamperedPackets) {
// Try 0.5% bit flip chance per byte.
BitFlipFuzzTest(0.005);
}
virtual void decrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
TEST_F(ViERtpFuzzTest, VideoEngineDealsWithAVeryLargeNumberOfTamperedPackets) {
// Try 5% bit flip chance per byte.
BitFlipFuzzTest(0.05);
}
virtual void encrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
TEST_F(ViERtpFuzzTest,
VideoEngineDealsWithAExtremelyLargeNumberOfTamperedPackets) {
// Try 25% bit flip chance per byte (madness!)
BitFlipFuzzTest(0.25);
}
virtual void decrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
private:
// Generates some completely random data with roughly the right length.
void GenerateRandomData(unsigned char* out_data, int bytes_in,
int* bytes_out) {
int out_length = MakeUpSimilarLength(bytes_in);
for (int i = 0; i < out_length; i++) {
// The modulo will skew the random distribution a bit, but I think it
// will be random enough.
out_data[i] = static_cast<unsigned char>(rand() % 256);
}
*bytes_out = out_length;
}
// Makes up a length within +- 50 of the original length, without
// overstepping the contract for encrypt / decrypt.
int MakeUpSimilarLength(int original_length) {
int sign = rand() - RAND_MAX / 2;
int length = original_length + sign * rand() % 50;
return Saturate(length, 0, static_cast<int>(webrtc::kViEMaxMtu));
}
};
TEST_F(ViERtpFuzzTest, VideoEngineDealsWithSeveralPeriodsOfTamperedPackets) {
// Try 0.05% bit flip chance per byte.
BitFlipFuzzTest(0.0005);
BitFlipFuzzTest(0.0005);
BitFlipFuzzTest(0.0005);
}
TEST_F(ViERtpFuzzTest, VideoEngineRecoversAfterSomeCompletelyRandomPackets) {
unsigned int rand_seed = FetchRandSeed();
ViETest::Log("Running test with rand seed %d.", rand_seed);
TbInterfaces video_engine("ViERtpTryInjectingRandomPacketsIntoRtpStream");
TbVideoChannel video_channel(video_engine, webrtc::kVideoCodecVP8);
TbCaptureDevice capture_device(video_engine);
capture_device.ConnectTo(video_channel.videoChannel);
// Enable PLI RTCP, which will allow the video engine to recover better.
video_engine.rtp_rtcp->SetKeyFrameRequestMethod(
video_channel.videoChannel, webrtc::kViEKeyFrameRequestPliRtcp);
video_channel.StartReceive();
video_channel.StartSend();
RenderInWindow(
video_engine.render, capture_device.captureId, window_1_, 0);
RenderInWindow(
video_engine.render, video_channel.videoChannel, window_2_, 1);
ViETest::Log("Running as usual. You should see video output.");
AutoTestSleep(2000);
ViETest::Log("Injecting completely random packets...");
RandomEncryption random_encryption(rand_seed);
video_engine.encryption->RegisterExternalEncryption(
video_channel.videoChannel, random_encryption);
video_engine_->encryption->RegisterExternalEncryption(
video_channel_->videoChannel, random_encryption);
AutoTestSleep(5000);
ViETest::Log("Back to normal.");
video_engine.encryption->DeregisterExternalEncryption(
video_channel.videoChannel);
video_engine_->encryption->DeregisterExternalEncryption(
video_channel_->videoChannel);
AutoTestSleep(5000);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2012 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 "video_engine/test/auto_test/helpers/bit_flip_encryption.h"
#include <cstdlib>
#include "video_engine/test/auto_test/interface/vie_autotest_defines.h"
float NormalizedRand() {
return static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
}
BitFlipEncryption::BitFlipEncryption(unsigned int rand_seed,
float flip_probability)
: flip_probability_(flip_probability),
flip_count_(0) {
srand(rand_seed);
}
void BitFlipEncryption::FlipSomeBitsInData(const unsigned char* in_data,
unsigned char* out_data,
int bytes_in, int* bytes_out) {
for (int i = 0; i < bytes_in; i++) {
out_data[i] = in_data[i];
if (NormalizedRand() < flip_probability_) {
int bit_to_flip = rand() % 8;
out_data[i] ^= 1 << bit_to_flip;
flip_count_++;
}
}
*bytes_out = bytes_in;
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2012 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.
*/
#ifndef SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_BIT_FLIP_ENCRYPTION_H_
#define SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_BIT_FLIP_ENCRYPTION_H_
#include "video_engine/include/vie_encryption.h"
// This encryption scheme will randomly flip bits every now and then in the
// input data.
class BitFlipEncryption : public webrtc::Encryption {
public:
// Args:
// rand_seed: the seed to initialize the test's random generator with.
// flip_probability: A number [0, 1] which is the percentage chance a bit
// gets flipped in a particular byte.
BitFlipEncryption(unsigned int rand_seed, float flip_probability);
virtual void encrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
FlipSomeBitsInData(in_data, out_data, bytes_in, bytes_out);
}
virtual void decrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
FlipSomeBitsInData(in_data, out_data, bytes_in, bytes_out);
}
virtual void encrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
FlipSomeBitsInData(in_data, out_data, bytes_in, bytes_out);
}
virtual void decrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
FlipSomeBitsInData(in_data, out_data, bytes_in, bytes_out);
}
int64_t flip_count() const { return flip_count_; }
private:
// The flip probability ([0, 1]).
float flip_probability_;
// The number of bits we've flipped so far.
int64_t flip_count_;
// Flips some bits in the data at random.
void FlipSomeBitsInData(const unsigned char *in_data, unsigned char* out_data,
int bytes_in, int* bytes_out);
};
#endif // SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_BIT_FLIP_ENCRYPTION_H_

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012 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 "video_engine/test/auto_test/helpers/random_encryption.h"
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include "video_engine/vie_defines.h"
static int Saturate(int value, int min, int max) {
return std::min(std::max(value, min), max);
}
RandomEncryption::RandomEncryption(unsigned int rand_seed) {
srand(rand_seed);
}
// Generates some completely random data with roughly the right length.
void RandomEncryption::GenerateRandomData(unsigned char* out_data, int bytes_in,
int* bytes_out) {
int out_length = MakeUpSimilarLength(bytes_in);
for (int i = 0; i < out_length; i++) {
// The modulo will skew the random distribution a bit, but I think it
// will be random enough.
out_data[i] = static_cast<unsigned char>(rand() % 256);
}
*bytes_out = out_length;
}
// Makes up a length within +- 50 of the original length, without
// overstepping the contract for encrypt / decrypt.
int RandomEncryption::MakeUpSimilarLength(int original_length) {
int sign = rand() - RAND_MAX / 2;
int length = original_length + sign * rand() % 50;
return Saturate(length, 0, static_cast<int>(webrtc::kViEMaxMtu));
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2012 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.
*/
#ifndef SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_RANDOM_ENCRYPTION_H_
#define SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_RANDOM_ENCRYPTION_H_
#include "video_engine/include/vie_encryption.h"
// These algorithms attempt to create an uncrackable encryption
// scheme by completely disregarding the input data.
class RandomEncryption : public webrtc::Encryption {
public:
explicit RandomEncryption(unsigned int rand_seed);
virtual void encrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
virtual void decrypt(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in, int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
virtual void encrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
virtual void decrypt_rtcp(int channel_no, unsigned char* in_data,
unsigned char* out_data, int bytes_in,
int* bytes_out) {
GenerateRandomData(out_data, bytes_in, bytes_out);
}
private:
// Generates some completely random data with roughly the right length.
void GenerateRandomData(unsigned char* out_data, int bytes_in,
int* bytes_out);
// Makes up a length within +- 50 of the original length, without
// overstepping the contract for encrypt / decrypt.
int MakeUpSimilarLength(int original_length);
};
#endif // SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_RANDOM_ENCRYPTION_H_

View File

@ -49,6 +49,10 @@
'interface/vie_window_manager_factory.h',
# Helper classes
'helpers/bit_flip_encryption.cc',
'helpers/bit_flip_encryption.h',
'helpers/random_encryption.cc',
'helpers/random_encryption.h',
'helpers/vie_fake_camera.cc',
'helpers/vie_fake_camera.h',
'helpers/vie_file_capture_device.cc',