From 0c6686690292199be23ec8ae18ef0a3357893364 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Wed, 23 Aug 2017 09:24:06 -0700 Subject: [PATCH] Add SRM integration tests [ Merge of http://go/wvgerrit/30582 ] Bug: 34285383 Test: WV unit, integration tests, cdm_feature_test.sh Change-Id: I725150a12a589144e58ab04470d50ba9317a4c46 --- .../cdm/core/src/crypto_session.cpp | 2 +- .../cdm/core/test/config_test_env.cpp | 59 ++- .../cdm/core/test/config_test_env.h | 15 + libwvdrmengine/cdm/test/cdm_feature_test.cpp | 497 ++++++++++++++++-- libwvdrmengine/cdm/test/cdm_feature_test.sh | 221 ++++++++ 5 files changed, 756 insertions(+), 38 deletions(-) create mode 100644 libwvdrmengine/cdm/test/cdm_feature_test.sh diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 50af8f54..c03b8c74 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -1744,7 +1744,7 @@ bool CryptoSession::RewrapDeviceRSAKey30(const std::string& message, wrapped_private_key->resize(wrapped_private_key_length); if (OEMCrypto_SUCCESS != status) { - LOGE("OEMCrypto_RewrapDeviceRSAKey fails with %d", status); + LOGE("OEMCrypto_RewrapDeviceRSAKey30 fails with %d", status); return false; } return true; diff --git a/libwvdrmengine/cdm/core/test/config_test_env.cpp b/libwvdrmengine/cdm/core/test/config_test_env.cpp index 1f034626..e05c4fb4 100644 --- a/libwvdrmengine/cdm/core/test/config_test_env.cpp +++ b/libwvdrmengine/cdm/core/test/config_test_env.cpp @@ -2,6 +2,8 @@ #include "config_test_env.h" +#include "string_conversions.h" + namespace wvcdm { namespace { @@ -24,7 +26,7 @@ const std::string kCpKeyId = "00000022" // pssh data size // pssh data: "08011a0d7769646576696e655f746573" - "74220f73747265616d696e675f636c69" + "74220f73747265616d696e675f636c69" // "streaming_clip1" "7031"; const std::string kCpOfflineKeyId = "00000040" // blob size @@ -34,7 +36,26 @@ const std::string kCpOfflineKeyId = "00000020" // pssh data size // pssh data: "08011a0d7769646576696e655f746573" - "74220d6f66666c696e655f636c697032"; + "74220d6f66666c696e655f636c697032"; // "offline_clip2" +const CdmInitData kCpStagingSrmOuputProtectionRequired = + "0000003d" // blob size + "70737368" // "pssh" + "00000000" // flags + "edef8ba979d64acea3c827dcd51d21ed" // Widevine system id + "0000001d" // pssh data size + // pssh data: + "08011a0d7769646576696e655f746573" + "74220a74656172735f73726d32"; // "tears_srm2" +const CdmInitData kCpStagingSrmOuputProtectionRequested = + "0000003d" // blob size + "70737368" // "pssh" + "00000000" // flags + "edef8ba979d64acea3c827dcd51d21ed" // Widevine system id + "0000001d" // pssh data size + // pssh data: + "08011a0d7769646576696e655f746573" + "74220a74656172735f73726d32"; // "tears_srm1" +const CdmInitData kEmptyData; const std::string kCpUatServiceCertificate = "0ABF020803121028703454C008F63618ADE7443DB6C4C8188BE7F99005228E023082010A02" "82010100B52112B8D05D023FCC5D95E2C251C1C649B4177CD8D2BEEF355BB06743DE661E3D" @@ -92,7 +113,7 @@ const std::string kCpProductionServiceCertificate = // Content Protection license server (staging) data const std::string kCpStagingLicenseServer = - "http://wv-staging-proxy.appspot.com/proxy"; + "https://proxy.staging.widevine.com/proxy"; const std::string kStagingProvisioningServerUrl = "https://staging-www.sandbox.googleapis.com/" "certificateprovisioning/v1/devicecertificates/create" @@ -198,6 +219,7 @@ ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming, } void ConfigTestEnv::Init(LicenseServerId server_id) { + server_id_ = server_id; client_auth_ = license_servers[server_id].client_tag; key_id_ = license_servers[server_id].key_id; key_system_ = kWidevineKeySystem; @@ -207,4 +229,35 @@ void ConfigTestEnv::Init(LicenseServerId server_id) { wrong_key_id_ = kWrongKeyId; } +const CdmInitData ConfigTestEnv::GetInitData(ContentId content_id) { + switch (content_id) { + case kContentIdStreaming: + return wvcdm::a2bs_hex(kCpKeyId); + case kContentIdOffline: + return wvcdm::a2bs_hex(kCpOfflineKeyId); + case kContentIdStagingSrmOuputProtectionRequested: + return wvcdm::a2bs_hex(kCpStagingSrmOuputProtectionRequested); + case kContentIdStagingSrmOuputProtectionRequired: + return wvcdm::a2bs_hex(kCpStagingSrmOuputProtectionRequired); + default: + return kEmptyData; + } +} + +const std::string& ConfigTestEnv::GetLicenseServerUrl( + LicenseServerId license_server_id) { + switch (license_server_id) { + case kGooglePlayServer: + return kGpLicenseServer; + case kContentProtectionUatServer: + return kCpUatLicenseServer; + case kContentProtectionStagingServer: + return kCpStagingLicenseServer; + case kContentProtectionProductionServer: + return kCpProductionLicenseServer; + default: + return kEmptyData; + } +} + } // namespace wvcdm diff --git a/libwvdrmengine/cdm/core/test/config_test_env.h b/libwvdrmengine/cdm/core/test/config_test_env.h index 0fa6f034..7f218da5 100644 --- a/libwvdrmengine/cdm/core/test/config_test_env.h +++ b/libwvdrmengine/cdm/core/test/config_test_env.h @@ -14,9 +14,19 @@ typedef enum { kContentProtectionProductionServer, } LicenseServerId; +// Identifies content used in tests. Specify Prod/Uat/Staging if content +// has been registered across license services. +enum ContentId { + kContentIdStreaming, + kContentIdOffline, + kContentIdStagingSrmOuputProtectionRequested, + kContentIdStagingSrmOuputProtectionRequired, +}; + // Configures default test environment. class ConfigTestEnv { public: + typedef struct { LicenseServerId id; std::string license_server_url; @@ -45,6 +55,10 @@ class ConfigTestEnv { } const KeyId& wrong_key_id() const { return wrong_key_id_; } + static const CdmInitData GetInitData(ContentId content_id); + static const std::string& GetLicenseServerUrl( + LicenseServerId license_server_id); + void set_key_id(KeyId& key_id) { key_id_.assign(key_id); } void set_key_system(CdmKeySystem& key_system) { key_system_.assign(key_system); @@ -66,6 +80,7 @@ class ConfigTestEnv { std::string provisioning_server_url_; std::string service_certificate_; KeyId wrong_key_id_; + LicenseServerId server_id_; CORE_DISALLOW_COPY_AND_ASSIGN(ConfigTestEnv); }; diff --git a/libwvdrmengine/cdm/test/cdm_feature_test.cpp b/libwvdrmengine/cdm/test/cdm_feature_test.cpp index 384f073b..397c6a86 100644 --- a/libwvdrmengine/cdm/test/cdm_feature_test.cpp +++ b/libwvdrmengine/cdm/test/cdm_feature_test.cpp @@ -21,6 +21,8 @@ #include #include "config_test_env.h" +#include "license_protocol.pb.h" +#include "license_request.h" #include "log.h" #include "oemcrypto_adapter.h" #include "OEMCryptoCENC.h" @@ -29,13 +31,21 @@ #include "test_printers.h" #include "url_request.h" #include "wv_cdm_constants.h" +#include "wv_cdm_event_listener.h" +#include "wv_cdm_types.h" #include "wv_content_decryption_module.h" +using ::testing::Each; +using ::testing::Invoke; +using ::testing::IsEmpty; +using ::testing::Not; +using ::testing::Pair; +using ::testing::StrictMock; using ::testing::_; namespace { -#define N_ELEM(a) (sizeof(a)/sizeof(a[0])) +#define N_ELEM(a) (sizeof(a) / sizeof(a[0])) const char kPathDelimiter = '/'; @@ -44,7 +54,6 @@ const int kHttpOk = 200; const int kHttpBadRequest = 400; const int kHttpInternalServerError = 500; - // 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; @@ -56,10 +65,182 @@ wvcdm::KeyId g_wrong_key_id; wvcdm::LicenseServerId g_license_server_id = wvcdm::kContentProtectionUatServer; std::string g_service_certificate; +wvcdm::KeyId kSrmHdKeyId1 = wvcdm::a2bs_hex("30303030303030303030303030303032"); +wvcdm::KeyId kSrmHdKeyId2 = wvcdm::a2bs_hex("30303030303030303030303030303033"); +wvcdm::KeyId kSrmHdKeyId3 = wvcdm::a2bs_hex("30303030303030303030303030303037"); +wvcdm::KeyId kSrmSdKeyId1 = wvcdm::a2bs_hex("30303030303030303030303030303030"); +wvcdm::KeyId kSrmSdKeyId2 = wvcdm::a2bs_hex("30303030303030303030303030303031"); +wvcdm::KeyId kSrmSdKeyId3 = wvcdm::a2bs_hex("30303030303030303030303030303034"); +wvcdm::KeyId kSrmSdKeyId4 = wvcdm::a2bs_hex("30303030303030303030303030303035"); +wvcdm::KeyId kSrmSdKeyId5 = wvcdm::a2bs_hex("30303030303030303030303030303036"); + +std::set kSrmExpectedAllKeyIds = { + kSrmHdKeyId1, kSrmHdKeyId2, kSrmHdKeyId3, kSrmSdKeyId1, + kSrmSdKeyId2, kSrmSdKeyId3, kSrmSdKeyId4, kSrmSdKeyId5, +}; + +std::set kSrmExpectedSdKeyIds = { + kSrmSdKeyId1, kSrmSdKeyId2, kSrmSdKeyId3, kSrmSdKeyId4, kSrmSdKeyId5, +}; + +std::vector kEncryptData = wvcdm::a2b_hex( + "64ab17b3e3dfab47245c7cce4543d4fc7a26dcf248f19f9b59f3c92601440b36" + "17c8ed0c96c656549e461f38708cd47a434066f8df28ccc28b79252eee3f9c2d" + "7f6c68ebe40141fe818fe082ca523c03d69ddaf183a93c022327fedc5582c5ab" + "ca9d342b71263a67f9cb2336f12108aaaef464f17177e44e9b0c4e56e61da53c" + "2150b4405cc82d994dfd9bf4087c761956d6688a9705db4cf350381085f383c4" + "9666d4aed135c519c1f0b5cba06e287feea96ea367bf54e7368dcf998276c6e4" + "6497e0c50e20fef74e42cb518fe7f22ef27202428688f86404e8278587017012" + "c1d65537c6cbd7dde04aae338d68115a9f430afc100ab83cdadf45dca39db685"); + +std::vector kEncryptDataIV = + wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"); + +uint32_t kSrmOutdatedVersion = 1; +uint32_t kSrmCurrentVersion = 3; + +struct SrmTestParameters { + const char* test_name; + bool update_supported; + uint32_t initial_version; + uint32_t final_version; + bool output_protection_required; // otherwise requested + bool revoked; + bool expected_can_play_hd; + std::set expected_key_ids; +}; + +SrmTestParameters kSrmTestConfiguration[] = { + {"VersionCurrent|OPRequested|Updatable|NotRevoked|CanPlayback", + true /* updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + false /* op requested */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionCurrent|OPRequested|NotUpdatable|NotRevoked|CanPlayback", + false /* not updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + false /* op requested */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionCurrent|OPRequired|Updatable|NotRevoked|CanPlayback", + true /* updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + true /* op required */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionCurrent|OPRequired|NotUpdatable|NotRevoked|CanPlayback", + false /* not updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + true /* op required */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + + {"VersionOutdated|OPRequested|Updatable|NotRevoked|CanPlayback", + true /* updatable */, kSrmOutdatedVersion, kSrmCurrentVersion, + false /* op requested */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequested|NotUpdatable|NotRevoked|CanPlayback", + false /* not updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + false /* op requested */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequired|Updatable|NotRevoked|CanPlayback", + true /* updatable */, kSrmOutdatedVersion, kSrmCurrentVersion, + true /* op required */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequired|NotUpdatable|NotRevoked|CannotPlayback", + false /* not updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + true /* op required */, false /* not revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, + + {"VersionCurrent|OPRequested|Updatable|Revoked|CanPlayback", + true /* updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + false /* op requested */, true /* revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionCurrent|OPRequested|NotUpdatable|Revoked|CanPlayback", + false /* not updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + false /* op requested */, true /* revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionCurrent|OPRequired|Updatable|Revoked|CannotPlayback", + true /* updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + true /* op required */, true /* revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, + {"VersionCurrent|OPRequired|NotUpdatable|Revoked|CannotPlayback", + false /* not updatable */, kSrmCurrentVersion, kSrmCurrentVersion, + true /* op required */, true /* revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, + + {"VersionOutdated|OPRequested|Updatable|Revoked|CanPlayback", + true /* updatable */, kSrmOutdatedVersion, kSrmCurrentVersion, + false /* op requested */, true /* revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequested|NotUpdatable|Revoked|CanPlayback", + false /* not updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + false /* op requested */, true /* revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequired|Updatable|Revoked|CannotPlayback", + true /* updatable */, kSrmOutdatedVersion, kSrmCurrentVersion, + true /* op required */, true /* revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, + {"VersionOutdated|OPRequired|NotUpdatable|Revoked|CannotPlayback", + false /* not updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + true /* op required */, true /* revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, +}; + +SrmTestParameters kSrmNotSupportedTestConfiguration[] = { + {"VersionOutdated|OPRequested|NotUpdatable|NotRevoked|CanPlayback", + false /* updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + false /* op requested */, false /* not revoked */, true /* can play */, + kSrmExpectedAllKeyIds}, + {"VersionOutdated|OPRequired|NotUpdatable|NotRevoked|CannotPlayback", + false /* updatable */, kSrmOutdatedVersion, kSrmOutdatedVersion, + true /* op required */, false /* not revoked */, false /* cannot play */, + kSrmExpectedSdKeyIds}, +}; + } // namespace namespace wvcdm { // Protobuf generated classes +using video_widevine::ClientIdentification_TokenType; +using video_widevine::ClientIdentification_TokenType_KEYBOX; +using video_widevine::ClientIdentification_TokenType_OEM_DEVICE_CERTIFICATE; +using video_widevine::ProvisioningRequest; +using video_widevine::SignedProvisioningMessage; + +class TestWvCdmEventListener : public WvCdmEventListener { + public: + TestWvCdmEventListener() : WvCdmEventListener() {} + MOCK_METHOD1(OnSessionRenewalNeeded, void(const CdmSessionId& session_id)); + MOCK_METHOD3(OnSessionKeysChange, void(const CdmSessionId& session_id, + const CdmKeyStatusMap& keys_status, + bool has_new_usable_key)); + MOCK_METHOD2(OnExpirationUpdate, void(const CdmSessionId& session_id, + int64_t new_expiry_time_seconds)); +}; + +class TestKeyVerifier { + public: + TestKeyVerifier() {} + TestKeyVerifier(std::set expected_usable_key_ids) + : expected_usable_key_ids_(expected_usable_key_ids) {} + + void Verify(const CdmSessionId& /* session_id */, + const CdmKeyStatusMap& status_map, + bool /* has_new_usable_key */) { + // LOGE("TestKeyVerifier::Verify: session_id: %s", session_id.c_str()); + // CdmKeyStatusMap key_status = status_map; + // const CdmKeyStatusMap::iterator iter; + uint32_t number_of_usable_keys = 0; + for (CdmKeyStatusMap::const_iterator iter = status_map.begin(); + iter != status_map.end(); ++iter) { + if (iter->second == kKeyStatusUsable) { + ++number_of_usable_keys; + EXPECT_NE(expected_usable_key_ids_.end(), + expected_usable_key_ids_.find(iter->first)); + } + // LOGE("TestKeyVerifier::Verify: %s %d", b2a_hex(iter->first).c_str(), + // iter->second); + } + EXPECT_EQ(expected_usable_key_ids_.size(), number_of_usable_keys); + } + + private: + std::set expected_usable_key_ids_; +}; class WvCdmFeatureTest : public WvCdmTestBase { public: @@ -76,8 +257,8 @@ class WvCdmFeatureTest : public WvCdmTestBase { std::string GetCertRequestResponse(const std::string& server_url) { // Use secure connection and chunk transfer coding. UrlRequest url_request(server_url); - EXPECT_TRUE(url_request.is_connected()) << "Fail to connect to " - << server_url; + EXPECT_TRUE(url_request.is_connected()) + << "Fail to connect to " << server_url; url_request.PostCertRequestInQueryString(key_msg_); std::string message; EXPECT_TRUE(url_request.GetResponse(&message)); @@ -90,14 +271,142 @@ class WvCdmFeatureTest : public WvCdmTestBase { return message; } + protected: + bool ExtractTokenType(const std::string& b64_provisioning_request_no_pad, + ClientIdentification_TokenType* token_type) { + std::string b64_provisioning_request = b64_provisioning_request_no_pad; + size_t binary_size = b64_provisioning_request.size() * 3 / 4; + // base64 message with pad = 4*ceil[n/3] + size_t pad_size = + ((binary_size + 2) / 3) * 4 - b64_provisioning_request.size(); + if (pad_size >= 3) return false; + b64_provisioning_request.append(pad_size, '='); + LOGW("ExtractTokenType: pad_size: %d", pad_size); + + std::vector bin_provisioning_request = + Base64SafeDecode(b64_provisioning_request); + if (bin_provisioning_request.empty()) return false; + std::string prov_request(bin_provisioning_request.begin(), + bin_provisioning_request.end()); + + SignedProvisioningMessage signed_provisioning_message; + if (!signed_provisioning_message.ParseFromString(prov_request)) + return false; + + ProvisioningRequest provisioning_request; + if (!provisioning_request.ParseFromString( + signed_provisioning_message.message())) + return false; + + *token_type = provisioning_request.client_id().type(); + LOGW("ExtractTokenType: success"); + return true; + } + + void GenerateKeyRequest(const std::string& init_data, + CdmLicenseType license_type) { + GenerateKeyRequest(init_data, license_type, NULL); + } + + void GenerateKeyRequest(const std::string& init_data, + CdmLicenseType license_type, + CdmClientPropertySet* property_set) { + CdmAppParameterMap app_parameters; + GenerateKeyRequest(init_data, app_parameters, license_type, property_set); + } + + void GenerateKeyRequest(const std::string& init_data, + CdmAppParameterMap& app_parameters, + CdmLicenseType license_type, + CdmClientPropertySet* property_set) { + std::string init_data_type = "video/mp4"; + GenerateKeyRequest(wvcdm::KEY_MESSAGE, init_data_type, init_data, + app_parameters, license_type, property_set); + } + + void GenerateKeyRequest(CdmResponseType expected_response, + const std::string& init_data_type, + const std::string& init_data, + CdmAppParameterMap& app_parameters, + CdmLicenseType license_type, + CdmClientPropertySet* property_set) { + CdmKeyRequest key_request; + std::string key_set_id; + license_type_ = license_type; + EXPECT_EQ( + expected_response, + decryptor_.GenerateKeyRequest( + session_id_, key_set_id, init_data_type, init_data, license_type, + app_parameters, property_set, kDefaultCdmIdentifier, &key_request)); + key_msg_ = key_request.message; + EXPECT_EQ(0u, key_request.url.size()); + } + + // Post a request and extract the drm message from the response + std::string GetKeyRequestResponse(const std::string& server_url, + const std::string& client_auth) { + // Use secure connection and chunk transfer coding. + UrlRequest url_request(server_url + client_auth); + EXPECT_TRUE(url_request.is_connected()) + << "Fail to connect to " << server_url << client_auth; + url_request.PostRequest(key_msg_); + std::string message; + EXPECT_TRUE(url_request.GetResponse(&message)); + + int http_status_code = url_request.GetStatusCode(message); + if (kHttpOk != http_status_code) { + LogResponseError(message, http_status_code); + } + EXPECT_EQ(kHttpOk, http_status_code); + + std::string drm_msg; + if (kHttpOk == http_status_code) { + LicenseRequest lic_request; + lic_request.GetDrmMessage(message, drm_msg); + LOGV("HTTP response body: (%u bytes)", drm_msg.size()); + } + return drm_msg; + } + + void VerifyKeyRequestResponse(const std::string& server_url, + const std::string& client_auth) { + std::string response; + VerifyKeyRequestResponse(server_url, client_auth, false); + } + + void VerifyUsageKeyRequestResponse(const std::string& server_url, + const std::string& client_auth) { + std::string response; + VerifyKeyRequestResponse(server_url, client_auth, true); + } + + void VerifyKeyRequestResponse(const std::string& server_url, + const std::string& client_auth, bool is_usage) { + std::string response; + VerifyKeyRequestResponse(server_url, client_auth, is_usage, &response); + } + + void VerifyKeyRequestResponse(const std::string& server_url, + const std::string& client_auth, bool is_usage, + std::string* response) { + *response = GetKeyRequestResponse(server_url, client_auth); + + EXPECT_EQ(decryptor_.AddKey(session_id_, *response, &key_set_id_), + wvcdm::KEY_ADDED); + EXPECT_EQ(is_usage || license_type_ == kLicenseTypeOffline, + key_set_id_.size() > 0); + } + protected: wvcdm::WvContentDecryptionModule decryptor_; CdmKeyMessage key_msg_; + CdmKeySetId key_set_id_; + CdmLicenseType license_type_; CdmSessionId session_id_; }; // To run this test set options, -// use_keybox 0 +// * use_keybox 0 TEST_F(WvCdmFeatureTest, OEMCertificateProvisioning) { decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL, &session_id_); @@ -105,31 +414,34 @@ TEST_F(WvCdmFeatureTest, OEMCertificateProvisioning) { CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; - EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest( - cert_type, cert_authority, - kDefaultCdmIdentifier, &key_msg_, - &provisioning_server_url)); + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.GetProvisioningRequest(cert_type, cert_authority, + kDefaultCdmIdentifier, &key_msg_, + &provisioning_server_url)); EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); - provisioning_server_url = - "https://staging-www.sandbox.googleapis.com/" - "certificateprovisioning/v1/devicecertificates/create" - "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; + ClientIdentification_TokenType token_type; + EXPECT_TRUE(ExtractTokenType(key_msg_, &token_type)); + EXPECT_EQ(ClientIdentification_TokenType_OEM_DEVICE_CERTIFICATE, token_type); - std::string response = - GetCertRequestResponse(provisioning_server_url); - //GetCertRequestResponse(g_config->provisioning_server_url()); + provisioning_server_url = + "https://staging-www.sandbox.googleapis.com/" + "certificateprovisioning/v1/devicecertificates/create" + "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; + + std::string response = GetCertRequestResponse(provisioning_server_url); + // GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( - kDefaultCdmIdentifier, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.HandleProvisioningResponse( + kDefaultCdmIdentifier, response, &cert, &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); } // To run this test set options, -// use_keybox 1 +// * use_keybox 1 TEST_F(WvCdmFeatureTest, KeyboxProvisioning) { decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL, &session_id_); @@ -137,29 +449,146 @@ TEST_F(WvCdmFeatureTest, KeyboxProvisioning) { CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; - EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest( - cert_type, cert_authority, - kDefaultCdmIdentifier, &key_msg_, - &provisioning_server_url)); + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.GetProvisioningRequest(cert_type, cert_authority, + kDefaultCdmIdentifier, &key_msg_, + &provisioning_server_url)); EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); - provisioning_server_url = - "https://staging-www.sandbox.googleapis.com/" - "certificateprovisioning/v1/devicecertificates/create" - "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; + ClientIdentification_TokenType token_type; + EXPECT_TRUE(ExtractTokenType(key_msg_, &token_type)); + EXPECT_EQ(ClientIdentification_TokenType_KEYBOX, token_type); + + provisioning_server_url = + "https://staging-www.sandbox.googleapis.com/" + "certificateprovisioning/v1/devicecertificates/create" + "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; + + std::string response = GetCertRequestResponse(provisioning_server_url); - std::string response = - GetCertRequestResponse(provisioning_server_url); - //GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( - kDefaultCdmIdentifier, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.HandleProvisioningResponse( + kDefaultCdmIdentifier, response, &cert, &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); } +// These parameterized tests validate SRM scenarios described in +// https://docs.google.com/a/google.com/document/d/1lS33zfTZknh7ab_J1tM0ecCT3kb_ghc0xFiosjpVgmU/edit?usp=sharing +class WvCdmSrmTest : public WvCdmFeatureTest, + public ::testing::WithParamInterface { +}; + +TEST_P(WvCdmSrmTest, Srm) { + SrmTestParameters* config = GetParam(); + + std::string str; + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.QueryStatus(kLevelDefault, + wvcdm::QUERY_KEY_CURRENT_SRM_VERSION, &str)); + + std::istringstream ss(str); + uint32_t value; + ss >> value; + EXPECT_FALSE(ss.fail()); + EXPECT_TRUE(ss.eof()); + EXPECT_EQ(config->initial_version, value); + + StrictMock listener; + TestKeyVerifier verify_keys_callback(config->expected_key_ids); + decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, &listener, + &session_id_); + + EXPECT_CALL(listener, + OnSessionKeysChange( + session_id_, + AllOf(Each(Pair(_, kKeyStatusUsable)), Not(IsEmpty())), true)) + .WillOnce(Invoke(&verify_keys_callback, &TestKeyVerifier::Verify)); + EXPECT_CALL(listener, OnExpirationUpdate(session_id_, _)); + + CdmInitData init_data = + config->output_protection_required + ? ConfigTestEnv::GetInitData( + kContentIdStagingSrmOuputProtectionRequired) + : ConfigTestEnv::GetInitData( + kContentIdStagingSrmOuputProtectionRequested); + + GenerateKeyRequest(init_data, kLicenseTypeStreaming); + VerifyKeyRequestResponse( + ConfigTestEnv::GetLicenseServerUrl(kContentProtectionStagingServer), + g_client_auth); + + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_.QueryStatus(kLevelDefault, + wvcdm::QUERY_KEY_CURRENT_SRM_VERSION, &str)); + + ss.clear(); + ss.str(str); + ss >> value; + EXPECT_FALSE(ss.fail()); + EXPECT_TRUE(ss.eof()); + EXPECT_EQ(config->final_version, value); + + decryptor_.CloseSession(session_id_); +} + +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmSrmTest, + ::testing::Range(&kSrmTestConfiguration[0], + &kSrmTestConfiguration[N_ELEM(kSrmTestConfiguration)])); + +// These parameterized tests validate SRM scenarios described in +// https://docs.google.com/a/google.com/document/d/1lS33zfTZknh7ab_J1tM0ecCT3kb_ghc0xFiosjpVgmU/edit?usp=sharing +class WvCdmSrmNotSupportedTest + : public WvCdmFeatureTest, + public ::testing::WithParamInterface {}; + +TEST_P(WvCdmSrmNotSupportedTest, Srm) { + SrmTestParameters* config = GetParam(); + + std::string str; + EXPECT_NE(wvcdm::NO_ERROR, + decryptor_.QueryStatus(kLevelDefault, + wvcdm::QUERY_KEY_CURRENT_SRM_VERSION, &str)); + + StrictMock listener; + TestKeyVerifier verify_keys_callback(config->expected_key_ids); + decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, &listener, + &session_id_); + + EXPECT_CALL(listener, + OnSessionKeysChange( + session_id_, + AllOf(Each(Pair(_, kKeyStatusUsable)), Not(IsEmpty())), true)) + .WillOnce(Invoke(&verify_keys_callback, &TestKeyVerifier::Verify)); + EXPECT_CALL(listener, OnExpirationUpdate(session_id_, _)); + + CdmInitData init_data = + config->output_protection_required + ? ConfigTestEnv::GetInitData( + kContentIdStagingSrmOuputProtectionRequired) + : ConfigTestEnv::GetInitData( + kContentIdStagingSrmOuputProtectionRequested); + + GenerateKeyRequest(init_data, kLicenseTypeStreaming); + VerifyKeyRequestResponse( + ConfigTestEnv::GetLicenseServerUrl(kContentProtectionStagingServer), + g_client_auth); + + EXPECT_NE(wvcdm::NO_ERROR, + decryptor_.QueryStatus(kLevelDefault, + wvcdm::QUERY_KEY_CURRENT_SRM_VERSION, &str)); + + decryptor_.CloseSession(session_id_); +} + +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmSrmNotSupportedTest, + ::testing::Range(&kSrmNotSupportedTestConfiguration[0], + &kSrmNotSupportedTestConfiguration[N_ELEM( + kSrmNotSupportedTestConfiguration)])); } // namespace wvcdm void show_menu(char* prog_name) { diff --git a/libwvdrmengine/cdm/test/cdm_feature_test.sh b/libwvdrmengine/cdm/test/cdm_feature_test.sh new file mode 100644 index 00000000..5c5d4453 --- /dev/null +++ b/libwvdrmengine/cdm/test/cdm_feature_test.sh @@ -0,0 +1,221 @@ +#!/bin/bash +# +# This test runs the cdm_feature_test +# Precondition: +# * cdm_feature_test has been pushed to the device and exits at +# /data/bin/cdm_feature_test +# * Follow instructions and load modifiable OEMCrypto as specified in +# https://docs.google.com/a/google.com/document/d/1hLK7ThUsBBKkokPhKh8urU1Zo9a8U4dX3bBKDgOU_iY/edit?usp=sharing + +KEYBOX="keybox" +OEMCERT="oemcert" +SRM_UPDATE_SUPPORTED="srm_update_supported" +SRM_UPDATE_NOT_SUPPORTED="srm_update_not_supported" +SRM_INITIAL_VERSION_CURRENT="srm_initial_version_current" +SRM_INITIAL_VERSION_OUTDATED="srm_initial_version_outdated" +SRM_INITIAL_VERSION_NOT_SUPPORTED="srm_initial_version_not_supported" +SRM_REVOKED="srm_attached_device_revoked" +SRM_NOT_REVOKED="srm_attached_device_not_revoked" +OPTIONS_TXT_FILENAME="options.txt" +HOST_OPTIONS_PATH="/tmp/$OPTIONS_TXT_FILENAME" + +# write_options_txt_file +# ["keybox"|"oemcert"|"srm_update_supported"|"srm_update_not_supported"| +# "srm_initial_version_current"|"srm_initial_version_outdated"| +# "srm_initial_version_not_supported"|"srm_attached_device_revoked" +# "srm_attached_device_not_revoked"] +write_options_txt_file() +{ + YES="yes" + NO="no" + + # default values + use_keybox=$YES + srm_initial_version_current=$NO + srm_initial_version_supported=$YES + srm_updatable=$NO + srm_revoked=$NO + + for var in "$@" + do + case $var in + $KEYBOX ) use_keybox=$YES ;; + $OEMCERT ) use_keybox=$NO ;; + $SRM_UPDATE_SUPPORTED ) srm_updatable=$YES ;; + $SRM_UPDATE_NOT_SUPPORTED ) srm_updatable=$NO ;; + $SRM_INITIAL_VERSION_CURRENT ) srm_initial_version_current=$YES ;; + $SRM_INITIAL_VERSION_OUTDATED ) srm_initial_version_current=$NO ;; + $SRM_INITIAL_VERSION_NOT_SUPPORTED ) srm_initial_version_supported=$NO ;; + $SRM_REVOKED) srm_revoked=$YES ;; + $SRM_NOT_REVOKED) srm_revoked=$NO ;; + esac + done + + echo "log_level 3" > $HOST_OPTIONS_PATH + echo "security_level 1" >> $HOST_OPTIONS_PATH + echo "current_hdcp 255" >> $HOST_OPTIONS_PATH + echo "max_hdcp 255" >> $HOST_OPTIONS_PATH + + if [ "$srm_updatable" == "$YES" ]; then + echo "srm_update_supported 1" >> $HOST_OPTIONS_PATH + else + echo "srm_update_supported 0" >> $HOST_OPTIONS_PATH + fi + + echo "srm_load_fail 0" >> $HOST_OPTIONS_PATH + + if [ "$srm_initial_version_supported" == "$YES" ]; then + if [ "$srm_initial_version_current" == "$YES" ]; then + echo "srm_initial_version 3" >> $HOST_OPTIONS_PATH + else + echo "srm_initial_version 1" >> $HOST_OPTIONS_PATH + fi + else + echo "srm_initial_version 0" >> $HOST_OPTIONS_PATH + fi + + echo "srm_load_version -1" >> $HOST_OPTIONS_PATH + + if [ "$srm_revoked" == "$YES" ]; then + echo "srm_blacklisted_device_attached 1" >> $HOST_OPTIONS_PATH + echo "srm_attached_device_id 20362845044" >> $HOST_OPTIONS_PATH + # echo "srm_attached_device_id 1079148782731" >> $HOST_OPTIONS_PATH + else + echo "srm_blacklisted_device_attached 0" >> $HOST_OPTIONS_PATH + echo "srm_attached_device_id 12345678" >> $HOST_OPTIONS_PATH + fi + + echo "security_patch_level 1" >> $HOST_OPTIONS_PATH + echo "max_buffer_size 0" >> $HOST_OPTIONS_PATH + + if [ "$use_keybox" == "$NO" ]; then + echo "use_keybox 0" >> $HOST_OPTIONS_PATH + else + echo "use_keybox 1" >> $HOST_OPTIONS_PATH + fi + + echo "use_fallback 1" >> $HOST_OPTIONS_PATH + echo "" >> $HOST_OPTIONS_PATH + echo "kLoggingTraceOEMCryptoCalls 1" >> $HOST_OPTIONS_PATH + echo "kLoggingDumpContentKeys 1" >> $HOST_OPTIONS_PATH + echo "kLoggingDumpKeyControlBlocks 1" >> $HOST_OPTIONS_PATH + echo "kLoggingDumpDerivedKeys 0" >> $HOST_OPTIONS_PATH + echo "kLoggingTraceNonce 0" >> $HOST_OPTIONS_PATH + echo "kLoggingTraceDecryption 0" >> $HOST_OPTIONS_PATH + echo "kLoggingTraceUsageTable 0" >> $HOST_OPTIONS_PATH + echo "kLoggingTraceDecryptCalls 0" >> $HOST_OPTIONS_PATH + echo "kLoggingDumpTraceAll 0" >> $HOST_OPTIONS_PATH +} + +if adb shell ls -l /data/vendor/mediadrm; then + TARGET_OPTIONS_PATH="/data/vendor/mediadrm/oemcrypto/$OPTIONS_TXT_FILENAME" +else + TARGET_OPTIONS_PATH="/data/mediadrm/oemcrypto/$OPTIONS_TXT_FILENAME" +fi + +## Test: OEMCertificateProvisioning +write_options_txt_file $OEMCERT +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=WvCdmFeatureTest.OEMCertificateProvisioning + +## Test: KeyboxProvisioning +write_options_txt_file +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=WvCdmFeatureTest.KeyboxProvisioning + + +## Test: Srm|VersionCurrent|OPRequested|Updatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/0 + +## Test: Srm|VersionCurrent|OPRequested|NotUpdatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/1 + +## Test: Srm|VersionCurrent|OPRequired|Updatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/2 + +## Test: Srm|VersionCurrent|OPRequired|NotUpdatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/3 + +## Test: Srm|VersionOutdated|OPRequested|Updatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/4 + +## Test: Srm|VersionOutdated|OPRequested|NotUpdatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/5 + +## Test: Srm|VersionOutdated|OPRequired|Updatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/6 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionOutdated|OPRequired|NotUpdatable|NotRevoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/7 + +## Test: Srm|VersionCurrent|OPRequested|Updatable|Revoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_SUPPORTED $SRM_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/8 + +## Test: Srm|VersionCurrent|OPRequested|NotUpdatable|Revoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_NOT_SUPPORTED $SRM_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/9 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionCurrent|OPRequired|Updatable|Revoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_SUPPORTED $SRM_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/10 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionCurrent|OPRequired|NotUpdatable|Revoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_CURRENT $SRM_UPDATE_NOT_SUPPORTED $SRM_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/11 + +## Test: Srm|VersionOutdated|OPRequested|Updatable|Revoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_SUPPORTED $SRM_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/12 + +## Test: Srm|VersionOutdated|OPRequested|NotUpdatable|Revoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_NOT_SUPPORTED $SRM_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/13 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionOutdated|OPRequired|Updatable|Revoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_SUPPORTED $SRM_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/14 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionOutdated|OPRequired|NotUpdatable|Revoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_OUTDATED $SRM_UPDATE_NOT_SUPPORTED $SRM_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmTest.Srm/15 + +## Test: Srm|VersionNotSupported|OPRequested|NotUpdatable|NotRevoked|CanPlayback +write_options_txt_file $SRM_INITIAL_VERSION_NOT_SUPPORTED $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmNotSupportedTest.Srm/0 + +# TODO(rfrias): Uncomment out test after b/64946456 is addressed +## Test: Srm|VersionNotSupported|OPRequired|NotUpdatable|NotRevoked|CannotPlayback +#write_options_txt_file $SRM_INITIAL_VERSION_NOT_SUPPORTED $SRM_UPDATE_NOT_SUPPORTED $SRM_NOT_REVOKED +#adb push $HOST_OPTIONS_PATH $TARGET_OPTIONS_PATH +#adb shell /data/bin/cdm_feature_test --gtest_filter=Cdm/WvCdmSrmNotSupportedTest.Srm/1