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

Mitigate libsrtp wraparound with loss decryption failure #1438

Merged
merged 6 commits into from
Aug 29, 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
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;
jmillan marked this conversation as resolved.
Show resolved Hide resolved
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
Loading