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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user