From 52b59d095ea75bef7a4ae47aa6844d3f92ccb117 Mon Sep 17 00:00:00 2001 From: "phoglund@webrtc.org" Date: Mon, 27 Feb 2012 15:29:52 +0000 Subject: [PATCH] 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 --- .../auto_test/automated/vie_rtp_fuzz_test.cc | 166 ++++++++++-------- .../auto_test/helpers/bit_flip_encryption.cc | 42 +++++ .../auto_test/helpers/bit_flip_encryption.h | 61 +++++++ .../auto_test/helpers/random_encryption.cc | 46 +++++ .../auto_test/helpers/random_encryption.h | 54 ++++++ .../test/auto_test/vie_auto_test.gypi | 4 + 6 files changed, 296 insertions(+), 77 deletions(-) create mode 100644 src/video_engine/test/auto_test/helpers/bit_flip_encryption.cc create mode 100644 src/video_engine/test/auto_test/helpers/bit_flip_encryption.h create mode 100644 src/video_engine/test/auto_test/helpers/random_encryption.cc create mode 100644 src/video_engine/test/auto_test/helpers/random_encryption.h diff --git a/src/video_engine/test/auto_test/automated/vie_rtp_fuzz_test.cc b/src/video_engine/test/auto_test/automated/vie_rtp_fuzz_test.cc index 5bab4562ab..113976cc0a 100644 --- a/src/video_engine/test/auto_test/automated/vie_rtp_fuzz_test.cc +++ b/src/video_engine/test/auto_test/automated/vie_rtp_fuzz_test.cc @@ -8,129 +8,141 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include -#include #include #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(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(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); } diff --git a/src/video_engine/test/auto_test/helpers/bit_flip_encryption.cc b/src/video_engine/test/auto_test/helpers/bit_flip_encryption.cc new file mode 100644 index 0000000000..423ad5adcf --- /dev/null +++ b/src/video_engine/test/auto_test/helpers/bit_flip_encryption.cc @@ -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 + +#include "video_engine/test/auto_test/interface/vie_autotest_defines.h" + +float NormalizedRand() { + return static_cast(rand()) / + static_cast(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; +} diff --git a/src/video_engine/test/auto_test/helpers/bit_flip_encryption.h b/src/video_engine/test/auto_test/helpers/bit_flip_encryption.h new file mode 100644 index 0000000000..ccc6974620 --- /dev/null +++ b/src/video_engine/test/auto_test/helpers/bit_flip_encryption.h @@ -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_ diff --git a/src/video_engine/test/auto_test/helpers/random_encryption.cc b/src/video_engine/test/auto_test/helpers/random_encryption.cc new file mode 100644 index 0000000000..04904b51f7 --- /dev/null +++ b/src/video_engine/test/auto_test/helpers/random_encryption.cc @@ -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 +#include +#include + +#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(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(webrtc::kViEMaxMtu)); +} diff --git a/src/video_engine/test/auto_test/helpers/random_encryption.h b/src/video_engine/test/auto_test/helpers/random_encryption.h new file mode 100644 index 0000000000..cbca844c04 --- /dev/null +++ b/src/video_engine/test/auto_test/helpers/random_encryption.h @@ -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_ diff --git a/src/video_engine/test/auto_test/vie_auto_test.gypi b/src/video_engine/test/auto_test/vie_auto_test.gypi index d7e80849ae..bbf92392f6 100644 --- a/src/video_engine/test/auto_test/vie_auto_test.gypi +++ b/src/video_engine/test/auto_test/vie_auto_test.gypi @@ -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',