Break Decrypt Buffers Into 100KiB Blocks As Needed

(This is a merge of go/wvgerrit/22949)

Starting with OEMCrypto v12, we are guaranteeing to integration partners
that the buffers passed to OEMCrypto_DecryptCENC and
OEMCrypto_CopyBuffer will not be more than 100KiB (102400 bytes) in
size. For requests larger than this, we will first try to send the
buffer to OEMCrypto anyway. (in case the integration supports buffers
larger than the minimum) In the event that the buffer is rejected, we
will break it up into 100KiB chunks and send them down individually for
decryption.

Breaking a subsample into smaller subsamples necessitates knowledge of
how to update other decryption parameters (like the offsets and the IV)
that previously the CDM Core has not needed to know about. Until now,
this knowledge lived in the glue layer on the Android CDM and nowhere
on the CE CDM. Now, the CryptoSession has a subset of this knowledge, in
order to break up buffers successfully.

For testing purposes, the Mock OEMCrypto has been modified to only
support the smallest buffer size. In order to make sure the chunking
code was being exercised by them, the CE CDM tests had to have the
amount of data they decrypt increased by several orders of magnitude. To
contain this growth, I have moved the test data to its own file.

Bug: 31381719
Test: Ran the updated CE CDM integration tests
Test: Modified the OEMCrypto dynamic adapter to pretend both L3 and L1
only support 100KiB buffers on a Marlin and a Ryu. Confirmed that the
GTS H.264 tests (which have subsamples over 100KiB) passed still. A
similar test was attempted on Fugu but Fugu cannot pass these tests even
without this change present.
Change-Id: Iabe7db3d87554cd1352f10a7524cd55352818397
This commit is contained in:
John W. Bruce
2017-01-12 14:19:47 -08:00
parent a83a9ae540
commit d30c5f8d33
3 changed files with 238 additions and 5 deletions

View File

@@ -27,6 +27,7 @@
namespace {
const uint8_t kBakedInCertificateMagicBytes[] = { 0xDE, 0xAD, 0xBE, 0xEF };
const size_t kMaxBufferSize = 1024 * 100; // 100KiB
} // namespace
namespace wvoec_mock {
@@ -605,18 +606,24 @@ OEMCryptoResult OEMCrypto_DecryptCENC(OEMCrypto_SESSION session,
const OEMCrypto_CENCEncryptPatternDesc* pattern,
uint8_t subsample_flags) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCTR"
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCENC"
"(OEMCrypto_SESSION session,\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_DecryptCTR: OEMCrypto Not Initialized.");
LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (data_addr == NULL || data_length == 0 ||
iv == NULL || out_buffer == NULL) {
LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]");
LOGE("[OEMCrypto_DecryptCENC(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (data_length > kMaxBufferSize) {
// For testing reasons only, pretend that this integration only supports
// the minimum possible buffer size.
LOGE("[OEMCrypto_DecryptCENC(): OEMCrypto_ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
uint8_t* destination = NULL;
size_t max_length = 0;
OEMCryptoResult sts = SetDestination(out_buffer, data_length, &destination,
@@ -625,14 +632,14 @@ OEMCryptoResult OEMCrypto_DecryptCENC(OEMCrypto_SESSION session,
#ifndef NDEBUG
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
LOGE("[OEMCrypto_DecryptCTR(): ERROR_KEYBOX_INVALID]");
LOGE("[OEMCrypto_DecryptCENC(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID;
}
#endif
SessionContext* session_ctx = crypto_engine->FindSession(session);
if (!session_ctx || !session_ctx->isValid()) {
LOGE("[OEMCrypto_DecryptCTR(): ERROR_INVALID_SESSION]");
LOGE("[OEMCrypto_DecryptCENC(): ERROR_INVALID_SESSION]");
return OEMCrypto_ERROR_INVALID_SESSION;
}
@@ -658,6 +665,12 @@ OEMCryptoResult OEMCrypto_CopyBuffer(const uint8_t *data_addr,
LOGE("[OEMCrypto_CopyBuffer(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (data_length > kMaxBufferSize) {
// For testing reasons only, pretend that this integration only supports
// the minimum possible buffer size.
LOGE("[OEMCrypto_CopyBuffer(): OEMCrypto_ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
uint8_t* destination = NULL;
size_t max_length = 0;
OEMCryptoResult sts = SetDestination(out_buffer, data_length, &destination,