diff --git a/libwvdrmengine/cdm/core/test/core_integration_test.cpp b/libwvdrmengine/cdm/core/test/core_integration_test.cpp index ae267b6f..9e7a7186 100644 --- a/libwvdrmengine/cdm/core/test/core_integration_test.cpp +++ b/libwvdrmengine/cdm/core/test/core_integration_test.cpp @@ -3,6 +3,7 @@ // Agreement. #include "certificate_provisioning.h" +#include "license_holder.h" #include "log.h" #include "provisioning_holder.h" #include "test_base.h" @@ -128,9 +129,11 @@ class CoreIntegrationTest : public WvCdmTestBaseWithEngine { } }; -// Verify that SPOIDs and DRM certificate serial number are stable between -// factory resets/provisioning attempts for the same app and different between -// different apps. Test using two different apps and origins. +/** + * Verify that SPOIDs and DRM certificate serial number are stable between + * factory resets/provisioning attempts for the same app and different between + * different apps. Test using two different apps and origins. + */ TEST_F(CoreIntegrationTest, ProvisioningStableSpoidTest) { std::string level; ASSERT_EQ( @@ -233,4 +236,44 @@ TEST_F(CoreIntegrationTest, ProvisioningStableSpoidTest) { ASSERT_NE(drm_cert_serial_number_app_1_origin_1[0], drm_cert_serial_number_app_1_origin_2[0]); } + +/** + * A clear lead without a license loaded. + */ +TEST_F(CoreIntegrationTest, ClearLead) { + LicenseHolder holder("CDM_Streaming", &cdm_engine_, config_); + const KeyId key_id = ""; + + ASSERT_NO_FATAL_FAILURE(holder.OpenSession()); + ASSERT_NO_FATAL_FAILURE(holder.FetchLicense()); + EXPECT_EQ(NO_ERROR, holder.DecryptClearLead(key_id)); + ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); +} + +/** + * Playback clear lead with a license loaded. Playback should succeed. + */ +TEST_F(CoreIntegrationTest, ClearLeadAfterLicenseLoad) { + LicenseHolder holder("CDM_Streaming", &cdm_engine_, config_); + const KeyId key_id = ""; + + ASSERT_NO_FATAL_FAILURE(holder.OpenSession()); + ASSERT_NO_FATAL_FAILURE(holder.FetchLicense()); + ASSERT_NO_FATAL_FAILURE(holder.LoadLicense()); + EXPECT_EQ(NO_ERROR, holder.DecryptClearLead(key_id)); + ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); +} + +/** + * Decrypt without a license loaded. Decrypt should fail with a NEED_KEY error. + */ +TEST_F(CoreIntegrationTest, NeedKeyBeforeLicenseLoad) { + LicenseHolder holder("CDM_Streaming", &cdm_engine_, config_); + const KeyId key_id = "0000000000000000"; + + ASSERT_NO_FATAL_FAILURE(holder.OpenSession()); + ASSERT_NO_FATAL_FAILURE(holder.FetchLicense()); + EXPECT_EQ(NEED_KEY, holder.Decrypt(key_id)); + ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); +} } // namespace wvcdm diff --git a/libwvdrmengine/cdm/core/test/license_holder.cpp b/libwvdrmengine/cdm/core/test/license_holder.cpp index 30300593..0e9837b7 100644 --- a/libwvdrmengine/cdm/core/test/license_holder.cpp +++ b/libwvdrmengine/cdm/core/test/license_holder.cpp @@ -176,6 +176,20 @@ CdmResponseType LicenseHolder::Decrypt(const std::string& key_id) { return cdm_engine_->DecryptV16(session_id_, params); } +CdmResponseType LicenseHolder::DecryptClearLead(const std::string& key_id) { + constexpr size_t buffer_size = 500; + const std::vector input(buffer_size, 0); + std::vector output(buffer_size, 0); + const std::vector iv(KEY_IV_SIZE, 0); + CdmDecryptionParametersV16 params(key_id); + params.is_secure = false; + CdmDecryptionSample sample(input.data(), output.data(), 0, input.size(), iv); + CdmDecryptionSubsample subsample(input.size(), 0); + sample.subsamples.push_back(subsample); + params.samples.push_back(sample); + return cdm_engine_->DecryptV16(session_id_, params); +} + void LicenseHolder::DecryptSecure(const KeyId& key_id) { ASSERT_TRUE(wvoec::global_features.test_secure_buffers); constexpr size_t buffer_size = 500; diff --git a/libwvdrmengine/cdm/core/test/license_holder.h b/libwvdrmengine/cdm/core/test/license_holder.h index 41578567..405af278 100644 --- a/libwvdrmengine/cdm/core/test/license_holder.h +++ b/libwvdrmengine/cdm/core/test/license_holder.h @@ -86,6 +86,9 @@ class LicenseHolder { // Try to decrypt some random data. This does not verify that the data is // decrypted correctly. Returns the result of the decrypt operation. CdmResponseType Decrypt(const std::string& key_id); + // Try to copy the clear lead to a secure buffer. Returns the result of the + // copy buffer operation. + CdmResponseType DecryptClearLead(const std::string& key_id); // Try to decrypt some random data to a secure buffer. If the test harness // does not allow creating a secure buffer, then this function fails // immediately. Otherwise, a secure buffer is created and used for a diff --git a/libwvdrmengine/cdm/core/test/policy_integration_test.cpp b/libwvdrmengine/cdm/core/test/policy_integration_test.cpp index ed523ff6..814b6d07 100644 --- a/libwvdrmengine/cdm/core/test/policy_integration_test.cpp +++ b/libwvdrmengine/cdm/core/test/policy_integration_test.cpp @@ -35,7 +35,9 @@ class CorePIGTest : public WvCdmTestBaseWithEngine { } }; -// An offline license with nonce not required. +/** + * An offline license with nonce not required. + */ TEST_F(CorePIGTest, OfflineNoNonce) { LicenseHolder holder("CDM_OfflineNoNonce", &cdm_engine_, config_); holder.set_can_persist(true); @@ -54,7 +56,9 @@ TEST_F(CorePIGTest, OfflineNoNonce) { ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); } -// An offline license with nonce and provider session token. +/** + * An offline license with nonce and provider session token. + */ TEST_F(CorePIGTest, OfflineWithPST) { LicenseHolder holder("CDM_OfflineWithPST", &cdm_engine_, config_); holder.set_can_persist(true); @@ -128,10 +132,12 @@ TEST_F(CorePIGTest, OfflineMultipleLicensesWithDefrag) { ASSERT_NO_FATAL_FAILURE(holder3.CloseSession()); } -// This test verifies that the system can download and install license with a -// key that requires secure buffers. It also verifies that we cannot decrypt to -// a non-secure buffer using this key, but that we can decrypt to a secure -// buffer, if the test harness supports secure buffers. +/** + * This test verifies that the system can download and install license with a + * key that requires secure buffers. It also verifies that we cannot decrypt to + * a non-secure buffer using this key, but that we can decrypt to a secure + * buffer, if the test harness supports secure buffers. + */ TEST_F(CorePIGTest, OfflineHWSecureRequired) { LicenseHolder holder("CDM_OfflineHWSecureRequired", &cdm_engine_, config_); holder.set_can_persist(true); @@ -170,8 +176,10 @@ TEST_F(CorePIGTest, OfflineHWSecureRequired) { ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); } -// Should be able to request license, perform playback, generate a license -// release, and receive the release response. +/** + * Should be able to request license, perform playback, generate a license + * release, and receive the release response. + */ TEST_F(CorePIGTest, LicenseRelease1) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Test for usage table devices only."; @@ -194,8 +202,10 @@ TEST_F(CorePIGTest, LicenseRelease1) { ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); } -// Should be able to request license, wait some time, generate a license -// release, and receive the release response. +/** + * Should be able to request license, wait some time, generate a license + * release, and receive the release response. + */ TEST_F(CorePIGTest, LicenseRelease2) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Test for usage table devices only.";