Source release 19.2.0
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
@@ -185,12 +186,31 @@ const std::vector<uint8_t> kKeyIdCtr =
|
||||
// kHlsInitData.
|
||||
const std::vector<uint8_t> kKeyIdCbc =
|
||||
a2b_hex("9b759040321a408a5c7768b4511287a6");
|
||||
// This Key ID must match a key embedded in kCencEntitlementInitData1.
|
||||
const std::vector<uint8_t> kKeyIdEntitlement1 =
|
||||
a2b_hex("c8326486bb5d5c4a958f00b1111afc81");
|
||||
// This Key ID must match a key embedded in kCencEntitlementInitData2.
|
||||
const std::vector<uint8_t> kKeyIdEntitlement2 =
|
||||
a2b_hex("f8488775a99855ff94b93ec5bd499356");
|
||||
|
||||
const std::string kEntitlementContentId = "CDM_Entitlement";
|
||||
// This entitlement key id has to match the key id in the license data for
|
||||
// content id "CDM_Entitlement" as seen in the integration console. And it
|
||||
// also has to match the key id derived by UAT for the content id
|
||||
// CDM_Entitlement, for the AUDIO track. When running backwards compatibility
|
||||
// tests, the SDK servers use the data in the integration console, and UAT
|
||||
// derives key data.
|
||||
const std::string kKeyIdEntitlement =
|
||||
wvutil::a2bs_hex("972F75C583835AABA6778E2565948825");
|
||||
// The key id and encrypted key are made up. The decrypted key is golden data
|
||||
// from a working system. This is TEST_ONLY data, so we may include it in source
|
||||
// code in the clear.
|
||||
const std::string kKeyIdEntitlement1 = // Key ID for entitled key 1.
|
||||
a2bs_hex("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
const std::string kEncEntitledKey1 = // Encrypted key data for entitled key 1.
|
||||
a2bs_hex("11111111111111111111111111111111");
|
||||
// Clear key data for entitled key 1, used to encrypt test data.
|
||||
const std::vector kEntitledKey1 = a2b_hex("AD789E1309DD67E55965679E72CE2328");
|
||||
const std::string kKeyIdEntitlement2 = // Key ID for entitled key 2.
|
||||
a2bs_hex("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
|
||||
const std::string kEncEntitledKey2 = // Encrypted key data for entitled key 2.
|
||||
a2bs_hex("22222222222222222222222222222222");
|
||||
// Clear key data for entitled key 2, used to encrypt test data.
|
||||
const std::vector kEntitledKey2 = a2b_hex("EA1E37D89066BF0B6FEF181DD5373580");
|
||||
|
||||
// A default pattern object disables patterns during decryption.
|
||||
const Cdm::Pattern kPatternNone;
|
||||
@@ -235,15 +255,6 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
// TODO: b/305093063 - Remove when Drm Reprovisioning server is implemented.
|
||||
// Many of these tests call EnsureProvisioned which tries to provision the
|
||||
// test device using a provisioning server. Until support is added for Drm
|
||||
// Reprovisioning on the server, skip these tests to avoid test failures.
|
||||
if (wvoec::global_features.provisioning_method ==
|
||||
OEMCrypto_DrmReprovisioning) {
|
||||
GTEST_SKIP()
|
||||
<< "Skipping until Drm Reprovisioning server support is implemented.";
|
||||
}
|
||||
WvCdmTestBase::SetUp();
|
||||
|
||||
// Clear anything stored, load default device cert.
|
||||
@@ -1469,14 +1480,10 @@ TEST_F(CdmTest, GetExpiration) {
|
||||
}
|
||||
|
||||
TEST_P(CdmTestWithRemoveParam, Remove) {
|
||||
const bool intermediate_close = GetParam();
|
||||
|
||||
// TODO: b/305093063 - Remove when Drm Reprovisioning server is implemented.
|
||||
if (wvoec::global_features.provisioning_method ==
|
||||
OEMCrypto_DrmReprovisioning) {
|
||||
GTEST_SKIP()
|
||||
<< "Skipping until Drm Reprovisioning server support is implemented.";
|
||||
if (!wvoec::global_features.usage_table) {
|
||||
GTEST_SKIP() << "Test for usage table devices only.";
|
||||
}
|
||||
const bool intermediate_close = GetParam();
|
||||
EnsureProvisioned();
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
@@ -1949,6 +1956,38 @@ TEST_F(CdmTest, GetStatusForHdcpResolution) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make some init data for an entitled license. The entitled key information is
|
||||
// in this PSSH, and the entitlement key information is in the license data on
|
||||
// UAT.
|
||||
std::string MakeEntitledData(const std::string& content_key_id,
|
||||
const std::string& encrypted_content_key) {
|
||||
video_widevine::WidevinePsshData pssh;
|
||||
pssh.set_content_id(kEntitlementContentId);
|
||||
const uint32_t kFourCcCenc = 0x63656e63;
|
||||
pssh.set_protection_scheme(kFourCcCenc);
|
||||
pssh.set_type(video_widevine::WidevinePsshData_Type_ENTITLED_KEY);
|
||||
pssh.set_crypto_period_index(20);
|
||||
pssh.set_crypto_period_seconds(2);
|
||||
video_widevine::WidevinePsshData_EntitledKey* key = pssh.add_entitled_keys();
|
||||
// The key id for the entitlement id. This id is in the license, too.
|
||||
key->set_entitlement_key_id(kKeyIdEntitlement);
|
||||
key->set_key_id(content_key_id); // Entitled content key id.
|
||||
key->set_key(encrypted_content_key); // encrypted entitled content key.
|
||||
key->set_iv(wvutil::a2bs_hex("1234567890abcdef1234567890abcdef"));
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// The other key ids are just to pad out the init data. Only the first one
|
||||
// is used.
|
||||
key = pssh.add_entitled_keys();
|
||||
char x = 'G' + static_cast<char>(i);
|
||||
key->set_entitlement_key_id(std::string(AES_BLOCK_SIZE, x));
|
||||
key->set_key_id(std::string(AES_BLOCK_SIZE, x));
|
||||
key->set_key(std::string(AES_BLOCK_SIZE, x));
|
||||
key->set_iv(std::string(AES_BLOCK_SIZE, x));
|
||||
}
|
||||
return MakePSSH(pssh);
|
||||
}
|
||||
|
||||
TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {
|
||||
EnsureProvisioned();
|
||||
std::string session_id;
|
||||
@@ -1960,13 +1999,15 @@ TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->createSession(Cdm::kTemporary, &session_id));
|
||||
|
||||
// Generate a license request for the 1st entitlement init data.
|
||||
const std::string init_data_string1 =
|
||||
MakeEntitledData(kKeyIdEntitlement1, kEncEntitledKey1);
|
||||
|
||||
std::string license_request;
|
||||
{
|
||||
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
|
||||
.WillOnce(SaveArg<2>(&license_request));
|
||||
ASSERT_EQ(Cdm::kSuccess,
|
||||
generateRequestWithRetry(session_id, Cdm::kCenc,
|
||||
kCencEntitlementInitData1));
|
||||
ASSERT_EQ(Cdm::kSuccess, generateRequestWithRetry(session_id, Cdm::kCenc,
|
||||
init_data_string1));
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
@@ -1981,13 +2022,22 @@ TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
// Set up input and expected output.
|
||||
std::vector<uint8_t> input(12345u);
|
||||
for (size_t i = 0; i < input.size(); i++) input[i] = i % 256;
|
||||
const std::vector<uint8_t> test_iv1(AES_BLOCK_SIZE, 42);
|
||||
const std::vector<uint8_t> test_iv2(AES_BLOCK_SIZE, 74);
|
||||
const std::vector<uint8_t> expected_output1 =
|
||||
Aes128CtrEncrypt(kEntitledKey1, test_iv1, input);
|
||||
const std::vector<uint8_t> expected_output2 =
|
||||
Aes128CtrEncrypt(kEntitledKey2, test_iv2, input);
|
||||
|
||||
// Set up subsample
|
||||
Cdm::Subsample subsample;
|
||||
subsample.protected_bytes = kInputSize;
|
||||
|
||||
subsample.protected_bytes = static_cast<uint32_t>(input.size());
|
||||
// Set up sample
|
||||
Cdm::Sample sample;
|
||||
sample.input.data = kInput;
|
||||
sample.input.data = input.data();
|
||||
sample.input.data_length = subsample.protected_bytes;
|
||||
sample.input.subsamples = &subsample;
|
||||
sample.input.subsamples_length = 1;
|
||||
@@ -2002,42 +2052,40 @@ TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {
|
||||
batch.encryption_scheme = Cdm::kAesCtr;
|
||||
|
||||
// Attempt multiple decrypts with a key from the first license.
|
||||
batch.key_id = kKeyIdEntitlement1.data();
|
||||
batch.key_id = reinterpret_cast<const uint8_t*>(kKeyIdEntitlement1.c_str());
|
||||
batch.key_id_length = static_cast<uint32_t>(kKeyIdEntitlement1.size());
|
||||
sample.input.iv = kIvEntitlement1;
|
||||
sample.input.iv_length = kIvEntitlement1Size;
|
||||
sample.input.iv = test_iv1.data();
|
||||
sample.input.iv_length = static_cast<uint32_t>(test_iv1.size());
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->decrypt(batch));
|
||||
const std::vector<uint8_t> expected_output1(
|
||||
kOutputEntitlement1, kOutputEntitlement1 + kOutputEntitlement1Size);
|
||||
EXPECT_EQ(expected_output1, output_buffer);
|
||||
memset(&(output_buffer[0]), 0, output_buffer.size());
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->decrypt(batch));
|
||||
EXPECT_EQ(expected_output1, output_buffer);
|
||||
|
||||
// Load the second entitlement license using the first. This should not
|
||||
// Load the second entitled license using the first. This should not
|
||||
// require any server roundtrip.
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->loadEmbeddedKeys(session_id, Cdm::kCenc,
|
||||
kCencEntitlementInitData2));
|
||||
const std::string init_data_string2 =
|
||||
MakeEntitledData(kKeyIdEntitlement2, kEncEntitledKey2);
|
||||
ASSERT_EQ(Cdm::kSuccess,
|
||||
cdm_->loadEmbeddedKeys(session_id, Cdm::kCenc, init_data_string2));
|
||||
|
||||
// Attempt multiple decrypts with a key from the second license.
|
||||
batch.key_id = kKeyIdEntitlement2.data();
|
||||
batch.key_id = reinterpret_cast<const uint8_t*>(kKeyIdEntitlement2.c_str());
|
||||
batch.key_id_length = static_cast<uint32_t>(kKeyIdEntitlement2.size());
|
||||
sample.input.iv = kIvEntitlement2;
|
||||
sample.input.iv_length = kIvEntitlement2Size;
|
||||
sample.input.iv = test_iv2.data();
|
||||
sample.input.iv_length = static_cast<uint32_t>(test_iv2.size());
|
||||
memset(&(output_buffer[0]), 0, output_buffer.size());
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->decrypt(batch));
|
||||
const std::vector<uint8_t> expected_output2(
|
||||
kOutputEntitlement2, kOutputEntitlement2 + kOutputEntitlement2Size);
|
||||
EXPECT_EQ(expected_output2, output_buffer);
|
||||
memset(&(output_buffer[0]), 0, output_buffer.size());
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->decrypt(batch));
|
||||
EXPECT_EQ(expected_output2, output_buffer);
|
||||
|
||||
// Attempt multiple decrypts with a key from the first license again.
|
||||
batch.key_id = kKeyIdEntitlement1.data();
|
||||
batch.key_id = reinterpret_cast<const uint8_t*>(kKeyIdEntitlement1.c_str());
|
||||
batch.key_id_length = static_cast<uint32_t>(kKeyIdEntitlement1.size());
|
||||
sample.input.iv = kIvEntitlement1;
|
||||
sample.input.iv_length = kIvEntitlement1Size;
|
||||
sample.input.iv = test_iv1.data();
|
||||
sample.input.iv_length = static_cast<uint32_t>(test_iv1.size());
|
||||
memset(&(output_buffer[0]), 0, output_buffer.size());
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->decrypt(batch));
|
||||
EXPECT_EQ(expected_output1, output_buffer);
|
||||
@@ -2172,12 +2220,6 @@ TEST_F(CdmTest, GetMetrics) {
|
||||
}
|
||||
|
||||
TEST_P(CdmTestWithDecryptParam, DecryptToClearBuffer) {
|
||||
// TODO: b/305093063 - Remove when Drm Reprovisioning server is implemented.
|
||||
if (wvoec::global_features.provisioning_method ==
|
||||
OEMCrypto_DrmReprovisioning) {
|
||||
GTEST_SKIP()
|
||||
<< "Skipping until Drm Reprovisioning server support is implemented.";
|
||||
}
|
||||
EnsureProvisioned();
|
||||
DecryptParam param = GetParam();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user