CAS Proxy SDK git checkin as per g3doc.

Adds support for specifying service type when creating a service certificate.

A recent change to the SDK allows for service certificates (DrmCertificate) to also specify a ServiceType indicating which type of service they are supposed to be used on.  This CL adds certificate creation service support for this.

-------------
Fix typo in cas proxy SDK.

-------------
Migrate C++ proto_library rules to cc_proto_library.

We update dependency edges of cc_* rules on proto_library() rules to use a cc_proto_library() intermediary in preparation for eliminating proto_library()'s cc support as per []

More information: []

Tested:
    TAP --sample for global presubmit queue
    []

-------------
Migrate cc proto_library to cc_proto_library. Also fixes build break introduced by []

-------------
Remove unnecessary #MOE directives

-------------
[Proxy_SDK] Move generateSignature in WvPLSDKEnvironment to signature_util.cc file.

-------------
[SDK]Add service_certificate type check in WVPL LSDK and PROXY SDK.

-------------
[Proxy_SDK] Add new API to get remote_attestation_cert_serial_number for proxy SDK.

-------------
[Proxy_SDK] Add getDrmDeviceId function

-------------
[Proxy_SDK] add getrequesttype function for proxy sdk

-------------
[SDK] Add videoFeature field to WvPLWidevinePsshData in WvPLWidevine.java and wvpl_type.h. Related to []

-------------
Allow specified devices to request licenses even if these devices are in TEST_ONLY state.
This will also override the global setting of TEST_ONLY devices not being allowed to
successfully receive licenses from Widevine License SDK.

-------------
[Proxy_SDK] Add ParseDCSL function and test case.

-------------
[Proxy_SDK] Return non-ok status for service_certificate_request when create proxy sdk session. Add test case in Java test.

-------------
[Proxy_SDK] Add video_feature parsing in GetPsshData function. Also check video_feature when geneateModularDrmLicenseRequest.

-------------
[SDK]Deprecated message_type() function, use request_type() instead.

-------------
Use JDK instead of JRE

The concept of a JRE is going away in JDK 11. The jre/ subdirectory in the JDK will no longer exist and the :jre targets will no longer make sense.

Currently in JDK 8, the JDK is a superset of the JRE (it contains all of the files in the JRE), so this is a safe change.

Tested:
    TAP found no affected targets
    []

-------------
Renaming WvPLSDKSession.request_type() API.
Added LICENSE_TYPE_UNSPECIFIED enumeration to WvPLLicenseType.

-------------
Additional VLOG messaging for licensing with TEST_ONLY devices.

-------------
Remove forward declarations of absl names. The style guide bans this, and those names are not for external users to redeclare. External users should include the public headers instead.

-------------
Change Kokoro to use latest bazel version

-------------
Update the abseil build to the December 18 release.

This fixes a problem where the MOE build is failing because there was no definition for node_hash_map.

-------------
[CAS_Proxy]Add WvPLCASProxyEnvironmentJNI.cc and com_google_video_widevine_sdk_wvpl_WvPLCASProxyEnvironment.h file to implement JNI layer for WvPLCASProxyEnvironment.

-------------
Apply changes to sdk to match device certificate status list updates.

Cleans up some of the protos we're using for the new SignedDeviceInfo. Also, adjusts the sdk implementation to reflect the proto and service changes.

-------------
[CAS_PROXY]Add WvPLCASProxyEnvironment.java, WvPLCASProxySession.java and WvPLCASProxyTest.java file.

-------------
Add API to return the DRM service certificate by provider.

-------------
[CAS_PROXY]Implement SetDrmServiceCertificate and SetDeviceCertificateStatusList JNI layer.

-------------
Get DeviceInfo from request.

-------------
CAS Proxy SDK updated to 1.1.5.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=248640225
This commit is contained in:
Ramji Chandramouli
2019-05-16 18:14:58 -07:00
parent 74b7f405c8
commit be0bb27305
44 changed files with 1496 additions and 577 deletions

View File

@@ -36,11 +36,14 @@ cc_library(
deps = [
":sdk",
"//base",
"//external:protobuf",
"//strings",
"@abseil_repo//absl/strings",
"@abseil_repo//absl/synchronization",
"//util/endian",
"//util/gtl:map_util",
"//util/random:global_id",
"//util:error_space",
"//common:aes_cbc_util",
"//common:client_cert",
"//common:crypto_util",
@@ -56,12 +59,14 @@ cc_library(
"//common:status",
"//common:verified_media_pipeline",
"//common:vmp_checker",
"//protos/public:client_identification_proto",
"//protos/public:errors_proto",
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:provisioned_device_info_proto",
"//protos/public:widevine_pssh_proto",
"//protos/public:oem_key_container_cc_proto",
"//protos/public:client_identification_cc_proto",
"//protos/public:device_certificate_status_cc_proto",
"//protos/public:errors_cc_proto",
"//protos/public:license_protocol_cc_proto",
"//protos/public:license_server_sdk_cc_proto",
"//protos/public:provisioned_device_info_cc_proto",
"//protos/public:widevine_pssh_cc_proto",
],
)
@@ -88,11 +93,11 @@ cc_library(
"//common:drm_service_certificate",
"//common:error_space",
"//common:status",
"//protos/public:client_identification_proto",
"//protos/public:errors_proto",
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:widevine_pssh_proto",
"//protos/public:client_identification_cc_proto",
"//protos/public:errors_cc_proto",
"//protos/public:license_protocol_cc_proto",
"//protos/public:license_server_sdk_cc_proto",
"//protos/public:widevine_pssh_cc_proto",
],
)
@@ -122,16 +127,17 @@ cc_test(
"//common:signing_key_util",
"//common:test_drm_certificates",
"//common:test_utils",
"//protos/public:client_identification_proto",
"//protos/public:device_certificate_status_proto",
"//protos/public:drm_certificate_proto",
"//protos/public:errors_proto",
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:provisioned_device_info_proto",
"//protos/public:remote_attestation_proto",
"//protos/public:signed_drm_certificate_proto",
"//protos/public:widevine_pssh_proto",
"//protos/public:client_identification_cc_proto",
"//protos/public:device_certificate_status_cc_proto",
"//protos/public:drm_certificate_cc_proto",
"//protos/public:errors_cc_proto",
"//protos/public:license_protocol_cc_proto",
"//protos/public:license_server_sdk_cc_proto",
"//protos/public:provisioned_device_info_cc_proto",
"//protos/public:remote_attestation_cc_proto",
"//protos/public:signed_device_info_cc_proto",
"//protos/public:signed_drm_certificate_cc_proto",
"//protos/public:widevine_pssh_cc_proto",
],
)
@@ -145,8 +151,8 @@ cc_test(
"//base",
"//testing:gunit_main",
"@abseil_repo//absl/strings",
"//protos/public:license_protocol_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:license_protocol_cc_proto",
"//protos/public:license_server_sdk_cc_proto",
],
)
@@ -160,7 +166,7 @@ cc_test(
"//testing:gunit_main",
"//util/endian",
"//common:error_space",
"//protos/public:errors_proto",
"//protos/public:license_server_sdk_proto",
"//protos/public:errors_cc_proto",
"//protos/public:license_server_sdk_cc_proto",
],
)

View File

@@ -28,6 +28,7 @@ bool GenerateErrorResponse(const Status& create_session_status,
std::string* license_response) {
DCHECK(license_response);
const std::string empty_provider = "";
LicenseError error_proto;
if (create_session_status.error_space() == error_space) {
switch (create_session_status.error_code()) {
@@ -45,15 +46,8 @@ bool GenerateErrorResponse(const Status& create_session_status,
error_proto.set_error_code(LicenseError::SERVICE_UNAVAILABLE);
break;
case SERVICE_CERTIFICATE_REQUEST_MESSAGE: {
SignedMessage signed_message;
signed_message.set_type(SignedMessage::SERVICE_CERTIFICATE);
signed_message.set_msg(
DrmServiceCertificate::GetDefaultDrmServiceCertificateOrDie()
->certificate());
if (!signed_message.SerializeToString(license_response)) {
return false;
}
return true;
return GenerateServiceCertificateResponse(empty_provider,
license_response);
}
default:
break;
@@ -84,4 +78,27 @@ bool GenerateErrorResponse(const Status& create_session_status,
}
return true;
}
bool GenerateServiceCertificateResponse(const std::string& provider,
std::string* license_response) {
DCHECK(license_response);
SignedMessage signed_message;
signed_message.set_type(SignedMessage::SERVICE_CERTIFICATE);
const DrmServiceCertificate* drm_cert;
if (provider.empty()) {
drm_cert = DrmServiceCertificate::GetDefaultDrmServiceCertificate();
} else {
drm_cert =
DrmServiceCertificate::GetDrmServiceCertificateByProvider(provider);
}
if (drm_cert == nullptr) {
return false;
}
signed_message.set_msg(drm_cert->certificate());
if (!signed_message.SerializeToString(license_response)) {
return false;
}
return true;
}
} // namespace widevine

View File

@@ -22,5 +22,12 @@ namespace widevine {
// there is an error license to be sent to the client, or false otherwise.
// Example usage in the Session::Create comments above.
bool GenerateErrorResponse(const Status& status, std::string* license_response);
// Generates a SignedMessage containing a service certifcate for the specified
// |provider|. Returns false if |provider| does not exist. Returns the default
// service certificate if |provider| is empty.
bool GenerateServiceCertificateResponse(const std::string& provider,
std::string* license_response);
} // namespace widevine
#endif // LICENSE_SERVER_SDK_INTERNAL_GENERATE_ERROR_RESPONSE_H_

View File

@@ -78,6 +78,7 @@ bool Generate(
}
switch (key_container.type()) {
case License::KeyContainer::CONTENT:
case License::KeyContainer::OEM_CONTENT:
case License::KeyContainer::ENTITLEMENT: {
if (key_container.has_required_protection() &&
key_container.required_protection().has_cgms_flags()) {

View File

@@ -14,6 +14,7 @@
#include <list>
#include <memory>
#include <string>
#include <utility>
#include "glog/logging.h"
#include "base/timestamp.h"
@@ -24,6 +25,7 @@
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "util/endian/endian.h"
#include "util/gtl/map_util.h"
#include "util/random/global_id.h"
#include "common/aes_cbc_util.h"
#include "common/client_cert.h"
@@ -43,9 +45,12 @@
#include "license_server_sdk/internal/key_control_block.h"
#include "license_server_sdk/internal/parse_content_id.h"
#include "license_server_sdk/internal/session_usage_report.h"
#include "protos/public/device_certificate_status.pb.h"
#include "protos/public/errors.pb.h"
#include "protos/public/widevine_pssh.pb.h"
using ::widevine::SignedDeviceCertificateStatusList;
namespace widevine {
// TODO(user): These constants are also defined in public/session.cc. Fix the
@@ -92,13 +97,24 @@ void SessionImpl::SetPreProvisioningKeys(
}
Status SessionImpl::SetCertificateStatusList(
const DrmRootCertificate* root_cert, const std::string& certificate_status_list,
const DrmRootCertificate* root_cert,
const std::string& serialized_signed_certificate_status_list,
uint32_t expiration_period_seconds, bool allow_unknown_devices) {
CHECK(root_cert);
// TODO(user): Refactor to enable SignedDeviceInfo response. This
// assumes a SignedDeviceCertificateStatusList request.
SignedDeviceCertificateStatusList signed_certificate_status_list;
if (!signed_certificate_status_list.ParseFromString(
serialized_signed_certificate_status_list)) {
return Status(error_space, INVALID_CERTIFICATE_STATUS_LIST,
"signed-certificate-status-list-parse-error");
}
Status status = DeviceStatusList::Instance()->UpdateStatusList(
root_cert->public_key(), certificate_status_list,
expiration_period_seconds);
root_cert->public_key(),
signed_certificate_status_list.certificate_status_list(),
signed_certificate_status_list.signature(), expiration_period_seconds);
if (!status.ok()) {
return status;
}
@@ -131,6 +147,10 @@ void SessionImpl::AllowDevelopmentClients(bool enable) {
VmpChecker::Instance()->set_allow_development_vmp(enable);
}
void SessionImpl::AllowTestOnlyDevices(const std::string& device_list) {
DeviceStatusList::Instance()->AllowTestOnlyDevices(device_list);
}
void SessionImpl::AllowRevokedDevices(const std::string& system_id_list) {
DeviceStatusList::Instance()->AllowRevokedDevices(system_id_list);
}
@@ -782,26 +802,40 @@ Status SessionImpl::GenerateSignedLicense(
return status;
}
}
std::string wrapping_key;
if (key_container && !key_container->empty()) {
if (!client_cert_.get()) {
status = Status(error_space, MISSING_CLIENT_CERT, "");
return status;
}
if (client_cert_) {
wrapping_key = DeriveKey(client_cert_->key(), kWrappingKeyLabel,
license_request_->protocol_version() < VERSION_2_2
? signed_message_->msg()
: Sha512_Hash(signed_message_->msg()),
kWrappingKeySizeBits);
}
std::map<std::string, std::string> oem_content_key_map;
if ((key_container && !key_container->empty()) ||
oem_key_container_ != nullptr) {
if (!client_cert_) {
status = Status(error_space, MISSING_CLIENT_CERT, "");
return status;
}
if (wrapping_key.empty()) {
status = Status(error_space, MISSING_ENCRYPTION_KEY, "");
return status;
}
for (std::list<License::KeyContainer>::const_iterator iter =
key_container->begin();
iter != key_container->end(); iter++) {
*license.add_key() = *iter;
if (oem_key_container_ == nullptr) {
for (std::list<License::KeyContainer>::const_iterator iter =
key_container->begin();
iter != key_container->end(); iter++) {
*license.add_key() = *iter;
}
} else {
for (auto oem_key : *oem_key_container_) {
*license.add_key() = oem_key.key();
if (oem_key.key().type() == License::KeyContainer::OEM_CONTENT &&
!oem_key.wrapping_key().empty()) {
oem_content_key_map.insert(
std::make_pair(oem_key.key().id(), oem_key.wrapping_key()));
}
}
}
}
std::string provider_client_token =
@@ -880,12 +914,20 @@ Status SessionImpl::GenerateSignedLicense(
// key. Key control blocks for renewals (type = KEY_CONTROL) are not
// encrypted.
kcb.set_iv(Random16Bytes());
std::string kcb_encryption_key; // key used to encrypt the KCB.
status = GetOemEncryptionKeyForKCB(oem_content_key_map, license.key(i),
&kcb_encryption_key);
if (!status.ok()) {
LOG(WARNING) << "Could not find KCB Encryption key: Status = "
<< status;
return status;
}
kcb.set_key_control_block(
license_request_->protocol_version() < VERSION_2_2
? crypto_util::EncryptAesCbc(license.key(i).key().substr(0, 16),
? crypto_util::EncryptAesCbc(kcb_encryption_key.substr(0, 16),
kcb.iv(), kcb.key_control_block())
: crypto_util::EncryptAesCbcNoPad(
license.key(i).key().substr(0, 16), kcb.iv(),
kcb_encryption_key.substr(0, 16), kcb.iv(),
kcb.key_control_block()));
}
}
@@ -905,6 +947,7 @@ Status SessionImpl::GenerateSignedLicense(
}
}
license.mutable_key(i)->set_iv(Random16Bytes());
// Encrypt specified CONTENT key or ENTITLEMENT or OEM_CONTENT key.
license.mutable_key(i)->set_key(
license_request_->protocol_version() < VERSION_2_2
? crypto_util::EncryptAesCbc(wrapping_key, license.key(i).iv(),
@@ -916,9 +959,22 @@ Status SessionImpl::GenerateSignedLicense(
}
}
}
if (!oem_content_key_map.empty()) {
oem_content_key_map.clear();
}
if (platform_verification_status_ != PLATFORM_NO_VERIFICATION) {
license.set_platform_verification_status(platform_verification_status_);
if (platform_verification_status_ == PLATFORM_HARDWARE_VERIFIED) {
// In the cases where the 'Platform' has already been verified at the
// proxy, it may make more sense to have the 'Remote Attestation' status
// to be sent from the proxy as part of the license request. However,
// since b/65054419 intends to do away with 'Remote Attestation'
// altogether, it is preferred not to add any 'Remote Attestation' status
// to the license request that is sent from the proxy
// (ModularDrmLicenseRequest).
remote_attestation_verified_ = true;
}
}
// TODO(b/65054419): Deprecate remote_attestation_verified altogether.
if (remote_attestation_verified_) {
@@ -966,6 +1022,12 @@ bool SessionImpl::GenerateErrorResponse(const Status& status,
return widevine::GenerateErrorResponse(status, signed_message_bytes);
}
bool SessionImpl::GenerateServiceCertificateResponse(
const std::string& provider, std::string* signed_message_bytes) {
return widevine::GenerateServiceCertificateResponse(
provider, signed_message_bytes);
}
std::string SessionImpl::GetSdkVersionString() {
return absl::StrCat(kMajorVersion, ".", kMinorVersion, ".", kRelease);
}
@@ -1156,7 +1218,7 @@ bool SessionImpl::GetClientInfo(ClientIdentification* client_info) const {
}
std::string SessionImpl::GetDrmDeviceServiceId() const {
if (client_cert_.get()) {
if (client_cert_) {
return client_cert_->service_id();
}
return std::string();
@@ -1166,7 +1228,35 @@ Status SessionImpl::GenerateDeviceStatusListRequest(
std::string* signed_device_certificate_status_list_request) {
std::string version = GetSdkVersionString();
return DeviceStatusList::GenerateSignedDeviceCertificateStatusListRequest(
version, signed_device_certificate_status_list_request);
version,
DrmServiceCertificate::GetDefaultDrmServiceCertificateOrDie()
->certificate(),
signed_device_certificate_status_list_request);
}
void SessionImpl::SetKeys(std::list<OemKeyContainer>* oem_key_container) {
oem_key_container_ = oem_key_container;
}
Status SessionImpl::GetOemEncryptionKeyForKCB(
const std::map<std::string, std::string>& oem_keys, const License::KeyContainer& key,
std::string* encryption_key) const {
if (encryption_key == nullptr) {
return Status(error_space, error::INVALID_ARGUMENT,
"encryption key cannot be null");
}
if (key.type() == License::KeyContainer::OEM_CONTENT) {
auto it = oem_keys.find(key.id());
if (it != oem_keys.end()) {
*encryption_key = (*it).second;
} else {
return Status(error_space, ENCRYPT_ERROR,
"Encryption key not found for paired OEM_CONTENT key");
}
} else {
*encryption_key = key.key();
}
return OkStatus();
}
} // namespace widevine

View File

@@ -21,6 +21,7 @@
#include "protos/public/client_identification.pb.h"
#include "protos/public/license_protocol.pb.h"
#include "protos/public/license_server_sdk.pb.h"
#include "protos/public/oem_key_container.pb.h"
#include "protos/public/provisioned_device_info.pb.h"
namespace widevine {
@@ -36,7 +37,7 @@ class SessionUsage;
const uint32_t kMajorVersion = 4;
const uint32_t kMinorVersion = 5;
const uint32_t kRelease = 2;
const uint32_t kRelease = 4;
const uint32_t kMasterSigningKeySizeBytes = 16;
const uint32_t kSigningKeySizeBytes = 64;
@@ -89,12 +90,19 @@ std::string GetProviderClientToken(const SessionInit& session_init,
// &init,
// &cache,
// &signed_license);
// // For renewal, either SessionState may be cached and provided to the call
// // to GenerateSignedLicense. Or if it is not possible to cache the
// // SessionState, then SessionInit must be provided with either
// // |signing_key| or |master_signing_key|, in order to allow the sdk to
// // validate the signature of the renewal request, and to sign the
// // license issued.
// For renewal, either SessionState may be cached and provided to the call
// to GenerateSignedLicense. Or if it is not possible to cache the
// SessionState, then SessionInit must be provided with either
// |signing_key| or |master_signing_key|, in order to allow the sdk to
// validate the signature of the renewal request, and to sign the
// license issued.
// To use the OEM_CONTENT_KEY key type, the API SetKeys(
// std::list<OemKeyContainer>* oem_key_container) must be called prior to the
// GenerateSignedLicense(...) API. Each OemKeyContainer contains a
// 'wrapping key', which will used to 'wrap' the KCB when generating a license.
// Note that when this SetKeys(std::list<OemKeyContainer>* oem_key_container) is
// called, license generation is only for the keys in this |oem_key_container|.
// The keys passed into the |key_container| parameter are ignored.
class SessionImpl {
public:
@@ -134,6 +142,12 @@ class SessionImpl {
// Defaults to false.
static void AllowDevelopmentClients(bool enable);
// Enable delivery of licenses to TEST_ONLY client devices. |device_list| is
// a comma separated list of devices to allow even if the device is in a
// TEST_ONLY state. This list wil be used only if
// AllowDevelopmentClient(false) is in use.
static void AllowTestOnlyDevices(const std::string& device_list);
// Enable delivery of licenses to revoked client devices. |system_id_list| is
// a comma separated list of systems Ids to allow even if the device is in the
// revoked state.
@@ -200,6 +214,12 @@ class SessionImpl {
static bool GenerateErrorResponse(const Status& status,
std::string* signed_message_bytes);
// Generates a SignedMessage containing a service certifcate for the specified
// |provider|. Returns false if |provider| does not exist. Returns the
// default service certificate if |provider| is empty.
static bool GenerateServiceCertificateResponse(const std::string& provider,
std::string* signed_message_bytes);
// DeriveKey uses the NIST 800-108 KDF recommendation, using AES-CMAC PRF.
// NIST 800-108:
// http://csrc.nist.gov/publications/nistpubs/800-108/sp800-108.pdf
@@ -343,6 +363,11 @@ class SessionImpl {
// Level 1 devices are verified by default.
virtual Status VerifyPlatform();
// Sets the list of keys that have been wrapped by associated wrapping keys.
// Each OemKeyContainer contains a "License.KeyContainer" and the associated
// wrapping key.
virtual void SetKeys(std::list<OemKeyContainer>* oem_key_container);
// Extracts the nonce from |request| and populates |key_control_nonce|. Sets
// |key_control_nonce| to true if the nonce is found.
static Status LoadKeyControlNonce(const LicenseRequest& request,
@@ -361,6 +386,12 @@ class SessionImpl {
// Validates the Provider Session Token from |pst_src|.
static Status CheckProviderSessionToken(const std::string& pst_src);
// Return true, if |key| is found in |oem_keys| and |encryption_key| is found.
// This |encryption_key| is used to encrypt the KCB.
Status GetOemEncryptionKeyForKCB(const std::map<std::string, std::string>& oem_keys,
const License::KeyContainer& key,
std::string* encryption_key) const;
std::unique_ptr<SignedMessage> signed_message_;
std::unique_ptr<LicenseRequest> license_request_;
// Client cert object used for all crypto operations.
@@ -374,8 +405,8 @@ class SessionImpl {
uint32_t key_control_nonce_;
std::unique_ptr<ProvisionedDeviceInfo> provisioned_device_info_;
std::string remote_attestation_cert_serial_number_;
std::list<OemKeyContainer>* oem_key_container_ = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(SessionImpl);
};

View File

@@ -49,6 +49,7 @@
#include "protos/public/license_server_sdk.pb.h"
#include "protos/public/provisioned_device_info.pb.h"
#include "protos/public/remote_attestation.pb.h"
#include "protos/public/signed_device_info.pb.h"
#include "protos/public/signed_drm_certificate.pb.h"
#include "protos/public/widevine_pssh.pb.h"
@@ -56,7 +57,7 @@ using google::protobuf::TextFormat;
using testing::Eq;
using testing::Return;
using widevine::DeviceCertificateStatusListRequest;
using widevine::SignedDeviceCertificateStatusListRequest;
using widevine::SignedDeviceInfoRequest;
// TODO(user): Add test case for generateSignedLicense.
namespace widevine {
namespace {
@@ -514,6 +515,10 @@ class SessionTest : public ::testing::Test {
license.platform_verification_status());
}
bool remote_attestation_verified(const SessionImpl& session) {
return session.remote_attestation_verified_;
}
void SetupCertificateStatusList(
bool allow_unknown_devices,
SignedDeviceCertificateStatusList* status_list) {
@@ -1375,7 +1380,77 @@ class SessionTest : public ::testing::Test {
ASSERT_TRUE(session.get());
}
void TestKeyControlBlocks(const std::string& request_msg) {
void TestOemContentKeysWithNoWrappingKey(const std::string& request_msg) {
SessionImpl* session_ptr = nullptr;
Status status =
SessionImpl::Create(test_root_.get(), request_msg, &session_ptr);
std::unique_ptr<SessionImpl> session(session_ptr);
ASSERT_EQ(OkStatus(), status);
ASSERT_TRUE(session.get());
std::list<OemKeyContainer> oem_keys;
OemKeyContainer oem_key;
oem_key.mutable_key()->set_key("0123456789abcdef0123456789abcdef");
oem_key.mutable_key()->set_id("oem_content");
oem_key.mutable_key()->set_type(License::KeyContainer::OEM_CONTENT);
oem_keys.push_back(oem_key);
// Specify content key via OemKeyContainer.
oem_key.Clear();
oem_key.mutable_key()->set_id("content");
oem_key.mutable_key()->set_key("fedcba9876543210");
oem_key.mutable_key()->set_type(License::KeyContainer::CONTENT);
oem_keys.push_back(oem_key);
session->SetKeys(&oem_keys);
SessionInit init;
License::Policy policies;
SessionState cache;
std::list<License::KeyContainer> keys;
std::string signed_license_bytes;
status = session->GenerateSignedLicense(&policies, &keys, &init, &cache,
&signed_license_bytes);
EXPECT_EQ(ENCRYPT_ERROR, status.error_code());
}
void TestOemContentKeys(const std::string& request_msg) {
SessionImpl* session_ptr = nullptr;
Status status =
SessionImpl::Create(test_root_.get(), request_msg, &session_ptr);
std::unique_ptr<SessionImpl> session(session_ptr);
ASSERT_EQ(OkStatus(), status);
ASSERT_TRUE(session.get());
std::list<OemKeyContainer> oem_keys;
License::KeyContainer key;
key.set_id("oem_content");
const std::string oem_content_key("0123456789abcdef0123456789abcdef");
key.set_key(oem_content_key);
key.set_type(License::KeyContainer::OEM_CONTENT);
OemKeyContainer oem_key;
oem_key.mutable_key()->CopyFrom(key);
const std::string content_key("0123456789abcdef");
oem_key.set_wrapping_key(content_key);
oem_keys.push_back(oem_key);
// Specify operator key via OemKeyContainer.
key.set_id("operator");
const std::string operator_key("fedcba9876543210");
key.set_key(operator_key);
key.set_type(License::KeyContainer::OPERATOR_SESSION);
oem_key.mutable_key()->CopyFrom(key);
oem_keys.push_back(oem_key);
session->SetKeys(&oem_keys);
SessionInit init;
init.set_purchase_id("Purchases!");
License::Policy policies;
policies.set_can_persist(true);
SessionState cache;
std::list<License::KeyContainer> keys;
std::string signed_license_bytes;
status = session->GenerateSignedLicense(&policies, &keys, &init, &cache,
&signed_license_bytes);
ASSERT_EQ(OkStatus(), status);
}
void TestKeyControlBlocks(const std::string& request_msg,
bool is_oem_key_container) {
SessionImpl* session_ptr = nullptr;
Status status =
SessionImpl::Create(test_root_.get(), request_msg, &session_ptr);
@@ -1403,6 +1478,17 @@ class SessionTest : public ::testing::Test {
key.clear_track_label();
keys.push_back(key);
// CONTENT keys added via OemKeyContainer proto.
if (is_oem_key_container) {
std::list<OemKeyContainer> oem_keys;
for (std::list<License::KeyContainer>::iterator it = keys.begin();
it != keys.end(); ++it) {
OemKeyContainer oem_key;
*oem_key.mutable_key() = *it;
oem_keys.push_back(oem_key);
}
session->SetKeys(&oem_keys);
}
SessionInit init;
init.set_purchase_id("Purchases!");
License::Policy policies;
@@ -1585,6 +1671,14 @@ class SessionTest : public ::testing::Test {
ra->set_salt(salt);
}
Status GetOemEncryptionKeyForKCB(const SessionImpl& session_impl,
const std::map<std::string, std::string>& oem_keys,
const License::KeyContainer& key,
std::string* encryption_key) {
return session_impl.GetOemEncryptionKeyForKCB(oem_keys, key,
encryption_key);
}
protected:
RsaTestKeys test_keys_;
std::unique_ptr<DrmRootCertificate> dev_root_;
@@ -2284,10 +2378,12 @@ TEST_F(SessionTest, NewLicenseWithKeyControlBlock) {
client_capabilities.set_client_token(false);
client_capabilities.set_session_token(false);
client_capabilities.set_anti_rollback_usage_table(false);
TestKeyControlBlocks(GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM));
TestKeyControlBlocks(
GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM),
false);
}
TEST_F(SessionTest, NewLicenseWithKeyControlBlockOffline) {
@@ -2295,10 +2391,12 @@ TEST_F(SessionTest, NewLicenseWithKeyControlBlockOffline) {
client_capabilities.set_client_token(false);
client_capabilities.set_session_token(false);
client_capabilities.set_anti_rollback_usage_table(false);
TestKeyControlBlocks(GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, OFFLINE, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM));
TestKeyControlBlocks(
GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, OFFLINE, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM),
false);
}
TEST_F(SessionTest, NewLicenseWithKeyControlBlockDeprecatedNonce) {
@@ -2306,10 +2404,12 @@ TEST_F(SessionTest, NewLicenseWithKeyControlBlockDeprecatedNonce) {
client_capabilities.set_client_token(false);
client_capabilities.set_session_token(false);
client_capabilities.set_anti_rollback_usage_table(false);
TestKeyControlBlocks(GenerateBasicLicenseRequest(
VERSION_2_1, kDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM));
TestKeyControlBlocks(
GenerateBasicLicenseRequest(
VERSION_2_1, kDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM),
false);
}
TEST_F(SessionTest, NewLicenseWithKeyControlBlockAntiRollback) {
@@ -2317,8 +2417,26 @@ TEST_F(SessionTest, NewLicenseWithKeyControlBlockAntiRollback) {
client_capabilities.set_client_token(false);
client_capabilities.set_session_token(false);
client_capabilities.set_anti_rollback_usage_table(true);
TestKeyControlBlocks(GenerateBasicLicenseRequest(
VERSION_2_1, kDeprecatedNonce, STREAMING, kUseCurrentTime,
TestKeyControlBlocks(
GenerateBasicLicenseRequest(
VERSION_2_1, kDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM),
false);
}
TEST_F(SessionTest, NewLicenseWithKeyControlBlockForOemContentKeys) {
ClientIdentification::ClientCapabilities client_capabilities;
TestOemContentKeys(GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM));
}
TEST_F(SessionTest, NewLicenseWithKeyControlBlockForOemContentKeysError) {
ClientIdentification::ClientCapabilities client_capabilities;
TestOemContentKeysWithNoWrappingKey(GenerateBasicLicenseRequest(
VERSION_2_1, kNoDeprecatedNonce, STREAMING, kUseCurrentTime,
client_capabilities, kIncludeProviderToken,
LicenseRequest::ContentIdentification::InitData::WEBM));
}
@@ -3055,22 +3173,73 @@ TEST_F(SessionTest, BasicRequestResponse_OEMVersion14) {
}
TEST_F(SessionTest, GenerateDeviceStatusListRequest) {
std::string signed_device_certificate_status_list;
std::string serialized_signed_device_info_request;
Status status = session_impl_.GenerateDeviceStatusListRequest(
&signed_device_certificate_status_list);
&serialized_signed_device_info_request);
EXPECT_TRUE(status.ok());
SignedDeviceCertificateStatusListRequest signed_request;
signed_request.ParseFromString(signed_device_certificate_status_list);
std::string device_certificate_status_list =
SignedDeviceInfoRequest signed_request;
signed_request.ParseFromString(serialized_signed_device_info_request);
std::string serialized_device_certificate_status_list_request =
signed_request.device_certificate_status_list_request();
DeviceCertificateStatusListRequest request;
request.ParseFromString(device_certificate_status_list);
request.ParseFromString(serialized_device_certificate_status_list_request);
EXPECT_EQ(request.sdk_version(), SessionImpl::GetSdkVersionString());
EXPECT_EQ(DeviceStatusList::Instance()->GetCurrentTime(),
request.sdk_time_seconds());
}
TEST_F(SessionTest, GetOemEncryptionKeyForKCBForOemContentKeySuccess) {
License::KeyContainer key;
key.set_id("oem_content");
const std::string oem_content_key("0123456789abcdef0123456789abcdef");
key.set_key(oem_content_key);
key.set_type(License::KeyContainer::OEM_CONTENT);
OemKeyContainer oem_key;
oem_key.mutable_key()->CopyFrom(key);
const std::string content_key("0123456789abcdef");
oem_key.set_wrapping_key(content_key);
std::map<std::string, std::string> oem_content_key_map;
// Expect to find the 'wrapping key'.
oem_content_key_map.insert(
std::make_pair(oem_key.key().id(), oem_key.wrapping_key()));
std::string encryption_key;
EXPECT_OK(GetOemEncryptionKeyForKCB(session_impl_, oem_content_key_map, key,
&encryption_key));
EXPECT_EQ(oem_key.wrapping_key(), encryption_key);
}
TEST_F(SessionTest, GetOemEncryptionKeyForKCBForOemContentKeyFailure) {
License::KeyContainer key;
key.set_id("oem_content");
const std::string oem_content_key("0123456789abcdef0123456789abcdef");
key.set_key(oem_content_key);
key.set_type(License::KeyContainer::OEM_CONTENT);
OemKeyContainer oem_key;
oem_key.mutable_key()->CopyFrom(key);
const std::string content_key("0123456789abcdef");
oem_key.set_wrapping_key(content_key);
std::map<std::string, std::string> oem_content_key_map;
std::string encryption_key;
Status status = GetOemEncryptionKeyForKCB(session_impl_, oem_content_key_map,
key, &encryption_key);
EXPECT_EQ(ENCRYPT_ERROR, status.error_code());
}
TEST_F(SessionTest, GetOemEncryptionKeyForKCBForContentKeySuccess) {
License::KeyContainer key;
key.set_id("content");
const std::string content_key("0123456789abcdef0123456789abcdef");
key.set_key(content_key);
key.set_type(License::KeyContainer::CONTENT);
std::map<std::string, std::string> oem_content_key_map;
// Expect to find the 'content key'.
std::string encryption_key;
EXPECT_OK(GetOemEncryptionKeyForKCB(session_impl_, oem_content_key_map, key,
&encryption_key));
EXPECT_EQ(key.key(), encryption_key);
}
INSTANTIATE_TEST_SUITE_P(SessionVmpTests, SessionVmpTest,
::testing::Values(PLATFORM_NO_VERIFICATION,
PLATFORM_UNVERIFIED,