Files
android/libwvdrmengine/cdm/test/request_license_test.cpp
Kyle Alexander 99941b86b6 DO NOT MERGE ANYWHERE Update license tests to use Widevine license service
Based from Widevine cl:
https://widevine-internal-review.googlesource.com/#/c/16322/

Bug: 26046529
Change-Id: Ib8a4fd1588de35a02973bca1914a298a62a71f7c
2015-12-15 17:46:18 +00:00

1377 lines
57 KiB
C++

// Copyright 2013 Google Inc. All Rights Reserved.
#include <errno.h>
#include <getopt.h>
#include <sstream>
#include "config_test_env.h"
#include "gtest/gtest.h"
#include "device_files.h"
#include "file_store.h"
#include "license_request.h"
#include "log.h"
#include "OEMCryptoCENC.h"
#include "oemcrypto_adapter.h"
#include "properties.h"
#include "string_conversions.h"
#include "url_request.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_event_listener.h"
#include "wv_content_decryption_module.h"
namespace {
const char kPathDelimiter = '/';
// Default license server, can be configured using --server command line option
// Default key id (pssh), can be configured using --keyid command line option
std::string g_client_auth;
wvcdm::ConfigTestEnv* g_config = NULL;
wvcdm::KeyId g_key_id;
wvcdm::CdmKeySystem g_key_system;
std::string g_license_server;
std::string g_port;
wvcdm::KeyId g_wrong_key_id;
bool g_use_chunked_transfer = false;
bool g_use_full_path = false;
bool g_use_secure_transfer = false;
wvcdm::LicenseServerId g_license_server_id = wvcdm::kContentProtectionServer;
std::string kServiceCertificate =
"0803121028703454C008F63618ADE7443DB6C4C8188BE7F99005228E023082010"
"A0282010100B52112B8D05D023FCC5D95E2C251C1C649B4177CD8D2BEEF355BB0"
"6743DE661E3D2ABC3182B79946D55FDC08DFE95407815E9A6274B322A2C7F5E06"
"7BB5F0AC07A89D45AEA94B2516F075B66EF811D0D26E1B9A6B894F2B9857962AA"
"171C4F66630D3E4C602718897F5E1EF9B6AAF5AD4DBA2A7E14176DF134A1D3185"
"B5A218AC05A4C41F081EFFF80A3A040C50B09BBC740EEDCD8F14D675A91980F92"
"CA7DDC646A06ADAD5101F74A0E498CC01F00532BAC217850BD905E90923656B7D"
"FEFEF42486767F33EF6283D4F4254AB72589390BEE55808F1D668080D45D893C2"
"BCA2F74D60A0C0D0A0993CEF01604703334C3638139486BC9DAF24FD67A07F9AD"
"94302030100013A1273746167696E672E676F6F676C652E636F6D";
// TODO(rfrias): refactor to print out the decryption test names
struct SubSampleInfo {
bool retrieve_key;
size_t num_of_subsamples;
bool validate_key_id;
bool is_encrypted;
bool is_secure;
wvcdm::KeyId key_id;
std::vector<uint8_t> encrypt_data;
std::vector<uint8_t> decrypt_data;
std::vector<uint8_t> iv;
size_t block_offset;
uint8_t subsample_flags;
};
SubSampleInfo clear_sub_sample = {
true, 1, true, false, false,
wvcdm::a2bs_hex("371EA35E1A985D75D198A7F41020DC23"),
wvcdm::a2b_hex(
"217ce9bde99bd91e9733a1a00b9b557ac3a433dc92633546156817fae26b6e1c"
"942ac20a89ff79f4c2f25fba99d6a44618a8c0420b27d54e3da17b77c9d43cca"
"595d259a1e4a8b6d7744cd98c5d3f921adc252eb7d8af6b916044b676a574747"
"8df21fdc42f166880d97a2225cd5c9ea5e7b752f4cf81bbdbe98e542ee10e1c6"
"ad868a6ac55c10d564fc23b8acff407daaf4ed2743520e02cda9680d9ea88e91"
"029359c4cf5906b6ab5bf60fbb3f1a1c7c59acfc7e4fb4ad8e623c04d503a3dd"
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659"),
wvcdm::a2b_hex(
"217ce9bde99bd91e9733a1a00b9b557ac3a433dc92633546156817fae26b6e1c"
"942ac20a89ff79f4c2f25fba99d6a44618a8c0420b27d54e3da17b77c9d43cca"
"595d259a1e4a8b6d7744cd98c5d3f921adc252eb7d8af6b916044b676a574747"
"8df21fdc42f166880d97a2225cd5c9ea5e7b752f4cf81bbdbe98e542ee10e1c6"
"ad868a6ac55c10d564fc23b8acff407daaf4ed2743520e02cda9680d9ea88e91"
"029359c4cf5906b6ab5bf60fbb3f1a1c7c59acfc7e4fb4ad8e623c04d503a3dd"
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659"),
wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"), 0, 3};
SubSampleInfo clear_sub_sample_no_key = {
false, 1, false, false, false,
wvcdm::a2bs_hex("77777777777777777777777777777777"),
wvcdm::a2b_hex(
"217ce9bde99bd91e9733a1a00b9b557ac3a433dc92633546156817fae26b6e1c"
"942ac20a89ff79f4c2f25fba99d6a44618a8c0420b27d54e3da17b77c9d43cca"
"595d259a1e4a8b6d7744cd98c5d3f921adc252eb7d8af6b916044b676a574747"
"8df21fdc42f166880d97a2225cd5c9ea5e7b752f4cf81bbdbe98e542ee10e1c6"
"ad868a6ac55c10d564fc23b8acff407daaf4ed2743520e02cda9680d9ea88e91"
"029359c4cf5906b6ab5bf60fbb3f1a1c7c59acfc7e4fb4ad8e623c04d503a3dd"
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659"),
wvcdm::a2b_hex(
"217ce9bde99bd91e9733a1a00b9b557ac3a433dc92633546156817fae26b6e1c"
"942ac20a89ff79f4c2f25fba99d6a44618a8c0420b27d54e3da17b77c9d43cca"
"595d259a1e4a8b6d7744cd98c5d3f921adc252eb7d8af6b916044b676a574747"
"8df21fdc42f166880d97a2225cd5c9ea5e7b752f4cf81bbdbe98e542ee10e1c6"
"ad868a6ac55c10d564fc23b8acff407daaf4ed2743520e02cda9680d9ea88e91"
"029359c4cf5906b6ab5bf60fbb3f1a1c7c59acfc7e4fb4ad8e623c04d503a3dd"
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659"),
wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"), 0, 3};
SubSampleInfo single_encrypted_sub_sample = {
// key SD, encrypted, 256b
true, 1, true, true, false,
wvcdm::a2bs_hex("371EA35E1A985D75D198A7F41020DC23"),
wvcdm::a2b_hex(
"64ab17b3e3dfab47245c7cce4543d4fc7a26dcf248f19f9b59f3c92601440b36"
"17c8ed0c96c656549e461f38708cd47a434066f8df28ccc28b79252eee3f9c2d"
"7f6c68ebe40141fe818fe082ca523c03d69ddaf183a93c022327fedc5582c5ab"
"ca9d342b71263a67f9cb2336f12108aaaef464f17177e44e9b0c4e56e61da53c"
"2150b4405cc82d994dfd9bf4087c761956d6688a9705db4cf350381085f383c4"
"9666d4aed135c519c1f0b5cba06e287feea96ea367bf54e7368dcf998276c6e4"
"6497e0c50e20fef74e42cb518fe7f22ef27202428688f86404e8278587017012"
"c1d65537c6cbd7dde04aae338d68115a9f430afc100ab83cdadf45dca39db685"),
wvcdm::a2b_hex(
"217ce9bde99bd91e9733a1a00b9b557ac3a433dc92633546156817fae26b6e1c"
"942ac20a89ff79f4c2f25fba99d6a44618a8c0420b27d54e3da17b77c9d43cca"
"595d259a1e4a8b6d7744cd98c5d3f921adc252eb7d8af6b916044b676a574747"
"8df21fdc42f166880d97a2225cd5c9ea5e7b752f4cf81bbdbe98e542ee10e1c6"
"ad868a6ac55c10d564fc23b8acff407daaf4ed2743520e02cda9680d9ea88e91"
"029359c4cf5906b6ab5bf60fbb3f1a1c7c59acfc7e4fb4ad8e623c04d503a3dd"
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659"),
wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"), 0, 3};
SubSampleInfo switch_key_encrypted_sub_sample[2] = {
// block 0, key SD, encrypted, 256b
{true, 2, true, true, false,
wvcdm::a2bs_hex("371EA35E1A985D75D198A7F41020DC23"),
wvcdm::a2b_hex(
"9efe1b7a3973324525e9b8c516855e554b52a73ce35cd181731b005a6525624f"
"a03875c89aee02f1da7f556b7e7d9a3eba89fe3061194bc2d1446233ca022892"
"ab95083f127d6ccb01b1368e6b6fa77e3570d84477a5517f2965ff72f8e0740c"
"d8282c22e7724ce44d88526dcd2d601002b717d8ca3b97087d28f9e3810efb8e"
"d4b08ee2da6bdb05a790b6363f8ee65cae8328e86848e4caf9be92db3e5492ad"
"6363a26051c23cf23b9aee79a8002470c4a5834c6aae956b509a42f4110262e0"
"565a043befd8ef3a335c9dfedca8d218f364215859d7daf7d040b1f0cb2eda87"
"c1be18f323fb0235dd9a6e7b3b2fea1cb9c6e5bc2b349962f0b8f0b92e749db2"),
wvcdm::a2b_hex(
"38a715e73c9209544c47e5eb089146de8136df5c6ed01e3e8d9cea8ae18a81c9"
"8c9c8ec67bf379dd80a21f57b0b00575827a240cd11332c5212defe9f1ef8b8e"
"2399271767bfe81e5a11abf7bca1307578217c4d5f8b942ab04351b4725d6e24"
"cd171fa3083570f7d7ae2b297224f701fd04d699c12c53e9ce9d3dab64ee6332"
"5fba183b7a1f3f20acaeabc0c446c9ca0df39fafb1e2891c72500741ad5b7941"
"4651729e30e9ddbb22f47a5026e09c795ff15a858123a7979e7be716cb8cd075"
"e8bfb91bc0cc83f7cacd5c4772f7479a1193d9307bc5f837185faed5499e66a7"
"e27db50b5d018d022279032016862883befd113b6c784889be8f9e6eb0f335f7"),
wvcdm::a2b_hex("fd38d7f754a97128b78440433e1ef4a8"), 0, 3},
// block 1, key HD, encrypted, 256b
{true, 2, true, true, false,
wvcdm::a2bs_hex("6D665122C01767FC087F340E6C335EA4"),
wvcdm::a2b_hex(
"d9392411d15f47de0d7dd854eae5eb5ffbd2d3f86c530d2ef619fc81725df866"
"2e6267041b947863e5779812da3220824a3d154e7b094c1af70238c65877454e"
"3c3bdcce836962ba29b69442d5e5b4a4ff32a4b026521f3fa4d442a400081cdd"
"ba6ed313c43cc34443c4dc2b9cdcc9dbd478bf6afc4d515c07b42d8b151c15cc"
"165270f6083ecd5c75313c496143068f45966bb53e35906c7568424e93e35989"
"7da702fb89eb7c970af838d56a64a7a68f7cffe529807765d62540bb06bbc633"
"6eeec62d20f5b639731e57a0851e23e146cb9502dbde93dc4aca20e471a3fa0b"
"df01a74ecb48d5f57ac2be98fb21d19de7587d8d1e6e1788726e1544d05137f6"),
wvcdm::a2b_hex(
"c48a94d07c34c4315e01010dbcc63a038d50a023b1ff2a07deae6e498cb03f84"
"57911d8c9d72fa5184c738d81a49999504b7cd4532b465436b7044606a6d40a2"
"74a653c4b93ebaf8db585d180211a02e5501a8027f2235fe56682390325c88ee"
"2ada85483eddb955c56f79634a2ceeb36d04b5d6faf7611817577d9b0fda088e"
"921fbdd7fa594ee4f557f7393f51f3049cd36973f645badf7cc4672ef8d973da"
"7dae8e59f32bf950c6569845a5261b5ed9cc500706eccf8d41f015b32026e16e"
"ab274465d880ff99a5eaea603eea66c7b0e6679bfd87145de0ec1a73ebfff092"
"866346a1d66db2923bca30664f417a6b66c07e91fb491be7872ebe5c9c2d03c2"),
wvcdm::a2b_hex("f56ab022666de858920e532f19bb32f6"), 0, 3}};
SubSampleInfo partial_single_encrypted_sub_sample = {
// block 1, key SD, encrypted, 1-125b, offset 0
true, 3, true, true, false,
wvcdm::a2bs_hex("371EA35E1A985D75D198A7F41020DC23"),
wvcdm::a2b_hex(
"53cc758763904ea5870458e6b23d36db1e6d7f7aaa2f3eeebb5393a7264991e7"
"ce4f57b198326e1a208a821799b2a29c90567ab57321b06e51fc20dc9bc5fc55"
"10720a8bb1f5e002c3e50ff70d2d806a9432cad237050d09581f5b0d59b00090"
"b3ad69b4087f5a155b17e13c44d33fa007475d207fc4ac2ef3b571ecb9"),
wvcdm::a2b_hex(
"52e65334501acadf78e2b26460def3ac973771ed7c64001a2e82917342a7eab3"
"047f5e85449692fae8f677be425a47bdea850df5a3ffff17043afb1f2b437ab2"
"b1d5e0784c4ed8f97fc24b8f565e85ed63fb7d1365980d9aea7b8b58f488f83c"
"1ce80b6096c60f3b113c988ff185b26e798da8fc6f327e4ff00e4b3fbf"),
wvcdm::a2b_hex("6ba18dd40f49da7f64c368e4db43fc88"), 0, 1};
SubSampleInfo partial_offset_single_encrypted_sub_sample = {
// key 3, encrypted, 123b, offset 5
true, 1, true, true, false,
wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"),
wvcdm::a2b_hex(
"97f39b919ba56f3c3a51ecdcd7318bc130f054320c74db3990f925"
"054734c03ec79ee0da68938dc4f8c2d91e46ec2342ef24f9328294a9475f7ead"
"8ad3e71db62d6328e826e4ab375f4796aa2bc8b9266551e3007fb3c253780293"
"31fbc32ed29afcb9e7152cf072712c5a22c6b52d60e381eb53eeb58d36528746"),
wvcdm::a2b_hex(
"d36911b44f470ff05d152a7bc69ea6b68aa812cd3676964acb4597"
"b518fe4b7ec0fe44469b1e4f8806922af9ac998d3e23349cea0e68f833564c15"
"e49584f94ef16b7ab6cd2d0b152430f1fb4d7644a0f591980388ac02012d3d42"
"73d6c9604517b1a622b66b8f4e8414e40b00351cc9859061bde810190c7b5df8"),
wvcdm::a2b_hex("43ba341482212c70f79d81c0f4faef8a"), 5};
struct SessionSharingSubSampleInfo {
SubSampleInfo* sub_sample;
bool session_sharing_enabled;
};
SessionSharingSubSampleInfo session_sharing_sub_samples[] = {
{ &clear_sub_sample, false },
{ &clear_sub_sample, true },
{ &clear_sub_sample_no_key, false },
{ &clear_sub_sample_no_key, true },
{ &single_encrypted_sub_sample, false },
{ &single_encrypted_sub_sample, true }
};
} // namespace
namespace wvcdm {
class TestWvCdmClientPropertySet : public CdmClientPropertySet {
public:
TestWvCdmClientPropertySet()
: use_privacy_mode_(false),
is_session_sharing_enabled_(false),
session_sharing_id_(0) {}
virtual ~TestWvCdmClientPropertySet() {}
virtual std::string security_level() const { return security_level_; }
virtual std::vector<uint8_t> service_certificate() const {
return service_certificate_;
}
virtual bool use_privacy_mode() const { return use_privacy_mode_; }
bool is_session_sharing_enabled() const {
return is_session_sharing_enabled_;
}
uint32_t session_sharing_id() const { return session_sharing_id_; }
void set_security_level(const std::string& security_level) {
if (!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3)) {
security_level_ = security_level;
}
}
void set_service_certificate(
const std::vector<uint8_t>& service_certificate) {
service_certificate_ = service_certificate;
}
void set_use_privacy_mode(bool use_privacy_mode) {
use_privacy_mode_ = use_privacy_mode;
}
void set_session_sharing_mode(bool enable) {
is_session_sharing_enabled_ = enable;
}
void set_session_sharing_id(uint32_t id) { session_sharing_id_ = id; }
private:
std::string security_level_;
std::vector<uint8_t> service_certificate_;
bool use_privacy_mode_;
bool is_session_sharing_enabled_;
uint32_t session_sharing_id_;
};
class TestWvCdmEventListener : public WvCdmEventListener {
public:
TestWvCdmEventListener() : WvCdmEventListener() {}
virtual void onEvent(const CdmSessionId& id, CdmEventType event) {
session_id_ = id;
event_type_ = event;
}
CdmSessionId session_id() { return session_id_; }
CdmEventType event_type() { return event_type_; }
private:
CdmSessionId session_id_;
CdmEventType event_type_;
};
class WvCdmRequestLicenseTest : public testing::Test {
public:
WvCdmRequestLicenseTest() {}
~WvCdmRequestLicenseTest() {}
protected:
void GetOfflineConfiguration(std::string* key_id, std::string* client_auth) {
ConfigTestEnv config(g_license_server_id, false);
if (g_key_id.compare(a2bs_hex(g_config->key_id())) == 0)
key_id->assign(wvcdm::a2bs_hex(config.key_id()));
else
key_id->assign(g_key_id);
if (g_client_auth.compare(g_config->client_auth()) == 0)
client_auth->assign(config.client_auth());
else
client_auth->assign(g_client_auth);
}
void GenerateKeyRequest(const std::string& key_system,
const std::string& init_data,
CdmLicenseType license_type) {
wvcdm::CdmAppParameterMap app_parameters;
std::string server_url;
std::string key_set_id;
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(session_id_, key_set_id, init_data,
license_type, app_parameters,
&key_msg_, &server_url));
EXPECT_EQ(0u, server_url.size());
}
void GenerateRenewalRequest(const std::string& key_system,
CdmLicenseType license_type,
std::string* server_url) {
// TODO application makes a license request, CDM will renew the license
// when appropriate.
std::string init_data;
wvcdm::CdmAppParameterMap app_parameters;
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(session_id_, key_set_id_, init_data,
license_type, app_parameters,
&key_msg_, server_url));
// TODO(edwinwong, rfrias): Add tests cases for when license server url
// is empty on renewal. Need appropriate key id at the server.
EXPECT_NE(0u, server_url->size());
}
void GenerateKeyRelease(CdmKeySetId key_set_id) {
CdmSessionId session_id;
CdmInitData init_data;
wvcdm::CdmAppParameterMap app_parameters;
std::string server_url;
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(session_id, key_set_id, init_data,
kLicenseTypeRelease, app_parameters,
&key_msg_, &server_url));
}
// Post a request and extract the drm message from the response
std::string GetKeyRequestResponse(const std::string& server_url,
const std::string& client_auth,
int expected_response) {
// Use secure connection and chunk transfer coding.
UrlRequest url_request(server_url + client_auth, g_port,
g_use_secure_transfer, g_use_chunked_transfer);
if (!url_request.is_connected()) {
return "";
}
url_request.PostRequest(key_msg_);
std::string message;
int resp_bytes = url_request.GetResponse(&message);
// Youtube server returns 400 for invalid message while play server returns
// 500, so just test inequity here for invalid message
int status_code = url_request.GetStatusCode(message);
if (expected_response == 200) {
EXPECT_EQ(200, status_code);
}
std::string drm_msg;
if (200 == status_code) {
LicenseRequest lic_request;
lic_request.GetDrmMessage(message, drm_msg);
LOGV("HTTP response body: (%u bytes)", drm_msg.size());
}
return drm_msg;
}
// Post a request and extract the signed provisioning message from
// the HTTP response.
std::string GetCertRequestResponse(const std::string& server_url,
int expected_response) {
// Use secure connection and chunk transfer coding.
UrlRequest url_request(server_url, kDefaultHttpsPort, true, true);
if (!url_request.is_connected()) {
return "";
}
url_request.PostCertRequestInQueryString(key_msg_);
std::string message;
int resp_bytes = url_request.GetResponse(&message);
LOGD("end %d bytes response dump", resp_bytes);
// Youtube server returns 400 for invalid message while play server returns
// 500, so just test inequity here for invalid message
int status_code = url_request.GetStatusCode(message);
if (expected_response == 200) {
EXPECT_EQ(200, status_code);
} else {
EXPECT_NE(200, status_code);
}
return message;
}
void VerifyKeyRequestResponse(const std::string& server_url,
const std::string& client_auth,
std::string& init_data, bool is_renewal) {
std::string resp = GetKeyRequestResponse(server_url, client_auth, 200);
if (is_renewal) {
// TODO application makes a license request, CDM will renew the license
// when appropriate
EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_),
wvcdm::KEY_ADDED);
} else {
EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_),
wvcdm::KEY_ADDED);
}
}
wvcdm::WvContentDecryptionModule decryptor_;
CdmKeyMessage key_msg_;
CdmSessionId session_id_;
CdmKeySetId key_set_id_;
};
class WvCdmDecryptionTest
: public WvCdmRequestLicenseTest,
public ::testing::WithParamInterface<SubSampleInfo*> {};
class WvCdmSessionSharingTest
: public WvCdmRequestLicenseTest,
public ::testing::WithParamInterface<SessionSharingSubSampleInfo*> {};
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
std::string provisioning_server_url;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
std::string provisioning_server_url;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
TestWvCdmClientPropertySet property_set_L1;
TestWvCdmClientPropertySet property_set_L3;
TestWvCdmClientPropertySet property_set_Ln;
CdmSessionId session_id_L1;
CdmSessionId session_id_L3;
CdmSessionId session_id_Ln;
property_set_L1.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L1);
property_set_L1.set_use_privacy_mode(true);
decryptor_.OpenSession(g_key_system, &property_set_L1, &session_id_L1);
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
property_set_L3.set_use_privacy_mode(false);
CdmResponseType sts = decryptor_.OpenSession(g_key_system, &property_set_L3,
&session_id_L3);
if (NEED_PROVISIONING == sts) {
std::string provisioning_server_url;
EXPECT_EQ(
NO_ERROR,
decryptor_.GetProvisioningRequest(&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set_L3,
&session_id_L3));
} else {
EXPECT_EQ(NO_ERROR, sts);
}
property_set_Ln.set_security_level("");
decryptor_.OpenSession(g_key_system, &property_set_Ln, &session_id_Ln);
std::string security_level = Properties::GetSecurityLevel(session_id_L1);
EXPECT_TRUE(!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3));
EXPECT_TRUE(Properties::UsePrivacyMode(session_id_L1));
EXPECT_EQ(Properties::GetSecurityLevel(session_id_L3),
QUERY_VALUE_SECURITY_LEVEL_L3);
EXPECT_FALSE(Properties::UsePrivacyMode(session_id_L3));
security_level = Properties::GetSecurityLevel(session_id_Ln);
EXPECT_TRUE(security_level.empty() ||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3));
decryptor_.CloseSession(session_id_L1);
decryptor_.CloseSession(session_id_L3);
decryptor_.CloseSession(session_id_Ln);
}
TEST_F(WvCdmRequestLicenseTest, ForceL3Test) {
TestWvCdmClientPropertySet property_set;
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
File file;
DeviceFiles handle;
EXPECT_TRUE(handle.Init(&file, kSecurityLevelL3));
EXPECT_TRUE(handle.DeleteAllFiles());
EXPECT_EQ(NEED_PROVISIONING,
decryptor_.OpenSession(g_key_system, &property_set, &session_id_));
std::string provisioning_server_url;
EXPECT_EQ(NO_ERROR,
decryptor_.GetProvisioningRequest(&key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
&session_id_));
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_PrivacyModeTest) {
TestWvCdmClientPropertySet property_set;
property_set.set_use_privacy_mode(true);
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
std::string resp = GetKeyRequestResponse(g_license_server,
g_client_auth, 200);
EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_),
wvcdm::NEED_KEY);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_PrivacyModeWithServiceCertificateTest) {
TestWvCdmClientPropertySet property_set;
property_set.set_use_privacy_mode(true);
property_set.set_service_certificate(a2b_hex(kServiceCertificate));
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
SessionSharingSubSampleInfo* session_sharing_info = GetParam();
TestWvCdmClientPropertySet property_set;
property_set.set_session_sharing_mode(
session_sharing_info->session_sharing_enabled);
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
CdmSessionId gp_session_id_1 = session_id_;
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
// TODO(rfrias): Move content information to ConfigTestEnv
std::string gp_client_auth2 =
"?source=YOUTUBE&video_id=z3S_NhwueaM&oauth=ya.gtsqawidevine";
std::string gp_key_id2 =
wvcdm::a2bs_hex(
"000000347073736800000000" // blob size and pssh
"edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id
"08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
CdmSessionId gp_session_id_2 = session_id_;
GenerateKeyRequest(g_key_system, gp_key_id2, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, gp_client_auth2, gp_key_id2, false);
SubSampleInfo* data = session_sharing_info->sub_sample;
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(&data->key_id,
&data->encrypt_data.front(),
data->encrypt_data.size(),
&data->iv,
data->block_offset,
&decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
if (session_sharing_info->session_sharing_enabled || !data->is_encrypted) {
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(gp_session_id_2,
data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
} else {
EXPECT_EQ(NEED_KEY, decryptor_.Decrypt(gp_session_id_2,
data->validate_key_id,
decryption_parameters));
}
decryptor_.CloseSession(gp_session_id_1);
decryptor_.CloseSession(gp_session_id_2);
}
INSTANTIATE_TEST_CASE_P(
Cdm, WvCdmSessionSharingTest,
::testing::Range(&session_sharing_sub_samples[0],
&session_sharing_sub_samples[6]));
TEST_F(WvCdmRequestLicenseTest, BaseMessageTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
GetKeyRequestResponse(g_license_server, g_client_auth, 200);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
std::string wrong_message = wvcdm::a2bs_hex(g_wrong_key_id);
GenerateKeyRequest(g_key_system, wrong_message, kLicenseTypeStreaming);
GetKeyRequestResponse(g_license_server, g_client_auth, 500);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_ReleaseOfflineKeyTest) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
session_id_.clear();
key_set_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
session_id_.clear();
key_set_id_.clear();
GenerateKeyRelease(key_set_id);
key_set_id_ = key_set_id;
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_ExpiryOnReleaseOfflineKeyTest) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
session_id_.clear();
key_set_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
CdmSessionId restore_session_id = session_id_;
TestWvCdmEventListener listener;
EXPECT_TRUE(decryptor_.AttachEventListener(restore_session_id, &listener));
EXPECT_EQ(wvcdm::KEY_ADDED,
decryptor_.RestoreKey(restore_session_id, key_set_id));
session_id_.clear();
key_set_id_.clear();
EXPECT_TRUE(listener.session_id().size() == 0);
GenerateKeyRelease(key_set_id);
key_set_id_ = key_set_id;
EXPECT_TRUE(listener.session_id().size() != 0);
EXPECT_TRUE(listener.session_id().compare(restore_session_id) == 0);
EXPECT_TRUE(listener.event_type() == LICENSE_EXPIRED_EVENT);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
decryptor_.CloseSession(restore_session_id);
}
TEST_F(WvCdmRequestLicenseTest, StreamingLicenseRenewal) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
std::string license_server;
GenerateRenewalRequest(g_key_system, kLicenseTypeStreaming, &license_server);
if (license_server.empty())
license_server = g_license_server;
VerifyKeyRequestResponse(license_server, g_client_auth, g_key_id, true);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
std::string license_server;
GenerateRenewalRequest(g_key_system, kLicenseTypeOffline, &license_server);
if (license_server.empty())
license_server = g_license_server;
VerifyKeyRequestResponse(license_server, client_auth, key_id, true);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, QuerySessionStatus) {
// Test that the global value is returned when no properties are modifying it.
CdmQueryMap system_query_info;
CdmQueryMap::iterator system_itr;
ASSERT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&system_query_info));
system_itr = system_query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(system_itr != system_query_info.end());
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
CdmQueryMap unmodified_query_info;
CdmQueryMap::iterator unmodified_itr;
ASSERT_EQ(wvcdm::NO_ERROR,
decryptor_.QuerySessionStatus(session_id_, &unmodified_query_info));
unmodified_itr = unmodified_query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(unmodified_itr != unmodified_query_info.end());
EXPECT_EQ(system_itr->second, unmodified_itr->second);
decryptor_.CloseSession(session_id_);
// Test that L3 is returned when properties downgrade security.
TestWvCdmClientPropertySet property_set_L3;
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
decryptor_.OpenSession(g_key_system, &property_set_L3, &session_id_);
CdmQueryMap modified_query_info;
CdmQueryMap::iterator modified_itr;
ASSERT_EQ(wvcdm::NO_ERROR,
decryptor_.QuerySessionStatus(session_id_, &modified_query_info));
modified_itr = modified_query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(modified_itr != modified_query_info.end());
EXPECT_EQ(QUERY_VALUE_SECURITY_LEVEL_L3, modified_itr->second);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
CdmQueryMap query_info;
CdmQueryMap::iterator itr;
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.QueryKeyStatus(session_id_, &query_info));
itr = query_info.find(wvcdm::QUERY_KEY_LICENSE_TYPE);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(wvcdm::QUERY_VALUE_STREAMING, itr->second);
itr = query_info.find(wvcdm::QUERY_KEY_PLAY_ALLOWED);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(wvcdm::QUERY_VALUE_TRUE, itr->second);
itr = query_info.find(wvcdm::QUERY_KEY_PERSIST_ALLOWED);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(wvcdm::QUERY_VALUE_FALSE, itr->second);
itr = query_info.find(wvcdm::QUERY_KEY_RENEW_ALLOWED);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(wvcdm::QUERY_VALUE_TRUE, itr->second);
int64_t remaining_time;
std::istringstream ss;
itr = query_info.find(wvcdm::QUERY_KEY_LICENSE_DURATION_REMAINING);
ASSERT_TRUE(itr != query_info.end());
ss.str(itr->second);
ASSERT_TRUE(ss >> remaining_time);
EXPECT_LT(0, remaining_time);
itr = query_info.find(wvcdm::QUERY_KEY_PLAYBACK_DURATION_REMAINING);
ASSERT_TRUE(itr != query_info.end());
ss.clear();
ss.str(itr->second);
ASSERT_TRUE(ss >> remaining_time);
EXPECT_LT(0, remaining_time);
itr = query_info.find(wvcdm::QUERY_KEY_RENEWAL_SERVER_URL);
ASSERT_TRUE(itr != query_info.end());
EXPECT_LT(0u, itr->second.size());
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
CdmQueryMap query_info;
CdmQueryMap::iterator itr;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&query_info));
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(2u, itr->second.size());
EXPECT_EQ(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.at(0), itr->second.at(0));
itr = query_info.find(wvcdm::QUERY_KEY_DEVICE_ID);
ASSERT_TRUE(itr != query_info.end());
EXPECT_GT(itr->second.size(), 0u);
itr = query_info.find(wvcdm::QUERY_KEY_SYSTEM_ID);
ASSERT_TRUE(itr != query_info.end());
std::istringstream ss(itr->second);
uint32_t system_id;
EXPECT_TRUE(ss >> system_id);
EXPECT_TRUE(ss.eof());
itr = query_info.find(wvcdm::QUERY_KEY_PROVISIONING_ID);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(16u, itr->second.size());
}
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
CdmQueryMap query_info;
CdmQueryMap::iterator itr;
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.QueryKeyControlInfo(session_id_, &query_info));
uint32_t oem_crypto_session_id;
itr = query_info.find(wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID);
ASSERT_TRUE(itr != query_info.end());
std::istringstream ss;
ss.str(itr->second);
EXPECT_TRUE(ss >> oem_crypto_session_id);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
CdmQueryMap query_info;
CdmQueryMap::iterator itr;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&query_info));
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
ASSERT_TRUE(itr != query_info.end());
EXPECT_EQ(2u, itr->second.size());
EXPECT_TRUE(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0 ||
itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0);
CdmSecurityLevel security_level =
(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0)
? kSecurityLevelL1
: kSecurityLevelL3;
std::string base_path;
EXPECT_TRUE(Properties::GetDeviceFilesBasePath(security_level, &base_path));
std::vector<std::string> security_dirs;
EXPECT_TRUE(Properties::GetSecurityLevelDirectories(&security_dirs));
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); i++) {
pos = base_path.rfind(security_dirs[i]);
if (std::string::npos != pos)
break;
}
EXPECT_NE(std::string::npos, pos);
std::string old_base_path(base_path, 0, pos);
std::string path(old_base_path);
path += kPathDelimiter;
size_t path_len = path.size();
File file;
for (size_t i = 0; i < security_dirs.size(); i++) {
path.append(security_dirs[i]);
file.Remove(path);
path.resize(path_len);
}
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
std::string provisioning_server_url;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
std::vector<std::string> files;
EXPECT_TRUE(file.List(base_path, &files));
EXPECT_TRUE(2u == files.size() || 3u == files.size());
for (size_t i = 0; i < files.size(); ++i) {
std::string from = base_path + files[i];
if (file.IsRegularFile(from)) {
std::string to = old_base_path + files[i];
EXPECT_TRUE(file.Copy(from, to));
}
}
EXPECT_TRUE(file.Remove(base_path));
// Setup complete to earlier version (non-security level based) path.
// Restore persistent license, retrieve L1, L3 streaming licenses to verify
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
if (security_level != kSecurityLevelL1) return;
TestWvCdmClientPropertySet property_set;
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
EXPECT_EQ(NO_ERROR,
decryptor_.OpenSession(g_key_system, &property_set, &session_id_));
wvcdm::CdmAppParameterMap app_parameters;
std::string server_url;
EXPECT_EQ(wvcdm::NEED_PROVISIONING,
decryptor_.GenerateKeyRequest(session_id_, key_set_id, g_key_id,
kLicenseTypeStreaming, app_parameters,
&key_msg_, &server_url));
EXPECT_EQ(NO_ERROR,
decryptor_.GetProvisioningRequest(&key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
response =
GetCertRequestResponse(g_config->provisioning_test_server_url(), 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
&session_id_));
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth, g_key_id, false);
decryptor_.CloseSession(session_id_);
}
TEST_P(WvCdmDecryptionTest, DecryptionTest) {
SubSampleInfo* data = GetParam();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
if (data->retrieve_key) {
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
}
for (size_t i = 0; i < data->num_of_subsamples; i++) {
std::vector<uint8_t> decrypt_buffer((data + i)->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&(data + i)->key_id, &(data + i)->encrypt_data.front(),
(data + i)->encrypt_data.size(), &(data + i)->iv,
(data + i)->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = (data + i)->is_encrypted;
decryption_parameters.is_secure = (data + i)->is_secure;
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_,
(data+i)->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal((data + i)->decrypt_data.begin(),
(data + i)->decrypt_data.end(),
decrypt_buffer.begin()));
}
decryptor_.CloseSession(session_id_);
}
INSTANTIATE_TEST_CASE_P(
Cdm, WvCdmDecryptionTest,
::testing::Values(&clear_sub_sample, &clear_sub_sample_no_key,
&single_encrypted_sub_sample,
&switch_key_encrypted_sub_sample[0],
&partial_single_encrypted_sub_sample));
TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
/*
// key 1, encrypted, 256b
DecryptionData data;
data.is_encrypted = true;
data.is_secure = false;
data.key_id = wvcdm::a2bs_hex("30313233343536373839414243444546");
data.encrypt_data = wvcdm::a2b_hex(
"b6d7d2430aa82b1cb8bd32f02e1f3b2a8d84f9eddf935ced5a6a98022cbb4561"
"8346a749fdb336858a64d7169fd0aa898a32891d14c24bed17fdc17fd62b8771"
"a8e22e9f093fa0f2aacd293d471b8e886d5ed8d0998ab2fde2d908580ff88c93"
"c0f0bbc14867267b3a3955bb6e7d05fca734a3aec3463d786d555cad83536ebe"
"4496d934d40df2aba5aea98c1145a2890879568ae31bb8a85d74714a4ad75785"
"7488523e697f5fd370eac746d56990a81cc76a178e3d6d65743520cdbc669412"
"9e73b86214256c67430cf78662346cab3e2bdd6f095dddf75b7fb3868c5ff5ff"
"3e1bbf08d456532ffa9df6e21a8bb2664c2d2a6d47ee78f9a6d53b2f2c8c087c");
data.iv = wvcdm::a2b_hex("86856b9409743ca107b043e82068c7b6");
data.block_offset = 0;
data.decrypt_data = wvcdm::a2b_hex(
"cc4a7fed8c5ac6e316e45317805c43e6d62a383ad738219c65e7a259dc12b46a"
"d50a3f8ce2facec8eeadff9cfa6b649212b88602b41f6d4c510c05af07fd523a"
"e7032634d9f8db5dd652d35f776376c5fc56e7031ed7cb28b72427fd4b367b6d"
"8c4eb6e46ed1249de5d24a61aeb08ebd60984c10581042ca8b0ef6bc44ec34a0"
"d4a77d68125c9bb1ace6f650e8716540f5b20d6482f7cfdf1b57a9ee9802160c"
"a632ce42934347410abc61bb78fba11b093498572de38bca96101ecece455e3b"
"5fef6805c44a2609cf97ce0dac7f15695c8058c590eda517f845108b90dfb29c"
"e73f3656000399f2fd196bc6fc225f3a7b8f578237751fd485ff070b5289e5cf");
std::vector<uint8_t> decrypt_buffer;
size_t encrypt_length = data.encrypt_data.size();
decrypt_buffer.resize(encrypt_length);
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_,
data.is_encrypted,
data.is_secure,
data.key_id,
&data.encrypt_data.front(),
encrypt_length,
data.iv,
data.block_offset,
&decrypt_buffer.front(),
0));
EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(),
decrypt_buffer.begin()));
*/
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_RestoreOfflineLicenseDecryptionTest) {
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
/*
// key 1, encrypted, 256b
DecryptionData data;
data.is_encrypted = true;
data.is_secure = false;
data.key_id = wvcdm::a2bs_hex("30313233343536373839414243444546");
data.encrypt_data = wvcdm::a2b_hex(
"b6d7d2430aa82b1cb8bd32f02e1f3b2a8d84f9eddf935ced5a6a98022cbb4561"
"8346a749fdb336858a64d7169fd0aa898a32891d14c24bed17fdc17fd62b8771"
"a8e22e9f093fa0f2aacd293d471b8e886d5ed8d0998ab2fde2d908580ff88c93"
"c0f0bbc14867267b3a3955bb6e7d05fca734a3aec3463d786d555cad83536ebe"
"4496d934d40df2aba5aea98c1145a2890879568ae31bb8a85d74714a4ad75785"
"7488523e697f5fd370eac746d56990a81cc76a178e3d6d65743520cdbc669412"
"9e73b86214256c67430cf78662346cab3e2bdd6f095dddf75b7fb3868c5ff5ff"
"3e1bbf08d456532ffa9df6e21a8bb2664c2d2a6d47ee78f9a6d53b2f2c8c087c");
data.iv = wvcdm::a2b_hex("86856b9409743ca107b043e82068c7b6");
data.block_offset = 0;
data.decrypt_data = wvcdm::a2b_hex(
"cc4a7fed8c5ac6e316e45317805c43e6d62a383ad738219c65e7a259dc12b46a"
"d50a3f8ce2facec8eeadff9cfa6b649212b88602b41f6d4c510c05af07fd523a"
"e7032634d9f8db5dd652d35f776376c5fc56e7031ed7cb28b72427fd4b367b6d"
"8c4eb6e46ed1249de5d24a61aeb08ebd60984c10581042ca8b0ef6bc44ec34a0"
"d4a77d68125c9bb1ace6f650e8716540f5b20d6482f7cfdf1b57a9ee9802160c"
"a632ce42934347410abc61bb78fba11b093498572de38bca96101ecece455e3b"
"5fef6805c44a2609cf97ce0dac7f15695c8058c590eda517f845108b90dfb29c"
"e73f3656000399f2fd196bc6fc225f3a7b8f578237751fd485ff070b5289e5cf");
std::vector<uint8_t> decrypt_buffer;
size_t encrypt_length = data.encrypt_data.size();
decrypt_buffer.resize(encrypt_length);
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_,
data.is_encrypted,
data.is_secure,
data.key_id,
&data.encrypt_data.front(),
encrypt_length,
data.iv,
data.block_offset,
&decrypt_buffer.front(),
0));
EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(),
decrypt_buffer.begin()));
*/
decryptor_.CloseSession(session_id_);
}
// TODO(rfrias, edwinwong): pending L1 OEMCrypto due to key block handling
/*
TEST_F(WvCdmRequestLicenseTest, KeyControlBlockDecryptionTest) {
decryptor_.OpenSession(g_key_system, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
DecryptionData data;
// block 4, key 2, encrypted
data.is_encrypted = true;
data.is_secure = false;
data.key_id = wvcdm::a2bs_hex("0915007CAA9B5931B76A3A85F046523E");
data.encrypt_data = wvcdm::a2b_hex(
"6758ac1c6ccf5d08479e3bfc62bbc0fd154aff4415aa7ed53d89e3983248d117"
"ab5137ae7cedd9f9d7321d4cf35a7013237afbcc2d893d1d928efa94e9f7e2ed"
"1855463cf75ff07ecc0246b90d0734f42d98aeea6a0a6d2618a8339bd0aca368"
"4fb4a4670c0385e5bd5de9e2d8b9226851b8f8955adfbab968793b46fd152f5e"
"e608467bb2695836f8f76c32731f5e208176d05e4b07020d58f6282c477f3840"
"b8079c02e8bd1d03191d190cc505ddfbb2e9bacc794534c91fe409d62f5389b9"
"35ed66134bd30f09f8da9dbfe6b8cf53d13cae34dae6e89109216e3a02233d5c"
"2f66aef74313aae4a99b654b485b5cc207b2dc8d44a8b99a4dc196a9820eccef");
data.iv = wvcdm::a2b_hex("c8f2d133ec357fe727cd233b3bfa755f");
data.block_offset = 0;
data.decrypt_data = wvcdm::a2b_hex(
"34bab89185f1be990dfc454410c7c9093d008bc783908838b02a65b26db28759"
"dca9dc5f117b3c8c3898358722d1b4c490e5a5d168ba0f9f8a3d4371b8fd1057"
"2d6dd65f3f9d1850de8d76dc71bd6dc6c23da4e1223fcc3e47162033a6f82890"
"e2bd6e9d6ddbe453830afc89064ed18078c786f8f746fcbafd88e83e7160cce5"
"62fa7a7d699ef8421bda020d242ae4f61a786213b707c3b17b83d77510f9a07e"
"d9d7e47d8f8fa2aff86eb26d61ddf384a27513e3facf6b1f5fe6c0d063b8856c"
"c486d930393ea79ba73ba293eda39059e2ce9ee7bd5d31ab11f35e55dc35dfe0"
"ea5e2ec684014852add6e29ce7d88a1595641ae4c0dd10155526b5a87560ec9d");
std::vector<uint8_t> decrypt_buffer;
size_t encrypt_length = data[i].encrypt_data.size();
decrypt_buffer.resize(encrypt_length);
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_,
data.is_encrypted,
data.is_secure,
data.key_id,
&data.encrypt_data.front(),
encrypt_length,
data.iv,
data.block_offset,
&decrypt_buffer.front()));
EXPECT_TRUE(std::equal(data.decrypt_data.begin(),
data.decrypt_data.end(),
decrypt_buffer.begin()));
}
decryptor_.CloseSession(session_id_);
}
*/
} // namespace wvcdm
void show_menu(char* prog_name) {
std::cout << std::endl;
std::cout << "usage: " << prog_name << " [options]" << std::endl << std::endl;
std::cout << " enclose multiple arguments in '' when using adb shell"
<< std::endl;
std::cout << " e.g. adb shell '" << prog_name << " --server=\"url\"'"
<< std::endl;
std::cout << " or adb shell '" << prog_name << " -u\"url\"'"
<< std::endl << std::endl;
std::cout << std::setw(35) << std::left << " -c/--chunked_transfer";
std::cout << "specifies chunked transfer encoding in request"
<< std::endl << std::endl;
std::cout << std::setw(35) << std::left << " -f/--use_full_path";
std::cout << "specify server url is not a proxy server" << std::endl;
std::cout << std::endl;
std::cout << std::setw(35) << std::left
<< " -i/--license_server_id=<gp/cp>";
std::cout << "specifies which default server settings to use: " << std::endl;
std::cout << std::setw(35) << std::left << " ";
std::cout << "gp (case sensitive) for GooglePlay server" << std::endl;
std::cout << std::setw(35) << std::left << " ";
std::cout << "cp (case sensitive) for Content Protection server"
<< std::endl << std::endl;
std::cout << std::setw(35) << std::left << " -k/--keyid=<key_id>";
std::cout << "configure the key id or pssh, in hex format"
<< std::endl << std::endl;
std::cout << std::setw(35) << std::left
<< " -p/--port=<port>";
std::cout << "specifies the connection port" << std::endl << std::endl;
std::cout << std::setw(35) << std::left
<< " -s/--secure_transfer";
std::cout << "use https transfer protocol" << std::endl << std::endl;
std::cout << std::setw(35) << std::left
<< " -u/--server=<server_url>";
std::cout
<< "configure the license server url, please include http[s] in the url"
<< std::endl << std::endl;
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
bool show_usage = false;
static const struct option long_options[] = {
{ "chunked_transfer", no_argument, NULL, 'c' },
{ "keyid", required_argument, NULL, 'k' },
{ "license_server_id", required_argument, NULL, 'i' },
{ "license_server_url", required_argument, NULL, 'u' },
{ "port", required_argument, NULL, 'p' },
{ "secure_transfer", no_argument, NULL, 's' },
{ "use_full_path", no_argument, NULL, 'f' },
{ NULL, 0, NULL, '\0' }
};
int option_index = 0;
int opt = 0;
while ((opt = getopt_long(argc, argv, "cfi:k:p:su:", long_options,
&option_index)) != -1) {
switch (opt) {
case 'c': {
g_use_chunked_transfer = true;
break;
}
case 'f': {
g_use_full_path = true;
break;
}
case 'i': {
std::string license_id(optarg);
if (!license_id.compare("gp")) {
g_license_server_id = wvcdm::kGooglePlayServer;
} else if (!license_id.compare("cp")) {
g_license_server_id = wvcdm::kContentProtectionServer;
} else {
std::cout << "Invalid license server id" << optarg << std::endl;
show_usage = true;
}
break;
}
case 'k': {
g_key_id.clear();
g_key_id.assign(optarg);
break;
}
case 'p': {
g_port.clear();
g_port.assign(optarg);
break;
}
case 's': {
g_use_secure_transfer = true;
break;
}
case 'u': {
g_license_server.clear();
g_license_server.assign(optarg);
break;
}
case '?': {
show_usage = true;
break;
}
}
}
if (show_usage) {
show_menu(argv[0]);
return 0;
}
g_config = new wvcdm::ConfigTestEnv(g_license_server_id);
g_client_auth.assign(g_config->client_auth());
g_key_system.assign(g_config->key_system());
g_wrong_key_id.assign(g_config->wrong_key_id());
// The following variables are configurable through command line
// options. If the command line arguments are absent, use the settings
// in license_servers[] pointed to by g_config.
if (g_key_id.empty()) {
g_key_id.assign(g_config->key_id());
}
if (g_license_server.empty()) {
g_license_server.assign(g_config->license_server());
}
if (g_port.empty()) {
g_port.assign(g_config->port());
}
if (!g_use_chunked_transfer) {
g_use_chunked_transfer = g_config->use_chunked_transfer();
}
if (!g_use_secure_transfer) {
g_use_secure_transfer = g_config->use_secure_transfer();
}
// Displays server url, port and key Id being used
std::cout << std::endl;
std::cout << "Server: " << g_license_server << std::endl;
std::cout << "Port: " << g_port << std::endl;
std::cout << "KeyID: " << g_key_id << std::endl << std::endl;
g_key_id = wvcdm::a2bs_hex(g_key_id);
g_config->set_license_server(g_license_server);
int status = RUN_ALL_TESTS();
delete g_config;
return status;
}