Source release 19.2.0

This commit is contained in:
Alex Dale
2024-06-25 14:03:53 -07:00
parent b8bdfccebe
commit cd8256726f
89 changed files with 2747 additions and 35949 deletions

View File

@@ -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