Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DTLS fuzzer #1346

Merged
merged 2 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions doc/Fuzzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ For memory leak detection enable the following environment variable:

The mediasoup-worker fuzzer reads some custom environment variables to decide which kind of fuzzing perform:

- `MS_FUZZ_STUN=1`: Do STUN fuzzing.
- `MS_FUZZ_RTP=1`: Do RTP fuzzing.
- `MS_FUZZ_RTCP=1`: Do RTCP fuzzing.
- `MS_FUZZ_UTILS=1`: Do C++ utils fuzzing.
- `MS_FUZZ_STUN=1`: Enable STUN fuzzer.
- `MS_FUZZ_DTLS=1`: Enable DTLS fuzzer.
- `MS_FUZZ_RTP=1`: Enable RTP fuzzer.
- `MS_FUZZ_RTCP=1`: Enable RTCP fuzzer.
- `MS_FUZZ_UTILS=1`: Enable C++ utils fuzzer.
- If none of them is given, then **all** fuzzers are enabled.

The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment variable to "debug", "warn" or "error" (it is "none" if unset).
Expand All @@ -55,6 +56,12 @@ The log level can also be set by setting the `MS_FUZZ_LOG_LEVEL` environment var
MS_FUZZ_STUN=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus
```

- Detect memory leaks and just fuzz DTLS:

```bash
MS_FUZZ_DTLS=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./out/Release/mediasoup-worker-fuzzer -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus
```

- Detect memory leaks and just fuzz RTP:

```bash
Expand Down
39 changes: 39 additions & 0 deletions worker/fuzzer/include/RTC/FuzzerDtlsTransport.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef MS_FUZZER_RTC_DTLS_TRANSPORT_HPP
#define MS_FUZZER_RTC_DTLS_TRANSPORT_HPP

#include "common.hpp"
#include "RTC/DtlsTransport.hpp"

namespace Fuzzer
{
namespace RTC
{
namespace DtlsTransport
{
class DtlsTransportListener : public ::RTC::DtlsTransport::Listener
{
/* Pure virtual methods inherited from RTC::DtlsTransport::Listener. */
public:
void OnDtlsTransportConnecting(const ::RTC::DtlsTransport* dtlsTransport) override;
void OnDtlsTransportConnected(
const ::RTC::DtlsTransport* dtlsTransport,
::RTC::SrtpSession::CryptoSuite srtpCryptoSuite,
uint8_t* srtpLocalKey,
size_t srtpLocalKeyLen,
uint8_t* srtpRemoteKey,
size_t srtpRemoteKeyLen,
std::string& remoteCert) override;
void OnDtlsTransportFailed(const ::RTC::DtlsTransport* dtlsTransport) override;
void OnDtlsTransportClosed(const ::RTC::DtlsTransport* dtlsTransport) override;
void OnDtlsTransportSendData(
const ::RTC::DtlsTransport* dtlsTransport, const uint8_t* data, size_t len) override;
void OnDtlsTransportApplicationDataReceived(
const ::RTC::DtlsTransport* dtlsTransport, const uint8_t* data, size_t len) override;
};

void Fuzz(const uint8_t* data, size_t len);
} // namespace DtlsTransport
} // namespace RTC
} // namespace Fuzzer

#endif
118 changes: 118 additions & 0 deletions worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#define MS_CLASS "Fuzzer::RTC::DtlsTransport"
// #define MS_LOG_DEV_LEVEL 3

#include "RTC/FuzzerDtlsTransport.hpp"
#include "Logger.hpp"
#include "Utils.hpp"

// DtlsTransport singleton. It's reset every time DTLS handshake fails or DTLS
// is closed.
thread_local static ::RTC::DtlsTransport* dtlsTransportSingleton{ nullptr };
// DtlsTransport Listener singleton. It's reset every time the DtlsTransport
// singletonDTLS is reset.
thread_local static Fuzzer::RTC::DtlsTransport::DtlsTransportListener* dtlsTransportListenerSingleton{
nullptr
};

void Fuzzer::RTC::DtlsTransport::Fuzz(const uint8_t* data, size_t len)
{
if (!::RTC::DtlsTransport::IsDtls(data, len))
{
return;
}

if (!dtlsTransportSingleton)
{
MS_DEBUG_DEV("no DtlsTransport singleton, creating it");

delete dtlsTransportListenerSingleton;
dtlsTransportListenerSingleton = new DtlsTransportListener();

dtlsTransportSingleton = new ::RTC::DtlsTransport(dtlsTransportListenerSingleton);

::RTC::DtlsTransport::Role localRole;
::RTC::DtlsTransport::Fingerprint dtlsRemoteFingerprint;

// Local DTLS role must be 'server' or 'client'. Choose it based on
// randomness of first given byte.
if (data[0] / 2 == 0)
{
localRole = ::RTC::DtlsTransport::Role::SERVER;
}
else
{
localRole = ::RTC::DtlsTransport::Role::CLIENT;
}

// Remote DTLS fingerprint random generation.
// NOTE: Use a random integer in range 1..5 since FingerprintAlgorithm enum
// has 5 possible values starting with value 1.
dtlsRemoteFingerprint.algorithm =
static_cast<::RTC::DtlsTransport::FingerprintAlgorithm>(::Utils::Crypto::GetRandomUInt(1u, 5u));

dtlsRemoteFingerprint.value =
::Utils::Crypto::GetRandomString(::Utils::Crypto::GetRandomUInt(3u, 20u));

dtlsTransportSingleton->Run(localRole);
dtlsTransportSingleton->SetRemoteFingerprint(dtlsRemoteFingerprint);
}

dtlsTransportSingleton->ProcessDtlsData(data, len);

// DTLS may have failed or closed after ProcessDtlsData(). If so, unset it.
if (
dtlsTransportSingleton->GetState() == ::RTC::DtlsTransport::DtlsState::FAILED ||
dtlsTransportSingleton->GetState() == ::RTC::DtlsTransport::DtlsState::CLOSED)
{
MS_DEBUG_DEV("DtlsTransport singleton state is 'failed' or 'closed', unsetting it");

delete dtlsTransportSingleton;
dtlsTransportSingleton = nullptr;
}
else
{
dtlsTransportSingleton->SendApplicationData(data, len);
}
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportConnecting(
const ::RTC::DtlsTransport* /*dtlsTransport*/)
{
MS_DEBUG_DEV("DtlsTransport singleton connecting");
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportConnected(
const ::RTC::DtlsTransport* /*dtlsTransport*/,
::RTC::SrtpSession::CryptoSuite /*srtpCryptoSuite*/,
uint8_t* /*srtpLocalKey*/,
size_t /*srtpLocalKeyLen*/,
uint8_t* /*srtpRemoteKey*/,
size_t /*srtpRemoteKeyLen*/,
std::string& /*remoteCert*/)
{
MS_DEBUG_DEV("DtlsTransport singleton connected");
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportFailed(
const ::RTC::DtlsTransport* /*dtlsTransport*/)
{
MS_DEBUG_DEV("DtlsTransport singleton failed");
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportClosed(
const ::RTC::DtlsTransport* /*dtlsTransport*/)
{
MS_DEBUG_DEV("DtlsTransport singleton closed");
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportSendData(
const ::RTC::DtlsTransport* /*dtlsTransport*/, const uint8_t* /*data*/, size_t /*len*/)
{
MS_DEBUG_DEV("DtlsTransport singleton wants to send data");
}

void Fuzzer::RTC::DtlsTransport::DtlsTransportListener::OnDtlsTransportApplicationDataReceived(
const ::RTC::DtlsTransport* /*dtlsTransport*/, const uint8_t* /*data*/, size_t /*len*/)
{
MS_DEBUG_DEV("DtlsTransport singleton received application data");
}
27 changes: 22 additions & 5 deletions worker/fuzzer/src/fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "LogLevel.hpp"
#include "Settings.hpp"
#include "Utils.hpp"
#include "RTC/DtlsTransport.hpp"
#include "RTC/FuzzerDtlsTransport.hpp"
#include "RTC/FuzzerRtpPacket.hpp"
#include "RTC/FuzzerRtpRetransmissionBuffer.hpp"
#include "RTC/FuzzerRtpStreamSend.hpp"
Expand All @@ -22,6 +24,7 @@
#include <stdint.h>

bool fuzzStun = false;
bool fuzzDtls = false;
bool fuzzRtp = false;
bool fuzzRtcp = false;
bool fuzzUtils = false;
Expand All @@ -41,6 +44,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len)
Fuzzer::RTC::StunPacket::Fuzz(data, len);
}

if (fuzzDtls)
{
Fuzzer::RTC::DtlsTransport::Fuzz(data, len);
}

if (fuzzRtp)
{
Fuzzer::RTC::RtpPacket::Fuzz(data, len);
Expand Down Expand Up @@ -85,35 +93,43 @@ int Init()
}

// Select what to fuzz.

if (std::getenv("MS_FUZZ_STUN") && std::string(std::getenv("MS_FUZZ_STUN")) == "1")
{
std::cout << "[fuzzer] STUN fuzzers enabled" << std::endl;
std::cout << "[fuzzer] STUN fuzzer enabled" << std::endl;

fuzzStun = true;
}
if (std::getenv("MS_FUZZ_DTLS") && std::string(std::getenv("MS_FUZZ_DTLS")) == "1")
{
std::cout << "[fuzzer] DTLS fuzzer enabled" << std::endl;

fuzzDtls = true;
}
if (std::getenv("MS_FUZZ_RTP") && std::string(std::getenv("MS_FUZZ_RTP")) == "1")
{
std::cout << "[fuzzer] RTP fuzzers enabled" << std::endl;
std::cout << "[fuzzer] RTP fuzzer enabled" << std::endl;

fuzzRtp = true;
}
if (std::getenv("MS_FUZZ_RTCP") && std::string(std::getenv("MS_FUZZ_RTCP")) == "1")
{
std::cout << "[fuzzer] RTCP fuzzers enabled" << std::endl;
std::cout << "[fuzzer] RTCP fuzzer enabled" << std::endl;

fuzzRtcp = true;
}
if (std::getenv("MS_FUZZ_UTILS") && std::string(std::getenv("MS_FUZZ_UTILS")) == "1")
{
std::cout << "[fuzzer] Utils fuzzers enabled" << std::endl;
std::cout << "[fuzzer] Utils fuzzer enabled" << std::endl;

fuzzUtils = true;
}
if (!fuzzUtils && !fuzzStun && !fuzzRtcp && !fuzzRtp)
if (!fuzzStun && !fuzzDtls && !fuzzRtcp && !fuzzRtp && !fuzzUtils)
{
std::cout << "[fuzzer] all fuzzers enabled" << std::endl;

fuzzStun = true;
fuzzDtls = true;
fuzzRtp = true;
fuzzRtcp = true;
fuzzUtils = true;
Expand All @@ -128,6 +144,7 @@ int Init()
DepUsrSCTP::ClassInit();
DepLibWebRTC::ClassInit();
Utils::Crypto::ClassInit();
::RTC::DtlsTransport::ClassInit();

return 0;
}
3 changes: 2 additions & 1 deletion worker/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,12 @@ executable(
sources: common_sources + [
'fuzzer/src/fuzzer.cpp',
'fuzzer/src/FuzzerUtils.cpp',
'fuzzer/src/RTC/FuzzerStunPacket.cpp',
'fuzzer/src/RTC/FuzzerDtlsTransport.cpp',
'fuzzer/src/RTC/FuzzerRtpPacket.cpp',
'fuzzer/src/RTC/FuzzerRtpRetransmissionBuffer.cpp',
'fuzzer/src/RTC/FuzzerRtpStreamSend.cpp',
'fuzzer/src/RTC/FuzzerSeqManager.cpp',
'fuzzer/src/RTC/FuzzerStunPacket.cpp',
'fuzzer/src/RTC/FuzzerTrendCalculator.cpp',
'fuzzer/src/RTC/RTCP/FuzzerBye.cpp',
'fuzzer/src/RTC/RTCP/FuzzerFeedbackPs.cpp',
Expand Down
Loading