From fd00a8af242e0ef3483ec5db7b50f75c486c281a Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Mon, 14 Mar 2022 02:15:04 -0700 Subject: [PATCH] Remove old test license holder [ Merged from http://go/wvgerrit/143750 ] The old test license holder would generate a minimal license response, but could not correctly mimic important server logic introduced in the v16 server. Since all integration tests now have policies on the UAT server, we do not need these minimalist license responses anymore. Bug: 192700112 Test: GtsMediaTestCases on sunfish Change-Id: I78c1b6085a6d0239840a11f2b904902210e5e61c --- libwvdrmengine/cdm/core/test/test_base.cpp | 260 --------------------- libwvdrmengine/cdm/core/test/test_base.h | 63 ----- 2 files changed, 323 deletions(-) diff --git a/libwvdrmengine/cdm/core/test/test_base.cpp b/libwvdrmengine/cdm/core/test/test_base.cpp index 3cfacd6e..e5b25465 100644 --- a/libwvdrmengine/cdm/core/test/test_base.cpp +++ b/libwvdrmengine/cdm/core/test/test_base.cpp @@ -576,266 +576,6 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[], return true; } -TestLicenseHolder::TestLicenseHolder(CdmEngine* cdm_engine) - : cdm_engine_(cdm_engine), - oemcrypto_api_(0), - session_opened_(false), - // Keys are initialized with simple values, and the correct size: - derived_mac_key_server_(MAC_KEY_SIZE, 'a'), - derived_mac_key_client_(MAC_KEY_SIZE, 'b'), - mac_key_server_(MAC_KEY_SIZE, 'c'), - mac_key_client_(MAC_KEY_SIZE, 'd'), - enc_key_(CONTENT_KEY_SIZE, 'e'), - session_key_(CONTENT_KEY_SIZE, 'f') {} - -TestLicenseHolder::~TestLicenseHolder() { CloseSession(); } - -void TestLicenseHolder::OpenSession(const std::string& key_system) { - CdmResponseType status = - cdm_engine_->OpenSession(key_system, nullptr, nullptr, &session_id_); - ASSERT_EQ(status, NO_ERROR); - ASSERT_NE("", session_id_) << "Could not open CDM session."; - ASSERT_TRUE(cdm_engine_->IsOpenSession(session_id_)); - session_opened_ = true; -} - -void TestLicenseHolder::CloseSession() { - if (session_opened_) { - cdm_engine_->CloseSession(session_id_); - session_opened_ = false; - } -} - -void TestLicenseHolder::GenerateKeyRequest( - const std::string& key_id, const std::string& init_data_type_string) { - ASSERT_TRUE(session_opened_); - CdmAppParameterMap app_parameters; - CdmKeySetId key_set_id; - InitializationData init_data(init_data_type_string, key_id); - if (wvutil::g_cutoff >= wvutil::CDM_LOG_DEBUG) init_data.DumpToLogs(); - CdmKeyRequest key_request; - CdmResponseType result = cdm_engine_->GenerateKeyRequest( - session_id_, key_set_id, init_data, kLicenseTypeStreaming, app_parameters, - &key_request); - EXPECT_EQ(KEY_MESSAGE, result); - signed_license_request_data_ = key_request.message; - EXPECT_EQ(kKeyRequestTypeInitial, key_request.type); -} - -void TestLicenseHolder::CreateDefaultLicense() { - video_widevine::SignedMessage signed_message; - EXPECT_TRUE(signed_message.ParseFromString(signed_license_request_data_)); - license_request_data_ = signed_message.msg(); - video_widevine::LicenseRequest license_request; - EXPECT_TRUE(license_request.ParseFromString(license_request_data_)); - video_widevine::ClientIdentification client_id = license_request.client_id(); - - EXPECT_EQ( - video_widevine::ClientIdentification_TokenType_DRM_DEVICE_CERTIFICATE, - client_id.type()); - - oemcrypto_api_ = - (client_id.has_client_capabilities() && - client_id.client_capabilities().has_oem_crypto_api_version()) - ? client_id.client_capabilities().oem_crypto_api_version() - : 0; - - std::string signed_buffer = license_request_data_; - std::string core_message = signed_message.has_oemcrypto_core_message() - ? signed_message.oemcrypto_core_message() - : ""; - if (oemcrypto_api_ >= 17) { - signed_buffer = signed_message.oemcrypto_core_message() + signed_buffer; - } - - // Extract the RSA key from the DRM certificate. - std::string token = client_id.token(); - video_widevine::SignedDrmCertificate signed_drm_cert; - EXPECT_TRUE(signed_drm_cert.ParseFromString(token)); - video_widevine::DrmCertificate drm_cert; - EXPECT_TRUE(drm_cert.ParseFromString(signed_drm_cert.drm_certificate())); - EXPECT_TRUE(rsa_key_.Init(drm_cert.public_key())); - EXPECT_TRUE( - rsa_key_.VerifySignature(signed_buffer, signed_message.signature())); - - DeriveKeysFromSessionKey(); - - video_widevine::LicenseIdentification* license_id = license()->mutable_id(); - license_id->set_request_id("TestCase"); - license_id->set_session_id(session_id_); - license_id->set_type(video_widevine::STREAMING); - license_id->set_version(0); - - ::video_widevine::License_Policy* policy = license()->mutable_policy(); - policy->set_can_play(true); - policy->set_can_persist(false); - policy->set_can_renew(false); - policy->set_playback_duration_seconds(0); - policy->set_license_duration_seconds(0); - - AddMacKey(); -} - -void TestLicenseHolder::AddMacKey() { - video_widevine::License_KeyContainer* key_container = license()->add_key(); - std::vector iv(KEY_IV_SIZE, 'v'); - std::string iv_s(iv.begin(), iv.end()); - key_container->set_iv(iv_s); - key_container->set_type(video_widevine::License_KeyContainer_KeyType_SIGNING); - - // Combine server and client mac keys. - std::vector keys(mac_key_server_); - keys.insert(keys.end(), mac_key_client_.begin(), mac_key_client_.end()); - std::string encrypted_keys = - WvCdmTestBase::Aes128CbcEncrypt(enc_key_, keys, iv); - key_container->set_key(encrypted_keys); -} - -video_widevine::License_KeyContainer* TestLicenseHolder::AddKey( - const KeyId& key_id, const std::vector& key_data, - const wvoec::KeyControlBlock& block_in) { - video_widevine::License_KeyContainer* key_container = license()->add_key(); - wvoec::KeyControlBlock block = block_in; - if (block.verification[0] == 0) { - block.verification[0] = 'k'; - block.verification[1] = 'c'; - block.verification[2] = '1'; - // This will work until oemcrypto api 20. - block.verification[3] = '0' + wvoec::global_features.api_version - 10; - } - key_container->set_id(key_id); - key_container->set_type(video_widevine::License_KeyContainer_KeyType_CONTENT); - key_container->set_level( - video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO); - - std::vector iv(KEY_IV_SIZE, 'v'); - std::string iv_s(iv.begin(), iv.end()); - key_container->set_iv(iv_s); - - std::string encrypted_key_data = - WvCdmTestBase::Aes128CbcEncrypt(enc_key_, key_data, iv); - // TODO(b/111069024): remove this! - std::string padding(CONTENT_KEY_SIZE, '-'); - key_container->set_key(encrypted_key_data + padding); - - // TODO(b/192700112): This mock license server should parse the core message - // request, and only encrypt the key control block if the API is greater than - // or equal to 16.5. For now, we can pass tests on the v17 branch by checking - // against v17.0. - if (oemcrypto_api_ >= 17) { - std::string block_s(reinterpret_cast(&block), - reinterpret_cast(&block) + sizeof(block)); - key_container->mutable_key_control()->set_key_control_block(block_s); - } else { - std::vector block_v( - reinterpret_cast(&block), - reinterpret_cast(&block) + sizeof(block)); - std::vector block_iv(KEY_IV_SIZE, 'w'); - std::string block_iv_s(block_iv.begin(), block_iv.end()); - std::string encrypted_block = - WvCdmTestBase::Aes128CbcEncrypt(key_data, block_v, block_iv); - key_container->mutable_key_control()->set_iv(block_iv_s); - key_container->mutable_key_control()->set_key_control_block( - encrypted_block); - } - return key_container; -} - -void TestLicenseHolder::SignAndLoadLicense() { -#if 0 // Need to turn off protobuf_lite to use this. - LOGV("License = %s\n", license_.DebugString().c_str()); -#endif - std::string license_data; - license_.SerializeToString(&license_data); - - std::string signature = - WvCdmTestBase::SignHMAC(license_data, derived_mac_key_server_); - - std::string session_key_s(session_key_.begin(), session_key_.end()); - std::string encrypted_session_key; - EXPECT_TRUE(rsa_key_.Encrypt(session_key_s, &encrypted_session_key)); - video_widevine::SignedMessage signed_response; - signed_response.set_msg(license_data); - signed_response.set_type(video_widevine::SignedMessage_MessageType_LICENSE); - signed_response.set_session_key(encrypted_session_key); - signed_response.set_signature(signature); - - std::string response_data; - signed_response.SerializeToString(&response_data); - - CdmKeySetId key_set_id; - CdmLicenseType license_type; // Required for AddKey. Result value ignored. - EXPECT_EQ(KEY_ADDED, cdm_engine_->AddKey(session_id_, response_data, - &license_type, &key_set_id)); -} - -void TestLicenseHolder::DeriveKeysFromSessionKey() { - std::string context; - GenerateMacContext(license_request_data_, &context); - std::vector mac_key_context(context.begin(), context.end()); - GenerateEncryptContext(license_request_data_, &context); - std::vector enc_key_context(context.begin(), context.end()); - - ASSERT_TRUE( - DeriveKey(session_key_, mac_key_context, 1, &derived_mac_key_server_)); - std::vector mac_key_part2; - ASSERT_TRUE(DeriveKey(session_key_, mac_key_context, 2, &mac_key_part2)); - derived_mac_key_server_.insert(derived_mac_key_server_.end(), - mac_key_part2.begin(), mac_key_part2.end()); - - ASSERT_TRUE( - DeriveKey(session_key_, mac_key_context, 3, &derived_mac_key_client_)); - ASSERT_TRUE(DeriveKey(session_key_, mac_key_context, 4, &mac_key_part2)); - derived_mac_key_client_.insert(derived_mac_key_client_.end(), - mac_key_part2.begin(), mac_key_part2.end()); - - std::vector enc_key; - ASSERT_TRUE(DeriveKey(session_key_, enc_key_context, 1, &enc_key_)); -} - -bool TestLicenseHolder::DeriveKey(const std::vector& key, - const std::vector& context, - int counter, std::vector* out) { - if (key.empty() || counter > 4 || context.empty() || out == nullptr) { - LOGE("DeriveKey(): bad context"); - return false; - } - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - CMAC_CTX* cmac_ctx = CMAC_CTX_new(); - - if (!cmac_ctx) { - LOGE("DeriveKey(): cmac failure"); - return false; - } - - if (!CMAC_Init(cmac_ctx, &key[0], key.size(), cipher, nullptr)) { - LOGE("DeriveKey(): CMAC_Init"); - CMAC_CTX_free(cmac_ctx); - return false; - } - - std::vector message; - message.push_back(counter); - message.insert(message.end(), context.begin(), context.end()); - - if (!CMAC_Update(cmac_ctx, &message[0], message.size())) { - LOGE("DeriveKey(): CMAC_Update"); - CMAC_CTX_free(cmac_ctx); - return false; - } - - size_t reslen; - uint8_t res[128]; - if (!CMAC_Final(cmac_ctx, res, &reslen)) { - LOGE("DeriveKey(): CMAC_Final"); - CMAC_CTX_free(cmac_ctx); - return false; - } - out->assign(res, res + reslen); - CMAC_CTX_free(cmac_ctx); - return true; -} - std::string MakePSSH(const video_widevine::WidevinePsshData& header) { std::string data; header.SerializeToString(&data); diff --git a/libwvdrmengine/cdm/core/test/test_base.h b/libwvdrmengine/cdm/core/test/test_base.h index 0c837203..7606ad37 100644 --- a/libwvdrmengine/cdm/core/test/test_base.h +++ b/libwvdrmengine/cdm/core/test/test_base.h @@ -108,69 +108,6 @@ class TestCryptoSession : public CryptoSession { CdmResponseType GenerateNonce(uint32_t* nonce) override; }; -// A holder for a license. Users of this class will first open a session with -// OpenSession, then generate a key request with GenerateKeyRequest, and then -// call CreateDefaultLicense to create a bare-bones license with no keys in it. -// The user may then access the license to adjust the policy, or use AddKey to -// add keys to the license. The license is then loaded via SignAndLoadLicense. -class TestLicenseHolder { - public: - // cdm_engine must exist and outlive the TestLicenseHolder. - TestLicenseHolder(CdmEngine* cdm_engine); - ~TestLicenseHolder(); - // Caller must ensure device already provisioned. - void OpenSession(const std::string& key_system); - void CloseSession(); - // Use the cdm_engine to generate a key request in the session. This should - // be called after OpenSession. This saves the signed license request, so - // that the DRM certificate can be extracted in CreateDefaultLicense. - void GenerateKeyRequest(const std::string& key_id, - const std::string& init_data_type_string); - // Create a bare-bones license from the license request. After this, the user - // may access and modify the license using license() below. - void CreateDefaultLicense(); - // Sign the license using the DRM certificate's RSA key. Then the license is - // passed to the cdm_engine using AddKey. After this, the license is loaded - // and the keys may be used. - void SignAndLoadLicense(); - - // The session id. This is only valid after a call to OpenSession. - const std::string& session_id() { return session_id_; } - // The license protobuf. This is only valid after CreateDefaultLicense. - video_widevine::License* license() { return &license_; }; - // Add a key with the given key control block and key data. - // If the block's verification is empty, it will be set to a valid value. - // The key data is encrypted correctly. - video_widevine::License_KeyContainer* AddKey( - const KeyId& key_id, const std::vector& key_data, - const wvoec::KeyControlBlock& block); - - private: - // Helper method to generate mac keys and encryption keys for the license. - void DeriveKeysFromSessionKey(); - // Derive a single mac key or encryption key using CMAC. - bool DeriveKey(const std::vector& key, - const std::vector& context, int counter, - std::vector* out); - // Add the mac keys to the license. - void AddMacKey(); - - CdmEngine* cdm_engine_; - uint32_t oemcrypto_api_; - std::string signed_license_request_data_; - std::string license_request_data_; - std::string session_id_; - bool session_opened_; - RsaPublicKey rsa_key_; // From the DRM Certificate. - video_widevine::License license_; - std::vector derived_mac_key_server_; - std::vector derived_mac_key_client_; - std::vector mac_key_server_; - std::vector mac_key_client_; - std::vector enc_key_; - std::vector session_key_; -}; - // Given a PSSH data structure, this makes a PSSH string for use in // generating a license request. std::string MakePSSH(const video_widevine::WidevinePsshData& header);