Call CopyBuffer in Decrypt if key handle is empty

(Merged from go/wvgerrit/193672)

Bug: 320785945
Test: GTS + unit tests
Change-Id: I4a0c7568bf8323187f1156874ea98718511120f4
This commit is contained in:
Vicky Min
2024-03-12 21:55:15 +00:00
committed by Rahul Frias
parent 6499e7063d
commit 6577f6f212
5 changed files with 69 additions and 34 deletions

View File

@@ -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,

View File

@@ -427,18 +427,22 @@ class CryptoSession {
OEMCryptoResult DecryptMultipleSamples(
const std::vector<OEMCrypto_SampleDescription>& 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.

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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<OEMCrypto_SampleDescription>& 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;