Correct setting of service certificate.
[ Merge of http://go/wvgerrit/23380 ] The service certificate was setup correctly if specified in mediadrm properties. If instead the service certificate was later fetched from the license service, it would not be marked as valid. This led to an infinite loop of service certificate fetches and processing. This prevented the license from being fetched and playback failures. b/34638410 Test: Verified by new service certificate unittests + Hulu playback using fugu. Change-Id: I2a4f8754614fccdad3c80d3e13fba0b44d177d61
This commit is contained in:
@@ -64,6 +64,7 @@ try_adb_push $OUT/system/bin/license_unittest
|
||||
try_adb_push $OUT/system/bin/license_keys_unittest
|
||||
try_adb_push $OUT/system/bin/initialization_data_unittest
|
||||
try_adb_push $OUT/system/bin/device_files_unittest
|
||||
try_adb_push $OUT/system/bin/service_certificate_unittest
|
||||
try_adb_push $OUT/system/bin/timer_unittest
|
||||
try_adb_push $OUT/system/bin/libwvdrmengine_test
|
||||
try_adb_push $OUT/system/bin/buffer_reader_test
|
||||
|
||||
@@ -95,18 +95,20 @@ bool ServiceCertificate::IsAvailable() {
|
||||
CdmResponseType ServiceCertificate::VerifyAndSet(
|
||||
const std::string& signed_service_certificate) {
|
||||
CdmResponseType status;
|
||||
std::string certificate;
|
||||
bool has_provider_id;
|
||||
status = VerifyAndExtractFromSignedCertificate(signed_service_certificate,
|
||||
&certificate, &has_provider_id,
|
||||
&certificate_,
|
||||
&has_provider_id,
|
||||
NULL);
|
||||
if (status == NO_ERROR) {
|
||||
Properties::SetServiceCertificate(session_id_, certificate);
|
||||
} else {
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("ServiceCertificate::VerifyAndSet: verify and extract failed with "
|
||||
"status %d", status);
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
|
||||
Properties::SetServiceCertificate(session_id_, signed_service_certificate);
|
||||
valid_ = true;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool ServiceCertificate::PrepareServiceCertificateRequest(
|
||||
@@ -130,7 +132,7 @@ bool ServiceCertificate::PrepareServiceCertificateRequest(
|
||||
|
||||
CdmResponseType ServiceCertificate::VerifyAndExtractFromSignedCertificate(
|
||||
const std::string& signed_certificate, std::string* certificate,
|
||||
bool* has_provider_id, std::string* provider_id) {
|
||||
bool* /* has_provider_id */, std::string* /* provider_id */) {
|
||||
SignedDrmDeviceCertificate signed_service_certificate;
|
||||
if (!signed_service_certificate.ParseFromString(signed_certificate)) {
|
||||
LOGE(
|
||||
@@ -185,7 +187,8 @@ CdmResponseType ServiceCertificate::VerifyAndExtractFromSignedCertificate(
|
||||
}
|
||||
#endif
|
||||
|
||||
if (certificate != NULL) {
|
||||
if (certificate != NULL &&
|
||||
!signed_service_certificate.drm_certificate().empty()) {
|
||||
*certificate = signed_service_certificate.drm_certificate();
|
||||
}
|
||||
return NO_ERROR;
|
||||
@@ -246,11 +249,16 @@ bool ServiceCertificate::SetupServiceCertificate() {
|
||||
certificate_.clear();
|
||||
|
||||
if (!Properties::GetServiceCertificate(session_id_, &signed_certificate)) {
|
||||
LOGV("ServiceCertificate::SetupServiceCertificate: no signed service "
|
||||
"certificate set");
|
||||
return false;
|
||||
}
|
||||
if (signed_certificate.empty()) {
|
||||
LOGV("ServiceCertificate::SetupServiceCertificate: service certificate "
|
||||
"empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string extracted_certificate;
|
||||
std::string extracted_provider_id;
|
||||
bool has_provider_id;
|
||||
@@ -259,9 +267,6 @@ bool ServiceCertificate::SetupServiceCertificate() {
|
||||
&has_provider_id, &extracted_provider_id)) {
|
||||
return false;
|
||||
}
|
||||
if (extracted_certificate.empty()) {
|
||||
return false;
|
||||
}
|
||||
has_provider_id_ = has_provider_id;
|
||||
if (has_provider_id_) {
|
||||
provider_id_ = extracted_provider_id;
|
||||
|
||||
176
libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp
Normal file
176
libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "service_certificate.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include "crypto_session.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
namespace {
|
||||
|
||||
const CdmSessionId kTestSessionId1 = "sid1";
|
||||
const CdmSessionId kTestSessionId2 = "sid2";
|
||||
const std::string kAppId = "com.example.test";
|
||||
|
||||
const std::string kTestSignedCertificate = a2bs_hex(
|
||||
"0AC102080312101705B917CC1204868B06333A2F772A8C1882B4829205228E023082010A02"
|
||||
"8201010099ED5B3B327DAB5E24EFC3B62A95B598520AD5BCCB37503E0645B814D876B8DF40"
|
||||
"510441AD8CE3ADB11BB88C4E725A5E4A9E0795291D58584023A7E1AF0E38A9127939300861"
|
||||
"0B6F158C878C7E21BFFBFEEA77E1019E1E5781E8A45F46263D14E60E8058A8607ADCE04FAC"
|
||||
"8457B137A8D67CCDEB33705D983A21FB4EECBD4A10CA47490CA47EAA5D438218DDBAF1CADE"
|
||||
"3392F13D6FFB6442FD31E1BF40B0C604D1C4BA4C9520A4BF97EEBD60929AFCEEF55BBAF564"
|
||||
"E2D0E76CD7C55C73A082B996120B8359EDCE24707082680D6F67C6D82C4AC5F3134490A74E"
|
||||
"EC37AF4B2F010C59E82843E2582F0B6B9F5DB0FC5E6EDF64FBD308B4711BCF1250019C9F5A"
|
||||
"0902030100013A146C6963656E73652E7769646576696E652E636F6D128003AE347314B5A8"
|
||||
"35297F271388FB7BB8CB5277D249823CDDD1DA30B93339511EB3CCBDEA04B944B927C12134"
|
||||
"6EFDBDEAC9D413917E6EC176A10438460A503BC1952B9BA4E4CE0FC4BFC20A9808AAAF4BFC"
|
||||
"D19C1DCFCDF574CCAC28D1B410416CF9DE8804301CBDB334CAFCD0D40978423A642E54613D"
|
||||
"F0AFCF96CA4A9249D855E42B3A703EF1767F6A9BD36D6BF82BE76BBF0CBA4FDE59D2ABCC76"
|
||||
"FEB64247B85C431FBCA52266B619FC36979543FCA9CBBDBBFAFA0E1A55E755A3C7BCE655F9"
|
||||
"646F582AB9CF70AA08B979F867F63A0B2B7FDB362C5BC4ECD555D85BCAA9C593C383C857D4"
|
||||
"9DAAB77E40B7851DDFD24998808E35B258E75D78EAC0CA16F7047304C20D93EDE4E8FF1C6F"
|
||||
"17E6243E3F3DA8FC1709870EC45FBA823A263F0CEFA1F7093B1909928326333705043A29BD"
|
||||
"A6F9B4342CC8DF543CB1A1182F7C5FFF33F10490FACA5B25360B76015E9C5A06AB8EE02F00"
|
||||
"D2E8D5986104AACC4DD475FD96EE9CE4E326F21B83C7058577B38732CDDABC6A6BED13FB0D"
|
||||
"49D38A45EB87A5F4");
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
class MockCryptoSession : public CryptoSession {
|
||||
public:
|
||||
MOCK_METHOD2(GetRandom, bool(size_t, uint8_t*));
|
||||
};
|
||||
|
||||
class ServiceCertificateTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() { crypto_session_ = new MockCryptoSession(); }
|
||||
|
||||
virtual void TearDown() {
|
||||
if (crypto_session_) delete crypto_session_;
|
||||
}
|
||||
|
||||
void CreateServiceCertificate() {
|
||||
service_certificate_ = new ServiceCertificate();
|
||||
}
|
||||
|
||||
ServiceCertificate* service_certificate_;
|
||||
MockCryptoSession* crypto_session_;
|
||||
};
|
||||
|
||||
class StubCdmClientPropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
StubCdmClientPropertySet()
|
||||
: security_level_(QUERY_VALUE_SECURITY_LEVEL_L1),
|
||||
use_privacy_mode_(false),
|
||||
is_session_sharing_enabled_(false),
|
||||
session_sharing_id_(0),
|
||||
app_id_(kAppId) {}
|
||||
|
||||
virtual const std::string& security_level() const { return security_level_; }
|
||||
|
||||
virtual bool use_privacy_mode() const { return use_privacy_mode_; }
|
||||
|
||||
virtual const std::string& service_certificate() const {
|
||||
return service_certificate_;
|
||||
}
|
||||
|
||||
virtual void set_service_certificate(const std::string& cert) {
|
||||
service_certificate_ = cert;
|
||||
}
|
||||
|
||||
virtual const std::string& device_provisioning_service_certificate() const {
|
||||
return device_provisioning_service_certificate_;
|
||||
}
|
||||
|
||||
virtual void set_device_provisioning_service_certificate(
|
||||
const std::string& cert) {
|
||||
device_provisioning_service_certificate_ = cert;
|
||||
}
|
||||
virtual bool is_session_sharing_enabled() const {
|
||||
return is_session_sharing_enabled_;
|
||||
}
|
||||
|
||||
virtual uint32_t session_sharing_id() const { return session_sharing_id_; }
|
||||
|
||||
virtual void set_session_sharing_id(uint32_t id) { session_sharing_id_ = id; }
|
||||
|
||||
virtual const std::string& app_id() const { return app_id_; }
|
||||
|
||||
void enable_privacy_mode() { use_privacy_mode_ = true; }
|
||||
|
||||
private:
|
||||
std::string security_level_;
|
||||
std::string service_certificate_;
|
||||
std::string device_provisioning_service_certificate_;
|
||||
bool use_privacy_mode_;
|
||||
bool is_session_sharing_enabled_;
|
||||
uint32_t session_sharing_id_;
|
||||
std::string app_id_;
|
||||
};
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitSuccess) {
|
||||
MockCryptoSession crypto_session;
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1, &crypto_session);
|
||||
EXPECT_FALSE(service_certificate_->IsRequired());
|
||||
EXPECT_FALSE(service_certificate_->IsAvailable());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) {
|
||||
MockCryptoSession crypto_session;
|
||||
StubCdmClientPropertySet property_set;
|
||||
|
||||
property_set.enable_privacy_mode();
|
||||
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1, &crypto_session);
|
||||
EXPECT_TRUE(service_certificate_->IsRequired());
|
||||
EXPECT_FALSE(service_certificate_->IsAvailable());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) {
|
||||
MockCryptoSession crypto_session;
|
||||
StubCdmClientPropertySet property_set;
|
||||
|
||||
property_set.enable_privacy_mode();
|
||||
property_set.set_service_certificate(kTestSignedCertificate);
|
||||
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1, &crypto_session);
|
||||
EXPECT_TRUE(service_certificate_->IsRequired());
|
||||
EXPECT_TRUE(service_certificate_->IsAvailable());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, SetServiceCertificate) {
|
||||
MockCryptoSession crypto_session;
|
||||
StubCdmClientPropertySet property_set;
|
||||
|
||||
property_set.enable_privacy_mode();
|
||||
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1, &crypto_session);
|
||||
EXPECT_TRUE(service_certificate_->IsRequired());
|
||||
EXPECT_FALSE(service_certificate_->IsAvailable());
|
||||
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
service_certificate_->VerifyAndSet(kTestSignedCertificate));
|
||||
EXPECT_TRUE(service_certificate_->IsRequired());
|
||||
EXPECT_TRUE(service_certificate_->IsAvailable());
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,10 @@ test_name := request_license_test
|
||||
test_src_dir := .
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
test_name := service_certificate_unittest
|
||||
test_src_dir := ../core/test
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
test_name := timer_unittest
|
||||
test_src_dir := .
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
@@ -80,6 +80,7 @@ adb_shell_run license_unittest
|
||||
adb_shell_run license_keys_unittest
|
||||
adb_shell_run initialization_data_unittest
|
||||
adb_shell_run device_files_unittest
|
||||
adb_shell_run service_certificate_unittest
|
||||
adb_shell_run timer_unittest
|
||||
adb_shell_run buffer_reader_test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user