tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 5536bc805c2cb95644f15e828c0ae18fd70e9408
parent 39d07234cfea49c813053b01908d35626d75f1c5
Author: alwu <alwu@mozilla.com>
Date:   Thu, 16 Oct 2025 19:00:37 +0000

Bug 1994550 - part1 : set CBCS related encryption information properly. r=jolin

For CBCS, the value of the crypto byte block and the skip byte block are
crucial, and it is also common to see the use of a constant IV for CBCS
for simplicity. This patch sets those attributes properly for the Media
Foundation Media Engine.

Differential Revision: https://phabricator.services.mozilla.com/D268803

Diffstat:
Mdom/media/ipc/PMediaDecoderParams.ipdlh | 3+++
Mdom/media/ipc/RemoteMediaData.cpp | 6++++++
Mdom/media/platforms/wmf/MFMediaEngineStream.cpp | 38++++++++++++++++++++++++++++++++------
3 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/dom/media/ipc/PMediaDecoderParams.ipdlh b/dom/media/ipc/PMediaDecoderParams.ipdlh @@ -22,9 +22,12 @@ struct MediaDataIPDL struct CryptoInfo { CryptoScheme mEncryptionScheme; uint8_t[] mIV; + uint8_t[] mConstantIV; uint8_t[] mKeyId; uint32_t[] mClearBytes; uint32_t[] mCipherBytes; + uint8_t mCryptByteBlock; + uint8_t mSkipByteBlock; }; } // namespace mozilla diff --git a/dom/media/ipc/RemoteMediaData.cpp b/dom/media/ipc/RemoteMediaData.cpp @@ -154,9 +154,12 @@ bool ArrayOfRemoteMediaRawData::Fill( ? Some(CryptoInfo{ entry->mCrypto.mCryptoScheme, entry->mCrypto.mIV, + entry->mCrypto.mConstantIV, entry->mCrypto.mKeyId, entry->mCrypto.mPlainSizes, entry->mCrypto.mEncryptedSizes, + entry->mCrypto.mCryptByteBlock, + entry->mCrypto.mSkipByteBlock, }) : Nothing()}); } @@ -219,10 +222,13 @@ already_AddRefed<MediaRawData> ArrayOfRemoteMediaRawData::ElementAt( CryptoSample& cypto = rawData->GetWritableCrypto(); cypto.mCryptoScheme = sample.mCryptoConfig->mEncryptionScheme(); cypto.mIV = std::move(sample.mCryptoConfig->mIV()); + cypto.mConstantIV = std::move(sample.mCryptoConfig->mConstantIV()); cypto.mIVSize = cypto.mIV.Length(); cypto.mKeyId = std::move(sample.mCryptoConfig->mKeyId()); cypto.mPlainSizes = std::move(sample.mCryptoConfig->mClearBytes()); cypto.mEncryptedSizes = std::move(sample.mCryptoConfig->mCipherBytes()); + cypto.mCryptByteBlock = sample.mCryptoConfig->mCryptByteBlock(); + cypto.mSkipByteBlock = sample.mCryptoConfig->mSkipByteBlock(); } perfRecorder.Record(); return rawData.forget(); diff --git a/dom/media/platforms/wmf/MFMediaEngineStream.cpp b/dom/media/platforms/wmf/MFMediaEngineStream.cpp @@ -366,10 +366,10 @@ HRESULT MFMediaEngineStream::CreateInputSample(IMFSample** aSample) { MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() != 0); RefPtr<MediaRawData> data = mRawDataQueueForFeedingEngine.PopFront(); SLOGV("CreateInputSample, pop data [%" PRId64 ", %" PRId64 - "] (duration=%" PRId64 ", kf=%d), queue size=%zu", + "] (duration=%" PRId64 ", kf=%d, encrypted=%d), queue size=%zu", data->mTime.ToMicroseconds(), data->GetEndTime().ToMicroseconds(), data->mDuration.ToMicroseconds(), data->mKeyframe, - mRawDataQueueForFeedingEngine.GetSize()); + data->mCrypto.IsEncrypted(), mRawDataQueueForFeedingEngine.GetSize()); PROFILER_MARKER( nsPrintfCString( "pop %s (stream=%" PRIu64 ")", @@ -414,12 +414,26 @@ HRESULT MFMediaEngineStream::AddEncryptAttributes( // Scheme MFSampleEncryptionProtectionScheme protectionScheme; if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cenc) { + SLOG("Set CENC encryption"); protectionScheme = MFSampleEncryptionProtectionScheme:: MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CTR; } else if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs || aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs_1_9) { protectionScheme = MFSampleEncryptionProtectionScheme:: MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CBC; + SLOG("Set CBC pattern encryption, crypt=%u, skip=%u", + aCryptoConfig.mCryptByteBlock, aCryptoConfig.mSkipByteBlock); + // Only need to set them when they are non-zero. See + // https://learn.microsoft.com/en-us/windows/win32/medfound/mfsampleextension-encryption-cryptbyteblock + // https://learn.microsoft.com/en-us/windows/win32/medfound/mfsampleextension-encryption-skipbyteblock + if (aCryptoConfig.mCryptByteBlock > 0 && aCryptoConfig.mSkipByteBlock > 0) { + RETURN_IF_FAILED( + aSample->SetUINT32(MFSampleExtension_Encryption_CryptByteBlock, + aCryptoConfig.mCryptByteBlock)); + RETURN_IF_FAILED( + aSample->SetUINT32(MFSampleExtension_Encryption_SkipByteBlock, + aCryptoConfig.mSkipByteBlock)); + } } else { SLOG("Unexpected encryption scheme"); return MF_E_UNEXPECTED; @@ -439,10 +453,22 @@ HRESULT MFMediaEngineStream::AddEncryptAttributes( // to store last key id and set it in CDM to refresh the decryptor. // IV - RETURN_IF_FAILED(aSample->SetBlob( - MFSampleExtension_Encryption_SampleID, - reinterpret_cast<const uint8_t*>(aCryptoConfig.mIV.Elements()), - aCryptoConfig.mIVSize)); + if (aCryptoConfig.mIVSize != 0) { + // Per-sample IV, usually seen in CENC. + SLOG("Use sample IV for decryption, IV size=%u", aCryptoConfig.mIVSize); + RETURN_IF_FAILED(aSample->SetBlob( + MFSampleExtension_Encryption_SampleID, + reinterpret_cast<const uint8_t*>(aCryptoConfig.mIV.Elements()), + aCryptoConfig.mIVSize)); + } else { + // A constant IV for all samples, usually seen in CBCS. + SLOG("Use constant IV for decryption, constantIV length=%zu", + aCryptoConfig.mConstantIV.Length()); + RETURN_IF_FAILED(aSample->SetBlob( + MFSampleExtension_Encryption_SampleID, + reinterpret_cast<const uint8_t*>(aCryptoConfig.mConstantIV.Elements()), + aCryptoConfig.mConstantIV.Length())); + } // Subsample entries. MOZ_ASSERT(aCryptoConfig.mEncryptedSizes.Length() ==