Merge "Validate Service Certificates Before Accepting Them" into mnc-dev

This commit is contained in:
John "Juce" Bruce
2015-06-12 19:49:45 +00:00
committed by Android (Google) Code Review
5 changed files with 36 additions and 14 deletions

View File

@@ -59,6 +59,9 @@ class CdmLicense {
return provider_session_token_;
}
static CdmResponseType VerifySignedServiceCertificate(
const std::string& signed_service_certificate);
private:
bool PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
std::string* server_url);
@@ -74,7 +77,7 @@ class CdmLicense {
bool PrepareContentId(const CdmLicenseType license_type,
const std::string& request_id, T* content_id);
CdmResponseType VerifySignedServiceCertificate(
static CdmResponseType VerifyAndExtractSignedServiceCertificate(
const std::string& signed_service_certificate,
std::string* service_certificate);
bool GetServiceCertificate(const CdmSessionId& session_id,

View File

@@ -442,7 +442,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
case SignedMessage::LICENSE:
break;
case SignedMessage::SERVICE_CERTIFICATE: {
CdmResponseType status = CdmLicense::VerifySignedServiceCertificate(
CdmResponseType status = VerifyAndExtractSignedServiceCertificate(
signed_response.msg(), &service_certificate_);
return status == NO_ERROR ? NEED_KEY : status;
}
@@ -553,7 +553,7 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
case SignedMessage::LICENSE:
break;
case SignedMessage::SERVICE_CERTIFICATE: {
CdmResponseType status = CdmLicense::VerifySignedServiceCertificate(
CdmResponseType status = VerifyAndExtractSignedServiceCertificate(
signed_response.msg(), &service_certificate_);
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();
}
CdmResponseType CdmLicense::VerifySignedServiceCertificate(
const std::string& signed_service_certificate) {
return VerifyAndExtractSignedServiceCertificate(signed_service_certificate,
NULL);
}
bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
std::string* server_url) {
if (!initialized_) {
@@ -809,12 +815,12 @@ bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
return true;
}
CdmResponseType CdmLicense::VerifySignedServiceCertificate(
CdmResponseType CdmLicense::VerifyAndExtractSignedServiceCertificate(
const std::string& signed_certificate, std::string* certificate) {
SignedDeviceCertificate signed_service_certificate;
if (!signed_service_certificate.ParseFromString(signed_certificate)) {
LOGE(
"CdmLicense::VerifySignedServiceCertificate: unable to parse"
"CdmLicense::VerifyAndExtractSignedServiceCertificate: unable to parse "
"signed device certificate");
return DEVICE_CERTIFICATE_ERROR_1;
}
@@ -825,7 +831,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
&kServiceCertificateCAPublicKey[sizeof(kServiceCertificateCAPublicKey)]);
if (!root_ca_key.Init(ca_public_key)) {
LOGE(
"CdmLicense::VerifySignedServiceCertificate: public key "
"CdmLicense::VerifyAndExtractSignedServiceCertificate: public key "
"initialization failed");
return DEVICE_CERTIFICATE_ERROR_2;
}
@@ -834,7 +840,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
signed_service_certificate.device_certificate(),
signed_service_certificate.signature())) {
LOGE(
"CdmLicense::VerifySignedServiceCertificate: service "
"CdmLicense::VerifyAndExtractSignedServiceCertificate: service "
"certificate verification failed");
return DEVICE_CERTIFICATE_ERROR_3;
}
@@ -843,7 +849,7 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
if (!service_certificate.ParseFromString(
signed_service_certificate.device_certificate())) {
LOGE(
"CdmLicense::VerifySignedServiceCertificate: unable to parse "
"CdmLicense::VerifyAndExtractSignedServiceCertificate: unable to parse "
"retrieved service certificate");
return DEVICE_CERTIFICATE_ERROR_4;
}
@@ -851,13 +857,15 @@ CdmResponseType CdmLicense::VerifySignedServiceCertificate(
if (service_certificate.type() !=
video_widevine_server::sdk::DeviceCertificate_CertificateType_SERVICE) {
LOGE(
"CdmLicense::VerifySignedServiceCertificate: certificate not of type"
" service, %d",
"CdmLicense::VerifyAndExtractSignedServiceCertificate: certificate not "
"of type service, %d",
service_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;
}
@@ -1055,8 +1063,8 @@ bool CdmLicense::GetServiceCertificate(const CdmSessionId& session_id,
if (!Properties::GetServiceCertificate(session_id,
&signed_service_certificate) ||
signed_service_certificate.empty() ||
NO_ERROR != VerifySignedServiceCertificate(signed_service_certificate,
service_certificate)) {
NO_ERROR != VerifyAndExtractSignedServiceCertificate(
signed_service_certificate, service_certificate)) {
*service_certificate = service_certificate_;
}

View File

@@ -25,6 +25,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
static bool IsSupported(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 IsValidServiceCertificate(const std::string& certificate);
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,

View File

@@ -5,6 +5,7 @@
#include "cdm_client_property_set.h"
#include "cdm_engine.h"
#include "initialization_data.h"
#include "license.h"
#include "log.h"
#include "properties.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();
}
bool WvContentDecryptionModule::IsValidServiceCertificate(
const std::string& certificate) {
return CdmLicense::VerifySignedServiceCertificate(certificate) == NO_ERROR;
}
CdmResponseType WvContentDecryptionModule::OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
const std::string& origin, WvCdmEventListener* event_listener,

View File

@@ -585,7 +585,11 @@ status_t WVDrmPlugin::setPropertyByteArray(const String8& name,
const Vector<uint8_t>& value) {
if (name == "serviceCertificate") {
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 {
ALOGE("App set unknown byte array property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE;