diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index e33ee8bd..1d0d428a 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -136,6 +136,7 @@ class DeviceFiles { FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test); FRIEND_TEST(WvCdmRequestLicenseTest, UsageInfoRetryTest); FRIEND_TEST(WvCdmUsageInfoTest, UsageInfo); + FRIEND_TEST(WvCdmUsageTest, WithClientId); FRIEND_TEST(WvCdmExtendedDurationTest, UsageOverflowTest); #endif diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index ea43cac6..61298e32 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -447,6 +447,13 @@ RenewWithClientIdTestConfiguration {true, false, true, true, "Test: Offline renewal/release, service cert provided"}}; +RenewWithClientIdTestConfiguration + usage_client_id_test_configuration[] = { + {false, false, false, false, + "Test: Usage reporting without client Id"}, + {true, false, false, false, + "Test: Usage reporting with client Id"}}; + } // namespace namespace wvcdm { @@ -1680,6 +1687,129 @@ INSTANTIATE_TEST_CASE_P( ::testing::Range(&offline_release_client_id_test_configuration[0], &offline_release_client_id_test_configuration[4])); +class WvCdmUsageTest + : public WvCdmRequestLicenseTest, + public ::testing::WithParamInterface< + RenewWithClientIdTestConfiguration*> {}; + +TEST_P(WvCdmUsageTest, WithClientId) { + Unprovision(); + Provision(kLevelDefault); + + CdmSecurityLevel security_level = GetDefaultSecurityLevel(); + std::string app_id = ""; + DeviceFiles handle; + EXPECT_TRUE(handle.Init(security_level)); + File file; + handle.SetTestFile(&file); + std::vector psts; + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts)); + + RenewWithClientIdTestConfiguration* config = GetParam(); + std::string key_id; + + if (config->renew_with_client_id) { + key_id = a2bs_hex( // streaming_clip20 + "000000427073736800000000" // blob size and pssh + "EDEF8BA979D64ACEA3C827DCD51D21ED00000023" // Widevine system id + "08011a0d7769646576696e655f746573" // pssh data + "74221073747265616d696e675f636c69703230"); + } else { + key_id = a2bs_hex( // streaming_clip3 + "000000427073736800000000" // blob size and pssh + "EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id + "08011a0d7769646576696e655f746573" // pssh data + "74220f73747265616d696e675f636c697033"); + } + wvcdm::CdmAppParameterMap app_parameters; + TestWvCdmClientPropertySet property_set; + + SubSampleInfo* data = &usage_info_sub_samples_icp[0]; + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, + &session_id_); + + GenerateKeyRequest(key_id, app_parameters, kLicenseTypeStreaming, + &property_set); + + std::string key_response; + VerifyKeyRequestResponse(g_license_server, g_client_auth, false, + &key_response); + + // Validate signed license + SignedMessage signed_message; + EXPECT_TRUE(signed_message.ParseFromString(key_response)) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::License license; + EXPECT_TRUE(license.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify renew_with_client_id + EXPECT_EQ(config->renew_with_client_id, + license.policy().has_renew_with_client_id()); + + EXPECT_FALSE(license.id().provider_session_token().empty()); + + std::vector decrypt_buffer(data->encrypt_data.size()); + CdmDecryptionParameters decryption_parameters( + &data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(), + &data->iv, data->block_offset, &decrypt_buffer[0]); + decryption_parameters.is_encrypted = data->is_encrypted; + decryption_parameters.is_secure = data->is_secure; + EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id, + decryption_parameters)); + + EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(), + decrypt_buffer.begin())); + decryptor_.CloseSession(session_id_); + + uint32_t num_usage_info = 0; + CdmUsageInfo usage_info; + CdmUsageInfoReleaseMessage release_msg; + CdmResponseType status = decryptor_.GetUsageInfo(app_id, &usage_info); + EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status); + + // Validate signed renewal request + EXPECT_TRUE(signed_message.ParseFromString(usage_info[0])) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE_REQUEST, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::LicenseRequest license_renewal; + EXPECT_TRUE(license_renewal.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify ClientId + EXPECT_EQ(config->renew_with_client_id && !config->enable_privacy_mode, + license_renewal.has_client_id()) + << config->test_description; + + if (config->enable_privacy_mode) { + EXPECT_EQ(config->renew_with_client_id, + license_renewal.has_encrypted_client_id()) + << config->test_description; + EXPECT_NE( + 0u, license_renewal.encrypted_client_id().encrypted_client_id().size()); + } + + release_msg = + GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[0]); + EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg)); +} + +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmUsageTest, + ::testing::Range(&usage_client_id_test_configuration[0], + &usage_client_id_test_configuration[2])); + TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) { Unprovision(); Provision(kLevelDefault);