Merge "Validate Service Certificates Before Accepting Them" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6dbc3749b0
@@ -59,6 +59,9 @@ class CdmLicense {
|
|||||||
return provider_session_token_;
|
return provider_session_token_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CdmResponseType VerifySignedServiceCertificate(
|
||||||
|
const std::string& signed_service_certificate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
bool PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
||||||
std::string* server_url);
|
std::string* server_url);
|
||||||
@@ -74,7 +77,7 @@ class CdmLicense {
|
|||||||
bool PrepareContentId(const CdmLicenseType license_type,
|
bool PrepareContentId(const CdmLicenseType license_type,
|
||||||
const std::string& request_id, T* content_id);
|
const std::string& request_id, T* content_id);
|
||||||
|
|
||||||
CdmResponseType VerifySignedServiceCertificate(
|
static CdmResponseType VerifyAndExtractSignedServiceCertificate(
|
||||||
const std::string& signed_service_certificate,
|
const std::string& signed_service_certificate,
|
||||||
std::string* service_certificate);
|
std::string* service_certificate);
|
||||||
bool GetServiceCertificate(const CdmSessionId& session_id,
|
bool GetServiceCertificate(const CdmSessionId& session_id,
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
|||||||
case SignedMessage::LICENSE:
|
case SignedMessage::LICENSE:
|
||||||
break;
|
break;
|
||||||
case SignedMessage::SERVICE_CERTIFICATE: {
|
case SignedMessage::SERVICE_CERTIFICATE: {
|
||||||
CdmResponseType status = CdmLicense::VerifySignedServiceCertificate(
|
CdmResponseType status = VerifyAndExtractSignedServiceCertificate(
|
||||||
signed_response.msg(), &service_certificate_);
|
signed_response.msg(), &service_certificate_);
|
||||||
return status == NO_ERROR ? NEED_KEY : status;
|
return status == NO_ERROR ? NEED_KEY : status;
|
||||||
}
|
}
|
||||||
@@ -553,7 +553,7 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
|||||||
case SignedMessage::LICENSE:
|
case SignedMessage::LICENSE:
|
||||||
break;
|
break;
|
||||||
case SignedMessage::SERVICE_CERTIFICATE: {
|
case SignedMessage::SERVICE_CERTIFICATE: {
|
||||||
CdmResponseType status = CdmLicense::VerifySignedServiceCertificate(
|
CdmResponseType status = VerifyAndExtractSignedServiceCertificate(
|
||||||
signed_response.msg(), &service_certificate_);
|
signed_response.msg(), &service_certificate_);
|
||||||
return status == NO_ERROR ? NEED_KEY : status;
|
return status == NO_ERROR ? NEED_KEY : status;
|
||||||
}
|
}
|
||||||
@@ -783,6 +783,12 @@ bool CdmLicense::IsKeyLoaded(const KeyId& key_id) {
|
|||||||
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
||||||
|
const std::string& signed_service_certificate) {
|
||||||
|
return VerifyAndExtractSignedServiceCertificate(signed_service_certificate,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
||||||
std::string* server_url) {
|
std::string* server_url) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
@@ -809,12 +815,12 @@ bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
CdmResponseType CdmLicense::VerifyAndExtractSignedServiceCertificate(
|
||||||
const std::string& signed_certificate, std::string* certificate) {
|
const std::string& signed_certificate, std::string* certificate) {
|
||||||
SignedDeviceCertificate signed_service_certificate;
|
SignedDeviceCertificate signed_service_certificate;
|
||||||
if (!signed_service_certificate.ParseFromString(signed_certificate)) {
|
if (!signed_service_certificate.ParseFromString(signed_certificate)) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::VerifySignedServiceCertificate: unable to parse"
|
"CdmLicense::VerifyAndExtractSignedServiceCertificate: unable to parse "
|
||||||
"signed device certificate");
|
"signed device certificate");
|
||||||
return DEVICE_CERTIFICATE_ERROR_1;
|
return DEVICE_CERTIFICATE_ERROR_1;
|
||||||
}
|
}
|
||||||
@@ -825,7 +831,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
|||||||
&kServiceCertificateCAPublicKey[sizeof(kServiceCertificateCAPublicKey)]);
|
&kServiceCertificateCAPublicKey[sizeof(kServiceCertificateCAPublicKey)]);
|
||||||
if (!root_ca_key.Init(ca_public_key)) {
|
if (!root_ca_key.Init(ca_public_key)) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::VerifySignedServiceCertificate: public key "
|
"CdmLicense::VerifyAndExtractSignedServiceCertificate: public key "
|
||||||
"initialization failed");
|
"initialization failed");
|
||||||
return DEVICE_CERTIFICATE_ERROR_2;
|
return DEVICE_CERTIFICATE_ERROR_2;
|
||||||
}
|
}
|
||||||
@@ -834,7 +840,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
|||||||
signed_service_certificate.device_certificate(),
|
signed_service_certificate.device_certificate(),
|
||||||
signed_service_certificate.signature())) {
|
signed_service_certificate.signature())) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::VerifySignedServiceCertificate: service "
|
"CdmLicense::VerifyAndExtractSignedServiceCertificate: service "
|
||||||
"certificate verification failed");
|
"certificate verification failed");
|
||||||
return DEVICE_CERTIFICATE_ERROR_3;
|
return DEVICE_CERTIFICATE_ERROR_3;
|
||||||
}
|
}
|
||||||
@@ -843,7 +849,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
|||||||
if (!service_certificate.ParseFromString(
|
if (!service_certificate.ParseFromString(
|
||||||
signed_service_certificate.device_certificate())) {
|
signed_service_certificate.device_certificate())) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::VerifySignedServiceCertificate: unable to parse "
|
"CdmLicense::VerifyAndExtractSignedServiceCertificate: unable to parse "
|
||||||
"retrieved service certificate");
|
"retrieved service certificate");
|
||||||
return DEVICE_CERTIFICATE_ERROR_4;
|
return DEVICE_CERTIFICATE_ERROR_4;
|
||||||
}
|
}
|
||||||
@@ -851,13 +857,15 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
|
|||||||
if (service_certificate.type() !=
|
if (service_certificate.type() !=
|
||||||
video_widevine_server::sdk::DeviceCertificate_CertificateType_SERVICE) {
|
video_widevine_server::sdk::DeviceCertificate_CertificateType_SERVICE) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::VerifySignedServiceCertificate: certificate not of type"
|
"CdmLicense::VerifyAndExtractSignedServiceCertificate: certificate not "
|
||||||
" service, %d",
|
"of type service, %d",
|
||||||
service_certificate.type());
|
service_certificate.type());
|
||||||
return INVALID_DEVICE_CERTIFICATE_TYPE;
|
return INVALID_DEVICE_CERTIFICATE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*certificate = signed_service_certificate.device_certificate();
|
if (certificate != NULL) {
|
||||||
|
*certificate = signed_service_certificate.device_certificate();
|
||||||
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1055,8 +1063,8 @@ bool CdmLicense::GetServiceCertificate(const CdmSessionId& session_id,
|
|||||||
if (!Properties::GetServiceCertificate(session_id,
|
if (!Properties::GetServiceCertificate(session_id,
|
||||||
&signed_service_certificate) ||
|
&signed_service_certificate) ||
|
||||||
signed_service_certificate.empty() ||
|
signed_service_certificate.empty() ||
|
||||||
NO_ERROR != VerifySignedServiceCertificate(signed_service_certificate,
|
NO_ERROR != VerifyAndExtractSignedServiceCertificate(
|
||||||
service_certificate)) {
|
signed_service_certificate, service_certificate)) {
|
||||||
*service_certificate = service_certificate_;
|
*service_certificate = service_certificate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
|||||||
static bool IsSupported(const std::string& init_data_type);
|
static bool IsSupported(const std::string& init_data_type);
|
||||||
static bool IsCenc(const std::string& init_data_type);
|
static bool IsCenc(const std::string& init_data_type);
|
||||||
static bool IsWebm(const std::string& init_data_type);
|
static bool IsWebm(const std::string& init_data_type);
|
||||||
|
static bool IsValidServiceCertificate(const std::string& certificate);
|
||||||
|
|
||||||
// Session related methods
|
// Session related methods
|
||||||
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
|
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "cdm_client_property_set.h"
|
#include "cdm_client_property_set.h"
|
||||||
#include "cdm_engine.h"
|
#include "cdm_engine.h"
|
||||||
#include "initialization_data.h"
|
#include "initialization_data.h"
|
||||||
|
#include "license.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
@@ -37,6 +38,11 @@ bool WvContentDecryptionModule::IsWebm(const std::string& init_data_type) {
|
|||||||
return InitializationData(init_data_type).is_webm();
|
return InitializationData(init_data_type).is_webm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WvContentDecryptionModule::IsValidServiceCertificate(
|
||||||
|
const std::string& certificate) {
|
||||||
|
return CdmLicense::VerifySignedServiceCertificate(certificate) == NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::OpenSession(
|
CdmResponseType WvContentDecryptionModule::OpenSession(
|
||||||
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
|
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
|
||||||
const std::string& origin, WvCdmEventListener* event_listener,
|
const std::string& origin, WvCdmEventListener* event_listener,
|
||||||
|
|||||||
@@ -585,7 +585,11 @@ status_t WVDrmPlugin::setPropertyByteArray(const String8& name,
|
|||||||
const Vector<uint8_t>& value) {
|
const Vector<uint8_t>& value) {
|
||||||
if (name == "serviceCertificate") {
|
if (name == "serviceCertificate") {
|
||||||
std::string cert(value.begin(), value.end());
|
std::string cert(value.begin(), value.end());
|
||||||
mPropertySet.set_service_certificate(cert);
|
if (WvContentDecryptionModule::IsValidServiceCertificate(cert)) {
|
||||||
|
mPropertySet.set_service_certificate(cert);
|
||||||
|
} else {
|
||||||
|
return android::BAD_VALUE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ALOGE("App set unknown byte array property %s", name.string());
|
ALOGE("App set unknown byte array property %s", name.string());
|
||||||
return android::ERROR_DRM_CANNOT_HANDLE;
|
return android::ERROR_DRM_CANNOT_HANDLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user