Source release 18.1.0

This commit is contained in:
John "Juce" Bruce
2023-06-23 15:45:08 -07:00
parent 2baa7c6e2b
commit b2c35151ad
2074 changed files with 196004 additions and 427059 deletions

View File

@@ -9,14 +9,15 @@
#include <memory>
#include "cdm_usage_table.h"
#include "crypto_key.h"
#include "crypto_wrapped_key.h"
#include "properties.h"
#include "service_certificate.h"
#include "string_conversions.h"
#include "system_id_extractor.h"
#include "test_base.h"
#include "test_printers.h"
#include "usage_table_header.h"
#include "wv_cdm_constants.h"
#include "wv_metrics.pb.h"
@@ -29,13 +30,14 @@ using ::testing::NotNull;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SetArgPointee;
using ::testing::StrEq;
namespace wvcdm {
namespace {
const std::string kEmptyString;
const uint32_t kSystemId = 1234;
const uint32_t kUpdatedSystemId = 5678;
const std::string kToken = wvutil::a2bs_hex(
"0AAE02080212107E0A892DEEB021E7AF696B938BB1D5B1188B85AD9D05228E023082010A02"
@@ -121,15 +123,16 @@ class MockDeviceFiles : public DeviceFiles {
(bool, std::string*, CryptoWrappedKey*, std::string*, uint32_t*),
(override));
MOCK_METHOD(bool, HasCertificate, (bool), (override));
MOCK_METHOD(bool, RemoveCertificate, (), (override));
};
class MockUsageTableHeader : public UsageTableHeader {
class MockCdmUsageTable : public CdmUsageTable {
public:
MockUsageTableHeader() : UsageTableHeader() {}
MockCdmUsageTable() : CdmUsageTable() {}
MOCK_METHOD(CdmResponseType, UpdateEntry,
(uint32_t usage_entry_number, CryptoSession* crypto_session,
CdmUsageEntry* usage_entry),
(UsageEntryIndex usage_entry_index, CryptoSession* crypto_session,
UsageEntry* usage_entry),
(override));
};
@@ -137,10 +140,10 @@ class MockCryptoSession : public TestCryptoSession {
public:
MockCryptoSession(metrics::CryptoMetrics* crypto_metrics)
: TestCryptoSession(crypto_metrics) {
// By default, call the concrete implementation of HasUsageInfoSupport.
ON_CALL(*this, HasUsageInfoSupport(_))
// By default, call the concrete implementation of HasUsageTableSupport.
ON_CALL(*this, HasUsageTableSupport(_))
.WillByDefault(
Invoke(this, &MockCryptoSession::BaseHasUsageInfoSupport));
Invoke(this, &MockCryptoSession::BaseHasUsageTableSupport));
}
MOCK_METHOD(CdmResponseType, GetProvisioningToken,
(std::string*, std::string*), (override));
@@ -151,14 +154,35 @@ class MockCryptoSession : public TestCryptoSession {
(override));
MOCK_METHOD(CdmResponseType, LoadCertificatePrivateKey,
(const CryptoWrappedKey&), (override));
MOCK_METHOD(bool, HasUsageInfoSupport, (bool*), (override));
MOCK_METHOD(UsageTableHeader*, GetUsageTableHeader, (), (override));
MOCK_METHOD(bool, HasUsageTableSupport, (bool*), (override));
MOCK_METHOD(CdmUsageTable*, GetUsageTable, (), (override));
bool BaseHasUsageInfoSupport(bool* has_support) {
return CryptoSession::HasUsageInfoSupport(has_support);
bool BaseHasUsageTableSupport(bool* has_support) {
return CryptoSession::HasUsageTableSupport(has_support);
}
};
class TestCdmClientPropertySet : public CdmClientPropertySet {
public:
TestCdmClientPropertySet(bool atsc_mode) : atsc_mode_(atsc_mode) {}
~TestCdmClientPropertySet() override {}
const std::string& security_level() const override { return kEmptyString; }
bool use_privacy_mode() const override { return false; }
const std::string& service_certificate() const override {
return kEmptyString;
}
void set_service_certificate(const std::string& /* cert */) override {}
bool is_session_sharing_enabled() const override { return false; }
uint32_t session_sharing_id() const override { return 1; }
void set_session_sharing_id(uint32_t /* id */) override {}
const std::string& app_id() const override { return kEmptyString; }
bool use_atsc_mode() const override { return atsc_mode_; }
private:
bool atsc_mode_;
};
class MockPolicyEngine : public PolicyEngine {
public:
MockPolicyEngine(CryptoSession* crypto_session)
@@ -177,13 +201,21 @@ class MockCdmLicense : public CdmLicense {
MOCK_METHOD(std::string, provider_session_token, (), (override));
};
class MockSystemIdExtractor : public SystemIdExtractor {
public:
MockSystemIdExtractor(CryptoSession* crypto_session, wvutil::FileSystem* fs)
: SystemIdExtractor(kLevelDefault, crypto_session, fs) {}
MOCK_METHOD(bool, ExtractSystemId, (uint32_t*), (override));
};
} // namespace
class CdmSessionTest : public WvCdmTestBase {
protected:
void SetUp() override {
WvCdmTestBase::SetUp();
metrics_.reset(new metrics::SessionMetrics);
metrics_ = std::make_shared<metrics::SessionMetrics>();
cdm_session_.reset(new CdmSession(nullptr, metrics_));
// Inject testing mocks.
license_parser_ = new MockCdmLicense(cdm_session_->session_id());
@@ -194,6 +226,9 @@ class CdmSessionTest : public WvCdmTestBase {
cdm_session_->set_policy_engine(policy_engine_);
file_handle_ = new MockDeviceFiles();
cdm_session_->set_file_handle(file_handle_);
system_id_extractor_ =
new MockSystemIdExtractor(crypto_session_, &global_file_system_);
cdm_session_->set_system_id_extractor(system_id_extractor_);
}
void TearDown() override {
@@ -209,25 +244,33 @@ class CdmSessionTest : public WvCdmTestBase {
NiceMock<MockCryptoSession>* crypto_session_;
MockPolicyEngine* policy_engine_;
MockDeviceFiles* file_handle_;
MockUsageTableHeader usage_table_header_;
MockCdmUsageTable usage_table_;
MockSystemIdExtractor* system_id_extractor_;
wvutil::FileSystem global_file_system_;
};
TEST_F(CdmSessionTest, InitWithBuiltInCertificate) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
.WillRepeatedly(Return(level));
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(false, NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(kSystemId),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*file_handle_, RemoveCertificate()).Times(0);
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kSystemId), Return(true)));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
}
@@ -236,13 +279,20 @@ TEST_F(CdmSessionTest, InitWithCertificate) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
.WillRepeatedly(Return(level));
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(false, NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(kSystemId),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*file_handle_, RemoveCertificate()).Times(0);
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kSystemId), Return(true)));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
@@ -257,17 +307,22 @@ TEST_F(CdmSessionTest, ReInitFail) {
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
.WillRepeatedly(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(false, NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(kSystemId),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kSystemId), Return(true)));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
ASSERT_NE(NO_ERROR, cdm_session_->Init(nullptr));
@@ -275,41 +330,117 @@ TEST_F(CdmSessionTest, ReInitFail) {
TEST_F(CdmSessionTest, InitFailCryptoError) {
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.WillOnce(Return(UNKNOWN_ERROR));
.WillOnce(Return(CdmResponseType(UNKNOWN_ERROR)));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init(nullptr));
}
TEST_F(CdmSessionTest, Init_SystemIdChanged_NeedsProvisioning) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.WillRepeatedly(Return(level));
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(false, NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(kSystemId),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*file_handle_, RemoveCertificate()).WillOnce(Return(true));
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kUpdatedSystemId), Return(true)));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init(nullptr));
}
TEST_F(CdmSessionTest, Init_AtscSystemIdChanged_NoReProvisionNeeded) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL3;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.WillRepeatedly(Return(level));
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(true)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RemoveCertificate()).Times(0);
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull())).Times(0);
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
TestCdmClientPropertySet atsc_property_set(true);
ASSERT_EQ(NO_ERROR, cdm_session_->Init(&atsc_property_set));
}
TEST_F(CdmSessionTest, Init_L3SystemIdChanged_NoReProvisionNeeded) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL3;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.WillRepeatedly(Return(level));
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RemoveCertificate()).Times(0);
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull())).Times(0);
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
}
TEST_F(CdmSessionTest, UpdateUsageEntry) {
// Setup common expectations for initializing the CdmSession object.
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
.WillOnce(Return(CdmResponseType(NO_ERROR)));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
.WillRepeatedly(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*crypto_session_, GetUsageTableHeader())
.WillOnce(Return(&usage_table_header_));
EXPECT_CALL(*file_handle_, RetrieveCertificate(false, NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(kSystemId),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*crypto_session_, GetUsageTable())
.WillOnce(Return(&usage_table_));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
EXPECT_CALL(*system_id_extractor_, ExtractSystemId(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kSystemId), Return(false)));
// Set up mocks and expectations for the UpdateUsageEntryInformation call.
EXPECT_CALL(*crypto_session_, HasUsageInfoSupport(_))
EXPECT_CALL(*crypto_session_, HasUsageTableSupport(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(true), Return(true)));
EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token"));
EXPECT_CALL(usage_table_header_, UpdateEntry(_, NotNull(), NotNull()))
.WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(usage_table_, UpdateEntry(_, NotNull(), NotNull()))
.WillRepeatedly(Return(CdmResponseType(NO_ERROR)));
EXPECT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
EXPECT_TRUE(cdm_session_->supports_usage_info());
EXPECT_TRUE(cdm_session_->SupportsUsageTable());
EXPECT_EQ(NO_ERROR, cdm_session_->UpdateUsageEntryInformation());
// Verify the UsageEntry metric is set.