An integration test for secure buffers

This is a squash of several different CLs with changes only affecting
policy_integration_test.cpp

* An integration test for secure buffers

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

This extends the previous CL that loads a license that has a key that
requires a secure buffer. It now creates a secure buffer and tries to
decrypt to it.

Bug: 38004627

* Test loading license requiring secure buffer

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

This adds a policy test to verify we can load a license that requires
hardware secure buffers.

Bug: 38004627
Test: WV  unit/integration tests
Change-Id: I1cc0b607ddf5b43fc6b7ba648f3c78d6163e14e9
This commit is contained in:
Rahul Frias
2021-03-08 02:46:10 -08:00
parent 0831e575ba
commit 3176f5f66f

View File

@@ -19,6 +19,7 @@
#include "license_request.h"
#include "log.h"
#include "metrics_collections.h"
#include "oec_device_features.h"
#include "test_base.h"
#include "test_printers.h"
#include "test_sleep.h"
@@ -115,22 +116,30 @@ class CorePIGTest : public WvCdmTestBaseWithEngine {
const std::vector<uint8_t> input(buffer_size, 0);
std::vector<uint8_t> output(buffer_size, 0);
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
Decrypt(session_id, key_id, input, iv, &output, NO_ERROR);
ASSERT_EQ(NO_ERROR, Decrypt(session_id, key_id, input, iv, &output));
}
// Try to use the key to decrypt, but expect the key has expired.
void FailDecrypt(const CdmSessionId& session_id, const KeyId& key_id) {
void FailDecrypt(const CdmSessionId& session_id, const KeyId& key_id,
CdmResponseType expected_status) {
constexpr size_t buffer_size = 500;
const std::vector<uint8_t> input(buffer_size, 0);
std::vector<uint8_t> output(buffer_size, 0);
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
Decrypt(session_id, key_id, input, iv, &output, NEED_KEY);
CdmResponseType status = Decrypt(session_id, key_id, input, iv, &output);
// If the server knows we cannot handle the key, it would not have given us
// the key. In that case, the status should indicate no key.
if (status != NEED_KEY) {
// Otherwise, we should have gotten the expected error.
ASSERT_EQ(expected_status, status);
}
}
void Decrypt(const CdmSessionId& session_id, const KeyId& key_id,
// Decrypt or fail to decrypt, with the expected status.
CdmResponseType Decrypt(const CdmSessionId& session_id, const KeyId& key_id,
const std::vector<uint8_t>& input,
const std::vector<uint8_t>& iv, std::vector<uint8_t>* output,
CdmResponseType expected_status) {
const std::vector<uint8_t>& iv,
std::vector<uint8_t>* output) {
CdmDecryptionParametersV16 params(key_id);
params.is_secure = false;
CdmDecryptionSample sample(input.data(), output->data(), 0, input.size(),
@@ -138,9 +147,54 @@ class CorePIGTest : public WvCdmTestBaseWithEngine {
CdmDecryptionSubsample subsample(0, input.size());
sample.subsamples.push_back(subsample);
params.samples.push_back(sample);
return cdm_engine_.DecryptV16(session_id, params);
}
// Use the key to decrypt to a secure buffer.
void DecryptSecure(const CdmSessionId& session_id, const KeyId& key_id) {
ASSERT_TRUE(wvoec::global_features.test_secure_buffers);
constexpr size_t buffer_size = 500;
const std::vector<uint8_t> input(buffer_size, 0);
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
// To create a secure buffer, we need to know the OEMCrypto session id.
CdmQueryMap query_map;
cdm_engine_.QueryOemCryptoSessionId(session_id, &query_map);
const std::string oec_session_id_string =
query_map[QUERY_KEY_OEMCRYPTO_SESSION_ID];
uint32_t oec_session_id = std::stoi(oec_session_id_string);
int secure_buffer_fid;
OEMCrypto_DestBufferDesc output_descriptor;
output_descriptor.type = OEMCrypto_BufferType_Secure;
output_descriptor.buffer.secure.handle_length = buffer_size;
ASSERT_EQ(
OEMCrypto_AllocateSecureBuffer(oec_session_id, buffer_size,
&output_descriptor, &secure_buffer_fid),
OEMCrypto_SUCCESS);
ASSERT_NE(output_descriptor.buffer.secure.handle, nullptr);
// It is OK if OEMCrypto changes the maximum size, but there must
// still be enough room for our data.
ASSERT_GE(output_descriptor.buffer.secure.handle_length, buffer_size);
output_descriptor.buffer.secure.offset = 0;
// Now create a sample array for the CDM layer.
CdmDecryptionParametersV16 params(key_id);
params.is_secure = true;
CdmDecryptionSample sample(input.data(),
output_descriptor.buffer.secure.handle, 0,
input.size(), iv);
CdmDecryptionSubsample subsample(0, input.size());
sample.subsamples.push_back(subsample);
params.samples.push_back(sample);
CdmResponseType status = cdm_engine_.DecryptV16(session_id, params);
ASSERT_EQ(expected_status, status);
// Free the secure buffer before we check the return status.
OEMCrypto_FreeSecureBuffer(oec_session_id, &output_descriptor,
secure_buffer_fid);
ASSERT_EQ(status, NO_ERROR);
}
};
@@ -192,4 +246,36 @@ TEST_F(CorePIGTest, OfflineWithPST) {
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
}
// This test verifies that the system can download and install license with a
// key that requires secure buffers. It also verifies that we cannot decrypt to
// a non-secure buffer using this key, but that we can decrypt to a secure
// buffer, if the test harness supports secure buffers.
TEST_F(CorePIGTest, OfflineHWSecureRequired) {
const std::string content_id = "GTS_HW_SECURE_ALL";
const KeyId key_id = "0000000000000002";
const CdmLicenseType license_type = kLicenseTypeOffline;
CdmSessionId session_id;
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
CdmKeyRequest key_request;
ASSERT_NO_FATAL_FAILURE(
GenerateKeyRequest(session_id, content_id, &key_request, license_type));
std::string key_response;
ASSERT_NO_FATAL_FAILURE(GetKeyResponse(key_request, &key_response));
CdmKeySetId key_set_id;
ASSERT_NO_FATAL_FAILURE(
AddKey(session_id, key_response, license_type, &key_set_id));
// First we try to decrypt to a non-secure buffer and verify that it fails.
// TODO(b/164517875): This error code should be something actionable.
ASSERT_NO_FATAL_FAILURE(FailDecrypt(session_id, key_id, DECRYPT_ERROR));
// Next, if possible, we try to decrypt to a secure buffer, and verify
// success.
if (wvoec::global_features.test_secure_buffers) {
ASSERT_NO_FATAL_FAILURE(DecryptSecure(session_id, key_id));
} else {
LOGI("Test harness cannot create secure buffers. test skipped.");
}
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
}
} // namespace wvcdm