diff --git a/libwvdrmengine/cdm/core/include/content_key_session.h b/libwvdrmengine/cdm/core/include/content_key_session.h index d63a4243..833cb5ce 100644 --- a/libwvdrmengine/cdm/core/include/content_key_session.h +++ b/libwvdrmengine/cdm/core/include/content_key_session.h @@ -43,9 +43,10 @@ class ContentKeySession : public KeySession { CdmCipherMode cipher_mode) override; // Decrypt for ContentKeySession - OEMCryptoResult Decrypt( - const OEMCrypto_SampleDescription* samples, size_t samples_length, - const OEMCrypto_CENCEncryptPatternDesc& pattern) override; + OEMCryptoResult Decrypt(const OEMCrypto_SampleDescription* samples, + size_t samples_length, + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) override; OEMCryptoResult GenericEncrypt(const std::string& in_buffer, const std::string& iv, diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 58c2c792..f114554e 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -427,18 +427,22 @@ class CryptoSession { OEMCryptoResult DecryptMultipleSamples( const std::vector& samples, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern); - OEMCryptoResult DecryptSample( - const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern); - OEMCryptoResult LegacyDecrypt( - const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern); + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected); + OEMCryptoResult DecryptSample(const OEMCrypto_SampleDescription& sample, + CdmCipherMode cipher_mode, + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected); + OEMCryptoResult LegacyDecrypt(const OEMCrypto_SampleDescription& sample, + CdmCipherMode cipher_mode, + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected); OEMCryptoResult LegacyCopyBufferInChunks( const OEMCrypto_SampleDescription& sample, size_t max_chunk_size); OEMCryptoResult LegacyDecryptInChunks( const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern, size_t max_chunk_size); + const OEMCrypto_CENCEncryptPatternDesc& pattern, size_t max_chunk_size, + bool is_any_subsample_protected); // These methods should be used to take the various CryptoSession mutexes in // preference to taking the mutexes directly. diff --git a/libwvdrmengine/cdm/core/include/key_session.h b/libwvdrmengine/cdm/core/include/key_session.h index a0465ca8..81197f19 100644 --- a/libwvdrmengine/cdm/core/include/key_session.h +++ b/libwvdrmengine/cdm/core/include/key_session.h @@ -36,7 +36,8 @@ class KeySession { CdmCipherMode cipher_mode) = 0; virtual OEMCryptoResult Decrypt( const OEMCrypto_SampleDescription* samples, size_t samples_length, - const OEMCrypto_CENCEncryptPatternDesc& pattern) = 0; + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) = 0; virtual OEMCryptoResult GenericEncrypt(const std::string& in_buffer, const std::string& iv, OEMCrypto_Algorithm algorithm, diff --git a/libwvdrmengine/cdm/core/src/content_key_session.cpp b/libwvdrmengine/cdm/core/src/content_key_session.cpp index 90a681fd..7926b1d1 100644 --- a/libwvdrmengine/cdm/core/src/content_key_session.cpp +++ b/libwvdrmengine/cdm/core/src/content_key_session.cpp @@ -52,18 +52,36 @@ OEMCryptoResult ContentKeySession::SelectKey(const std::string& key_id, // Decrypt for ContentKeySession OEMCryptoResult ContentKeySession::Decrypt( const OEMCrypto_SampleDescription* samples, size_t samples_length, - const OEMCrypto_CENCEncryptPatternDesc& pattern) { + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) { size_t total_size = 0; for (size_t i = 0; i < samples_length; ++i) { total_size += samples[i].buffers.input_data_length; } - OEMCryptoResult sts; - M_TIME(sts = OEMCrypto_DecryptCENC(security_level_, key_handle_.data(), - key_handle_.size(), samples, - samples_length, &pattern), - metrics_, oemcrypto_decrypt_cenc_, sts, - metrics::Pow2Bucket(total_size)); + OEMCryptoResult sts = OEMCrypto_SUCCESS; + if (key_handle_.size() == 0 && !is_any_subsample_protected) { + for (size_t i = 0; i < samples_length; ++i) { + if (samples[i].subsamples != nullptr && + samples[i].subsamples_length > 0) { + const OEMCrypto_SubSampleDescription& subsample = + samples[i].subsamples[0]; + M_TIME(sts = OEMCrypto_CopyBuffer(oec_session_id_, + samples[i].buffers.input_data, + samples[i].buffers.input_data_length, + &samples[i].buffers.output_descriptor, + subsample.subsample_flags), + metrics_, oemcrypto_copy_buffer_, sts, + metrics::Pow2Bucket(samples[i].buffers.input_data_length)); + } + } + } else { + M_TIME(sts = OEMCrypto_DecryptCENC(security_level_, key_handle_.data(), + key_handle_.size(), samples, + samples_length, &pattern), + metrics_, oemcrypto_decrypt_cenc_, sts, + metrics::Pow2Bucket(total_size)); + } return sts; } diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index eb1efb39..057d11d2 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -1906,8 +1906,8 @@ CdmResponseType CryptoSession::Decrypt( } // Perform decrypt - const OEMCryptoResult sts = - DecryptMultipleSamples(oec_samples, params.cipher_mode, oec_pattern); + const OEMCryptoResult sts = DecryptMultipleSamples( + oec_samples, params.cipher_mode, oec_pattern, is_any_sample_protected); if (sts != OEMCrypto_SUCCESS && last_decrypt_error_ != sts) { // Decrypt errors and warnings are only logged when the error code @@ -3120,22 +3120,24 @@ bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output, OEMCryptoResult CryptoSession::DecryptMultipleSamples( const std::vector& samples, - CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern) { + CdmCipherMode cipher_mode, const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) { OEMCryptoResult sts = OEMCrypto_ERROR_BUFFER_TOO_LARGE; // If there's only one sample, automatically fall through to avoid a redundant // roundtrip through OEMCrypto_DecryptCENC() if (samples.size() > 1) { WithOecSessionLock("DecryptMultipleSamples", [&] { - sts = key_session_->Decrypt(samples.data(), samples.size(), pattern); + sts = key_session_->Decrypt(samples.data(), samples.size(), pattern, + is_any_subsample_protected); }); } if (sts == OEMCrypto_ERROR_BUFFER_TOO_LARGE) { // Fall back to sending each sample individually for (const OEMCrypto_SampleDescription& sample : samples) { - sts = DecryptSample(sample, cipher_mode, pattern); + sts = DecryptSample(sample, cipher_mode, pattern, + is_any_subsample_protected); if (sts != OEMCrypto_SUCCESS) break; } } @@ -3145,7 +3147,8 @@ OEMCryptoResult CryptoSession::DecryptMultipleSamples( OEMCryptoResult CryptoSession::DecryptSample( const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern) { + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) { OEMCryptoResult sts = OEMCrypto_ERROR_BUFFER_TOO_LARGE; // If there's only one subsample and it contains only one type of region, @@ -3155,7 +3158,8 @@ OEMCryptoResult CryptoSession::DecryptSample( (sample.subsamples[0].num_bytes_clear > 0 && sample.subsamples[0].num_bytes_encrypted > 0)) { WithOecSessionLock("DecryptSample", [&] { - sts = key_session_->Decrypt(&sample, 1, pattern); + sts = key_session_->Decrypt(&sample, 1, pattern, + is_any_subsample_protected); }); } @@ -3187,7 +3191,8 @@ OEMCryptoResult CryptoSession::DecryptSample( fake_sample.subsamples = &clear_subsample; fake_sample.subsamples_length = 1; - sts = LegacyDecrypt(fake_sample, cipher_mode, pattern); + sts = LegacyDecrypt(fake_sample, cipher_mode, pattern, + is_any_subsample_protected); if (sts != OEMCrypto_SUCCESS) break; fake_sample.buffers.input_data += length; @@ -3213,7 +3218,8 @@ OEMCryptoResult CryptoSession::DecryptSample( fake_sample.subsamples = &encrypted_subsample; fake_sample.subsamples_length = 1; - sts = LegacyDecrypt(fake_sample, cipher_mode, pattern); + sts = LegacyDecrypt(fake_sample, cipher_mode, pattern, + is_any_subsample_protected); if (sts != OEMCrypto_SUCCESS) break; fake_sample.buffers.input_data += length; @@ -3232,7 +3238,8 @@ OEMCryptoResult CryptoSession::DecryptSample( OEMCryptoResult CryptoSession::LegacyDecrypt( const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern) { + const OEMCrypto_CENCEncryptPatternDesc& pattern, + bool is_any_subsample_protected) { const size_t max_chunk_size = GetMaxSubsampleRegionSize(); OEMCryptoResult sts = OEMCrypto_ERROR_NOT_IMPLEMENTED; @@ -3262,7 +3269,8 @@ OEMCryptoResult CryptoSession::LegacyDecrypt( } if (is_encrypted || sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) { WithOecSessionLock("LegacyDecrypt() calling key_session_->Decrypt()", [&] { - sts = key_session_->Decrypt(&sample, 1, pattern); + sts = key_session_->Decrypt(&sample, 1, pattern, + is_any_subsample_protected); }); if (sts == OEMCrypto_ERROR_BUFFER_TOO_LARGE) { @@ -3278,7 +3286,8 @@ OEMCryptoResult CryptoSession::LegacyDecrypt( : max_chunk_size; if (sample.buffers.input_data_length > chunk_size) { - sts = LegacyDecryptInChunks(sample, cipher_mode, pattern, chunk_size); + sts = LegacyDecryptInChunks(sample, cipher_mode, pattern, chunk_size, + is_any_subsample_protected); } } } @@ -3327,7 +3336,8 @@ OEMCryptoResult CryptoSession::LegacyCopyBufferInChunks( OEMCryptoResult CryptoSession::LegacyDecryptInChunks( const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode, - const OEMCrypto_CENCEncryptPatternDesc& pattern, size_t max_chunk_size) { + const OEMCrypto_CENCEncryptPatternDesc& pattern, size_t max_chunk_size, + bool is_any_subsample_protected) { const OEMCrypto_SubSampleDescription& subsample = sample.subsamples[0]; const bool is_protected = (subsample.num_bytes_encrypted > 0); @@ -3361,7 +3371,8 @@ OEMCryptoResult CryptoSession::LegacyDecryptInChunks( // pattern length long, which is also guaranteed to be an exact number // of AES blocks long. WithOecSessionLock("LegacyDecryptInChunks", [&] { - sts = key_session_->Decrypt(&fake_sample, 1, pattern); + sts = key_session_->Decrypt(&fake_sample, 1, pattern, + is_any_subsample_protected); }); if (sts != OEMCrypto_SUCCESS) break;