Merges to android Pi release (part 2)
These are a set of CLs merged from the wv cdm repo to the android repo. * Update service certificate. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28065 ] The updated service certificate fixes a number of failing tests. There are still some that fail, apparently due to mismatches with key set IDs and usage tables. Also updated QA server URL to point to QA proxy (although neither can be used by this client). Also fixed segfault in CdmTest.ListUsageRecords. * Add CDM APIs for Handling Service Certificates. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28064 ] The responsibility for managing Service Certificates has been moved out of the CDM. Instead, provide CDM and CdmEngine methods to generate a service certificate request message, and handle a service certificate response. The API client can use these calls if it needs to get the service certificate from the License Server. These functions assume the request and response are base64 (web-safe) encoded (see b/37481392). Not all servers are operating this way yet. Any adaptations for non-compliant servers is handled outside the CDM. See test WvCdmEnginePreProvTest::ServiceCertificateRequestResponse in cdm_engine_test.cpp for an example of this. These changes also eliminate the stored init_data and deferred license type which were used to perform a service certificate request during a license request. * Fix and rename ClosesSessionWithoutReturningError test. Author: Edwin Wong <edwinwong@google.com> [ Merge of http://go/wvgerrit/27880 ] ClosesSessionWithoutReturningError should not check for Status::OK since it is expecting an error code back. The test is renamed to ClosesSessionWithError. Test: libwvdrmdrmplugin_hidl_test BUG: 62205215 * Get rid of default service certificate. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/27981 ] Instead, we need at least two service certs - one for the QA/Test servers, and one for UAT (and prod?) There are still some issues around the signature verififcation of the service cert, and in license_unittest.cpp, the use of the default service cert has been commented out. I don't know why this test needs a service cert. If it really does, then the same mechanism that is used elsewhere for selecting a specific server type will be needed here. BUG: 71650075 Test: Not currently passing. Will be addressed in a subsequent commit in the chain. Change-Id: Ieab815fb202c809ad5714cd0364c4bdfa068f77d
This commit is contained in:
@@ -30,6 +30,9 @@ const size_t kUsageReportsPerRequest = 1;
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
using video_widevine::SignedMessage;
|
||||
using video_widevine::LicenseError;
|
||||
|
||||
class UsagePropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
UsagePropertySet() {}
|
||||
@@ -84,6 +87,82 @@ CdmResponseType CdmEngine::SetServiceCertificate(
|
||||
return service_certificate_.Init(certificate);
|
||||
}
|
||||
|
||||
bool CdmEngine::HasServiceCertificate() {
|
||||
return service_certificate_.has_certificate();
|
||||
}
|
||||
|
||||
bool CdmEngine::GetServiceCertificateRequest(CdmKeyMessage* request) {
|
||||
if (!request) {
|
||||
LOGE("ServiceCertificate::PrepareRequest: no request parameter provided");
|
||||
return false;
|
||||
}
|
||||
SignedMessage message;
|
||||
message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST);
|
||||
message.SerializeToString(request);
|
||||
|
||||
// Convert to base64.
|
||||
std::vector<uint8_t> request_vector(request->begin(), request->end());
|
||||
std::string request_b64 = Base64SafeEncodeNoPad(request_vector);
|
||||
request->swap(request_b64);
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ParseServiceCertificateResponse(
|
||||
const std::string& response, std::string* certificate) {
|
||||
if (response.empty()) {
|
||||
LOGE("CdmEngine::ParseServiceCertificateResponse: empty response");
|
||||
return EMPTY_RESPONSE_ERROR_1;
|
||||
}
|
||||
if (!certificate) {
|
||||
LOGE("CdmEngine::ParseServiceCertificateResponse: null return parameter");
|
||||
return INVALID_PARAMETERS_ENG_24;
|
||||
}
|
||||
|
||||
// The response is base64 encoded - decode it before parsing the string.
|
||||
std::string padded_response(response);
|
||||
while (padded_response.size() % 4 != 0) {
|
||||
padded_response = padded_response + "=";
|
||||
}
|
||||
std::vector<uint8_t> raw_message = Base64SafeDecode(padded_response);
|
||||
std::string raw_string(raw_message.begin(), raw_message.end());
|
||||
|
||||
SignedMessage signed_response;
|
||||
if (!signed_response.ParseFromString(raw_string)) {
|
||||
LOGE(
|
||||
"CdmEngine::ParseServiceCertificateResponse: cannot parse response");
|
||||
return PARSE_RESPONSE_ERROR_1;
|
||||
}
|
||||
if (signed_response.type() == SignedMessage::SERVICE_CERTIFICATE) {
|
||||
|
||||
CdmResponseType status;
|
||||
status = service_certificate_.Init(signed_response.msg());
|
||||
if (status != NO_ERROR) {
|
||||
LOGE(
|
||||
"CdmEngine::ParseServiceCertificateResponse: certificate handling "
|
||||
"failure, status=%d", status);
|
||||
return PARSE_SERVICE_CERTIFICATE_ERROR;
|
||||
}
|
||||
certificate->assign(signed_response.msg());
|
||||
|
||||
} else if (signed_response.type() == SignedMessage::ERROR_RESPONSE) {
|
||||
|
||||
LicenseError license_error;
|
||||
if (!license_error.ParseFromString(signed_response.msg())) {
|
||||
LOGE("CdmEngine::ParseServiceCertificateResponse: cannot parse "
|
||||
"license error");
|
||||
return PARSE_RESPONSE_ERROR_2;
|
||||
}
|
||||
LOGE("CdmEngine::ParseServiceCertificateResponse: server returned error:"
|
||||
"error code = %d", license_error.error_code());
|
||||
return PARSE_RESPONSE_ERROR_3;
|
||||
} else {
|
||||
LOGE(
|
||||
"CdmEngine::ParseServiceCertificateResponse: response is wrong type");
|
||||
return PARSE_RESPONSE_ERROR_4;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::OpenSession(
|
||||
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
|
||||
const CdmSessionId& forced_session_id, WvCdmEventListener* event_listener) {
|
||||
|
||||
@@ -102,6 +102,7 @@ CdmResponseType CdmSession::Init(
|
||||
// client_token and client_token_type are determined here; they are needed
|
||||
// to initialize the license parser.
|
||||
std::string client_token;
|
||||
std::string serial_number;
|
||||
CdmClientTokenType client_token_type =
|
||||
crypto_session_->GetPreProvisionTokenType();
|
||||
if ((client_token_type == kClientTokenKeybox) &&
|
||||
@@ -124,7 +125,8 @@ CdmResponseType CdmSession::Init(
|
||||
// License server client ID token is a stored certificate. Stage it or
|
||||
// indicate that provisioning is needed. Get token from stored certificate
|
||||
std::string wrapped_key;
|
||||
if (!file_handle_->RetrieveCertificate(&client_token, &wrapped_key)) {
|
||||
if (!file_handle_->RetrieveCertificate(&client_token, &wrapped_key,
|
||||
&serial_number, nullptr)) {
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
bool load_cert_sts;
|
||||
@@ -169,7 +171,7 @@ CdmResponseType CdmSession::Init(
|
||||
|
||||
if (!license_parser_->Init(
|
||||
service_certificate, client_token, client_token_type,
|
||||
crypto_session_.get(), policy_engine_.get()))
|
||||
serial_number, crypto_session_.get(), policy_engine_.get()))
|
||||
return LICENSE_PARSER_INIT_ERROR;
|
||||
|
||||
license_received_ = false;
|
||||
@@ -274,26 +276,6 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
case kLicenseTypeRelease:
|
||||
is_release_ = true;
|
||||
break;
|
||||
case kLicenseTypeDeferred:
|
||||
// If you're going to pass Deferred, you must have empty init data in
|
||||
// this call and stored init data from the previous call.
|
||||
if (!init_data.IsEmpty() || !license_parser_->HasInitData()) {
|
||||
return INVALID_LICENSE_TYPE;
|
||||
}
|
||||
// The arguments check out.
|
||||
// The is_release_ and is_offline_ flags were already set last time based
|
||||
// on the original license type. Do not change them, and use them to
|
||||
// re-derive the original license type.
|
||||
if (is_release_) {
|
||||
license_type = kLicenseTypeRelease;
|
||||
} else if (is_offline_) {
|
||||
license_type = kLicenseTypeOffline;
|
||||
} else if (is_temporary_) {
|
||||
license_type = kLicenseTypeTemporary;
|
||||
} else {
|
||||
license_type = kLicenseTypeStreaming;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmSession::GenerateKeyRequest: unrecognized license type: %ld",
|
||||
license_type);
|
||||
@@ -307,16 +289,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
} else {
|
||||
key_request->type = kKeyRequestTypeInitial;
|
||||
|
||||
if (!license_parser_->HasInitData()) {
|
||||
if (!init_data.is_supported()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: unsupported init data type (%s)",
|
||||
init_data.type().c_str());
|
||||
return UNSUPPORTED_INIT_DATA;
|
||||
}
|
||||
if (init_data.IsEmpty()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: init data absent");
|
||||
return INIT_DATA_NOT_FOUND;
|
||||
}
|
||||
if (!init_data.is_supported()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: unsupported init data type (%s)",
|
||||
init_data.type().c_str());
|
||||
return UNSUPPORTED_INIT_DATA;
|
||||
}
|
||||
if (init_data.IsEmpty()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: init data absent");
|
||||
return INIT_DATA_NOT_FOUND;
|
||||
}
|
||||
if (is_offline_ && key_set_id_.empty()) {
|
||||
LOGE("CdmSession::GenerateKeyRequest: Unable to generate key set ID");
|
||||
@@ -328,16 +308,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
init_data, license_type,
|
||||
app_parameters, &key_request->message,
|
||||
&key_request->url);
|
||||
|
||||
if (KEY_MESSAGE != status) return status;
|
||||
if (status != KEY_MESSAGE)
|
||||
return status;
|
||||
|
||||
key_request_ = key_request->message;
|
||||
if (is_offline_) {
|
||||
offline_init_data_ = init_data.data();
|
||||
offline_release_server_url_ = key_request->url;
|
||||
|
||||
}
|
||||
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
71
libwvdrmengine/cdm/core/src/cdm_session_map.cpp
Normal file
71
libwvdrmengine/cdm/core/src/cdm_session_map.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "cdm_session_map.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "cdm_session.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
CdmSessionMap::~CdmSessionMap() {
|
||||
AutoLock lock(lock_);
|
||||
for (CdmIdToSessionMap::iterator i = sessions_.begin();
|
||||
i != sessions_.end(); ++i) {
|
||||
i->second->Close();
|
||||
i->second.reset();
|
||||
}
|
||||
sessions_.clear();
|
||||
}
|
||||
|
||||
void CdmSessionMap::Add(const std::string& id, CdmSession* session) {
|
||||
AutoLock lock(lock_);
|
||||
sessions_[id].reset(session);
|
||||
}
|
||||
|
||||
bool CdmSessionMap::CloseSession(const std::string& id) {
|
||||
AutoLock lock(lock_);
|
||||
std::shared_ptr<CdmSession> session;
|
||||
if (!FindSessionNoLock(id, &session)) {
|
||||
return false;
|
||||
}
|
||||
session->Close();
|
||||
sessions_.erase(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CdmSessionMap::Exists(const std::string& id) {
|
||||
AutoLock lock(lock_);
|
||||
return sessions_.find(id) != sessions_.end();
|
||||
}
|
||||
|
||||
bool CdmSessionMap::FindSession(const CdmSessionId& id,
|
||||
std::shared_ptr<CdmSession>* session) {
|
||||
AutoLock lock(lock_);
|
||||
return FindSessionNoLock(id, session);
|
||||
}
|
||||
|
||||
bool CdmSessionMap::FindSessionNoLock(const CdmSessionId& session_id,
|
||||
std::shared_ptr<CdmSession>* session) {
|
||||
CdmIdToSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
return false;
|
||||
}
|
||||
*session = iter->second;
|
||||
assert(session->get() != NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CdmSessionMap::GetSessionList(CdmSessionList& sessions) {
|
||||
sessions.clear();
|
||||
AutoLock lock(lock_);
|
||||
for (CdmIdToSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
if (!(iter->second)->IsClosed()) {
|
||||
sessions.push_back(iter->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -115,7 +115,7 @@ bool CertificateProvisioning::SetSpoidParameter(
|
||||
// Use the SPOID that has been pre-provided
|
||||
request->set_spoid(spoid);
|
||||
} else if (Properties::UseProviderIdInProvisioningRequest()) {
|
||||
if (service_certificate_->HasProviderId()) {
|
||||
if (!service_certificate_->provider_id().empty()) {
|
||||
request->set_provider_id(service_certificate_->provider_id());
|
||||
} else {
|
||||
LOGE("CertificateProvisioning::SetSpoidParameter: Failure getting "
|
||||
@@ -190,7 +190,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
client_id->set_type(token_type);
|
||||
|
||||
#if 0 // TODO(gmorgan) Encrypt ClientIdentification. Pending Design.
|
||||
if (service_certificate_->has_certificate()) {
|
||||
if (service_certificate_->HasCertificate()) {
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
provisioning_request.mutable_encrypted_client_id();
|
||||
CdmResponseType status;
|
||||
@@ -329,7 +329,8 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
||||
// If Provisioning 3.0 (OEM Cert provisioned), verify that the
|
||||
// message is properly signed.
|
||||
if (crypto_session_.GetPreProvisionTokenType() == kClientTokenOemCert) {
|
||||
if (!service_certificate_->VerifySignedMessage(signed_message, signature)) {
|
||||
if (service_certificate_->VerifySignedMessage(signed_message, signature)
|
||||
!= NO_ERROR) {
|
||||
LOGE("HandleProvisioningResponse: message not properly signed");
|
||||
return CERT_PROVISIONING_RESPONSE_ERROR_6;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "file_store.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
@@ -41,6 +42,9 @@ using video_widevine_client::sdk::
|
||||
using video_widevine_client::sdk::
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO;
|
||||
|
||||
using video_widevine::SignedDrmDeviceCertificate;
|
||||
using video_widevine::DrmDeviceCertificate;
|
||||
|
||||
namespace {
|
||||
|
||||
const char kCertificateFileName[] = "cert.bin";
|
||||
@@ -117,7 +121,9 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
|
||||
std::string* wrapped_private_key) {
|
||||
std::string* wrapped_private_key,
|
||||
std::string* serial_number,
|
||||
uint32_t* system_id) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveCertificate: not initialized");
|
||||
return false;
|
||||
@@ -146,6 +152,42 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
|
||||
DeviceCertificate device_certificate = file.device_certificate();
|
||||
*certificate = device_certificate.certificate();
|
||||
*wrapped_private_key = device_certificate.wrapped_private_key();
|
||||
return ExtractDeviceInfo(device_certificate.certificate(), serial_number,
|
||||
system_id);
|
||||
}
|
||||
|
||||
bool DeviceFiles::ExtractDeviceInfo(const std::string& device_certificate,
|
||||
std::string* serial_number,
|
||||
uint32_t* system_id) {
|
||||
LOGI("ExtractDeviceInfo Entry");
|
||||
if (!serial_number && !system_id) {
|
||||
LOGE("Invalid paramters to DeviceFiles::ExtractDeviceInfo");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get serial number and system ID from certificate
|
||||
SignedDrmDeviceCertificate signed_drm_device_certificate;
|
||||
if (!signed_drm_device_certificate.ParseFromString(device_certificate) ||
|
||||
!signed_drm_device_certificate.has_drm_certificate()) {
|
||||
LOGE("DeviceFiles::ExtractDeviceInfo: fails parsing signed drm device "
|
||||
"certificate.");
|
||||
return false;
|
||||
}
|
||||
DrmDeviceCertificate drm_device_certificate;
|
||||
if (!drm_device_certificate.ParseFromString(
|
||||
signed_drm_device_certificate.drm_certificate()) ||
|
||||
(drm_device_certificate.type() !=
|
||||
video_widevine::DrmDeviceCertificate::DRM_USER_DEVICE)) {
|
||||
LOGE("DeviceFiles::ExtractDeviceInfo: fails parsing drm device "
|
||||
"certificate message.");
|
||||
return false;
|
||||
}
|
||||
if (serial_number != NULL) {
|
||||
*serial_number = drm_device_certificate.serial_number();
|
||||
}
|
||||
if (system_id != NULL) {
|
||||
*system_id = drm_device_certificate.system_id();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace {
|
||||
std::string kCompanyNameKey = "company_name";
|
||||
std::string kModelNameKey = "model_name";
|
||||
std::string kArchitectureNameKey = "architecture_name";
|
||||
std::string kDeviceNameKey = "device_name";
|
||||
std::string kProductNameKey = "product_name";
|
||||
std::string kBuildInfoKey = "build_info";
|
||||
std::string kDeviceIdKey = "device_id";
|
||||
std::string kWVCdmVersionKey = "widevine_cdm_version";
|
||||
std::string kOemCryptoSecurityPatchLevelKey = "oem_crypto_security_patch_level";
|
||||
} // namespace
|
||||
const std::string kCompanyNameKey = "company_name";
|
||||
const std::string kModelNameKey = "model_name";
|
||||
const std::string kArchitectureNameKey = "architecture_name";
|
||||
const std::string kDeviceNameKey = "device_name";
|
||||
const std::string kProductNameKey = "product_name";
|
||||
const std::string kBuildInfoKey = "build_info";
|
||||
const std::string kDeviceIdKey = "device_id";
|
||||
const std::string kWVCdmVersionKey = "widevine_cdm_version";
|
||||
const std::string kOemCryptoSecurityPatchLevelKey =
|
||||
"oem_crypto_security_patch_level";
|
||||
|
||||
const uint32_t kFourCcCbc1 = 0x63626331;
|
||||
const uint32_t kFourCcCbcs = 0x63626373;
|
||||
@@ -37,13 +37,13 @@ const uint32_t kFourCcLittleEndianCbcs = 0x73636263;
|
||||
const uint32_t kFourCcCenc = 0x63656e63;
|
||||
const uint32_t kFourCcCens = 0x63656e73;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// Protobuf generated classes.
|
||||
using video_widevine::ClientIdentification;
|
||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
||||
using video_widevine::
|
||||
ClientIdentification_ClientCapabilities_CertificateKeyType;
|
||||
using video_widevine::ClientIdentification_NameValue;
|
||||
using video_widevine::DrmDeviceCertificate;
|
||||
using video_widevine::EncryptedClientIdentification;
|
||||
@@ -146,8 +146,8 @@ CdmLicense::~CdmLicense() {}
|
||||
|
||||
bool CdmLicense::Init(
|
||||
ServiceCertificate* service_certificate, const std::string& client_token,
|
||||
CdmClientTokenType client_token_type, CryptoSession* session,
|
||||
PolicyEngine* policy_engine) {
|
||||
CdmClientTokenType client_token_type, const std::string& device_id,
|
||||
CryptoSession* session, PolicyEngine* policy_engine) {
|
||||
if (clock_.get() == NULL) {
|
||||
LOGE("CdmLicense::Init: clock parameter not provided");
|
||||
return false;
|
||||
@@ -172,6 +172,7 @@ bool CdmLicense::Init(
|
||||
service_certificate_ = service_certificate;
|
||||
client_token_ = client_token;
|
||||
client_token_type_ = client_token_type;
|
||||
device_id_ = device_id;
|
||||
crypto_session_ = session;
|
||||
policy_engine_ = policy_engine;
|
||||
initialized_ = true;
|
||||
@@ -186,12 +187,6 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||
LOGE("CdmLicense::PrepareKeyRequest: not initialized");
|
||||
return LICENSE_PARSER_NOT_INITIALIZED_4;
|
||||
}
|
||||
if (init_data.IsEmpty() && stored_init_data_.get()) {
|
||||
InitializationData restored_init_data = *stored_init_data_;
|
||||
stored_init_data_.reset();
|
||||
return PrepareKeyRequest(restored_init_data, license_type, app_parameters,
|
||||
signed_request, server_url);
|
||||
}
|
||||
if (!init_data.is_supported()) {
|
||||
LOGE("CdmLicense::PrepareKeyRequest: unsupported init data type (%s)",
|
||||
init_data.type().c_str());
|
||||
@@ -213,13 +208,10 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||
// If privacy mode and no service certificate, initiate a
|
||||
// service certificate request.
|
||||
if (Properties::UsePrivacyMode(session_id_) &&
|
||||
!service_certificate_->HasCertificate()) {
|
||||
stored_init_data_.reset(new InitializationData(init_data));
|
||||
*server_url = server_url_;
|
||||
if (service_certificate_->PrepareRequest(signed_request)) {
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
return LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR;
|
||||
!service_certificate_->has_certificate()) {
|
||||
LOGE("CdmLicense::PrepareKeyRequest: failure with privacy mode - "
|
||||
"no service certificate.");
|
||||
return PRIVACY_MODE_ERROR_1;
|
||||
}
|
||||
|
||||
std::string request_id;
|
||||
@@ -304,12 +296,10 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
|
||||
|
||||
if (renew_with_client_id_) {
|
||||
if (Properties::UsePrivacyMode(session_id_) &&
|
||||
!service_certificate_->HasCertificate()) {
|
||||
*server_url = server_url_;
|
||||
if (service_certificate_->PrepareRequest(signed_request)) {
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
return LICENSE_RENEWAL_SERVICE_CERTIFICATE_GENERATION_ERROR;
|
||||
!service_certificate_->has_certificate()) {
|
||||
LOGE("CdmLicense::PrepareKeyUpdateRequest: failure with privacy mode - "
|
||||
"no service certificate.");
|
||||
return PRIVACY_MODE_ERROR_2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,14 +414,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
switch (signed_response.type()) {
|
||||
case SignedMessage::LICENSE:
|
||||
break;
|
||||
case SignedMessage::SERVICE_CERTIFICATE: {
|
||||
CdmResponseType status;
|
||||
status = service_certificate_->HandleResponse(signed_response.msg());
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
return NEED_KEY;
|
||||
}
|
||||
case SignedMessage::ERROR_RESPONSE:
|
||||
return HandleKeyErrorResponse(signed_response);
|
||||
default:
|
||||
@@ -543,14 +525,6 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
switch (signed_response.type()) {
|
||||
case SignedMessage::LICENSE:
|
||||
break;
|
||||
case SignedMessage::SERVICE_CERTIFICATE: {
|
||||
CdmResponseType status;
|
||||
status = service_certificate_->HandleResponse(signed_response.msg());
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
return NEED_KEY;
|
||||
}
|
||||
case SignedMessage::ERROR_RESPONSE:
|
||||
return HandleKeyErrorResponse(signed_response);
|
||||
default:
|
||||
@@ -876,7 +850,11 @@ CdmResponseType CdmLicense::PrepareClientId(
|
||||
client_info->set_name(kBuildInfoKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
|
||||
if (!device_id_.empty()) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(b2a_hex(device_id_));
|
||||
} else if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(value);
|
||||
@@ -969,9 +947,9 @@ CdmResponseType CdmLicense::PrepareClientId(
|
||||
client_capabilities->set_srm_version(srm_version);
|
||||
|
||||
if (Properties::UsePrivacyMode(session_id_)) {
|
||||
if (!service_certificate_->HasCertificate()) {
|
||||
if (service_certificate_->certificate().empty()) {
|
||||
LOGE("CdmLicense::PrepareClientId: Service Certificate not staged");
|
||||
return LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR;
|
||||
return PRIVACY_MODE_ERROR_3;
|
||||
}
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
license_request->mutable_encrypted_client_id();
|
||||
|
||||
@@ -199,7 +199,8 @@ static bool VerifyPSSSignature(EVP_PKEY *pkey, const std::string &message,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) != 1) {
|
||||
if (EVP_PKEY_CTX_set_signature_md(pctx,
|
||||
const_cast<EVP_MD *>(EVP_sha1())) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_signature_md failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -11,41 +11,214 @@
|
||||
|
||||
namespace {
|
||||
// Service certificate for Google/Widevine Provisioning and License servers.
|
||||
const unsigned char kServiceCertificateCAPublicKey[] = {
|
||||
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xb4, 0xfe, 0x39,
|
||||
0xc3, 0x65, 0x90, 0x03, 0xdb, 0x3c, 0x11, 0x97, 0x09, 0xe8, 0x68, 0xcd,
|
||||
0xf2, 0xc3, 0x5e, 0x9b, 0xf2, 0xe7, 0x4d, 0x23, 0xb1, 0x10, 0xdb, 0x87,
|
||||
0x65, 0xdf, 0xdc, 0xfb, 0x9f, 0x35, 0xa0, 0x57, 0x03, 0x53, 0x4c, 0xf6,
|
||||
0x6d, 0x35, 0x7d, 0xa6, 0x78, 0xdb, 0xb3, 0x36, 0xd2, 0x3f, 0x9c, 0x40,
|
||||
0xa9, 0x95, 0x26, 0x72, 0x7f, 0xb8, 0xbe, 0x66, 0xdf, 0xc5, 0x21, 0x98,
|
||||
0x78, 0x15, 0x16, 0x68, 0x5d, 0x2f, 0x46, 0x0e, 0x43, 0xcb, 0x8a, 0x84,
|
||||
0x39, 0xab, 0xfb, 0xb0, 0x35, 0x80, 0x22, 0xbe, 0x34, 0x23, 0x8b, 0xab,
|
||||
0x53, 0x5b, 0x72, 0xec, 0x4b, 0xb5, 0x48, 0x69, 0x53, 0x3e, 0x47, 0x5f,
|
||||
0xfd, 0x09, 0xfd, 0xa7, 0x76, 0x13, 0x8f, 0x0f, 0x92, 0xd6, 0x4c, 0xdf,
|
||||
0xae, 0x76, 0xa9, 0xba, 0xd9, 0x22, 0x10, 0xa9, 0x9d, 0x71, 0x45, 0xd6,
|
||||
0xd7, 0xe1, 0x19, 0x25, 0x85, 0x9c, 0x53, 0x9a, 0x97, 0xeb, 0x84, 0xd7,
|
||||
0xcc, 0xa8, 0x88, 0x82, 0x20, 0x70, 0x26, 0x20, 0xfd, 0x7e, 0x40, 0x50,
|
||||
0x27, 0xe2, 0x25, 0x93, 0x6f, 0xbc, 0x3e, 0x72, 0xa0, 0xfa, 0xc1, 0xbd,
|
||||
0x29, 0xb4, 0x4d, 0x82, 0x5c, 0xc1, 0xb4, 0xcb, 0x9c, 0x72, 0x7e, 0xb0,
|
||||
0xe9, 0x8a, 0x17, 0x3e, 0x19, 0x63, 0xfc, 0xfd, 0x82, 0x48, 0x2b, 0xb7,
|
||||
0xb2, 0x33, 0xb9, 0x7d, 0xec, 0x4b, 0xba, 0x89, 0x1f, 0x27, 0xb8, 0x9b,
|
||||
0x88, 0x48, 0x84, 0xaa, 0x18, 0x92, 0x0e, 0x65, 0xf5, 0xc8, 0x6c, 0x11,
|
||||
0xff, 0x6b, 0x36, 0xe4, 0x74, 0x34, 0xca, 0x8c, 0x33, 0xb1, 0xf9, 0xb8,
|
||||
0x8e, 0xb4, 0xe6, 0x12, 0xe0, 0x02, 0x98, 0x79, 0x52, 0x5e, 0x45, 0x33,
|
||||
0xff, 0x11, 0xdc, 0xeb, 0xc3, 0x53, 0xba, 0x7c, 0x60, 0x1a, 0x11, 0x3d,
|
||||
0x00, 0xfb, 0xd2, 0xb7, 0xaa, 0x30, 0xfa, 0x4f, 0x5e, 0x48, 0x77, 0x5b,
|
||||
0x17, 0xdc, 0x75, 0xef, 0x6f, 0xd2, 0x19, 0x6d, 0xdc, 0xbe, 0x7f, 0xb0,
|
||||
0x78, 0x8f, 0xdc, 0x82, 0x60, 0x4c, 0xbf, 0xe4, 0x29, 0x06, 0x5e, 0x69,
|
||||
0x8c, 0x39, 0x13, 0xad, 0x14, 0x25, 0xed, 0x19, 0xb2, 0xf2, 0x9f, 0x01,
|
||||
0x82, 0x0d, 0x56, 0x44, 0x88, 0xc8, 0x35, 0xec, 0x1f, 0x11, 0xb3, 0x24,
|
||||
0xe0, 0x59, 0x0d, 0x37, 0xe4, 0x47, 0x3c, 0xea, 0x4b, 0x7f, 0x97, 0x31,
|
||||
0x1c, 0x81, 0x7c, 0x94, 0x8a, 0x4c, 0x7d, 0x68, 0x15, 0x84, 0xff, 0xa5,
|
||||
0x08, 0xfd, 0x18, 0xe7, 0xe7, 0x2b, 0xe4, 0x47, 0x27, 0x12, 0x11, 0xb8,
|
||||
0x23, 0xec, 0x58, 0x93, 0x3c, 0xac, 0x12, 0xd2, 0x88, 0x6d, 0x41, 0x3d,
|
||||
0xc5, 0xfe, 0x1c, 0xdc, 0xb9, 0xf8, 0xd4, 0x51, 0x3e, 0x07, 0xe5, 0x03,
|
||||
0x6f, 0xa7, 0x12, 0xe8, 0x12, 0xf7, 0xb5, 0xce, 0xa6, 0x96, 0x55, 0x3f,
|
||||
0x78, 0xb4, 0x64, 0x82, 0x50, 0xd2, 0x33, 0x5f, 0x91, 0x02, 0x03, 0x01,
|
||||
0x00, 0x01};
|
||||
static const unsigned char kRootCertForDev[] = {
|
||||
0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00,
|
||||
0x18, 0xc3, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e,
|
||||
0x03, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01,
|
||||
0x81, 0x00, 0xc0, 0x00, 0x36, 0x6f, 0x8e, 0xe9,
|
||||
0xcf, 0x86, 0xdb, 0xcd, 0xdd, 0x4e, 0xfd, 0xcd,
|
||||
0x45, 0xbf, 0x6d, 0x96, 0x05, 0x00, 0xb8, 0x72,
|
||||
0xff, 0x9c, 0xb4, 0x39, 0xa8, 0xd8, 0xc0, 0x09,
|
||||
0x73, 0xc0, 0x24, 0x6a, 0x39, 0x4d, 0x36, 0x3f,
|
||||
0x9a, 0xe4, 0xb8, 0x76, 0xdc, 0x34, 0xe3, 0xee,
|
||||
0x5f, 0xdd, 0x13, 0x20, 0x08, 0xdc, 0x4e, 0x6f,
|
||||
0x4e, 0x9f, 0xc0, 0x36, 0xf9, 0xce, 0xc6, 0xb7,
|
||||
0xdb, 0xe0, 0x51, 0x2d, 0x30, 0x0b, 0xae, 0x0a,
|
||||
0x20, 0xd2, 0x29, 0x3c, 0x2c, 0x1d, 0x87, 0x65,
|
||||
0xeb, 0x5f, 0x93, 0xd7, 0x3f, 0x12, 0x08, 0x50,
|
||||
0x0e, 0x55, 0xf3, 0xf1, 0x19, 0xee, 0x18, 0x21,
|
||||
0x6e, 0xea, 0xb6, 0x0a, 0x4a, 0x0b, 0x9c, 0x72,
|
||||
0x37, 0xeb, 0x0b, 0x68, 0xfc, 0x52, 0x46, 0x62,
|
||||
0xd0, 0xa2, 0x99, 0x66, 0xe2, 0x2b, 0x74, 0xdd,
|
||||
0x5c, 0xaf, 0x9a, 0x03, 0xc4, 0x5d, 0x93, 0xfb,
|
||||
0xcd, 0x45, 0x9a, 0xee, 0xfb, 0x7b, 0x18, 0x94,
|
||||
0xc1, 0x8c, 0x82, 0x34, 0x7f, 0x02, 0x12, 0x21,
|
||||
0xfc, 0x40, 0xc1, 0x50, 0xc9, 0xf4, 0x7c, 0xd5,
|
||||
0x96, 0xbe, 0x55, 0x7f, 0x3c, 0x1d, 0x70, 0x34,
|
||||
0xb4, 0xa2, 0x03, 0xc4, 0x3f, 0x89, 0x60, 0xe4,
|
||||
0x24, 0x09, 0x1a, 0x74, 0xc4, 0xb6, 0x39, 0xf0,
|
||||
0x34, 0x60, 0x8e, 0xa7, 0x5f, 0x02, 0x7f, 0xb9,
|
||||
0x2a, 0xc5, 0xaa, 0xb2, 0x4c, 0x34, 0xd3, 0x5a,
|
||||
0x5d, 0xfa, 0x07, 0xf2, 0xb9, 0xb3, 0xc1, 0xba,
|
||||
0xab, 0xbe, 0x89, 0x99, 0xe3, 0x6d, 0x9b, 0xa9,
|
||||
0xd3, 0xaf, 0x2a, 0x08, 0x76, 0xf3, 0x0e, 0xc9,
|
||||
0xe0, 0xb3, 0xbf, 0x51, 0x0c, 0xc5, 0xf4, 0xf3,
|
||||
0x15, 0x7b, 0x08, 0x11, 0x8f, 0x61, 0x1f, 0x61,
|
||||
0x64, 0xdb, 0x15, 0x84, 0x5b, 0x8a, 0xd1, 0x28,
|
||||
0x40, 0xde, 0xc5, 0x32, 0xb5, 0xad, 0xad, 0x65,
|
||||
0x4c, 0xf5, 0xf7, 0xd1, 0x90, 0x14, 0x5d, 0xc2,
|
||||
0x85, 0x98, 0xcc, 0xe9, 0xe6, 0x95, 0x42, 0xe1,
|
||||
0x3e, 0xfc, 0x7f, 0xc4, 0x49, 0xed, 0x9c, 0xe4,
|
||||
0x49, 0x3f, 0x03, 0x1b, 0x0d, 0xa0, 0xfb, 0xf5,
|
||||
0x38, 0x49, 0xd2, 0xdf, 0xa3, 0x88, 0xb2, 0x76,
|
||||
0x93, 0x08, 0x20, 0x18, 0xfe, 0xdc, 0x72, 0x6c,
|
||||
0x6e, 0xbf, 0x61, 0x37, 0x03, 0xdb, 0xe5, 0x72,
|
||||
0x68, 0xe0, 0x99, 0x2f, 0xb9, 0xe0, 0x2e, 0xbb,
|
||||
0x9f, 0x96, 0x36, 0x61, 0xaa, 0x2d, 0xa4, 0x93,
|
||||
0xe8, 0x50, 0x58, 0xe6, 0x61, 0xe1, 0x14, 0xcf,
|
||||
0xac, 0x86, 0x98, 0x7f, 0x3c, 0x67, 0x16, 0xce,
|
||||
0xb8, 0x70, 0x90, 0x3a, 0x5a, 0xd4, 0xe1, 0xe2,
|
||||
0x35, 0x98, 0xbf, 0x93, 0x41, 0x11, 0xb2, 0x44,
|
||||
0xb2, 0x64, 0xc2, 0xe7, 0x09, 0x45, 0xb7, 0x6f,
|
||||
0xb0, 0xbd, 0x6e, 0xe8, 0x67, 0xfa, 0x8d, 0xd4,
|
||||
0xfa, 0x4b, 0xef, 0xa8, 0x9d, 0x8a, 0x0a, 0xd9,
|
||||
0x14, 0x77, 0x09, 0x11, 0x9e, 0xc3, 0x50, 0x14,
|
||||
0x6c, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0x12,
|
||||
0x80, 0x03, 0x17, 0x01, 0x60, 0x24, 0xe1, 0xfd,
|
||||
0x75, 0x60, 0x17, 0x5c, 0x5e, 0x6f, 0x9f, 0x7f,
|
||||
0xdf, 0xee, 0xf0, 0xf7, 0x7d, 0xb2, 0x50, 0x65,
|
||||
0x36, 0x26, 0x14, 0x19, 0x01, 0x5e, 0x98, 0x94,
|
||||
0x65, 0x97, 0x83, 0xaa, 0x4a, 0x2b, 0x98, 0x2e,
|
||||
0x02, 0xf3, 0xb2, 0xc9, 0xb2, 0xed, 0xd3, 0x1b,
|
||||
0x20, 0x27, 0x9e, 0xe1, 0x25, 0xc7, 0x86, 0xf0,
|
||||
0x66, 0x68, 0x5d, 0xd2, 0x3d, 0xa7, 0xbb, 0xbc,
|
||||
0x22, 0xfc, 0x29, 0xfa, 0x17, 0x16, 0xf4, 0xa2,
|
||||
0x00, 0x10, 0x87, 0xb4, 0x5d, 0x51, 0x45, 0x6b,
|
||||
0xc8, 0xf4, 0x6b, 0xcc, 0x92, 0x91, 0xe7, 0xa7,
|
||||
0x93, 0xbc, 0xc7, 0x2e, 0xdc, 0xac, 0x82, 0x2b,
|
||||
0x85, 0x56, 0x7b, 0xae, 0xf2, 0xd8, 0xda, 0xa6,
|
||||
0xd7, 0xfa, 0x6d, 0x70, 0x2a, 0x2e, 0xcf, 0x69,
|
||||
0xef, 0x57, 0x91, 0xa7, 0xaa, 0x40, 0x15, 0x4a,
|
||||
0x49, 0x1b, 0xbc, 0x36, 0xbb, 0x1c, 0x94, 0x33,
|
||||
0x36, 0x61, 0x22, 0x9d, 0x22, 0x66, 0xf0, 0x88,
|
||||
0x5e, 0x7c, 0x3c, 0xa5, 0xff, 0x81, 0xcf, 0x1a,
|
||||
0x44, 0xa1, 0x2b, 0xdf, 0xc9, 0x3d, 0xd5, 0xc7,
|
||||
0xc7, 0x3a, 0x75, 0xac, 0x29, 0xfa, 0xfd, 0x5b,
|
||||
0xda, 0xf5, 0x8f, 0xd9, 0xdf, 0x08, 0xa4, 0x8d,
|
||||
0x19, 0x4a, 0xa4, 0x79, 0x6e, 0x47, 0xf6, 0x07,
|
||||
0xe0, 0xbd, 0xbf, 0x30, 0x3a, 0xf9, 0xf5, 0xc0,
|
||||
0x90, 0x6d, 0x70, 0x27, 0x44, 0xa8, 0x5e, 0x70,
|
||||
0xcd, 0x43, 0x3e, 0xaf, 0xf0, 0xd7, 0x20, 0xd3,
|
||||
0x5e, 0x97, 0x2d, 0x32, 0x1a, 0x3d, 0x2d, 0x0f,
|
||||
0x0f, 0xcf, 0xac, 0x4e, 0x88, 0x75, 0x98, 0x6c,
|
||||
0xfa, 0xe8, 0x42, 0x58, 0x99, 0xaa, 0x45, 0x0c,
|
||||
0x41, 0x0c, 0x6e, 0x27, 0x58, 0x57, 0xd2, 0x5b,
|
||||
0x82, 0x3d, 0x75, 0x2f, 0x9e, 0xf3, 0xe4, 0x00,
|
||||
0xcf, 0x91, 0x48, 0x25, 0xca, 0x98, 0xf2, 0x91,
|
||||
0x6b, 0x41, 0xa5, 0xe8, 0xcd, 0x64, 0xa7, 0x2e,
|
||||
0x78, 0xc7, 0x76, 0x82, 0x3f, 0xf8, 0x57, 0x8a,
|
||||
0x9d, 0x78, 0x25, 0xad, 0xf3, 0x1a, 0x8b, 0xfc,
|
||||
0x83, 0x9a, 0x98, 0x87, 0xe4, 0x55, 0x3e, 0x1c,
|
||||
0xa7, 0x80, 0x8f, 0xd6, 0x76, 0xab, 0x03, 0xc7,
|
||||
0x05, 0x66, 0xc3, 0xa0, 0x4c, 0x33, 0x1f, 0x39,
|
||||
0x74, 0x1b, 0x2a, 0xbf, 0xe6, 0xb0, 0x9f, 0x6b,
|
||||
0xc1, 0xd6, 0xd3, 0xf4, 0x46, 0x9b, 0xf3, 0xab,
|
||||
0xca, 0x2e, 0x88, 0x3d, 0x84, 0x5f, 0xc9, 0x9b,
|
||||
0x47, 0xbb, 0x57, 0x64, 0x08, 0x0e, 0x18, 0x74,
|
||||
0x83, 0x44, 0xd4, 0xc3, 0x18, 0x97, 0xcf, 0x89,
|
||||
0x6a, 0x49, 0x51, 0xc6, 0xff, 0x8d, 0x39, 0xc5,
|
||||
0x23, 0xf9, 0xd5, 0x01, 0xd7, 0x2f, 0xa9, 0xa5,
|
||||
0x5d, 0xa9, 0xf3, 0xc9, 0xfd, 0xc4, 0x52, 0x19,
|
||||
0x7d, 0xf6, 0xa4, 0x2c, 0x0c, 0xa0, 0x07, 0xdf,
|
||||
0x7b, 0x44, 0xd7, 0xe5, 0xbf, 0x57, 0x87, 0xc9,
|
||||
0x8c, 0xfe, 0x30, 0xb2, 0x89, 0x5d, 0x00, 0x03,
|
||||
0x3b, 0xe5
|
||||
};
|
||||
|
||||
static const unsigned char kRootCertForProd[] = {
|
||||
0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00,
|
||||
0x18, 0xdd, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e,
|
||||
0x03, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01,
|
||||
0x81, 0x00, 0xb4, 0xfe, 0x39, 0xc3, 0x65, 0x90,
|
||||
0x03, 0xdb, 0x3c, 0x11, 0x97, 0x09, 0xe8, 0x68,
|
||||
0xcd, 0xf2, 0xc3, 0x5e, 0x9b, 0xf2, 0xe7, 0x4d,
|
||||
0x23, 0xb1, 0x10, 0xdb, 0x87, 0x65, 0xdf, 0xdc,
|
||||
0xfb, 0x9f, 0x35, 0xa0, 0x57, 0x03, 0x53, 0x4c,
|
||||
0xf6, 0x6d, 0x35, 0x7d, 0xa6, 0x78, 0xdb, 0xb3,
|
||||
0x36, 0xd2, 0x3f, 0x9c, 0x40, 0xa9, 0x95, 0x26,
|
||||
0x72, 0x7f, 0xb8, 0xbe, 0x66, 0xdf, 0xc5, 0x21,
|
||||
0x98, 0x78, 0x15, 0x16, 0x68, 0x5d, 0x2f, 0x46,
|
||||
0x0e, 0x43, 0xcb, 0x8a, 0x84, 0x39, 0xab, 0xfb,
|
||||
0xb0, 0x35, 0x80, 0x22, 0xbe, 0x34, 0x23, 0x8b,
|
||||
0xab, 0x53, 0x5b, 0x72, 0xec, 0x4b, 0xb5, 0x48,
|
||||
0x69, 0x53, 0x3e, 0x47, 0x5f, 0xfd, 0x09, 0xfd,
|
||||
0xa7, 0x76, 0x13, 0x8f, 0x0f, 0x92, 0xd6, 0x4c,
|
||||
0xdf, 0xae, 0x76, 0xa9, 0xba, 0xd9, 0x22, 0x10,
|
||||
0xa9, 0x9d, 0x71, 0x45, 0xd6, 0xd7, 0xe1, 0x19,
|
||||
0x25, 0x85, 0x9c, 0x53, 0x9a, 0x97, 0xeb, 0x84,
|
||||
0xd7, 0xcc, 0xa8, 0x88, 0x82, 0x20, 0x70, 0x26,
|
||||
0x20, 0xfd, 0x7e, 0x40, 0x50, 0x27, 0xe2, 0x25,
|
||||
0x93, 0x6f, 0xbc, 0x3e, 0x72, 0xa0, 0xfa, 0xc1,
|
||||
0xbd, 0x29, 0xb4, 0x4d, 0x82, 0x5c, 0xc1, 0xb4,
|
||||
0xcb, 0x9c, 0x72, 0x7e, 0xb0, 0xe9, 0x8a, 0x17,
|
||||
0x3e, 0x19, 0x63, 0xfc, 0xfd, 0x82, 0x48, 0x2b,
|
||||
0xb7, 0xb2, 0x33, 0xb9, 0x7d, 0xec, 0x4b, 0xba,
|
||||
0x89, 0x1f, 0x27, 0xb8, 0x9b, 0x88, 0x48, 0x84,
|
||||
0xaa, 0x18, 0x92, 0x0e, 0x65, 0xf5, 0xc8, 0x6c,
|
||||
0x11, 0xff, 0x6b, 0x36, 0xe4, 0x74, 0x34, 0xca,
|
||||
0x8c, 0x33, 0xb1, 0xf9, 0xb8, 0x8e, 0xb4, 0xe6,
|
||||
0x12, 0xe0, 0x02, 0x98, 0x79, 0x52, 0x5e, 0x45,
|
||||
0x33, 0xff, 0x11, 0xdc, 0xeb, 0xc3, 0x53, 0xba,
|
||||
0x7c, 0x60, 0x1a, 0x11, 0x3d, 0x00, 0xfb, 0xd2,
|
||||
0xb7, 0xaa, 0x30, 0xfa, 0x4f, 0x5e, 0x48, 0x77,
|
||||
0x5b, 0x17, 0xdc, 0x75, 0xef, 0x6f, 0xd2, 0x19,
|
||||
0x6d, 0xdc, 0xbe, 0x7f, 0xb0, 0x78, 0x8f, 0xdc,
|
||||
0x82, 0x60, 0x4c, 0xbf, 0xe4, 0x29, 0x06, 0x5e,
|
||||
0x69, 0x8c, 0x39, 0x13, 0xad, 0x14, 0x25, 0xed,
|
||||
0x19, 0xb2, 0xf2, 0x9f, 0x01, 0x82, 0x0d, 0x56,
|
||||
0x44, 0x88, 0xc8, 0x35, 0xec, 0x1f, 0x11, 0xb3,
|
||||
0x24, 0xe0, 0x59, 0x0d, 0x37, 0xe4, 0x47, 0x3c,
|
||||
0xea, 0x4b, 0x7f, 0x97, 0x31, 0x1c, 0x81, 0x7c,
|
||||
0x94, 0x8a, 0x4c, 0x7d, 0x68, 0x15, 0x84, 0xff,
|
||||
0xa5, 0x08, 0xfd, 0x18, 0xe7, 0xe7, 0x2b, 0xe4,
|
||||
0x47, 0x27, 0x12, 0x11, 0xb8, 0x23, 0xec, 0x58,
|
||||
0x93, 0x3c, 0xac, 0x12, 0xd2, 0x88, 0x6d, 0x41,
|
||||
0x3d, 0xc5, 0xfe, 0x1c, 0xdc, 0xb9, 0xf8, 0xd4,
|
||||
0x51, 0x3e, 0x07, 0xe5, 0x03, 0x6f, 0xa7, 0x12,
|
||||
0xe8, 0x12, 0xf7, 0xb5, 0xce, 0xa6, 0x96, 0x55,
|
||||
0x3f, 0x78, 0xb4, 0x64, 0x82, 0x50, 0xd2, 0x33,
|
||||
0x5f, 0x91, 0x02, 0x03, 0x01, 0x00, 0x01, 0x12,
|
||||
0x80, 0x03, 0x58, 0xf1, 0xd6, 0x4d, 0x04, 0x09,
|
||||
0x7b, 0xdf, 0xd7, 0xef, 0x5d, 0x3b, 0x02, 0x39,
|
||||
0x17, 0xfa, 0x14, 0x36, 0x75, 0x4a, 0x38, 0x67,
|
||||
0x85, 0x57, 0x12, 0xa7, 0x14, 0xee, 0x35, 0x16,
|
||||
0xd5, 0x3d, 0xbf, 0x42, 0x86, 0xf6, 0x69, 0x00,
|
||||
0x76, 0xcd, 0x93, 0xf4, 0x7c, 0xb2, 0xdf, 0x9e,
|
||||
0x44, 0xcd, 0x4c, 0xd4, 0xae, 0x09, 0x18, 0x53,
|
||||
0x44, 0x32, 0xec, 0xe0, 0x61, 0x1b, 0xe5, 0xda,
|
||||
0x13, 0xd3, 0x55, 0xc5, 0xdd, 0x1a, 0xcb, 0x90,
|
||||
0x1e, 0x7e, 0x5b, 0xc6, 0xe9, 0x0f, 0x22, 0x9f,
|
||||
0xbe, 0x85, 0x02, 0xfe, 0x90, 0x31, 0xcc, 0x6b,
|
||||
0x03, 0x84, 0xbd, 0x22, 0xc4, 0x55, 0xfa, 0xf5,
|
||||
0xf2, 0x08, 0xcd, 0x65, 0x41, 0x58, 0xe8, 0x7d,
|
||||
0x29, 0xda, 0x04, 0x58, 0x82, 0xf5, 0x37, 0x69,
|
||||
0xbc, 0xf3, 0x5a, 0x57, 0x84, 0x17, 0x7b, 0x32,
|
||||
0x87, 0x70, 0xb2, 0xb0, 0x76, 0x9c, 0xb2, 0xc3,
|
||||
0x15, 0xd1, 0x11, 0x26, 0x2a, 0x23, 0x75, 0x99,
|
||||
0x3e, 0xb9, 0x77, 0x22, 0x32, 0x0d, 0xbc, 0x1a,
|
||||
0x19, 0xc1, 0xd5, 0x65, 0x90, 0x76, 0x55, 0x74,
|
||||
0x0f, 0x0e, 0x69, 0x4d, 0x5f, 0x4d, 0x8f, 0x19,
|
||||
0xaf, 0xdf, 0xd6, 0x16, 0x31, 0x94, 0xa8, 0x92,
|
||||
0x5f, 0x4f, 0xbc, 0x7a, 0x31, 0xf8, 0xae, 0x8e,
|
||||
0xad, 0x33, 0xb7, 0xe9, 0x30, 0xd0, 0x8c, 0x0a,
|
||||
0x8a, 0x6c, 0x83, 0x35, 0xf8, 0x8a, 0x81, 0xb2,
|
||||
0xfe, 0x1c, 0x88, 0xac, 0x2a, 0x66, 0xc5, 0xff,
|
||||
0xbd, 0xe6, 0x17, 0xd0, 0x62, 0x0b, 0xdc, 0x8a,
|
||||
0x45, 0xf7, 0xb0, 0x3e, 0x5a, 0xc8, 0x1e, 0x4a,
|
||||
0x24, 0x2f, 0x6c, 0xa5, 0xe3, 0x1c, 0x88, 0x14,
|
||||
0x83, 0xd5, 0xc5, 0xef, 0x5e, 0x9f, 0x3d, 0x85,
|
||||
0x45, 0x73, 0xe2, 0x6b, 0x50, 0x52, 0x57, 0x4c,
|
||||
0xfb, 0x92, 0x6c, 0x66, 0x75, 0x8a, 0xd6, 0x0d,
|
||||
0x1b, 0xae, 0xf3, 0xec, 0xaf, 0x51, 0x22, 0x03,
|
||||
0x5d, 0x0a, 0x2e, 0x63, 0x93, 0x9c, 0x0b, 0x01,
|
||||
0x20, 0xa8, 0xa9, 0x84, 0x2e, 0x17, 0xca, 0xae,
|
||||
0x73, 0xec, 0x22, 0x1b, 0x79, 0xae, 0xf6, 0xa0,
|
||||
0x72, 0x2c, 0xdf, 0x07, 0x47, 0xdb, 0x88, 0x86,
|
||||
0x30, 0x14, 0x78, 0x21, 0x11, 0x22, 0x88, 0xac,
|
||||
0xd7, 0x54, 0x74, 0xf9, 0xf3, 0x26, 0xc2, 0xa5,
|
||||
0x56, 0xc8, 0x56, 0x4f, 0x00, 0x29, 0x1d, 0x08,
|
||||
0x7b, 0x7a, 0xfb, 0x95, 0x89, 0xc3, 0xee, 0x98,
|
||||
0x54, 0x9e, 0x3c, 0x6b, 0x94, 0x05, 0x13, 0x12,
|
||||
0xf6, 0x71, 0xb9, 0xab, 0x13, 0xc3, 0x0c, 0x9b,
|
||||
0x46, 0x08, 0x7b, 0x3d, 0x32, 0x6a, 0x68, 0xca,
|
||||
0x1e, 0x9c, 0x90, 0x62, 0xc5, 0xed, 0x10, 0xb9,
|
||||
0x1f, 0x17, 0x25, 0xce, 0x90, 0xb9, 0x6d, 0xcd,
|
||||
0xc4, 0x46, 0xf5, 0xa3, 0x62, 0x13, 0x74, 0x02,
|
||||
0xa7, 0x62, 0xa4, 0xfa, 0x55, 0xd9, 0xde, 0xcf,
|
||||
0xa2, 0xe6, 0x80, 0x74, 0x55, 0x06, 0x49, 0xd5,
|
||||
0x02, 0x0c
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -57,46 +230,82 @@ using video_widevine::EncryptedClientIdentification;
|
||||
using video_widevine::SignedDrmDeviceCertificate;
|
||||
using video_widevine::SignedMessage;
|
||||
|
||||
void ServiceCertificate::Clear() {
|
||||
fetch_in_progress_ = false;
|
||||
certificate_.clear();
|
||||
provider_id_.clear();
|
||||
}
|
||||
CdmResponseType ServiceCertificate::Init(const std::string& certificate) {
|
||||
// TODO(tinskip): Get rid of conditional compilation.
|
||||
#if defined(QA_TEST_SERVER)
|
||||
std::string root_cert_str(reinterpret_cast<const char*>(&kRootCertForDev[0]),
|
||||
sizeof(kRootCertForDev));
|
||||
#else
|
||||
std::string root_cert_str(reinterpret_cast<const char*>(&kRootCertForProd[0]),
|
||||
sizeof(kRootCertForProd));
|
||||
#endif // !defined(QA_TEST_SERVER);
|
||||
|
||||
CdmResponseType ServiceCertificate::Init(const std::string& raw_certificate) {
|
||||
return VerifyAndExtract(raw_certificate);
|
||||
// Load root cert public key. Don't bother verifying it.
|
||||
SignedDrmDeviceCertificate signed_root_cert;
|
||||
if (!signed_root_cert.ParseFromString(root_cert_str)) {
|
||||
LOGE("Failed to deserialize signed root certificate.");
|
||||
return DEVICE_CERTIFICATE_ERROR_1;
|
||||
}
|
||||
DrmDeviceCertificate root_cert;
|
||||
if (!root_cert.ParseFromString(signed_root_cert.drm_certificate())) {
|
||||
LOGE("Failed to deserialize signed root certificate.");
|
||||
return DEVICE_CERTIFICATE_ERROR_1;
|
||||
}
|
||||
RsaPublicKey root_key;
|
||||
if (!root_key.Init(root_cert.public_key())) {
|
||||
LOGE("Failed to load root certificate public key.");
|
||||
return DEVICE_CERTIFICATE_ERROR_1;
|
||||
}
|
||||
|
||||
// Load the provided service certificate.
|
||||
// First, parse it and verify its signature.
|
||||
SignedDrmDeviceCertificate signed_service_cert;
|
||||
if (!signed_service_cert.ParseFromString(certificate)) {
|
||||
LOGE("Failed to parse signed service certificate.");
|
||||
return DEVICE_CERTIFICATE_ERROR_2;
|
||||
}
|
||||
if (!root_key.VerifySignature(signed_service_cert.drm_certificate(),
|
||||
signed_service_cert.signature())) {
|
||||
LOGE("Service certificate signature verification failed.");
|
||||
return DEVICE_CERTIFICATE_ERROR_3;
|
||||
}
|
||||
DrmDeviceCertificate service_cert;
|
||||
if (!service_cert.ParseFromString(signed_service_cert.drm_certificate())) {
|
||||
LOGE("Failed to parse service certificate.");
|
||||
return DEVICE_CERTIFICATE_ERROR_2;
|
||||
}
|
||||
if (service_cert.type() !=
|
||||
video_widevine::DrmDeviceCertificate_CertificateType_SERVICE) {
|
||||
LOGE("Not a service certificate.");
|
||||
return DEVICE_CERTIFICATE_ERROR_3;
|
||||
}
|
||||
|
||||
// Service certificate passes all checks - set up its RSA public key.
|
||||
public_key_.reset(new RsaPublicKey);
|
||||
if (!public_key_->Init(service_cert.public_key())) {
|
||||
public_key_.reset();
|
||||
LOGE("Failed to load service certificate public key.");
|
||||
return DEVICE_CERTIFICATE_ERROR_2;
|
||||
}
|
||||
|
||||
// Have service certificate and its public key - keep relevant fields.
|
||||
certificate_ = certificate;
|
||||
serial_number_ = service_cert.serial_number();
|
||||
provider_id_ = service_cert.provider_id();
|
||||
has_certificate_ = true;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType ServiceCertificate::VerifySignedMessage(
|
||||
const std::string& message, const std::string& signature) {
|
||||
|
||||
if (certificate_.empty()) {
|
||||
LOGE("ServiceCertificate::VerifySignedMessage: "
|
||||
"service certificate is not properly initialized");
|
||||
return UNKNOWN_ERROR;
|
||||
if (!public_key_) {
|
||||
LOGE("Service certificate not set.");
|
||||
return DEVICE_CERTIFICATE_ERROR_4;
|
||||
}
|
||||
|
||||
DrmDeviceCertificate service_certificate;
|
||||
if (!service_certificate.ParseFromString(certificate_)) {
|
||||
LOGE("ServiceCertificate::EncryptClientId: unable to parse retrieved "
|
||||
"service certificate");
|
||||
return PARSE_SERVICE_CERTIFICATE_ERROR;
|
||||
}
|
||||
|
||||
if (service_certificate.type() !=
|
||||
video_widevine::DrmDeviceCertificate_CertificateType_SERVICE) {
|
||||
LOGE("ServiceCertificate::EncryptClientId: retrieved certificate not of "
|
||||
"type service, %d", service_certificate.type());
|
||||
return SERVICE_CERTIFICATE_TYPE_ERROR;
|
||||
}
|
||||
|
||||
// TODO(gm) verify; rework error codes.
|
||||
RsaPublicKey rsa;
|
||||
if (!rsa.Init(service_certificate.public_key()))
|
||||
return CLIENT_ID_RSA_INIT_ERROR;
|
||||
|
||||
if (!rsa.VerifySignature(message, signature))
|
||||
return CLIENT_ID_RSA_ENCRYPT_ERROR;
|
||||
if (!public_key_->VerifySignature(message, signature))
|
||||
return CLIENT_ID_RSA_ENCRYPT_ERROR; // TODO(tinskip): Need new error code.
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -104,28 +313,13 @@ CdmResponseType ServiceCertificate::VerifySignedMessage(
|
||||
CdmResponseType ServiceCertificate::EncryptClientId(
|
||||
CryptoSession* crypto_session, const ClientIdentification* clear_client_id,
|
||||
EncryptedClientIdentification* encrypted_client_id) {
|
||||
DrmDeviceCertificate service_certificate;
|
||||
|
||||
if (certificate_.empty()) {
|
||||
LOGE("ServiceCertificate::EncryptClientId: "
|
||||
"service certificate is not properly initialized");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (!service_certificate.ParseFromString(certificate_)) {
|
||||
LOGE("ServiceCertificate::EncryptClientId: unable to parse retrieved "
|
||||
"service certificate");
|
||||
return PARSE_SERVICE_CERTIFICATE_ERROR;
|
||||
if (!public_key_) {
|
||||
LOGE("Service certificate not set.");
|
||||
return DEVICE_CERTIFICATE_ERROR_4;
|
||||
}
|
||||
|
||||
if (service_certificate.type() !=
|
||||
video_widevine::DrmDeviceCertificate_CertificateType_SERVICE) {
|
||||
LOGE("ServiceCertificate::EncryptClientId: retrieved certificate not of "
|
||||
"type service, %d", service_certificate.type());
|
||||
return SERVICE_CERTIFICATE_TYPE_ERROR;
|
||||
}
|
||||
encrypted_client_id->set_provider_id(service_certificate.provider_id());
|
||||
encrypted_client_id->set_service_certificate_serial_number(
|
||||
service_certificate.serial_number());
|
||||
encrypted_client_id->set_provider_id(provider_id_);
|
||||
encrypted_client_id->set_service_certificate_serial_number(serial_number_);
|
||||
|
||||
std::string iv(KEY_IV_SIZE, 0);
|
||||
std::string key(KEY_SIZE, 0);
|
||||
@@ -143,10 +337,8 @@ CdmResponseType ServiceCertificate::EncryptClientId(
|
||||
if (!aes.Init(key)) return CLIENT_ID_AES_INIT_ERROR;
|
||||
if (!aes.Encrypt(id, &enc_id, &iv)) return CLIENT_ID_AES_ENCRYPT_ERROR;
|
||||
|
||||
RsaPublicKey rsa;
|
||||
if (!rsa.Init(service_certificate.public_key()))
|
||||
return CLIENT_ID_RSA_INIT_ERROR;
|
||||
if (!rsa.Encrypt(key, &enc_key)) return CLIENT_ID_RSA_ENCRYPT_ERROR;
|
||||
if (!public_key_->Encrypt(key, &enc_key))
|
||||
return CLIENT_ID_RSA_ENCRYPT_ERROR;
|
||||
|
||||
encrypted_client_id->set_encrypted_client_id_iv(iv);
|
||||
encrypted_client_id->set_encrypted_privacy_key(enc_key);
|
||||
@@ -154,97 +346,4 @@ CdmResponseType ServiceCertificate::EncryptClientId(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool ServiceCertificate::PrepareRequest(CdmKeyMessage* signed_request) {
|
||||
if (!signed_request) {
|
||||
LOGE("ServiceCertificate::PrepareRequest: no signed request provided");
|
||||
return false;
|
||||
}
|
||||
SignedMessage signed_message;
|
||||
signed_message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST);
|
||||
signed_message.SerializeToString(signed_request);
|
||||
|
||||
fetch_in_progress_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType ServiceCertificate::HandleResponse(
|
||||
const std::string& signed_response) {
|
||||
if (!fetch_in_progress_) {
|
||||
LOGE("ServiceCertificate::HandleResponse: unexpected service "
|
||||
"certificate response.");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
fetch_in_progress_ = false;
|
||||
CdmResponseType status = VerifyAndExtract(signed_response);
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType ServiceCertificate::VerifyAndExtract(
|
||||
const std::string& raw_certificate) {
|
||||
if (raw_certificate.empty()) {
|
||||
Clear();
|
||||
return NO_ERROR;
|
||||
}
|
||||
// Deserialize and parse raw certificate.
|
||||
SignedDrmDeviceCertificate signed_service_certificate;
|
||||
if (!signed_service_certificate.ParseFromString(raw_certificate)) {
|
||||
LOGE(
|
||||
"ServiceCertificate::VerifyAndExtract: unable to parse signed "
|
||||
"service certificate");
|
||||
return DEVICE_CERTIFICATE_ERROR_1;
|
||||
}
|
||||
|
||||
// Set up root key (for verifying signature).
|
||||
RsaPublicKey root_ca_key;
|
||||
std::string ca_public_key(
|
||||
reinterpret_cast<const char*>(&kServiceCertificateCAPublicKey[0]),
|
||||
sizeof(kServiceCertificateCAPublicKey));
|
||||
if (!root_ca_key.Init(ca_public_key)) {
|
||||
LOGE(
|
||||
"ServiceCertificate::VerifyAndExtract: public key initialization "
|
||||
"failed");
|
||||
return DEVICE_CERTIFICATE_ERROR_2;
|
||||
}
|
||||
|
||||
// Verify the signature.
|
||||
if (!root_ca_key.VerifySignature(
|
||||
signed_service_certificate.drm_certificate(),
|
||||
signed_service_certificate.signature())) {
|
||||
LOGE(
|
||||
"ServiceCertificate::VerifyAndExtract: service certificate "
|
||||
"verification failed");
|
||||
return DEVICE_CERTIFICATE_ERROR_3;
|
||||
}
|
||||
|
||||
// Deserialize and parse actual certificate.
|
||||
DrmDeviceCertificate service_certificate;
|
||||
if (!service_certificate.ParseFromString(
|
||||
signed_service_certificate.drm_certificate())) {
|
||||
LOGE(
|
||||
"ServiceCertificate::VerifyAndExtract: unable to parse retrieved "
|
||||
"service certificate");
|
||||
return DEVICE_CERTIFICATE_ERROR_4;
|
||||
}
|
||||
|
||||
// Verify, extract needed fields.
|
||||
if (service_certificate.type() !=
|
||||
video_widevine::DrmDeviceCertificate_CertificateType_SERVICE) {
|
||||
LOGE(
|
||||
"ServiceCertificate::VerifyAndExtract: certificate not of type "
|
||||
"service, %d", service_certificate.type());
|
||||
return INVALID_DEVICE_CERTIFICATE_TYPE;
|
||||
}
|
||||
if (service_certificate.has_provider_id()) {
|
||||
provider_id_.assign(service_certificate.provider_id());
|
||||
} else {
|
||||
provider_id_.clear();
|
||||
}
|
||||
certificate_.assign(signed_service_certificate.drm_certificate());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -24,6 +24,7 @@ UsageTableHeader::UsageTableHeader()
|
||||
: security_level_(kSecurityLevelUninitialized),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_inited_(false) {
|
||||
file_system_.reset(new FileSystem());
|
||||
file_handle_.reset(new DeviceFiles(file_system_.get()));
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
|
||||
|
||||
metrics::CryptoMetrics alternate_metrics;
|
||||
metrics::CryptoMetrics* metrics =
|
||||
crypto_session->GetCryptoMetrics() != nullptr ?
|
||||
crypto_session->GetCryptoMetrics() != NULL ?
|
||||
crypto_session->GetCryptoMetrics() : &alternate_metrics;
|
||||
|
||||
UpgradeFromUsageTable(file_handle_.get(), metrics);
|
||||
|
||||
Reference in New Issue
Block a user