Resize OEMCrypto buffer-based results on success.

[ Merge of http://go/wvgerrit/151191 ]

Within the CDM and OEMCrypto tests, there were a few OEMCrypto function
calls where the final size of the output buffers were not being
resized.  For several of these functions, an initial call is made with
zero-length output buffers, expecting OEMCrypto to return
ERROR_SHORT_BUFFER; followed by a call with buffers at least as large
as specified by OEMCrypto.  However, for some operations, OEMCrypto
makes an estimate on the final size on the first call, specifying the
exact size only after performing the operations.

This is the case for the wrapped key returned by
OEMCrypto_LoadProvisioning().  The provisioning response contains a
padded + encrypted DRM key.  OEMCrypto does not know the actual size
of the key until decrypted, and the actual DRM key might be smaller.

There was a OEMCrypto test for OEMCrypto_BuildInformation() which
was enforcing the wrong behaviour.  This has been updated.

Bug: 230661565
Test: oemcrypto_test
Change-Id: Iad297d56ffbb085894641fdf8698ce5fd18edbf2
This commit is contained in:
Alex Dale
2022-05-02 11:39:16 -07:00
parent 1563fb2a27
commit 1069ae39cc
4 changed files with 85 additions and 44 deletions

View File

@@ -2099,6 +2099,11 @@ CdmResponseType CryptoSession::LoadProvisioning(
metrics_, oemcrypto_load_provisioning_, status);
});
if (status == OEMCrypto_SUCCESS) {
wrapped_private_key->resize(wrapped_private_key_length);
return NO_ERROR;
}
wrapped_private_key->clear();
return MapOEMCryptoResult(status, LOAD_PROVISIONING_ERROR,
"LoadProvisioning");
}
@@ -2283,29 +2288,25 @@ bool CryptoSession::GetBuildInformation(RequestedSecurityLevel security_level,
RequestedSecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(false);
RETURN_IF_NULL(info, false);
OEMCryptoResult build_information;
std::string buf;
size_t buf_length = 0;
WithOecReadLock("GetBuildInformation", [&] {
build_information =
OEMCrypto_BuildInformation(&buf[0], &buf_length, security_level);
size_t info_length = 128;
info->assign(info_length, '\0');
OEMCryptoResult result = WithOecReadLock("GetBuildInformation", [&] {
return OEMCrypto_BuildInformation(&info->front(), &info_length,
security_level);
});
if (build_information == OEMCrypto_ERROR_SHORT_BUFFER) {
buf.resize(buf_length);
WithOecReadLock("GetBuildInformation Attempt 2", [&] {
build_information =
OEMCrypto_BuildInformation(&buf[0], &buf_length, security_level);
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
info->assign(info_length, '\0');
result = WithOecReadLock("GetBuildInformation Attempt 2", [&] {
return OEMCrypto_BuildInformation(&info->front(), &info_length,
security_level);
});
}
if (build_information == OEMCrypto_SUCCESS) {
*info = buf;
} else {
LOGE("Unexpected return value");
if (result != OEMCrypto_SUCCESS) {
LOGE("GetBuildInformation failed: result = %d", result);
info->clear();
return false;
}
info->resize(info_length);
return true;
}

View File

@@ -1737,14 +1737,19 @@ OEMCryptoResult OEMCrypto_BuildInformation(
if (fcn->BuildInformation_V16 == nullptr) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (buffer_length == nullptr) return OEMCrypto_ERROR_INVALID_CONTEXT;
if (buffer == nullptr && *buffer_length > 0)
return OEMCrypto_ERROR_INVALID_CONTEXT;
constexpr size_t kMaxBuildInfoLength = 128;
const char* build_info = fcn->BuildInformation_V16();
size_t max_length = strnlen(build_info, 128);
if (*buffer_length < max_length) {
*buffer_length = max_length;
if (build_info == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
const size_t build_info_length = strnlen(build_info, kMaxBuildInfoLength);
if (*buffer_length < build_info_length) {
*buffer_length = build_info_length;
return OEMCrypto_ERROR_SHORT_BUFFER;
}
*buffer_length = max_length;
memcpy(buffer, build_info, *buffer_length);
*buffer_length = build_info_length;
memcpy(buffer, build_info, build_info_length);
return OEMCrypto_SUCCESS;
}
return fcn->BuildInformation(buffer, buffer_length);