Allow Apps to Voluntarily Downgrade to L3 Crypto
This merges the following changes from the Widevine CDM repository: 564f4cc Add CdmClientPropertySet to CDM Adds an interface to the CDM that allows it to query its client for certain properties. In this case, this includes the ability to specify what security level is desired, as well as support for service ceritifcate privacy mode. 9cfbd3e Force Level 3 fallback Adds support for voluntarily invoking L3 crypto to the OEMCrypto wrapper. 95d12c1 Add pointer to CdmClientPropertySet class to OpenSession. Adds support for storing the property set on a session-by-session basis and choosing the appropriate crypto level. 17de442 Add Settable Properties for Clank to Android Adds support for setting the aforementioned properties to the DrmEngine bbe704d Fixes to force fallback to level three security Corrections to invoke provisioning, OEMCrypto API with configured security level rather than the default. Unit tests were also revised. Note that some parts of this are also support for the ability to use a service certificate-based privacy mode. The remaining code for supporting this mode is still forthcoming. Bug: 10109249 Change-Id: I2755e4dea1de3e8a56cff237360298f7b7f1bddc
This commit is contained in:
@@ -6,9 +6,13 @@
|
||||
|
||||
#include "config_test_env.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "license_request.h"
|
||||
#include "log.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "url_request.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
@@ -186,6 +190,38 @@ SubSampleInfo partial_offset_single_encrypted_sub_sample = {
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
TestWvCdmClientPropertySet()
|
||||
: service_certificate_(std::vector<uint8_t>()),
|
||||
use_privacy_mode_(false) {}
|
||||
virtual ~TestWvCdmClientPropertySet() {}
|
||||
|
||||
virtual std::string security_level() const { return security_level_; }
|
||||
virtual std::vector<uint8_t> service_certificate() const {
|
||||
return service_certificate_;
|
||||
}
|
||||
virtual bool use_privacy_mode() const { return use_privacy_mode_; }
|
||||
|
||||
void set_security_level(const std::string& security_level) {
|
||||
if (!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
|
||||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3)) {
|
||||
security_level_ = security_level;
|
||||
}
|
||||
}
|
||||
void set_service_certificate(
|
||||
const std::vector<uint8_t>& service_certificate) {
|
||||
service_certificate_ = service_certificate;
|
||||
}
|
||||
void set_use_privacy_mode(bool use_privacy_mode) {
|
||||
use_privacy_mode_ = use_privacy_mode;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string security_level_;
|
||||
std::vector<uint8_t> service_certificate_;
|
||||
bool use_privacy_mode_;
|
||||
};
|
||||
|
||||
class TestWvCdmEventListener : public WvCdmEventListener {
|
||||
public:
|
||||
@@ -337,7 +373,7 @@ class WvCdmDecryptionTest
|
||||
public ::testing::WithParamInterface<SubSampleInfo*> {};
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
std::string provisioning_server_url;
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
@@ -352,7 +388,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
std::string provisioning_server_url;
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
@@ -376,15 +412,108 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
|
||||
TestWvCdmClientPropertySet property_set_L1;
|
||||
TestWvCdmClientPropertySet property_set_L3;
|
||||
TestWvCdmClientPropertySet property_set_Ln;
|
||||
CdmSessionId session_id_L1;
|
||||
CdmSessionId session_id_L3;
|
||||
CdmSessionId session_id_Ln;
|
||||
|
||||
property_set_L1.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L1);
|
||||
property_set_L1.set_use_privacy_mode(true);
|
||||
decryptor_.OpenSession(g_key_system, &property_set_L1, &session_id_L1);
|
||||
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||
property_set_L3.set_use_privacy_mode(false);
|
||||
decryptor_.OpenSession(g_key_system, &property_set_L3, &session_id_L3);
|
||||
property_set_Ln.set_security_level("");
|
||||
decryptor_.OpenSession(g_key_system, &property_set_Ln, &session_id_Ln);
|
||||
|
||||
std::string security_level = Properties::GetSecurityLevel(session_id_L1);
|
||||
EXPECT_TRUE(!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
|
||||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3));
|
||||
EXPECT_TRUE(Properties::UsePrivacyMode(session_id_L1));
|
||||
EXPECT_EQ(Properties::GetSecurityLevel(session_id_L3),
|
||||
QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||
EXPECT_FALSE(Properties::UsePrivacyMode(session_id_L3));
|
||||
security_level = Properties::GetSecurityLevel(session_id_Ln);
|
||||
EXPECT_TRUE(security_level.empty() ||
|
||||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3));
|
||||
decryptor_.CloseSession(session_id_L1);
|
||||
decryptor_.CloseSession(session_id_L3);
|
||||
decryptor_.CloseSession(session_id_Ln);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ForceL3Test) {
|
||||
TestWvCdmClientPropertySet property_set;
|
||||
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||
|
||||
File file;
|
||||
DeviceFiles handle;
|
||||
EXPECT_TRUE(handle.Init(&file, kSecurityLevelL3));
|
||||
EXPECT_TRUE(handle.DeleteAllFiles());
|
||||
|
||||
EXPECT_EQ(NEED_PROVISIONING,
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_));
|
||||
std::string provisioning_server_url;
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
decryptor_.GetProvisioningRequest(&key_msg_,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, config_.provisioning_server_url());
|
||||
std::string response =
|
||||
GetCertRequestResponse(config_.provisioning_test_server_url(), 200);
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response));
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
|
||||
&session_id_));
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, UsePrivacyModeTest) {
|
||||
TestWvCdmClientPropertySet property_set;
|
||||
|
||||
property_set.set_use_privacy_mode(true);
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
|
||||
|
||||
if (property_set.service_certificate().empty()) {
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
std::string resp = GetKeyRequestResponse(g_license_server,
|
||||
g_client_auth, 200);
|
||||
EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_),
|
||||
wvcdm::NEED_KEY);
|
||||
std::vector<uint8_t> service_certificate(key_msg_.begin(), key_msg_.end());
|
||||
property_set.set_service_certificate(service_certificate);
|
||||
}
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
// property has service certificate set from previous request
|
||||
EXPECT_FALSE(property_set.service_certificate().empty());
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
property_set.set_use_privacy_mode(false);
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, BaseMessageTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
GetKeyRequestResponse(g_license_server, g_client_auth, 200);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
|
||||
std::string wrong_message = wvcdm::a2bs_hex(g_wrong_key_id);
|
||||
GenerateKeyRequest(g_key_system, wrong_message, kLicenseTypeStreaming);
|
||||
@@ -393,21 +522,21 @@ TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, AddSteamingKeyTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -416,13 +545,13 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
session_id_.clear();
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -432,7 +561,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
||||
|
||||
session_id_.clear();
|
||||
key_set_id_.clear();
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
@@ -444,7 +573,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -454,7 +583,7 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
|
||||
|
||||
session_id_.clear();
|
||||
key_set_id_.clear();
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
CdmSessionId restore_session_id = session_id_;
|
||||
TestWvCdmEventListener listener;
|
||||
EXPECT_TRUE(decryptor_.AttachEventListener(restore_session_id, &listener));
|
||||
@@ -474,7 +603,7 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, StreamingLicenseRenewal) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -484,7 +613,7 @@ TEST_F(WvCdmRequestLicenseTest, StreamingLicenseRenewal) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -494,7 +623,7 @@ TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -564,7 +693,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -585,7 +714,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
|
||||
TEST_P(WvCdmDecryptionTest, DecryptionTest) {
|
||||
SubSampleInfo* data = GetParam();
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
if (data->retrieve_key) {
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
@@ -616,7 +745,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
&partial_single_encrypted_sub_sample));
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
@@ -669,7 +798,7 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, DISABLED_RestoreOfflineLicenseDecryptionTest) {
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
CdmKeySetId key_set_id = key_set_id_;
|
||||
@@ -677,7 +806,7 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_RestoreOfflineLicenseDecryptionTest) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
|
||||
session_id_.clear();
|
||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
|
||||
/*
|
||||
// key 1, encrypted, 256b
|
||||
|
||||
Reference in New Issue
Block a user