// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include "certificate_provisioning.h" #include #include #include #include "crypto_session.h" #include "metrics_collections.h" #include "test_base.h" #include "wv_cdm_types.h" namespace { const std::string kSignedDeviceCertificate = wvutil::a2bs_hex( "0A3D0802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C09A0C" "28D2093A11746573742E7769646576696E652E636F6D6080B51812097369676E617475726" "5"); const std::string kSignedDeviceCertificateCreationTimeUnlimited = wvutil::a2bs_hex( "0A370802121B7769646576696E655F746573745F73657269616C5F6E756D6265721800" "28D2093A11746573742E7769646576696E652E636F6D12097369676E6174757265"); const std::string kSignedDeviceCertificateExpirationTimeInvalid = wvutil::a2bs_hex( "0A390802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C0" "9A0C28D2093A11746573742E7769646576696E652E636F6D12097369676E617475726" "5"); const std::string kSignedDeviceCertificateExpirationTimeUnlimited = wvutil::a2bs_hex( "0A3B0802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C0" "9A0C28D2093A11746573742E7769646576696E652E636F6D600012097369676E617475" "7265"); const std::string kSignedDeviceCertificateInvalid = wvutil::a2bs_hex( "76340802121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2093A" "11746573742E7769646576696E652E636F6D12097369676E6174757265"); const std::string kSignedDeviceCertificateInvalidCertificateType = wvutil::a2bs_hex( "0A350801121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2" "093A11746573742E7769646576696E652E636F6D12097369676E6174757265"); const std::string kSignedDeviceCertificateNoDrmCertificate = wvutil::a2bs_hex("12097369676E6174757265"); const std::string kSignedDeviceCertificateTimesInvalid = wvutil::a2bs_hex( "0A350802121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2093A" "11746573742E7769646576696E652E636F6D12097369676E6174757265"); const int64_t kCreationTime = 200000; const int64_t kExpirationTime = 400000; const std::string kSerialNumber = "widevine_test_serial_number"; const uint32_t kSystemId = 1234; } // unnamed namespace namespace wvcdm { class MockCryptoSession : public TestCryptoSession { public: MockCryptoSession(metrics::CryptoMetrics* metrics) : TestCryptoSession(metrics) {} MOCK_METHOD(CdmResponseType, Open, (wvcdm::RequestedSecurityLevel), (override)); // Usage Table Header. MOCK_METHOD(CdmResponseType, CreateUsageTableHeader, (wvcdm::RequestedSecurityLevel, UsageTableHeader*), (override)); MOCK_METHOD(CdmResponseType, LoadUsageTableHeader, (wvcdm::RequestedSecurityLevel, const UsageTableHeader&), (override)); MOCK_METHOD(CdmResponseType, ShrinkUsageTableHeader, (wvcdm::RequestedSecurityLevel, uint32_t, UsageTableHeader*), (override)); // Usage Entry. MOCK_METHOD(CdmResponseType, CreateUsageEntry, (UsageEntryIndex*), (override)); MOCK_METHOD(CdmResponseType, LoadUsageEntry, (UsageEntryIndex, const UsageEntry&), (override)); MOCK_METHOD(CdmResponseType, UpdateUsageEntry, (UsageTableHeader*, UsageEntry*), (override)); MOCK_METHOD(CdmResponseType, MoveUsageEntry, (UsageEntryIndex), (override)); }; class TestStubCryptoSessionFactory : public CryptoSessionFactory { CryptoSession* MakeCryptoSession( metrics::CryptoMetrics* crypto_metrics) override { return new MockCryptoSession(crypto_metrics); } }; class CertificateProvisioningTest : public WvCdmTestBase { protected: void SetUp() override { WvCdmTestBase::SetUp(); CryptoSession::SetCryptoSessionFactory(new TestStubCryptoSessionFactory()); metrics_.reset(new metrics::CryptoMetrics()); certificate_provisioning_.reset( new CertificateProvisioning(metrics_.get())); } void TearDown() override {} std::unique_ptr metrics_; std::unique_ptr certificate_provisioning_; }; // Tests ExtractDeviceInfo failure scenarios // * invalid output parmeters // * invalid signed drm device certificate // * signed drm device certificate contains no drm certificate // * drm certificate has an invalid certificate type TEST_F(CertificateProvisioningTest, ExtractDeviceInfo_InvalidInput) { std::string serial_number; uint32_t system_id; EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificate, nullptr, nullptr, nullptr, nullptr)); int64_t creation_time_seconds, expiration_time_seconds; EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateInvalid, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateNoDrmCertificate, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateInvalidCertificateType, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); } // Tests ExtractDeviceInfo success scenarios // * able to extract both |serial_number| and |system_id| // * able to extract only |serial_number| // * able to extract only |system_id| TEST_F(CertificateProvisioningTest, ExtractDeviceInfo) { std::string serial_number; uint32_t system_id; int64_t creation_time_seconds, expiration_time_seconds; EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateTimesInvalid, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(INVALID_TIME, creation_time_seconds); EXPECT_EQ(INVALID_TIME, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateTimesInvalid, nullptr, &system_id, nullptr, nullptr)); EXPECT_EQ(kSystemId, system_id); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateTimesInvalid, &serial_number, nullptr, nullptr, nullptr)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateCreationTimeUnlimited, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(UNLIMITED_DURATION, creation_time_seconds); EXPECT_EQ(INVALID_TIME, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateExpirationTimeInvalid, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(kCreationTime, creation_time_seconds); EXPECT_EQ(INVALID_TIME, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateExpirationTimeUnlimited, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(kCreationTime, creation_time_seconds); EXPECT_EQ(UNLIMITED_DURATION, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificate, &serial_number, &system_id, &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(kCreationTime, creation_time_seconds); EXPECT_EQ(kExpirationTime, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificate, &serial_number, &system_id, nullptr, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(kExpirationTime, expiration_time_seconds); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateExpirationTimeUnlimited, &serial_number, &system_id, &creation_time_seconds, nullptr)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); EXPECT_EQ(kCreationTime, creation_time_seconds); EXPECT_EQ(kExpirationTime, expiration_time_seconds); } } // namespace wvcdm