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

@@ -278,7 +278,6 @@
'sources': [
'<(INTERMEDIATE_DIR)/cert.cc',
],
'defines': ['HAS_EMBEDDED_CERT'],
}], # embedded_cert!=""
# This block defines preprocessor values that match the client

View File

@@ -138,6 +138,7 @@
'include',
],
'dependencies': [
'../cdm/cdm.gyp:device_files',
'../third_party/googletest.gyp:gmock',
'../third_party/googletest.gyp:gtest',
'<(device_files_target)',

68
cdm/extract_bcc_tool.gyp Normal file
View File

@@ -0,0 +1,68 @@
# Copyright 2024 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
#
# Any top-level targets in this file (and their dependencies) will be built by
# the CE CDM's ./build.py build system. Refer to the distribution package's
# README for details.
{
'includes': [
'platform_properties.gypi',
],
'variables': {
},
'targets': [{
'toolsets' : [ 'target' ],
'target_name': 'extract_bcc_tool',
'sources': [
'../oemcrypto/test/extract_bcc_tool.cpp',
],
'include_dirs': [
'../cdm/include',
'../core/include',
'../metrics/include',
'../oemcrypto/include',
'../util/include',
],
'dependencies': [
'cdm.gyp:widevine_ce_cdm_static',
],
'msvs_settings': {
'VCLinkerTool': {
# Additionally, since they are loaded locally, suppress these
# warnings.
'AdditionalOptions': [
'/IGNORE:4049',
'/IGNORE:4217',
],
},
},
'conditions': [
['OS=="ios"', {
'type': 'loadable_module',
'mac_xctest_bundle': '1',
'defines': [
'GTEST_FILTER="<(gtest_filter)"',
],
'dependencies': [
'cdm_unittests.gyp:dummy_app',
],
'sources': [
'test/gtest_xctest_wrapper.mm',
],
'xcode_settings': {
'BUNDLE_LOADER': '$(TEST_HOST)',
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
'WRAPPER_EXTENSION': 'xctest',
},
}, {
'type': 'executable',
}],
['oemcrypto_lib=="target"', {
'dependencies': [
'<(oemcrypto_gyp_path)',
],
}],
],
}],
}

View File

@@ -10,7 +10,7 @@
# define CDM_VERSION_MAJOR 19
#endif
#ifndef CDM_VERSION_MINOR
# define CDM_VERSION_MINOR 1
# define CDM_VERSION_MINOR 2
#endif
#ifndef CDM_VERSION_PATCH
# define CDM_VERSION_PATCH 0

View File

@@ -0,0 +1,70 @@
# Copyright 2024 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
#
# Any top-level targets in this file (and their dependencies) will be built by
# the CE CDM's ./build.py build system. Refer to the distribution package's
# README for details.
{
'includes': [
'platform_properties.gypi',
],
'variables': {
},
'targets': [{
'toolsets' : [ 'target' ],
'target_name': 'install_prov30_oem_cert_tool',
'type': 'executable',
'sources': [
'../oemcrypto/test/install_prov30_oem_cert_tool.cpp',
],
'include_dirs': [
'../cdm/include',
'../core/include',
'../metrics/include',
'../oemcrypto/include',
'../oemcrypto/test',
'../util/include',
],
'dependencies': [
'cdm.gyp:widevine_ce_cdm_static',
],
'msvs_settings': {
'VCLinkerTool': {
# Additionally, since they are loaded locally, suppress these
# warnings.
'AdditionalOptions': [
'/IGNORE:4049',
'/IGNORE:4217',
],
},
},
'conditions': [
['OS=="ios"', {
'type': 'loadable_module',
'mac_xctest_bundle': '1',
'defines': [
'GTEST_FILTER="<(gtest_filter)"',
],
'dependencies': [
'cdm_unittests.gyp:dummy_app',
],
'sources': [
'test/gtest_xctest_wrapper.mm',
],
'xcode_settings': {
'BUNDLE_LOADER': '$(TEST_HOST)',
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
'WRAPPER_EXTENSION': 'xctest',
},
}, {
'type': 'executable',
}],
['oemcrypto_lib=="target"', {
'dependencies': [
'<(oemcrypto_gyp_path)',
],
}],
],
}],
}

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