Skip to content

Commit

Permalink
Mitigate libsrtp wraparound with loss decryption failure (#1438)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibc authored Aug 29, 2024
1 parent 3604b1e commit d3a7ae8
Show file tree
Hide file tree
Showing 12 changed files with 783 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### NEXT

- `Worker`: Fix `io_uring` support detection ([PR #1445](https://github.com/versatica/mediasoup/pull/1445)).
- Mitigate libsrtp wraparound with loss decryption failure ([PR #1438](https://github.com/versatica/mediasoup/pull/1438)).

### 3.14.11

Expand Down
3 changes: 2 additions & 1 deletion worker/include/RTC/PipeConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ namespace RTC
absl::flat_hash_map<uint32_t, RTC::RtpStreamSend*> mapSsrcRtpStream;
bool keyFrameSupported{ false };
absl::flat_hash_map<RTC::RtpStreamSend*, bool> mapRtpStreamSyncRequired;
absl::flat_hash_map<RTC::RtpStreamSend*, RTC::SeqManager<uint16_t>> mapRtpStreamRtpSeqManager;
absl::flat_hash_map<RTC::RtpStreamSend*, std::unique_ptr<RTC::SeqManager<uint16_t>>>
mapRtpStreamRtpSeqManager;
};
} // namespace RTC

Expand Down
2 changes: 2 additions & 0 deletions worker/include/RTC/SeqManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace RTC

public:
SeqManager() = default;
SeqManager(T initialOutput);

public:
void Sync(T input);
Expand All @@ -50,6 +51,7 @@ namespace RTC
private:
// Whether at least a sequence number has been inserted.
bool started{ false };
T initialOutput{ 0 };
T base{ 0 };
T maxOutput{ 0 };
T maxInput{ 0 };
Expand Down
2 changes: 1 addition & 1 deletion worker/include/RTC/SimpleConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace RTC
RTC::RtpStreamRecv* producerRtpStream{ nullptr };
bool keyFrameSupported{ false };
bool syncRequired{ false };
RTC::SeqManager<uint16_t> rtpSeqManager;
std::unique_ptr<RTC::SeqManager<uint16_t>> rtpSeqManager;
bool managingBitrate{ false };
std::unique_ptr<RTC::Codecs::EncodingContext> encodingContext;
};
Expand Down
2 changes: 1 addition & 1 deletion worker/include/RTC/SimulcastConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ namespace RTC
bool syncRequired{ false };
int16_t spatialLayerToSync{ -1 };
bool lastSentPacketHasMarker{ false };
RTC::SeqManager<uint16_t> rtpSeqManager;
std::unique_ptr<RTC::SeqManager<uint16_t>> rtpSeqManager;
int16_t preferredSpatialLayer{ -1 };
int16_t preferredTemporalLayer{ -1 };
int16_t provisionalTargetSpatialLayer{ -1 };
Expand Down
2 changes: 1 addition & 1 deletion worker/include/RTC/SvcConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ namespace RTC
std::vector<RTC::RtpStreamSend*> rtpStreams;
RTC::RtpStreamRecv* producerRtpStream{ nullptr };
bool syncRequired{ false };
RTC::SeqManager<uint16_t> rtpSeqManager;
std::unique_ptr<RTC::SeqManager<uint16_t>> rtpSeqManager;
int16_t preferredSpatialLayer{ -1 };
int16_t preferredTemporalLayer{ -1 };
int16_t provisionalTargetSpatialLayer{ -1 };
Expand Down
17 changes: 13 additions & 4 deletions worker/src/RTC/PipeConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "RTC/PipeConsumer.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Utils.hpp"
#include "RTC/Codecs/Tools.hpp"

namespace RTC
Expand Down Expand Up @@ -264,7 +265,7 @@ namespace RTC
// Packets with only padding are not forwarded.
if (packet->GetPayloadLength() == 0)
{
rtpSeqManager.Drop(packet->GetSequenceNumber());
rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD);
Expand All @@ -284,15 +285,15 @@ namespace RTC
MS_DEBUG_TAG(rtp, "sync key frame received");
}

rtpSeqManager.Sync(packet->GetSequenceNumber() - 1);
rtpSeqManager->Sync(packet->GetSequenceNumber() - 1);

syncRequired = false;
}

// Update RTP seq number and timestamp.
uint16_t seq;

rtpSeqManager.Input(packet->GetSequenceNumber(), seq);
rtpSeqManager->Input(packet->GetSequenceNumber(), seq);

// Save original packet fields.
auto origSsrc = packet->GetSsrc();
Expand Down Expand Up @@ -680,7 +681,15 @@ namespace RTC
this->mapMappedSsrcSsrc[consumableEncoding.ssrc] = encoding.ssrc;
this->mapSsrcRtpStream[encoding.ssrc] = rtpStream;
this->mapRtpStreamSyncRequired[rtpStream] = false;
this->mapRtpStreamRtpSeqManager[rtpStream];

// Let's choose an initial output seq number between 1000 and 32768 to avoid
// libsrtp bug:
// https://github.com/versatica/mediasoup/issues/1437
const uint16_t initialOutputSeq =
Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits<uint16_t>::max() / 2);

this->mapRtpStreamRtpSeqManager[rtpStream].reset(
new RTC::SeqManager<uint16_t>(initialOutputSeq));
}
}

Expand Down
16 changes: 16 additions & 0 deletions worker/src/RTC/SeqManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,17 @@ namespace RTC
return isSeqHigherThan(lhs, rhs);
}

template<typename T, uint8_t N>
SeqManager<T, N>::SeqManager(T initialOutput) : initialOutput(initialOutput)
{
MS_TRACE();
}

template<typename T, uint8_t N>
void SeqManager<T, N>::Sync(T input)
{
MS_TRACE();

// Update base.
this->base = (this->maxOutput - input) & MaxValue;

Expand All @@ -55,6 +63,8 @@ namespace RTC
template<typename T, uint8_t N>
void SeqManager<T, N>::Drop(T input)
{
MS_TRACE();

// Mark as dropped if 'input' is higher than anyone already processed.
if (SeqManager<T, N>::IsSeqHigherThan(input, this->maxInput))
{
Expand All @@ -71,6 +81,8 @@ namespace RTC
template<typename T, uint8_t N>
bool SeqManager<T, N>::Input(T input, T& output)
{
MS_TRACE();

auto base = this->base;

// No dropped inputs to consider.
Expand Down Expand Up @@ -140,6 +152,8 @@ namespace RTC
}
}

output = (output + this->initialOutput) & MaxValue;

return true;
}

Expand All @@ -162,6 +176,8 @@ namespace RTC
template<typename T, uint8_t N>
void SeqManager<T, N>::ClearDropped()
{
MS_TRACE();

// Cleanup dropped values.
if (this->dropped.empty())
{
Expand Down
17 changes: 13 additions & 4 deletions worker/src/RTC/SimpleConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "DepLibUV.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Utils.hpp"
#include "RTC/Codecs/Tools.hpp"
#include "RTC/SimpleConsumer.hpp"

Expand Down Expand Up @@ -36,6 +37,14 @@ namespace RTC
// Create RtpStreamSend instance for sending a single stream to the remote.
CreateRtpStream();

// Let's chosee an initial output seq number between 1000 and 32768 to avoid
// libsrtp bug:
// https://github.com/versatica/mediasoup/issues/1437
const uint16_t initialOutputSeq =
Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits<uint16_t>::max() / 2);

this->rtpSeqManager.reset(new RTC::SeqManager<uint16_t>(initialOutputSeq));

// Create the encoding context for Opus.
if (
mediaCodec->mimeType.type == RTC::RtpCodecMimeType::Type::AUDIO &&
Expand Down Expand Up @@ -340,7 +349,7 @@ namespace RTC
packet->GetSequenceNumber(),
packet->GetTimestamp());

this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC);
Expand All @@ -363,7 +372,7 @@ namespace RTC
// Packets with only padding are not forwarded.
if (packet->GetPayloadLength() == 0)
{
this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD);
Expand All @@ -383,15 +392,15 @@ namespace RTC
MS_DEBUG_TAG(rtp, "sync key frame received");
}

this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1);
this->rtpSeqManager->Sync(packet->GetSequenceNumber() - 1);

this->syncRequired = false;
}

// Update RTP seq number and timestamp.
uint16_t seq;

this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq);
this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq);

// Save original packet fields.
auto origSsrc = packet->GetSsrc();
Expand Down
19 changes: 14 additions & 5 deletions worker/src/RTC/SimulcastConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "DepLibUV.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Utils.hpp"
#include "RTC/Codecs/Tools.hpp"

namespace RTC
Expand Down Expand Up @@ -98,6 +99,14 @@ namespace RTC
"%s codec not supported for simulcast", mediaCodec->mimeType.ToString().c_str());
}

// Let's chosee an initial output seq number between 1000 and 32768 to avoid
// libsrtp bug:
// https://github.com/versatica/mediasoup/issues/1437
const uint16_t initialOutputSeq =
Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits<uint16_t>::max() / 2);

this->rtpSeqManager.reset(new RTC::SeqManager<uint16_t>(initialOutputSeq));

RTC::Codecs::EncodingContext::Params params;

params.spatialLayers = encoding.spatialLayers;
Expand Down Expand Up @@ -802,7 +811,7 @@ namespace RTC
// not have payload other than padding, then drop it.
if (spatialLayer == this->currentSpatialLayer && packet->GetPayloadLength() == 0)
{
this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD);
Expand Down Expand Up @@ -951,7 +960,7 @@ namespace RTC
// 'packet->GetSequenceNumber() -2' may increase SeqManager::base and
// increase the output sequence number.
// https://github.com/versatica/mediasoup/issues/408
this->rtpSeqManager.Sync(packet->GetSequenceNumber() - (this->lastSentPacketHasMarker ? 1 : 2));
this->rtpSeqManager->Sync(packet->GetSequenceNumber() - (this->lastSentPacketHasMarker ? 1 : 2));

this->encodingContext->SyncRequired();

Expand Down Expand Up @@ -1013,7 +1022,7 @@ namespace RTC
// Rewrite payload if needed. Drop packet if necessary.
if (!packet->ProcessPayload(this->encodingContext.get(), marker))
{
this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC);
Expand All @@ -1032,7 +1041,7 @@ namespace RTC
uint16_t seq;
const uint32_t timestamp = packet->GetTimestamp() - this->tsOffset;

this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq);
this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq);

// Save original packet fields.
auto origSsrc = packet->GetSsrc();
Expand Down Expand Up @@ -1066,7 +1075,7 @@ namespace RTC
// Process the packet.
if (this->rtpStream->ReceivePacket(packet, sharedPacket))
{
if (this->rtpSeqManager.GetMaxOutput() == packet->GetSequenceNumber())
if (this->rtpSeqManager->GetMaxOutput() == packet->GetSequenceNumber())
{
this->lastSentPacketHasMarker = packet->HasMarker();
}
Expand Down
17 changes: 13 additions & 4 deletions worker/src/RTC/SvcConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "DepLibUV.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Utils.hpp"
#include "RTC/Codecs/Tools.hpp"

namespace RTC
Expand Down Expand Up @@ -79,6 +80,14 @@ namespace RTC
MS_THROW_TYPE_ERROR("%s codec not supported for svc", mediaCodec->mimeType.ToString().c_str());
}

// Let's chosee an initial output seq number between 1000 and 32768 to avoid
// libsrtp bug:
// https://github.com/versatica/mediasoup/issues/1437
const uint16_t initialOutputSeq =
Utils::Crypto::GetRandomUInt(1000u, std::numeric_limits<uint16_t>::max() / 2);

this->rtpSeqManager.reset(new RTC::SeqManager<uint16_t>(initialOutputSeq));

RTC::Codecs::EncodingContext::Params params;

params.spatialLayers = encoding.spatialLayers;
Expand Down Expand Up @@ -681,7 +690,7 @@ namespace RTC
// Packets with only padding are not forwarded.
if (packet->GetPayloadLength() == 0)
{
this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD);
Expand All @@ -701,7 +710,7 @@ namespace RTC
MS_DEBUG_TAG(rtp, "sync key frame received");
}

this->rtpSeqManager.Sync(packet->GetSequenceNumber() - 1);
this->rtpSeqManager->Sync(packet->GetSequenceNumber() - 1);
this->encodingContext->SyncRequired();

this->syncRequired = false;
Expand All @@ -715,7 +724,7 @@ namespace RTC

if (!packet->ProcessPayload(this->encodingContext.get(), marker))
{
this->rtpSeqManager.Drop(packet->GetSequenceNumber());
this->rtpSeqManager->Drop(packet->GetSequenceNumber());

#ifdef MS_RTC_LOGGER_RTP
packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::DROPPED_BY_CODEC);
Expand All @@ -738,7 +747,7 @@ namespace RTC
// Update RTP seq number and timestamp based on NTP offset.
uint16_t seq;

this->rtpSeqManager.Input(packet->GetSequenceNumber(), seq);
this->rtpSeqManager->Input(packet->GetSequenceNumber(), seq);

// Save original packet fields.
auto origSsrc = packet->GetSsrc();
Expand Down
Loading

0 comments on commit d3a7ae8

Please sign in to comment.