Fix media_cas_proxy_sdk build issue.

Add example binary for testing building the SDK after 'git clone' from our repo.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=227583629
This commit is contained in:
Fang Yu
2019-01-02 14:37:34 -08:00
parent a991e2dbb3
commit 79f14e6e0b
76 changed files with 2072 additions and 1513 deletions

View File

@@ -41,7 +41,6 @@ cc_library(
"@abseil_repo//absl/synchronization",
"//util/endian",
"//util/random:global_id",
"//util:status",
"//common:aes_cbc_util",
"//common:certificate_type",
"//common:client_cert",
@@ -51,9 +50,11 @@ cc_library(
"//common:random_util",
"//common:remote_attestation_verifier",
"//common:drm_root_certificate",
"//common:rsa_key",
"//common:drm_service_certificate",
"//common:rsa_key",
"//common:sha_util",
"//common:signing_key_util",
"//common:status",
"//common:verified_media_pipeline",
"//common:vmp_checker",
"//protos/public:client_identification_proto",
@@ -86,7 +87,6 @@ cc_library(
"//external:openssl",
"//util/endian",
"//util/gtl:map_util",
"//util:status",
"//common:client_cert",
"//common:crypto_util",
"//common:device_status_list",
@@ -96,6 +96,7 @@ cc_library(
"//common:drm_root_certificate",
"//common:drm_service_certificate",
"//common:signing_key_util",
"//common:status",
"//common:wvm_token_handler",
"//sdk/external/common/wvpl:wvpl_types",
"//protos/public:client_identification_proto",
@@ -120,6 +121,7 @@ cc_test(
"//base",
"//external:protobuf",
"//testing:gunit_main",
"@abseil_repo//absl/memory",
"@abseil_repo//absl/strings",
"//common:aes_cbc_util",
"//common:client_cert",
@@ -131,6 +133,7 @@ cc_test(
"//common:rsa_key",
"//common:rsa_test_keys",
"//common:rsa_util",
"//common:sha_util",
"//common:signing_key_util",
"//common:test_drm_certificates",
"//common:test_utils",

View File

@@ -16,7 +16,6 @@
#include "protos/public/errors.pb.h"
#include "protos/public/license_protocol.pb.h"
namespace util = widevine::util;
using widevine::DRM_DEVICE_CERTIFICATE_REVOKED;
using widevine::DrmServiceCertificate;
using widevine::EXPIRED_CERTIFICATE_STATUS_LIST;
@@ -26,7 +25,7 @@ using widevine::SERVICE_CERTIFICATE_REQUEST_MESSAGE;
using widevine::SignedMessage;
namespace widevine {
bool GenerateErrorResponse(const util::Status& create_session_status,
bool GenerateErrorResponse(const Status& create_session_status,
std::string* license_response) {
DCHECK(license_response);
@@ -61,9 +60,8 @@ bool GenerateErrorResponse(const util::Status& create_session_status,
break;
}
}
if ((create_session_status.error_space() ==
util::Status::canonical_space()) &&
(create_session_status.error_code() == util::error::UNAVAILABLE)) {
if ((create_session_status.error_space() == Status::canonical_space()) &&
(create_session_status.error_code() == error::UNAVAILABLE)) {
error_proto.set_error_code(LicenseError::SERVICE_UNAVAILABLE);
}
if (!error_proto.has_error_code()) {

View File

@@ -11,17 +11,16 @@
#include <string>
#include "util/status.h"
#include "common/status.h"
namespace widevine {
// Generates a SignedMessage containing a message generated in response to
// an error condition. |status| is a previous error status returned by the
// Session or util::Status(util::error::UNAVAILABLE, ...) to indicate that the
// Session or Status(error::UNAVAILABLE, ...) to indicate that the
// backend is unavailable, |signed_message| points to a std::string to contain the
// serialized SignedMessage, and may not be NULL. This method returns true if
// 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 util::Status& status,
std::string* license_response);
bool GenerateErrorResponse(const Status& status, std::string* license_response);
} // namespace widevine
#endif // LICENSE_SERVER_SDK_INTERNAL_GENERATE_ERROR_RESPONSE_H_

View File

@@ -37,19 +37,18 @@ void AddKeyIdIfNotFound(const std::string& key_id,
entry->add_key_ids(key_id);
}
util::Status AddWidevinePsshInfo(
const std::string& pssh_data,
ContentInfo::ContentInfoEntry* content_info_entry) {
Status AddWidevinePsshInfo(const std::string& pssh_data,
ContentInfo::ContentInfoEntry* content_info_entry) {
if (pssh_data.empty()) {
return util::Status(error_space, INVALID_WIDEVINE_PSSH_DATA,
"widevine-pssh-data-is-empty");
return Status(error_space, INVALID_WIDEVINE_PSSH_DATA,
"widevine-pssh-data-is-empty");
}
if (!content_info_entry->mutable_pssh()
->mutable_widevine_data()
->ParseFromString(pssh_data)) {
return util::Status(error_space, INVALID_WIDEVINE_PSSH_DATA,
"invalid-widevine-pssh-data");
return Status(error_space, INVALID_WIDEVINE_PSSH_DATA,
"invalid-widevine-pssh-data");
}
content_info_entry->mutable_pssh()->set_system_id(
std::string(kWidevineSystemId, kWidevineSystemId + sizeof(kWidevineSystemId)));
@@ -58,39 +57,37 @@ util::Status AddWidevinePsshInfo(
for (int idx = 0; idx < wv_pssh.key_ids_size(); ++idx)
AddKeyIdIfNotFound(wv_pssh.key_ids(idx), content_info_entry);
return util::OkStatus();
return OkStatus();
}
util::Status ParseCencId(
const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
Status ParseCencId(const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
content_info->set_init_data_type(
LicenseRequest::ContentIdentification::InitData::CENC);
for (int idx = 0; idx < content_id.cenc_id_deprecated().pssh_size(); ++idx) {
util::Status status =
Status status =
AddWidevinePsshInfo(content_id.cenc_id_deprecated().pssh(idx),
content_info->add_content_info_entry());
if (!status.ok()) return status;
}
return util::OkStatus();
return OkStatus();
}
util::Status AddWebmKeyId(const std::string& key_id, ContentInfo* content_info) {
Status AddWebmKeyId(const std::string& key_id, ContentInfo* content_info) {
content_info->set_init_data_type(
LicenseRequest::ContentIdentification::InitData::WEBM);
content_info->add_content_info_entry()->add_key_ids(key_id);
return util::OkStatus();
return OkStatus();
}
util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_info) {
Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_info) {
const uint32_t kPsshType = 0x70737368;
const size_t kPsshSystemIdSize = 16;
const size_t kKeyIdSize = 16;
const size_t kMinPsshSize = kPsshSystemIdSize + 8;
if (boxes.empty()) {
return util::Status(error_space, INVALID_CENC_INIT_DATA,
"init-data-is-empty");
return Status(error_space, INVALID_CENC_INIT_DATA, "init-data-is-empty");
}
const char* r_ptr = boxes.data();
@@ -100,8 +97,7 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
ContentInfo::ContentInfoEntry content_info_entry;
if (r_ptr + 8 > end_ptr)
return util::Status(error_space, INVALID_CENC_INIT_DATA,
"init-data-too-short");
return Status(error_space, INVALID_CENC_INIT_DATA, "init-data-too-short");
const char* box_start = r_ptr;
uint64_t box_size = BigEndian::Load32(r_ptr);
@@ -111,8 +107,8 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
if (box_size == 1) {
if (r_ptr + 8 > end_ptr) {
return util::Status(error_space, INVALID_CENC_INIT_DATA,
"init-data-too-short");
return Status(error_space, INVALID_CENC_INIT_DATA,
"init-data-too-short");
}
box_size = BigEndian::Load64(r_ptr);
r_ptr += 8;
@@ -120,12 +116,10 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
const char* box_end = box_start + box_size;
if (box_end > end_ptr) {
return util::Status(error_space, INVALID_CENC_INIT_DATA,
"init-data-too-short");
return Status(error_space, INVALID_CENC_INIT_DATA, "init-data-too-short");
}
if (box_end < r_ptr) {
return util::Status(error_space, INVALID_CENC_INIT_DATA,
"invalid-box-size");
return Status(error_space, INVALID_CENC_INIT_DATA, "invalid-box-size");
}
if (box_type != kPsshType) {
@@ -134,15 +128,15 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
}
if (r_ptr + kMinPsshSize > box_end)
return util::Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
const uint32_t version_and_flags = BigEndian::Load32(r_ptr);
r_ptr += 4;
const uint8_t version = static_cast<uint8_t>(version_and_flags >> 24);
if (version > 1) {
return util::Status(error_space, UNSUPPORTED_PSSH_VERSION,
absl::StrCat("unsupported-pssh-version ", version));
return Status(error_space, UNSUPPORTED_PSSH_VERSION,
absl::StrCat("unsupported-pssh-version ", version));
}
content_info_entry.mutable_pssh()->set_system_id(
@@ -153,16 +147,14 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
if (version == 1) {
if (r_ptr + 4 > box_end) {
return util::Status(error_space, INVALID_PSSH,
"pssh-contents-too-short");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
}
const uint32_t num_key_ids = BigEndian::Load32(r_ptr);
r_ptr += 4;
if (r_ptr + (num_key_ids * kKeyIdSize) > box_end) {
return util::Status(error_space, INVALID_PSSH,
"pssh-contents-too-short");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
}
for (uint32_t idx = 0; idx < num_key_ids; ++idx) {
@@ -173,18 +165,18 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
}
if (r_ptr + 4 > box_end)
return util::Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
uint32_t data_size = BigEndian::Load32(r_ptr);
r_ptr += 4;
if (r_ptr + data_size > box_end)
return util::Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-short");
if (r_ptr + data_size < box_end)
return util::Status(error_space, INVALID_PSSH, "pssh-contents-too-long");
return Status(error_space, INVALID_PSSH, "pssh-contents-too-long");
if (is_widevine_pssh) {
util::Status status = AddWidevinePsshInfo(
std::string(r_ptr, r_ptr + data_size), &content_info_entry);
Status status = AddWidevinePsshInfo(std::string(r_ptr, r_ptr + data_size),
&content_info_entry);
if (!status.ok()) return status;
} else {
content_info_entry.mutable_pssh()->set_raw_data(
@@ -195,14 +187,13 @@ util::Status ParseIsoBmffBoxes(const std::string& boxes, ContentInfo* content_in
*content_info->add_content_info_entry() = content_info_entry;
}
return util::OkStatus();
return OkStatus();
}
util::Status ParseInitData(
const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
Status ParseInitData(const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
if (!content_id.init_data().has_init_data())
return util::Status(error_space, MISSING_INIT_DATA, "missing-init-data");
return Status(error_space, MISSING_INIT_DATA, "missing-init-data");
if (content_id.init_data().init_data_type() ==
LicenseRequest::ContentIdentification::InitData::CENC) {
@@ -212,15 +203,13 @@ util::Status ParseInitData(
LicenseRequest::ContentIdentification::InitData::WEBM) {
return AddWebmKeyId(content_id.init_data().init_data(), content_info);
}
return util::Status(error_space, UNKNOWN_INIT_DATA_TYPE,
"unknown-init-data-type");
return Status(error_space, UNKNOWN_INIT_DATA_TYPE, "unknown-init-data-type");
}
} // namespace
util::Status ParseContentId(
const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
Status ParseContentId(const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info) {
DCHECK(content_info);
content_info->Clear();
@@ -235,8 +224,8 @@ util::Status ParseContentId(
default:
break;
}
return util::Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
return Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
}
} // namespace widevine

View File

@@ -9,7 +9,7 @@
#ifndef LICENSE_SERVER_SDK_INTERNAL_PARSE_CONTENT_ID_H__
#define LICENSE_SERVER_SDK_INTERNAL_PARSE_CONTENT_ID_H__
#include "util/status.h"
#include "common/status.h"
#include "protos/public/license_protocol.pb.h"
namespace widevine {
@@ -20,9 +20,8 @@ class ContentInfo;
// the ContentInfo message passed into |content_info|. This function deep parses
// PSSH boxes and the Widevine PSSH Data. |content_info| may not be NULL and the
// caller retains ownership.
util::Status ParseContentId(
const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info);
Status ParseContentId(const LicenseRequest::ContentIdentification& content_id,
ContentInfo* content_info);
} // namespace widevine

View File

@@ -107,7 +107,7 @@ void MakeInitDataWebmContentId(
void VerifyWebmContentId(
const LicenseRequest::ContentIdentification& content_id) {
ContentInfo content_info;
ASSERT_EQ(util::OkStatus(), ParseContentId(content_id, &content_info));
ASSERT_EQ(OkStatus(), ParseContentId(content_id, &content_info));
ASSERT_EQ(LicenseRequest::ContentIdentification::InitData::WEBM,
content_info.init_data_type());
ASSERT_EQ(1, content_info.content_info_entry_size());
@@ -140,7 +140,7 @@ void MakeExistingLicenseContentId(
void VerifyCencContentId(
const LicenseRequest::ContentIdentification& content_id) {
ContentInfo content_info;
ASSERT_EQ(util::OkStatus(), ParseContentId(content_id, &content_info));
ASSERT_EQ(OkStatus(), ParseContentId(content_id, &content_info));
ASSERT_EQ(LicenseRequest::ContentIdentification::InitData::CENC,
content_info.init_data_type());
ASSERT_EQ(1, content_info.content_info_entry_size());
@@ -194,7 +194,7 @@ TEST(ParseContentIdTest, PsshV1) {
MakeInitDataCencContentId(std::string(kWvPsshV1, kWvPsshV1 + sizeof(kWvPsshV1)),
&content_id);
ContentInfo content_info;
EXPECT_EQ(util::OkStatus(), ParseContentId(content_id, &content_info));
EXPECT_EQ(OkStatus(), ParseContentId(content_id, &content_info));
EXPECT_EQ(LicenseRequest::ContentIdentification::InitData::CENC,
content_info.init_data_type());
ASSERT_EQ(1, content_info.content_info_entry_size());
@@ -210,9 +210,9 @@ TEST(ParseContentIdTest, ExistingLicense) {
LicenseRequest::ContentIdentification content_id;
ContentInfo content_info;
MakeExistingLicenseContentId(&content_id);
EXPECT_EQ(util::Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type"),
ParseContentId(content_id, &content_info));
EXPECT_EQ(
Status(error_space, INVALID_CONTENT_ID_TYPE, "invalid-content-id-type"),
ParseContentId(content_id, &content_info));
}
TEST(ParseContentIdTest, MultipleBoxes) {
@@ -227,7 +227,7 @@ TEST(ParseContentIdTest, MultipleBoxes) {
std::string(kNonPsshBox, kNonPsshBox + sizeof(kNonPsshBox)),
&content_id);
ContentInfo content_info;
EXPECT_EQ(util::OkStatus(), ParseContentId(content_id, &content_info));
EXPECT_EQ(OkStatus(), ParseContentId(content_id, &content_info));
EXPECT_EQ(LicenseRequest::ContentIdentification::InitData::CENC,
content_info.init_data_type());
EXPECT_EQ(3, content_info.content_info_entry_size());

View File

@@ -35,6 +35,7 @@
#include "common/random_util.h"
#include "common/remote_attestation_verifier.h"
#include "common/rsa_key.h"
#include "common/sha_util.h"
#include "common/signing_key_util.h"
#include "common/verified_media_pipeline.h"
#include "common/vmp_checker.h"
@@ -49,8 +50,8 @@ namespace widevine {
// TODO(user): These constants are also defined in public/session.cc. Fix the
// duplicate definitions.
const char* SessionImpl::kEncryptionKeyLabel = "ENCRYPTION";
const uint32_t SessionImpl::kEncryptionKeySizeBits = 128;
const char* SessionImpl::kWrappingKeyLabel = "ENCRYPTION";
const uint32_t SessionImpl::kWrappingKeySizeBits = 128;
const char* SessionImpl::kSigningKeyLabel = "AUTHENTICATION";
const uint32_t SessionImpl::kSigningKeySizeBits = 256;
bool SessionImpl::is_service_certificate_loaded_ = false;
@@ -90,12 +91,12 @@ void SessionImpl::SetPreProvisioningKeys(
KeyboxClientCert::SetPreProvisioningKeys(keys);
}
util::Status SessionImpl::SetCertificateStatusList(
Status SessionImpl::SetCertificateStatusList(
const DrmRootCertificate* root_cert, const std::string& certificate_status_list,
uint32_t expiration_period_seconds, bool allow_unknown_devices) {
CHECK(root_cert);
util::Status status = DeviceStatusList::Instance()->UpdateStatusList(
Status status = DeviceStatusList::Instance()->UpdateStatusList(
root_cert->public_key(), certificate_status_list,
expiration_period_seconds);
if (!status.ok()) {
@@ -104,16 +105,16 @@ util::Status SessionImpl::SetCertificateStatusList(
DeviceStatusList::Instance()->set_allow_unknown_devices(
allow_unknown_devices);
return util::OkStatus();
return OkStatus();
}
util::Status SessionImpl::AddDrmServiceCertificate(
Status SessionImpl::AddDrmServiceCertificate(
const DrmRootCertificate* root_cert, const std::string& service_certificate,
const std::string& service_private_key,
const std::string& service_private_key_passphrase) {
CHECK(root_cert);
util::Status status = DrmServiceCertificate::AddDrmServiceCertificate(
Status status = DrmServiceCertificate::AddDrmServiceCertificate(
root_cert, service_certificate, service_private_key,
service_private_key_passphrase);
if (!status.ok()) {
@@ -134,24 +135,24 @@ void SessionImpl::AllowRevokedDevices(const std::string& system_id_list) {
DeviceStatusList::Instance()->AllowRevokedDevices(system_id_list);
}
util::Status SessionImpl::Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session) {
Status SessionImpl::Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session) {
if (!is_service_certificate_loaded_) {
return util::Status(error_space, SERVICE_CERTIFICATE_NOT_FOUND, "");
return Status(error_space, SERVICE_CERTIFICATE_NOT_FOUND, "");
}
return SessionImpl::Create(root_cert, signed_license_request, session,
nullptr);
}
util::Status SessionImpl::Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session,
LicenseRequest* parsed_request_out) {
Status SessionImpl::Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session,
LicenseRequest* parsed_request_out) {
CHECK(root_cert);
DCHECK(session);
util::Status status;
Status status;
LicenseRequest* request_ptr = new LicenseRequest();
SignedMessage* signed_message_ptr = new SignedMessage();
@@ -168,7 +169,7 @@ util::Status SessionImpl::Create(const DrmRootCertificate* root_cert,
}
if (request->has_encrypted_client_id()) {
if (request->has_client_id()) {
status = util::Status(error_space, MULTIPLE_CLIENT_ID, "");
status = Status(error_space, MULTIPLE_CLIENT_ID, "");
return status;
}
status = DrmServiceCertificate::DecryptClientIdentification(
@@ -200,12 +201,12 @@ util::Status SessionImpl::Create(const DrmRootCertificate* root_cert,
return status;
}
util::Status SessionImpl::CreateForProxy(
Status SessionImpl::CreateForProxy(
const DrmRootCertificate* root_cert, const std::string& signed_license_request,
const PlatformVerificationStatus platform_verification_status,
const ClientIdentification* client_id, SessionImpl** session,
LicenseRequest* parsed_request_out) {
util::Status status(util::OkStatus());
Status status(OkStatus());
DCHECK(session);
DCHECK(*session == nullptr);
@@ -248,13 +249,13 @@ util::Status SessionImpl::CreateForProxy(
return status;
}
util::Status SessionImpl::LoadKeyControlNonce(const LicenseRequest& request,
bool* has_key_control_nonce,
uint32_t* key_control_nonce) {
Status SessionImpl::LoadKeyControlNonce(const LicenseRequest& request,
bool* has_key_control_nonce,
uint32_t* key_control_nonce) {
DCHECK(has_key_control_nonce);
DCHECK(key_control_nonce);
util::Status status;
Status status;
*has_key_control_nonce = false;
if (request.has_key_control_nonce()) {
// Newer type uint32_t nonce.
@@ -269,39 +270,38 @@ util::Status SessionImpl::LoadKeyControlNonce(const LicenseRequest& request,
kc_nonce_string.resize(nul_pos);
}
if (!absl::SimpleAtoi(kc_nonce_string, key_control_nonce)) {
return util::Status(error_space, INVALID_KEY_CONTROL_NONCE,
request.key_control_nonce_deprecated());
return Status(error_space, INVALID_KEY_CONTROL_NONCE,
request.key_control_nonce_deprecated());
}
*has_key_control_nonce = true;
}
return util::OkStatus();
return OkStatus();
}
util::Status SessionImpl::CheckLicenseRequestFields(
const LicenseRequest& request) {
Status SessionImpl::CheckLicenseRequestFields(const LicenseRequest& request) {
if (request.type() == LicenseRequest::NEW) {
if (!request.has_client_id()) {
return util::Status(error_space, MISSING_CLIENT_ID,
"new-license-missing-client-id");
return Status(error_space, MISSING_CLIENT_ID,
"new-license-missing-client-id");
}
} else {
if (!request.has_content_id()) {
return util::Status(error_space, MISSING_CONTENT_ID,
"renew-release-license-missing-content-id");
return Status(error_space, MISSING_CONTENT_ID,
"renew-release-license-missing-content-id");
}
if (!request.content_id().has_existing_license()) {
return util::Status(error_space, MISSING_LICENSE_ID,
"renew-release-license-missing-existing-license");
return Status(error_space, MISSING_LICENSE_ID,
"renew-release-license-missing-existing-license");
}
if (!request.content_id().existing_license().has_license_id()) {
return util::Status(error_space, MISSING_LICENSE_ID,
"renew-release-license-missing-license-id");
return Status(error_space, MISSING_LICENSE_ID,
"renew-release-license-missing-license-id");
}
}
return util::OkStatus();
return OkStatus();
}
util::Status SessionImpl::ParseLicenseRequestFromString(
Status SessionImpl::ParseLicenseRequestFromString(
const std::string& signed_license_request, SignedMessage* signed_message,
LicenseRequest* license_request) {
DCHECK(signed_message);
@@ -309,21 +309,20 @@ util::Status SessionImpl::ParseLicenseRequestFromString(
// Deserialize the signed message
if (!signed_message->ParseFromString(signed_license_request)) {
return util::Status(error_space, SIGNED_MESSAGE_PARSE_ERROR, "");
return Status(error_space, SIGNED_MESSAGE_PARSE_ERROR, "");
}
if (signed_message->type() == SignedMessage::SERVICE_CERTIFICATE_REQUEST) {
return util::Status(error_space, SERVICE_CERTIFICATE_REQUEST_MESSAGE,
std::string());
return Status(error_space, SERVICE_CERTIFICATE_REQUEST_MESSAGE, std::string());
}
if (signed_message->type() != SignedMessage::LICENSE_REQUEST &&
signed_message->type() != SignedMessage::CAS_LICENSE_REQUEST) {
return util::Status(error_space, INVALID_MESSAGE_TYPE, std::string());
return Status(error_space, INVALID_MESSAGE_TYPE, std::string());
}
if (!license_request->ParseFromString(signed_message->msg())) {
return util::Status(error_space, LICENSE_REQUEST_PARSE_ERROR, "");
return Status(error_space, LICENSE_REQUEST_PARSE_ERROR, "");
}
return util::OkStatus();
return OkStatus();
}
std::string SessionImpl::DeriveKey(const std::string& key, const std::string& label,
@@ -347,12 +346,12 @@ SessionImpl::SessionImpl(SignedMessage* message, LicenseRequest* request,
SessionImpl::~SessionImpl() {}
util::Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
if (license_request_->has_client_id()) {
// Check the client token and verify the message signature.
ClientCert* client_cert_ptr = NULL;
util::Status status = ClientCert::Create(
Status status = ClientCert::Create(
root_cert, license_request_->client_id().type(),
license_request_->client_id().token(), &client_cert_ptr);
client_cert_.reset(client_cert_ptr);
@@ -365,8 +364,8 @@ util::Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
if (!client_cert_->service_id().empty() &&
DrmServiceCertificate::GetDefaultDrmServiceCertificateOrDie()
->provider_id() == client_cert_->service_id()) {
status = util::Status(error_space, PROVIDER_ID_MISMATCH,
"client-cert-service-cert-id-mismatch");
status = Status(error_space, PROVIDER_ID_MISMATCH,
"client-cert-service-cert-id-mismatch");
return status;
}
provisioned_device_info_.reset(new ProvisionedDeviceInfo);
@@ -381,7 +380,7 @@ util::Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
// Generate/Derive a new signing key if one does not previously exist.
client_cert_->GenerateSigningKey(signed_message_->msg(),
license_request_->protocol_version());
util::Status status = client_cert_->VerifySignature(
Status status = client_cert_->VerifySignature(
signed_message_->msg(), signed_message_->signature(),
license_request_->protocol_version());
if (!status.ok()) {
@@ -393,7 +392,7 @@ util::Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
// proxy. platform_verification_status_ would either be set at the proxy
// or as result of calling VerifyPlatform().
if (platform_verification_status_ == PLATFORM_NO_VERIFICATION) {
util::Status status = VerifyPlatform();
Status status = VerifyPlatform();
if (!status.ok()) {
LOG(ERROR) << "Platform verification failed. Status: " << status
<< ", License Request: "
@@ -401,7 +400,7 @@ util::Status SessionImpl::Init(const DrmRootCertificate* root_cert) {
return status;
}
}
return util::OkStatus();
return OkStatus();
}
const std::string& SessionImpl::GetSessionId() {
@@ -428,75 +427,76 @@ bool SessionImpl::GetProvisionedDeviceInfo(
return false;
}
util::Status SessionImpl::GetRequestId(std::string* request_id) const {
Status SessionImpl::GetRequestId(std::string* request_id) const {
DCHECK(request_id);
DCHECK(license_request_);
if (!license_request_->has_content_id())
return util::Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
return Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
const LicenseRequest::ContentIdentification& content_id =
license_request_->content_id();
if (content_id.has_init_data()) {
*request_id = content_id.init_data().request_id();
return util::OkStatus();
return OkStatus();
}
if (content_id.has_cenc_id_deprecated()) {
*request_id = content_id.cenc_id_deprecated().request_id();
return util::OkStatus();
return OkStatus();
}
if (content_id.has_webm_id_deprecated()) {
*request_id = content_id.webm_id_deprecated().request_id();
return util::OkStatus();
return OkStatus();
}
return util::Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
return Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
}
util::Status SessionImpl::GetLicenseType(LicenseType* license_type) const {
Status SessionImpl::GetLicenseType(LicenseType* license_type) const {
DCHECK(license_type);
if (!license_request_->has_content_id())
return util::Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
return Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
const LicenseRequest::ContentIdentification& content_id =
license_request_->content_id();
if (content_id.has_init_data()) {
*license_type = content_id.init_data().license_type();
return util::OkStatus();
return OkStatus();
}
if (content_id.has_cenc_id_deprecated()) {
*license_type = content_id.cenc_id_deprecated().license_type();
return util::OkStatus();
return OkStatus();
}
if (content_id.has_webm_id_deprecated()) {
*license_type = content_id.webm_id_deprecated().license_type();
return util::OkStatus();
return OkStatus();
}
if (content_id.has_existing_license()) {
*license_type = content_id.existing_license().license_id().type();
return util::OkStatus();
return OkStatus();
}
return util::Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
return Status(error_space, INVALID_CONTENT_ID_TYPE,
"invalid-content-id-type");
}
util::Status SessionImpl::GetContentInfo(ContentInfo* content_info) const {
Status SessionImpl::GetContentInfo(ContentInfo* content_info) const {
DCHECK(content_info);
if (!license_request_->has_content_id())
return util::Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
return Status(error_space, MISSING_CONTENT_ID, "missing-content-id");
return ParseContentId(license_request_->content_id(), content_info);
}
util::Status SessionImpl::GenerateNewLicenseInfo(
const SessionInit* session_init, LicenseIdentification* new_id,
std::string* renewal_signing_key, std::string* signing_key) {
Status SessionImpl::GenerateNewLicenseInfo(const SessionInit* session_init,
LicenseIdentification* new_id,
std::string* renewal_signing_key,
std::string* signing_key) {
DCHECK(new_id);
DCHECK(renewal_signing_key);
DCHECK(signing_key);
std::string request_id;
util::Status status = GetRequestId(&request_id);
Status status = GetRequestId(&request_id);
if (!status.ok()) return status;
new_id->set_request_id(request_id);
@@ -512,7 +512,7 @@ util::Status SessionImpl::GenerateNewLicenseInfo(
// GetSessionID().
if (session_init && session_init->has_session_id()) {
if (!session_id_.empty() && (session_id_ != session_init->session_id())) {
status = util::Status(error_space, SESSION_ID_MISMATCH, "");
status = Status(error_space, SESSION_ID_MISMATCH, "");
} else {
new_id->set_session_id(session_init->session_id());
}
@@ -540,12 +540,12 @@ util::Status SessionImpl::GenerateNewLicenseInfo(
if (!status.ok()) return status;
uint32_t signing_key_material_size_bytes =
SigningKeyMaterialSize(license_request_->protocol_version()) / 8;
SigningKeyMaterialSizeBits(license_request_->protocol_version()) / 8;
if (session_init) {
if (session_init->has_signing_key()) {
if (session_init->signing_key().size() !=
signing_key_material_size_bytes) {
status = util::Status(error_space, INVALID_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_SIGNING_KEY_SIZE, "");
return status;
}
*renewal_signing_key = session_init->signing_key();
@@ -555,35 +555,37 @@ util::Status SessionImpl::GenerateNewLicenseInfo(
} else if (session_init->has_master_signing_key()) {
if (session_init->master_signing_key().size() !=
kMasterSigningKeySizeBytes) {
status =
util::Status(error_space, INVALID_MASTER_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_MASTER_SIGNING_KEY_SIZE, "");
return status;
}
std::string context;
if (new_id->SerializeToString(&context)) {
*renewal_signing_key = DeriveKey(
session_init->master_signing_key(), std::string(kSigningKeyLabel),
context,
SigningKeyMaterialSize(license_request_->protocol_version()));
license_request_->protocol_version() < VERSION_2_2
? context
: Sha512_Hash(context),
SigningKeyMaterialSizeBits(license_request_->protocol_version()));
}
}
}
using crypto_util::kSigningKeySizeBytes;
if (!renewal_signing_key->empty() &&
renewal_signing_key->size() != signing_key_material_size_bytes) {
status = util::Status(error_space, INVALID_RENEWAL_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_RENEWAL_SIGNING_KEY_SIZE, "");
}
new_id->set_version(0);
*signing_key = client_cert_->signing_key();
return status;
}
util::Status SessionImpl::GeneratePriorLicenseInfo(
const SessionInit* session_init, SessionState* session_state,
LicenseIdentification* new_id, std::string* signing_key) {
Status SessionImpl::GeneratePriorLicenseInfo(const SessionInit* session_init,
SessionState* session_state,
LicenseIdentification* new_id,
std::string* signing_key) {
DCHECK(new_id);
DCHECK(signing_key);
util::Status status;
Status status;
if (session_state) {
// If the session_state is provided, we expect to have the previous
// LicenseIdentification to compare against.
@@ -600,7 +602,7 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
!google::protobuf::util::MessageDifferencer::Equals(
license_request_->content_id().existing_license().license_id(),
session_state->license_id())) {
status = util::Status(error_space, RENEWAL_LICENSE_ID_MISMATCH, "");
status = Status(error_space, RENEWAL_LICENSE_ID_MISMATCH, "");
return status;
}
}
@@ -619,18 +621,17 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
} else if (session_init) {
if (session_init->has_signing_key()) {
uint32_t signing_key_material_size_bytes =
SigningKeyMaterialSize(license_request_->protocol_version()) / 8;
SigningKeyMaterialSizeBits(license_request_->protocol_version()) / 8;
if (session_init->signing_key().size() !=
signing_key_material_size_bytes) {
status = util::Status(error_space, INVALID_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_SIGNING_KEY_SIZE, "");
return status;
}
*signing_key = session_init->signing_key();
} else if (session_init->has_master_signing_key()) {
if (session_init->master_signing_key().size() !=
kMasterSigningKeySizeBytes) {
status =
util::Status(error_space, INVALID_MASTER_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_MASTER_SIGNING_KEY_SIZE, "");
return status;
}
LicenseIdentification id;
@@ -641,20 +642,22 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
if (id.SerializeToString(&context)) {
*signing_key = DeriveKey(
session_init->master_signing_key(), std::string(kSigningKeyLabel),
context,
SigningKeyMaterialSize(license_request_->protocol_version()));
license_request_->protocol_version() < VERSION_2_2
? context
: Sha512_Hash(context),
SigningKeyMaterialSizeBits(license_request_->protocol_version()));
}
}
}
if (signing_key->empty()) {
status = util::Status(error_space, MISSING_RENEWAL_SIGNING_KEY, "");
status = Status(error_space, MISSING_RENEWAL_SIGNING_KEY, "");
return status;
}
uint32_t signing_key_material_size_bytes =
SigningKeyMaterialSize(license_request_->protocol_version()) / 8;
SigningKeyMaterialSizeBits(license_request_->protocol_version()) / 8;
if (signing_key->size() < signing_key_material_size_bytes) {
status = util::Status(error_space, INVALID_RENEWAL_SIGNING_KEY_SIZE, "");
status = Status(error_space, INVALID_RENEWAL_SIGNING_KEY_SIZE, "");
return status;
}
signing_key->resize(signing_key_material_size_bytes);
@@ -662,7 +665,7 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
GetClientSigningKey(*signing_key,
license_request_->protocol_version()),
signed_message_->signature(), signed_message_->msg())) {
status = util::Status(error_space, INVALID_RENEWAL_SIGNATURE, "");
status = Status(error_space, INVALID_RENEWAL_SIGNATURE, "");
return status;
}
@@ -676,8 +679,7 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
.existing_license()
.session_usage_table_entry();
if (session_usage.size() <= kSha1SignatureSizeBytes) {
status =
util::Status(error_space, INVALID_SESSION_USAGE_TABLE_ENTRY, "");
status = Status(error_space, INVALID_SESSION_USAGE_TABLE_ENTRY, "");
return status;
}
if (!crypto_util::VerifySignatureHmacSha1(
@@ -685,7 +687,7 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
license_request_->protocol_version()),
session_usage.substr(0, kSha1SignatureSizeBytes),
session_usage.substr(kSha1SignatureSizeBytes))) {
status = util::Status(error_space, INVALID_SESSION_USAGE_SIGNATURE, "");
status = Status(error_space, INVALID_SESSION_USAGE_SIGNATURE, "");
return status;
}
}
@@ -700,8 +702,8 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
system_id = client_cert_->system_id();
}
if (system_id && !DeviceStatusList::Instance()->IsSystemIdActive(system_id)) {
status = util::Status(error_space, UNSUPPORTED_SYSTEM_ID,
"system-id-for-renewal-not-active");
status = Status(error_space, UNSUPPORTED_SYSTEM_ID,
"system-id-for-renewal-not-active");
return status;
}
*new_id = license_request_->content_id().existing_license().license_id();
@@ -709,7 +711,7 @@ util::Status SessionImpl::GeneratePriorLicenseInfo(
return status;
}
util::Status SessionImpl::GenerateSignedLicense(
Status SessionImpl::GenerateSignedLicense(
const License::Policy* policy,
const std::list<License::KeyContainer>* key_container,
const SessionInit* session_init, SessionState* session_state,
@@ -717,14 +719,13 @@ util::Status SessionImpl::GenerateSignedLicense(
DCHECK(signed_message_bytes);
*signed_message_bytes = "";
util::Status status;
Status status;
LicenseIdentification new_id;
std::string signing_key, renewal_signing_key;
if (license_request_->type() != LicenseRequest::NEW) {
if (key_container && !key_container->empty()) {
status = util::Status(error_space,
RENEWAL_WITH_CONTENT_KEYS_NOT_ALLOWED, "");
status = Status(error_space, RENEWAL_WITH_CONTENT_KEYS_NOT_ALLOWED, "");
return status;
}
status = GeneratePriorLicenseInfo(session_init, session_state, &new_id,
@@ -736,7 +737,7 @@ util::Status SessionImpl::GenerateSignedLicense(
if (!status.ok()) return status;
if (signing_key.empty()) {
status = util::Status(error_space, MISSING_SIGNING_KEY, "");
status = Status(error_space, MISSING_SIGNING_KEY, "");
return status;
}
// Build up the license using the information passed in.
@@ -766,33 +767,35 @@ util::Status SessionImpl::GenerateSignedLicense(
VLOG(3) << "Renewal Signing Key before encryption: "
<< absl::BytesToHexString(renewal_signing_key);
} else if (license.policy().can_renew()) {
status =
util::Status(error_space, MISSING_RENEWAL_SIGNING_KEY,
"required for NEW license with can_renew = true.");
status = Status(error_space, MISSING_RENEWAL_SIGNING_KEY,
"required for NEW license with can_renew = true.");
return status;
}
if ((license.id().type() == OFFLINE) && !license.policy().can_persist()) {
status = util::Status(error_space, INVALID_OFFLINE_CAN_PERSIST, "");
status = Status(error_space, INVALID_OFFLINE_CAN_PERSIST, "");
return status;
}
} else if (license_request_->type() == LicenseRequest::RELEASE) {
if (license.has_policy() && license.policy().can_play()) {
// Invalid RELEASE response. can_play should be false.
status = util::Status(error_space, INVALID_RELEASE_CAN_PLAY_VALUE, "");
status = Status(error_space, INVALID_RELEASE_CAN_PLAY_VALUE, "");
return status;
}
}
std::string encryption_key;
std::string wrapping_key;
if (key_container && !key_container->empty()) {
if (!client_cert_.get()) {
status = util::Status(error_space, MISSING_CLIENT_CERT, "");
status = Status(error_space, MISSING_CLIENT_CERT, "");
return status;
}
encryption_key = DeriveKey(client_cert_->key(), std::string(kEncryptionKeyLabel),
signed_message_->msg(), kEncryptionKeySizeBits);
if (encryption_key.empty()) {
status = util::Status(error_space, MISSING_ENCRYPTION_KEY, "");
wrapping_key = DeriveKey(client_cert_->key(), kWrappingKeyLabel,
license_request_->protocol_version() < VERSION_2_2
? signed_message_->msg()
: Sha512_Hash(signed_message_->msg()),
kWrappingKeySizeBits);
if (wrapping_key.empty()) {
status = Status(error_space, MISSING_ENCRYPTION_KEY, "");
return status;
}
for (std::list<License::KeyContainer>::const_iterator iter =
@@ -801,23 +804,22 @@ util::Status SessionImpl::GenerateSignedLicense(
*license.add_key() = *iter;
}
}
std::string provider_client_token =
GetProviderClientToken(*session_init, license_request_->client_id());
if (session_state) {
if (!provider_client_token.empty()) {
session_state->set_provider_client_token(provider_client_token);
} else if (license_request_->client_id().has_provider_client_token()) {
session_state->set_provider_client_token(
license_request_->client_id().provider_client_token());
}
session_state->set_license_counter(
license_request_->client_id().license_counter());
}
if (license_request_->type() == LicenseRequest::NEW) {
std::string provider_client_token =
GetProviderClientToken(*session_init, license_request_->client_id());
if (!provider_client_token.empty()) {
license.set_provider_client_token(provider_client_token);
}
if (session_state) {
if (license.has_provider_client_token()) {
session_state->set_provider_client_token(
license.provider_client_token());
} else if (license_request_->client_id().has_provider_client_token()) {
session_state->set_provider_client_token(
license_request_->client_id().provider_client_token());
}
session_state->set_license_counter(
license_request_->client_id().license_counter());
}
// Put the protection scheme contained in the PSSH into the license.
ContentInfo content_info;
if (ParseContentId(license_request_->content_id(), &content_info).ok()) {
@@ -847,8 +849,8 @@ util::Status SessionImpl::GenerateSignedLicense(
std::unique_ptr<RsaPublicKey> rsa_public_key;
rsa_public_key.reset(RsaPublicKey::Create(client_cert_->public_key()));
if (rsa_public_key == nullptr) {
return util::Status(error_space, INVALID_DRM_CERTIFICATE,
"create-device-public-key-failed");
return Status(error_space, INVALID_DRM_CERTIFICATE,
"create-device-public-key-failed");
}
}
}
@@ -868,8 +870,8 @@ util::Status SessionImpl::GenerateSignedLicense(
license.id().has_provider_session_token(), session_init,
license.id().type(), system_id,
kcb.mutable_key_control_block())) {
status = util::Status(error_space, KEYCONTROL_GENERATION_ERROR,
"Could not generate key control block.");
status = Status(error_space, KEYCONTROL_GENERATION_ERROR,
"Could not generate key control block.");
return status;
}
if (license.key(i).has_key() &&
@@ -879,14 +881,18 @@ util::Status SessionImpl::GenerateSignedLicense(
// encrypted.
kcb.set_iv(Random16Bytes());
kcb.set_key_control_block(
crypto_util::EncryptAesCbc(license.key(i).key().substr(0, 16),
kcb.iv(), kcb.key_control_block()));
license_request_->protocol_version() < VERSION_2_2
? crypto_util::EncryptAesCbc(license.key(i).key().substr(0, 16),
kcb.iv(), kcb.key_control_block())
: crypto_util::EncryptAesCbcNoPad(
license.key(i).key().substr(0, 16), kcb.iv(),
kcb.key_control_block()));
}
}
if (license.key(i).has_key()) {
if (license.key(i).type() == License::KeyContainer::CONTENT) {
if (license.key(i).key().size() != kContentKeySize) {
return util::Status(
return Status(
error_space, INVALID_KEY_SIZE,
absl::StrCat(
"content key size in license is wrong. Key size should be ",
@@ -894,29 +900,29 @@ util::Status SessionImpl::GenerateSignedLicense(
}
} else if (license.key(i).type() == License::KeyContainer::ENTITLEMENT) {
if (license.key(i).key().size() != kEntitlementKeySize) {
return util::Status(error_space, INVALID_KEY_SIZE,
"invalid-entitlement-key-size");
return Status(error_space, INVALID_KEY_SIZE,
"invalid-entitlement-key-size");
}
}
license.mutable_key(i)->set_iv(Random16Bytes());
license.mutable_key(i)->set_key(crypto_util::EncryptAesCbc(
encryption_key, license.key(i).iv(), license.key(i).key()));
license.mutable_key(i)->set_key(
license_request_->protocol_version() < VERSION_2_2
? crypto_util::EncryptAesCbc(wrapping_key, license.key(i).iv(),
license.key(i).key())
: crypto_util::EncryptAesCbcNoPad(
wrapping_key, license.key(i).iv(), license.key(i).key()));
if (license.key(i).key().empty()) {
return util::Status(error_space, ENCRYPT_ERROR, "key-encrypt-failed");
return Status(error_space, ENCRYPT_ERROR, "key-encrypt-failed");
}
}
}
switch (platform_verification_status_) {
case PLATFORM_NO_VERIFICATION:
break;
case PLATFORM_HARDWARE_VERIFIED:
// TODO(b/65054419): Deprecate remote_attestation_verified altogether.
license.set_remote_attestation_verified(true);
ABSL_FALLTHROUGH_INTENDED;
default:
license.set_platform_verification_status(platform_verification_status_);
break;
if (platform_verification_status_ != PLATFORM_NO_VERIFICATION) {
license.set_platform_verification_status(platform_verification_status_);
}
// TODO(b/65054419): Deprecate remote_attestation_verified altogether.
if (remote_attestation_verified_) {
license.set_remote_attestation_verified(true);
}
@@ -955,7 +961,7 @@ util::Status SessionImpl::GenerateSignedLicense(
return status;
}
bool SessionImpl::GenerateErrorResponse(const util::Status& status,
bool SessionImpl::GenerateErrorResponse(const Status& status,
std::string* signed_message_bytes) {
return widevine::GenerateErrorResponse(status, signed_message_bytes);
}
@@ -1027,9 +1033,9 @@ bool SessionImpl::ShouldSetProviderSessionToken(
return false;
}
util::Status SessionImpl::VerifyPlatform() {
Status SessionImpl::VerifyPlatform() {
if (platform_verification_status_ != PLATFORM_NO_VERIFICATION) {
return util::OkStatus();
return OkStatus();
}
// Verify the platform only if it has not been verified at the proxy. This
// verification can be performed by content providers who host their own
@@ -1039,7 +1045,7 @@ util::Status SessionImpl::VerifyPlatform() {
ProvisionedDeviceInfo::LEVEL_1) {
platform_verification_status_ = PLATFORM_HARDWARE_VERIFIED;
} else {
util::Status status = VerifyRemoteAttestation();
Status status = VerifyRemoteAttestation();
if (!status.ok()) {
VLOG(1) << "Remote Attestation Failure: " << status
<< ", license request: " << license_request_->ShortDebugString();
@@ -1048,9 +1054,8 @@ util::Status SessionImpl::VerifyPlatform() {
}
if (platform_verification_status_ == PLATFORM_UNVERIFIED &&
license_request_ && !license_request_->client_id().vmp_data().empty()) {
util::Status status =
VerifyVmpData(license_request_->client_id().vmp_data(),
&platform_verification_status_);
Status status = VerifyVmpData(license_request_->client_id().vmp_data(),
&platform_verification_status_);
if (!status.ok()) {
VLOG(1) << "Platform Verification Failure: " << status
<< ", license request: " << license_request_->ShortDebugString();
@@ -1058,7 +1063,7 @@ util::Status SessionImpl::VerifyPlatform() {
}
}
return util::OkStatus();
return OkStatus();
}
std::string SessionImpl::GetDrmDeviceId() const {
@@ -1071,10 +1076,10 @@ std::string SessionImpl::GetDrmDeviceId() const {
return std::string();
}
util::Status SessionImpl::VerifyDeviceCapabilities(
Status SessionImpl::VerifyDeviceCapabilities(
const ClientIdentification::ClientCapabilities& device_capabilities,
const License::KeyContainer::OutputProtection& output_protection) const {
util::Status status(util::OkStatus());
Status status(OkStatus());
if (output_protection.has_hdcp() &&
device_capabilities.has_max_hdcp_version()) {
// TODO(user): Implement the HDCP use case.
@@ -1087,26 +1092,26 @@ util::Status SessionImpl::VerifyDeviceCapabilities(
device_capabilities.analog_output_capabilities() !=
ClientIdentification::ClientCapabilities::ANALOG_OUTPUT_NONE) &&
!device_capabilities.can_disable_analog_output()) {
return util::Status(util::error::PERMISSION_DENIED,
"Analog output must be disabled.");
return Status(error::PERMISSION_DENIED,
"Analog output must be disabled.");
}
}
if (output_protection.cgms_flags() !=
License::KeyContainer::OutputProtection::CGMS_NONE) {
if (device_capabilities.analog_output_capabilities() ==
ClientIdentification::ClientCapabilities::ANALOG_OUTPUT_SUPPORTED) {
return util::Status(util::error::PERMISSION_DENIED,
"Analog output must support CGMS-A.");
return Status(error::PERMISSION_DENIED,
"Analog output must support CGMS-A.");
}
}
return status;
}
util::Status SessionImpl::CheckProviderSessionToken(const std::string& pst_src) {
Status SessionImpl::CheckProviderSessionToken(const std::string& pst_src) {
if (pst_src.size() > kProviderSessionTokenSizeBytes) {
return util::Status(error_space, INVALID_PROVIDER_SESSION_TOKEN_SIZE, "");
return Status(error_space, INVALID_PROVIDER_SESSION_TOKEN_SIZE, "");
}
return util::OkStatus();
return OkStatus();
}
@@ -1114,19 +1119,18 @@ PlatformVerificationStatus SessionImpl::GetPlatformVerificationStatus() const {
return platform_verification_status_;
}
util::Status SessionImpl::VerifyRemoteAttestation() {
Status SessionImpl::VerifyRemoteAttestation() {
platform_verification_status_ = PLATFORM_UNVERIFIED;
if (signed_message_ != nullptr && signed_message_->has_remote_attestation()) {
if (!signed_message_->has_msg()) {
return util::Status(error_space, INVALID_MESSAGE,
"SignedMessage-msg-missing");
return Status(error_space, INVALID_MESSAGE, "SignedMessage-msg-missing");
}
util::Status status =
RemoteAttestationVerifier::get().VerifyRemoteAttestation(
signed_message_->msg(), signed_message_->remote_attestation(),
&remote_attestation_cert_serial_number_);
Status status = RemoteAttestationVerifier::get().VerifyRemoteAttestation(
signed_message_->msg(), signed_message_->remote_attestation(),
&remote_attestation_cert_serial_number_);
if (status.ok()) {
platform_verification_status_ = PLATFORM_HARDWARE_VERIFIED;
remote_attestation_verified_ = true;
} else if ((status.error_space() == error_space) &&
(status.error_code() == REMOTE_ATTESTATION_FAILED)) {
platform_verification_status_ = PLATFORM_TAMPERED;
@@ -1135,7 +1139,7 @@ util::Status SessionImpl::VerifyRemoteAttestation() {
}
}
return util::OkStatus();
return OkStatus();
}
// TODO(user): add check to get client_id from EncryptedClientIdentification.
@@ -1158,4 +1162,11 @@ std::string SessionImpl::GetDrmDeviceServiceId() const {
return std::string();
}
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);
}
} // namespace widevine

View File

@@ -16,8 +16,8 @@
#include <cstdint>
#include "base/macros.h"
#include "util/status.h"
#include "absl/synchronization/mutex.h"
#include "common/status.h"
#include "protos/public/client_identification.pb.h"
#include "protos/public/license_protocol.pb.h"
#include "protos/public/license_server_sdk.pb.h"
@@ -65,8 +65,8 @@ std::string GetProviderClientToken(const SessionInit& session_init,
// std::string signed_license_request;
// // assign signed_license_request to incoming license request.
// Session* session = NULL;
// util::Status status = Session::Create(root_cert, signed_license_request,
// &session);
// Status status = Session::Create(root_cert, signed_license_request,
// &session);
// if (!status.ok()) {
// std::string error_license;
// if (Session::GenerateErrorResponse(status, &error_license)) {
@@ -112,10 +112,10 @@ class SessionImpl {
// certificate_status_list expires after its creation time
// (creation_time_seconds). If |allow_unknown_devices| is false, an error is
// returned if the device does not appear in the certificate_status_list.
static util::Status SetCertificateStatusList(
const DrmRootCertificate* root_cert,
const std::string& certificate_status_list, uint32_t expiration_period_seconds,
bool allow_unknown_devices);
static Status SetCertificateStatusList(const DrmRootCertificate* root_cert,
const std::string& certificate_status_list,
uint32_t expiration_period_seconds,
bool allow_unknown_devices);
// Add a service certificate system-wide. |root_cert| is the root certificate
// which signed the service certificate;
@@ -124,7 +124,7 @@ class SessionImpl {
// |service_private_key| is the encrypted PKCS#8 private RSA key corresponding
// to the service certificate; and |service_private_key_passphrase| is the
// password required to decrypt |service_private_key|.
static util::Status AddDrmServiceCertificate(
static Status AddDrmServiceCertificate(
const DrmRootCertificate* root_cert, const std::string& service_certificate,
const std::string& service_private_key,
const std::string& service_private_key_passphrase);
@@ -143,13 +143,13 @@ class SessionImpl {
// |signed_license_request| is the serialized SignedMessage received from the
// client. |session| points to a Session*, which must be initialized to NULL
// on entry, but |session| itself may not be NULL. The new Session object will
// be owned by the caller. This method returns util::Status::OK if successful,
// be owned by the caller. This method returns Status::OK if successful,
// or an appropriate error status, in which case
// Session::GenerateErrorResponse should be invoked.
// Example usage:
// Session* session = NULL;
// util::Status status = Session::Create(root_cert, request_from_client,
// &session);
// Status status = Session::Create(root_cert, request_from_client,
// &session);
// if (!status.ok()) {
// std::string error_license;
// if (Session::GenerateErrorResponse(status, &error_license)) {
@@ -160,16 +160,16 @@ class SessionImpl {
// return ...
// }
// // Create license, invoke GenerateSignedLicense, etc.
static util::Status Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session);
static Status Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session);
// Variation of Session::Create which also fills in the parsed LicenseRequest,
// for use in logging or debugging.
static util::Status Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session,
LicenseRequest* parsed_request_out);
static Status Create(const DrmRootCertificate* root_cert,
const std::string& signed_license_request,
SessionImpl** session,
LicenseRequest* parsed_request_out);
// Same as Create(), but caller can specify the ClientIdentification
// message and/or PlatformVerificationStatus. If ClientIdentification is
@@ -184,7 +184,7 @@ class SessionImpl {
// platform verification. The provider will specify the
// clear client identification in |client_id| and the platform verification
// in |platform_verification_status|.
static util::Status CreateForProxy(
static Status CreateForProxy(
const DrmRootCertificate* root_cert, const std::string& signed_license_request,
const PlatformVerificationStatus platform_verification_status,
const ClientIdentification* client_id, SessionImpl** session,
@@ -192,12 +192,12 @@ class SessionImpl {
// Generates a SignedMessage containing a message generated in response to
// an error condition. |status| is a previous error status returned by the
// Session or util::Status(util::error::UNAVAILABLE, ...) to indicate that the
// Session or Status(error::UNAVAILABLE, ...) to indicate that the
// backend is unavailable, |signed_message| points to a std::string to contain the
// serialized SignedMessage, and may not be NULL. This method returns true if
// there is an error license to be sent to the client, or false otherwise.
// Example usage in the Session::Create comments above.
static bool GenerateErrorResponse(const util::Status& status,
static bool GenerateErrorResponse(const Status& status,
std::string* signed_message_bytes);
// DeriveKey uses the NIST 800-108 KDF recommendation, using AES-CMAC PRF.
@@ -217,8 +217,8 @@ class SessionImpl {
return is_service_certificate_loaded_;
}
static const char* kEncryptionKeyLabel; // NOLINT
static const uint32_t kEncryptionKeySizeBits;
static const char* kWrappingKeyLabel; // NOLINT
static const uint32_t kWrappingKeySizeBits;
static const char* kSigningKeyLabel; // NOLINT
static const uint32_t kSigningKeySizeBits;
@@ -239,13 +239,13 @@ class SessionImpl {
// places in the liciense request protcol buffer. Use this method instead
// of accessing directly. |request_id| is a pointer to a std::string to contain
// the request ID upon successful return.
virtual util::Status GetRequestId(std::string* request_id) const;
virtual Status GetRequestId(std::string* request_id) const;
// Accessor for license_type field which may be encoded in one of multiple
// places in the license request protcol buffer. Use this method instead
// of accessing directly. |license_type| is a pointer to a value to contain
// the license type upon successful return.
virtual util::Status GetLicenseType(LicenseType* license_type) const;
virtual Status GetLicenseType(LicenseType* license_type) const;
// Method used to get ContentIdentification in a consistent message regardless
// of the type or version of initialization data contained in the content_id
@@ -253,7 +253,7 @@ class SessionImpl {
// fields of ContentIdentification directly. |content_info| is a pointer to a
// message to contain the parsed values from content_id upon successful
// return.
virtual util::Status GetContentInfo(ContentInfo* content_info) const;
virtual Status GetContentInfo(ContentInfo* content_info) const;
// Returns the serial number of certificate associated with this device and
// content provider.
@@ -271,7 +271,7 @@ class SessionImpl {
// are necessary to fulfill the request (such as the case with license
// renewal), |policy| and/or |key_container| may be NULL.
// The response is expected to be sent to the Widevine CDM.
virtual util::Status GenerateSignedLicense(
virtual Status GenerateSignedLicense(
/*IN*/ const License::Policy* policy,
/*IN*/ const std::list<License::KeyContainer>* key_container,
/*IN*/ const SessionInit* session_init,
@@ -280,7 +280,7 @@ class SessionImpl {
// Verify the required |output_protection| can be satisified based on the
// |device_capabilities| specified by the client.
virtual util::Status VerifyDeviceCapabilities(
virtual Status VerifyDeviceCapabilities(
const ClientIdentification::ClientCapabilities& device_capabilities,
const License::KeyContainer::OutputProtection& output_protection) const;
@@ -294,10 +294,17 @@ class SessionImpl {
// false.
virtual bool HasKeyControlNonce() const { return has_key_control_nonce_; }
// Generate a signed request to be sent to Widevine Certificate Provisioning
// Server to retrieve 'DeviceCertificateStatusList'.
virtual Status GenerateDeviceStatusListRequest(
std::string* signed_device_certificate_status_list_request);
protected:
friend class Session;
PlatformVerificationStatus platform_verification_status_ =
PLATFORM_NO_VERIFICATION;
bool remote_attestation_verified_ = false;
// For testing only. This allows unit tests to define a mock Session class.
SessionImpl();
@@ -310,12 +317,12 @@ class SessionImpl {
uint32_t nonce, widevine::ProvisionedDeviceInfo* device_info);
// Called by the SessionImpl::Create factory to initialize a new session.
util::Status Init(const DrmRootCertificate* root_cert);
util::Status GenerateNewLicenseInfo(/*IN*/ const SessionInit* session_init,
/*OUT*/ LicenseIdentification* new_id,
/*OUT*/ std::string* renewal_signing_key,
/*OUT*/ std::string* signing_key);
util::Status GeneratePriorLicenseInfo(
Status Init(const DrmRootCertificate* root_cert);
Status GenerateNewLicenseInfo(/*IN*/ const SessionInit* session_init,
/*OUT*/ LicenseIdentification* new_id,
/*OUT*/ std::string* renewal_signing_key,
/*OUT*/ std::string* signing_key);
Status GeneratePriorLicenseInfo(
/*IN*/ const SessionInit* session_init,
/*INOUT*/ SessionState* session_state,
/*OUT*/ LicenseIdentification* new_id,
@@ -324,7 +331,7 @@ class SessionImpl {
// Verifies remote attestation in the license request and sets
// |platform_verification_status_|.
virtual util::Status VerifyRemoteAttestation();
virtual Status VerifyRemoteAttestation();
// Return true if the provider session token should get included in the
// license response.
static bool ShouldSetProviderSessionToken(
@@ -334,25 +341,25 @@ class SessionImpl {
// Verifies the platform by platform-specific means such as Remote Attestion
// or host code verification. Only meaningful for Widevine Level 2-3, as
// Level 1 devices are verified by default.
virtual util::Status VerifyPlatform();
virtual Status VerifyPlatform();
// Extracts the nonce from |request| and populates |key_control_nonce|. Sets
// |key_control_nonce| to true if the nonce is found.
static util::Status LoadKeyControlNonce(const LicenseRequest& request,
bool* has_key_control_nonce,
uint32_t* key_control_nonce);
static Status LoadKeyControlNonce(const LicenseRequest& request,
bool* has_key_control_nonce,
uint32_t* key_control_nonce);
// Validates required fields are set in the license |request|.
static util::Status CheckLicenseRequestFields(const LicenseRequest& request);
static Status CheckLicenseRequestFields(const LicenseRequest& request);
// De-serialize the license request from the |signed_license_request|
// into |license_request| and |signed_message|.
static util::Status ParseLicenseRequestFromString(
static Status ParseLicenseRequestFromString(
const std::string& signed_license_request, SignedMessage* signed_message,
LicenseRequest* license_request);
// Validates the Provider Session Token from |pst_src|.
static util::Status CheckProviderSessionToken(const std::string& pst_src);
static Status CheckProviderSessionToken(const std::string& pst_src);
std::unique_ptr<SignedMessage> signed_message_;
std::unique_ptr<LicenseRequest> license_request_;

File diff suppressed because it is too large Load Diff