Resize OEMCrypto buffer-based results on success.

[ Merge of http://go/wvgerrit/152772 ]
[ Cherry-pick of http://ag/18126088 ]

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 55e07d488b
commit 77752a9600
3 changed files with 44 additions and 27 deletions

View File

@@ -1965,6 +1965,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");
}
@@ -2172,17 +2177,16 @@ bool CryptoSession::GetBuildInformation(SecurityLevel security_level,
SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(false);
RETURN_IF_NULL(info, false);
const char* build_information;
WithOecReadLock("GetBuildInformation", [&] {
build_information = OEMCrypto_BuildInformation(security_level);
const char* build_information = WithOecReadLock("GetBuildInformation", [&] {
return OEMCrypto_BuildInformation(security_level);
});
if (build_information == nullptr) {
LOGE("OEMCrypto_BuildInformation failed: Returned null");
return false;
}
info->assign(build_information);
constexpr size_t kMaxBuildInfoLength = 255;
const size_t info_length = strnlen(build_information, kMaxBuildInfoLength);
info->assign(build_information, info_length);
return true;
}

View File

@@ -234,6 +234,9 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
// We need to fill in core request and verify signature only for calls other
// than OEMCryptoMemory buffer overflow test. Any test other than buffer
// overflow will pass true.
if (result == OEMCrypto_SUCCESS) {
gen_signature.resize(gen_signature_length);
}
if (!verify_request || result != OEMCrypto_SUCCESS) return result;
if (global_features.api_version >= kCoreMessagesAPI) {
std::string core_message(reinterpret_cast<char*>(data.data()),
@@ -454,11 +457,14 @@ OEMCryptoResult ProvisioningRoundTrip::LoadResponse(Session* session) {
sizeof(response_data_));
}
size_t wrapped_key_length = 0;
const OEMCryptoResult sts = LoadResponseNoRetry(session, &wrapped_key_length);
OEMCryptoResult sts = LoadResponseNoRetry(session, &wrapped_key_length);
if (sts != OEMCrypto_ERROR_SHORT_BUFFER) return sts;
wrapped_rsa_key_.clear();
wrapped_rsa_key_.assign(wrapped_key_length, 0);
return LoadResponseNoRetry(session, &wrapped_key_length);
sts = LoadResponseNoRetry(session, &wrapped_key_length);
if (sts == OEMCrypto_SUCCESS) {
wrapped_rsa_key_.resize(wrapped_key_length);
}
return sts;
}
#ifdef TEST_OEMCRYPTO_V15
@@ -1458,6 +1464,7 @@ void Session::LoadOEMCert(bool verify_cert) {
public_cert.resize(public_cert_length);
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetOEMPublicCertificate(
public_cert.data(), &public_cert_length));
public_cert.resize(public_cert_length);
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadOEMPrivateKey(session_id()));
// The cert is a PKCS7 signed data type. First, parse it into an OpenSSL
@@ -1685,6 +1692,8 @@ void Session::UpdateUsageEntry(std::vector<uint8_t>* header_buffer) {
OEMCrypto_UpdateUsageEntry(
session_id(), header_buffer->data(), &header_buffer_length,
encrypted_usage_entry_.data(), &entry_buffer_length));
header_buffer->resize(header_buffer_length);
encrypted_usage_entry_.resize(entry_buffer_length);
}
void Session::LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer) {
@@ -1731,6 +1740,7 @@ void Session::GenerateReport(const std::string& pst,
if (expected_result != OEMCrypto_SUCCESS) {
return;
}
pst_report_buffer_.resize(length);
EXPECT_EQ(wvcdm::Unpacked_PST_Report::report_size(pst.length()), length);
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
key_deriver_.ClientSignPstReport(pst_report_buffer_, &computed_signature);

View File

@@ -275,7 +275,7 @@ TEST_F(OEMCryptoClientTest, VersionNumber) {
cout << " Resource Rating Tier: " << tier << endl;
const char* build_info = OEMCrypto_BuildInformation();
ASSERT_NE(nullptr, build_info);
ASSERT_TRUE(strnlen(build_info, 256) <= 256)
ASSERT_TRUE(strnlen(build_info, 256) < 256)
<< "BuildInformation should be a short printable string.";
cout << " BuildInformation: " << build_info << endl;
}
@@ -933,9 +933,9 @@ TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) {
uint8_t dev_id[128] = {0};
size_t dev_id_len = 128;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
cout << " NormalGetDeviceId: dev_id = "
<< MaybeHex(dev_id, dev_id_len) << " len = " << dev_id_len << endl;
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryGetDeviceIdForHugeIdLength) {
@@ -1078,7 +1078,6 @@ TEST_F(OEMCryptoProv30Test, GetDeviceId) {
dev_id.resize(dev_id_len);
cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id)
<< " len = " << dev_id_len << endl;
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
// The OEM certificate must be valid.
@@ -1221,6 +1220,7 @@ class OEMCryptoSessionTests : public OEMCryptoClientTest {
&header_buffer_length);
if (expect_success) {
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
encrypted_usage_header_.resize(header_buffer_length);
} else {
ASSERT_NE(OEMCrypto_SUCCESS, sts);
}
@@ -5127,11 +5127,10 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) {
&signature_length, kSign_RSASSA_PSS);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
ASSERT_NE(static_cast<size_t>(0), signature_length);
uint8_t* signature = new uint8_t[signature_length];
sts = OEMCrypto_GenerateRSASignature(s.session_id(), licenseRequest.data(),
licenseRequest.size(), signature,
&signature_length, kSign_RSASSA_PSS);
delete[] signature;
std::vector<uint8_t> signature(signature_length, 0);
sts = OEMCrypto_GenerateRSASignature(
s.session_id(), licenseRequest.data(), licenseRequest.size(),
signature.data(), &signature_length, kSign_RSASSA_PSS);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
count++;
}
@@ -5312,7 +5311,7 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
EXPECT_NE(OEMCrypto_SUCCESS, sts)
<< "Signed with forbidden padding scheme=" << (int)scheme
<< ", size=" << (int)size;
vector<uint8_t> zero(signature_length, 0);
const vector<uint8_t> zero(signature.size(), 0);
ASSERT_EQ(zero, signature); // signature should not be computed.
}
@@ -5334,19 +5333,19 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
ASSERT_NE(static_cast<size_t>(0), signature_length);
uint8_t* signature = new uint8_t[signature_length];
sts = OEMCrypto_GenerateRSASignature(s.session_id(), licenseRequest.data(),
licenseRequest.size(), signature,
&signature_length, scheme);
std::vector<uint8_t> signature(signature_length, 0);
sts = OEMCrypto_GenerateRSASignature(
s.session_id(), licenseRequest.data(), licenseRequest.size(),
signature.data(), &signature_length, scheme);
ASSERT_EQ(OEMCrypto_SUCCESS, sts)
<< "Failed to sign with padding scheme=" << (int)scheme
<< ", size=" << (int)size;
<< ", size=" << size;
signature.resize(signature_length);
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(licenseRequest, signature,
signature_length, scheme));
delete[] signature;
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(
licenseRequest, signature.data(), signature_length, scheme));
}
void DisallowDeriveKeys() {
@@ -5691,7 +5690,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
ASSERT_EQ(OEMCrypto_SUCCESS, sts)
<< "Failed to sign with padding scheme=" << (int)scheme
<< ", size=" << (int)message.size();
<< ", size=" << message.size();
signature.resize(signature_length);
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
@@ -8360,6 +8360,9 @@ class OEMCryptoUsageTableDefragTest : public OEMCryptoUsageTableTest {
new_size, encrypted_usage_header_.data(), &header_buffer_length);
// For the second call, we always demand the expected result.
ASSERT_EQ(expected_result, sts);
if (sts == OEMCrypto_SUCCESS) {
encrypted_usage_header_.resize(header_buffer_length);
}
}
};