diff --git a/libwvdrmengine/cdm/core/test/keybox_ota_test.cpp b/libwvdrmengine/cdm/core/test/keybox_ota_test.cpp index 1c3ec680..fc5a2df9 100644 --- a/libwvdrmengine/cdm/core/test/keybox_ota_test.cpp +++ b/libwvdrmengine/cdm/core/test/keybox_ota_test.cpp @@ -10,6 +10,7 @@ #include "create_test_file_system.h" #include "crypto_session.h" #include "properties.h" +#include "provisioning_holder.h" #include "test_base.h" #include "test_printers.h" #include "test_sleep.h" @@ -43,47 +44,11 @@ class CdmOtaKeyboxTest : public ::testing::Test { void Provision(TestCdmEngine* cdm_engine) { ConfigTestEnv config = *WvCdmTestBase::default_config_; + ProvisioningHolder provisioner(cdm_engine, config.provisioning_server(), + config.provisioning_service_certificate()); CdmCertificateType cert_type = kCertificateWidevine; - std::string cert_authority; - CdmProvisioningRequest prov_request; - std::string provisioning_server_url; - CdmResponseType result(CERT_PROVISIONING_NONCE_GENERATION_ERROR); - // Get a provisioning request. We might need one retry if there is a nonce - // flood failure. - for (int i = 0; i < 2; i++) { - result = cdm_engine->GetProvisioningRequest( - cert_type, cert_authority, config.provisioning_service_certificate(), - kLevelDefault, &prov_request, &provisioning_server_url); - if (result == CERT_PROVISIONING_NONCE_GENERATION_ERROR) { - wvutil::TestSleep::Sleep(2); - continue; - } - break; - } - ASSERT_EQ(NO_ERROR, result); - LOGV("Provisioning request: req = %s", prov_request.c_str()); - - // Ignore URL provided by CdmEngine. Use ours, as configured - // for test vs. production server. - provisioning_server_url.assign(config.provisioning_server()); - - // Make request. - UrlRequest url_request(provisioning_server_url); - if (!url_request.is_connected()) { - LOGE("Failed to connect to provisioning server: url = %s", - provisioning_server_url.c_str()); - } - url_request.PostCertRequestInQueryString(prov_request); - - // Receive and parse response. - std::string http_message; - ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&http_message)) - << "Keybox OTA provisioning request failed."; - LOGV("http_message: \n%s\n", http_message.c_str()); - - std::string cert, wrapped_key; - ASSERT_EQ(NO_ERROR, cdm_engine->HandleProvisioningResponse( - http_message, kLevelDefault, &cert, &wrapped_key)); + constexpr bool binary_provisioning = false; + provisioner.Provision(cert_type, binary_provisioning); } }; diff --git a/libwvdrmengine/cdm/core/test/policy_integration_test.cpp b/libwvdrmengine/cdm/core/test/policy_integration_test.cpp index f82160d4..f254e934 100644 --- a/libwvdrmengine/cdm/core/test/policy_integration_test.cpp +++ b/libwvdrmengine/cdm/core/test/policy_integration_test.cpp @@ -6,6 +6,9 @@ // would do. They verify that policies specified on UAT are honored on the // device. +#include +#include +#include #include #include @@ -16,9 +19,9 @@ #include "license_holder.h" #include "log.h" #include "oec_device_features.h" +#include "provisioning_holder.h" #include "test_base.h" #include "test_printers.h" - #include "wv_cdm_types.h" namespace wvcdm { @@ -111,4 +114,101 @@ TEST_F(CorePIGTest, OfflineHWSecureRequired) { ASSERT_NO_FATAL_FAILURE(holder.CloseSession()); } +TEST_F(CorePIGTest, CastReceiverProvisioning) { + auto digest = wvutil::a2b_hex( // digest info header + "3021300906052b0e03021a05000414" + // sha1 of kMessage + "d2662f893aaec72f3ca6decc2aa942f3949e8b21"); + + if (!wvoec::global_features.cast_receiver) { + GTEST_SKIP() << "OEMCrypto does not support CAST Receiver functionality"; + } + + // Provision x509 cert for CAST Receiver. + ProvisioningHolder provisioner(&cdm_engine_, config_.provisioning_server(), + config_.provisioning_service_certificate()); + provisioner.Provision(kCertificateX509, binary_provisioning_); + + // cdm_engine_.OpenSession here is to load test keybox + // in order to successfully OEMCrypto_LoadDRMPrivateKey + std::string session_id; + CdmResponseType status = cdm_engine_.OpenSession( + config_.key_system(), nullptr, nullptr, &session_id); + ASSERT_EQ(NO_ERROR, status); + ASSERT_TRUE(cdm_engine_.IsOpenSession(session_id)); + + std::string wrapped_key_str = provisioner.wrapped_key(); + std::vector wrapped_key(wrapped_key_str.begin(), + wrapped_key_str.end()); + OEMCrypto_SESSION oemcrypto_session; + OEMCryptoResult sts = + OEMCrypto_OpenSession(&oemcrypto_session, kLevelDefault); + if (sts != OEMCrypto_SUCCESS) { + LOGE("Fail in OEMCrypto_OpenSession"); + } + + // Stop test when OEMCrypto_LoadDRMPrivateKey fails. + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadDRMPrivateKey( + oemcrypto_session, OEMCrypto_RSA_Private_Key, + wrapped_key.data(), wrapped_key.size())); + + // Generate signature for the digest + size_t signatureSize = 0; + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, + OEMCrypto_GenerateRSASignature(oemcrypto_session, digest.data(), + digest.size(), nullptr, + &signatureSize, kSign_PKCS1_Block1)); + std::vector signature; + signature.resize(signatureSize); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_GenerateRSASignature(oemcrypto_session, digest.data(), + digest.size(), signature.data(), + &signatureSize, kSign_PKCS1_Block1)); + LOGI("digest.size(): %zu, signature.size(): %zu", digest.size(), + signature.size()); + + // Verify the generated signature + std::string cert = provisioner.certificate(); + const char* cert_str_ptr = cert.c_str(); + LOGI("cert: %s", cert_str_ptr); + + // Extract the public key from the x509 cert chain + BIO* bio = BIO_new(BIO_s_mem()); + ASSERT_NE(bio, nullptr); + ASSERT_GT(BIO_puts(bio, cert_str_ptr), 0); + X509* x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); + ASSERT_NE(x509, nullptr); + EVP_PKEY* pubkey = X509_get_pubkey(x509); + ASSERT_NE(pubkey, nullptr); + + // remove digest info header for verification + // SHA1 is 20 bytes long + digest.erase(digest.begin(), digest.begin() + digest.size() - 20); + + // Modified from openssl example + // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_verify_init.html + // Set RSA padding as RSA_PKCS1_PADDING and digest algo to SHA1. + EVP_PKEY_CTX* ctx; + unsigned char* md = digest.data(); + unsigned char* sig = signature.data(); + size_t mdlen = digest.size(); + size_t siglen = signature.size(); + + ctx = EVP_PKEY_CTX_new(pubkey, nullptr /* no engine */); + ASSERT_NE(ctx, nullptr); + ASSERT_GT(EVP_PKEY_verify_init(ctx), 0); + ASSERT_GT(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), 0); + ASSERT_GT(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()), 0); + + /* Perform operation */ + EXPECT_EQ(1, EVP_PKEY_verify(ctx, sig, siglen, md, mdlen)); + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pubkey); + BIO_free(bio); + X509_free(x509); + + OEMCrypto_CloseSession(oemcrypto_session); + cdm_engine_.CloseSession(session_id); +} } // namespace wvcdm diff --git a/libwvdrmengine/cdm/core/test/provisioning_holder.cpp b/libwvdrmengine/cdm/core/test/provisioning_holder.cpp new file mode 100644 index 00000000..8155d61f --- /dev/null +++ b/libwvdrmengine/cdm/core/test/provisioning_holder.cpp @@ -0,0 +1,193 @@ +// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine License +// Agreement. + +#include "provisioning_holder.h" + +#include + +#include "cdm_engine.h" +#include "config_test_env.h" + +#include "log.h" +#include "oec_device_features.h" +#include "test_printers.h" +#include "test_sleep.h" +#include "url_request.h" + +namespace wvcdm { + +void ProvisioningHolder::Provision(CdmCertificateType cert_type, + bool binary_provisioning) { + CdmProvisioningRequest request; + std::string provisioning_server_url; + std::string cert_authority; + + CdmSessionId session_id; + + if (cert_type == kCertificateX509) { + cert_authority = "cast.google.com"; + } + LOGV("Provision with type %s.", CdmCertificateTypeToString(cert_type)); + CdmResponseType result(CERT_PROVISIONING_NONCE_GENERATION_ERROR); + // Get a provisioning request. We might need one retry if there is a nonce + // flood failure. + for (int i = 0; i < 2 && result == CERT_PROVISIONING_NONCE_GENERATION_ERROR; + i++) { + result = cdm_engine_->GetProvisioningRequest( + cert_type, cert_authority, provisioning_service_certificate_, + kLevelDefault, &request, &provisioning_server_url); + if (result == CERT_PROVISIONING_NONCE_GENERATION_ERROR) { + wvutil::TestSleep::Sleep(2); + } + } + ASSERT_EQ(NO_ERROR, result); + LOGV("cert_authority = %s", cert_authority.c_str()); + + if (binary_provisioning) { + request = wvutil::Base64SafeEncodeNoPad(request); + } + LOGV("Provisioning request: req = %s", request.c_str()); + + // Ignore URL provided by CdmEngine. Use ours, as configured + // for test vs. production server. + provisioning_server_url.assign(provisioning_server_url_); + + // Make request. + UrlRequest url_request(provisioning_server_url); + if (!url_request.is_connected()) { + LOGE("Failed to connect to provisioning server: url = %s", + provisioning_server_url.c_str()); + } + url_request.PostCertRequestInQueryString(request); + + // Receive and parse response. + std::string response; + ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&response)) + << "Failed to fetch provisioning response. " + << DumpProvAttempt(request, response, cert_type); + + if (binary_provisioning) { + // extract provisioning response from received message + // Extracts signed response from JSON string, result is serialized + // protobuf. + std::string protobuf_response; + const bool extract_ok = ExtractSignedMessage(response, &protobuf_response); + ASSERT_TRUE(extract_ok) << "Failed to extract signed serialized " + "response from JSON response"; + LOGV("Extracted response message: \n%s\n", protobuf_response.c_str()); + + ASSERT_FALSE(protobuf_response.empty()) + << "Protobuf response is unexpectedly empty"; + + // base64 decode response to yield binary protobuf + const std::vector response_vec( + wvutil::Base64SafeDecode(protobuf_response)); + ASSERT_FALSE(response_vec.empty()) + << "Failed to decode base64 of response: response = " + << protobuf_response; + + const std::string binary_protobuf_response(response_vec.begin(), + response_vec.end()); + + ASSERT_EQ(NO_ERROR, cdm_engine_->HandleProvisioningResponse( + binary_protobuf_response, kLevelDefault, + &certificate_, &wrapped_key_)) + << "Binary provisioning failed. " + << DumpProvAttempt(request, response, cert_type); + } else { + ASSERT_EQ(NO_ERROR, + cdm_engine_->HandleProvisioningResponse( + response, kLevelDefault, &certificate_, &wrapped_key_)) + << "Non-binary provisioning failed. " + << DumpProvAttempt(request, response, cert_type); + } +} + +bool ProvisioningHolder::ExtractSignedMessage(const std::string& response, + std::string* result) { + static const std::string kMessageStart = "\"signedResponse\": \""; + static const std::string kMessageEnd = "\""; + std::string response_string; + size_t start = response.find(kMessageStart); + + if (start == response.npos) { + // Assume serialized protobuf message. + result->assign(response); + } else { + // Assume JSON-wrapped protobuf. + size_t end = response.find(kMessageEnd, start + kMessageStart.length()); + if (end == response.npos) { + LOGE("ExtractSignedMessage cannot locate end substring"); + result->clear(); + return false; + } + size_t result_string_size = end - start - kMessageStart.length(); + result->assign(response, start + kMessageStart.length(), + result_string_size); + } + + if (result->empty()) { + LOGE("ExtractSignedMessage: Response message is empty"); + return false; + } + return true; +} + +std::string ProvisioningHolder::DumpProvAttempt(const std::string& request, + const std::string& response, + CdmCertificateType cert_type) { + std::stringstream info; + info << "Cert Type: "; + PrintTo(cert_type, &info); + info << "\n"; + info << "Provisioning url: " << provisioning_server_url_ << "\n"; + info << "Provisioning Request: " << request << "\n\n"; + info << "Provisioning Response: " << response << "\n\n"; + std::string system_id; + cdm_engine_->QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &system_id); + info << "system id: " << system_id << "\n"; + if (wvoec::global_features.derive_key_method == + wvoec::DeviceFeatures::TEST_PROVISION_30) { + std::vector cert; + size_t cert_length = 0; + OEMCryptoResult result = OEMCrypto_GetOEMPublicCertificate( + cert.data(), &cert_length, kLevelDefault); + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + cert.resize(cert_length); + result = OEMCrypto_GetOEMPublicCertificate(cert.data(), &cert_length, + kLevelDefault); + } + if (result != OEMCrypto_SUCCESS) { + info << "--- ERROR GETTING CERT. result=" << result; + } else { + info << "OEM Cert = (len=" << cert_length << ") " + << wvutil::unlimited_b2a_hex(cert); + } + } + if (wvoec::global_features.derive_key_method == + wvoec::DeviceFeatures::TEST_PROVISION_40) { + std::vector bcc; + size_t bcc_length = 0; + std::vector signature; + size_t signature_length = 0; + OEMCryptoResult result = OEMCrypto_GetBootCertificateChain( + bcc.data(), &bcc_length, signature.data(), &signature_length); + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + bcc.resize(bcc_length); + signature.resize(signature_length); + result = OEMCrypto_GetBootCertificateChain( + bcc.data(), &bcc_length, signature.data(), &signature_length); + } + if (result != OEMCrypto_SUCCESS) { + info << "--- ERROR GETTING BCC. result=" << result; + } else { + info << "BCC = (len=" << bcc_length << ") " + << wvutil::unlimited_b2a_hex(bcc) << "\n" + << "Additional Sig = (len=" << signature_length << ") " + << wvutil::unlimited_b2a_hex(signature) << "\n"; + } + } + return info.str(); +} +} // namespace wvcdm diff --git a/libwvdrmengine/cdm/core/test/provisioning_holder.h b/libwvdrmengine/cdm/core/test/provisioning_holder.h new file mode 100644 index 00000000..073b46a8 --- /dev/null +++ b/libwvdrmengine/cdm/core/test/provisioning_holder.h @@ -0,0 +1,48 @@ +// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine License +// Agreement. + +#ifndef WVCDM_CORE_TEST_PROVISIONING_HOLDER_H_ +#define WVCDM_CORE_TEST_PROVISIONING_HOLDER_H_ + +#include "test_base.h" + +#include + +namespace wvcdm { + +class ProvisioningHolder { + public: + ProvisioningHolder(TestCdmEngine* cdm_engine, + const std::string& provisioning_server_url, + const std::string& provisioning_service_certificate) + : cdm_engine_(cdm_engine), + provisioning_server_url_(provisioning_server_url), + provisioning_service_certificate_(provisioning_service_certificate) {} + void Provision(CdmCertificateType cert_type, bool binary_provisioning); + std::string certificate() const { return certificate_; } + std::string wrapped_key() const { return wrapped_key_; } + + protected: + TestCdmEngine* cdm_engine_; + std::string provisioning_server_url_; + std::string provisioning_service_certificate_; + std::string certificate_; + std::string wrapped_key_; + + // Locate the portion of the server's provisioning response message that is + // between the strings jason_start_substr and json_end_substr. Returns the + // string through *result. If the start substring match fails, assume the + // entire string represents a serialized protobuf mesaage and return true with + // the entire string. If the end_substring match fails, return false with an + // empty *result. + bool ExtractSignedMessage(const std::string& response, std::string* result); + // Dump request and response information for use in a debug or failure log. + std::string DumpProvAttempt(const std::string& request, + const std::string& response, + CdmCertificateType cert_type); +}; + +} // namespace wvcdm + +#endif // WVCDM_CORE_TEST_PROVISIONING_HOLDER_H_ diff --git a/libwvdrmengine/cdm/core/test/test_base.cpp b/libwvdrmengine/cdm/core/test/test_base.cpp index 4d3365e6..d6fde02a 100644 --- a/libwvdrmengine/cdm/core/test/test_base.cpp +++ b/libwvdrmengine/cdm/core/test/test_base.cpp @@ -26,6 +26,7 @@ #include "oec_test_data.h" #include "platform.h" #include "properties.h" +#include "provisioning_holder.h" #include "test_printers.h" #include "test_sleep.h" #include "url_request.h" @@ -143,101 +144,6 @@ void show_menu(const char* prog_name, const std::string& extra_help_text) { std::cout << extra_help_text << std::endl; } - -/* - * Locate the portion of the server's response message that is between - * the strings jason_start_substr and json_end_substr. Returns the string - * through *result. If the start substring match fails, assume the entire - * string represents a serialized protobuf mesaage and return true with - * the entire string. If the end_substring match fails, return false with - * an empty *result. - */ -bool ExtractSignedMessage(const std::string& response, - const std::string& json_start_substr, - const std::string& json_end_substr, - std::string* result) { - std::string response_string; - size_t start = response.find(json_start_substr); - - if (start == response.npos) { - // Assume serialized protobuf message. - result->assign(response); - } else { - // Assume JSON-wrapped protobuf. - size_t end = - response.find(json_end_substr, start + json_start_substr.length()); - if (end == response.npos) { - LOGE("ExtractSignedMessage cannot locate end substring"); - result->clear(); - return false; - } - size_t result_string_size = end - start - json_start_substr.length(); - result->assign(response, start + json_start_substr.length(), - result_string_size); - } - - if (result->empty()) { - LOGE("ExtractSignedMessage: Response message is empty"); - return false; - } - return true; -} - -// TODO(b/242744857): This extra debugging may not be needed in all cases. When -// provisioning fails, this dumps the cert and other information. -std::string DumpProvAttempt(const std::string& url, const std::string& request, - const std::string& http_message, - CdmEngine* cdm_engine) { - std::stringstream info; - info << "Provisioning url: " << url << "\n"; - info << "Request: " << wvutil::unlimited_b2a_hex(request) << "\n"; - info << "http_message: " << wvutil::unlimited_b2a_hex(http_message) << "\n"; - std::string system_id; - cdm_engine->QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &system_id); - info << "system id: " << system_id << "\n"; - if (wvoec::global_features.derive_key_method == - wvoec::DeviceFeatures::TEST_PROVISION_30) { - std::vector cert; - size_t cert_length = 0; - OEMCryptoResult result = OEMCrypto_GetOEMPublicCertificate( - cert.data(), &cert_length, kLevelDefault); - if (result == OEMCrypto_ERROR_SHORT_BUFFER) { - cert.resize(cert_length); - result = OEMCrypto_GetOEMPublicCertificate(cert.data(), &cert_length, - kLevelDefault); - } - if (result != OEMCrypto_SUCCESS) { - info << "--- ERROR GETTING CERT. result=" << result; - } else { - info << "OEM Cert = (len=" << cert_length << ") " - << wvutil::unlimited_b2a_hex(cert); - } - } - if (wvoec::global_features.derive_key_method == - wvoec::DeviceFeatures::TEST_PROVISION_40) { - std::vector bcc; - size_t bcc_length = 0; - std::vector signature; - size_t signature_length = 0; - OEMCryptoResult result = OEMCrypto_GetBootCertificateChain( - bcc.data(), &bcc_length, signature.data(), &signature_length); - if (result == OEMCrypto_ERROR_SHORT_BUFFER) { - bcc.resize(bcc_length); - signature.resize(signature_length); - result = OEMCrypto_GetBootCertificateChain( - bcc.data(), &bcc_length, signature.data(), &signature_length); - } - if (result != OEMCrypto_SUCCESS) { - info << "--- ERROR GETTING BCC. result=" << result; - } else { - info << "BCC = (len=" << bcc_length << ") " - << wvutil::unlimited_b2a_hex(bcc) << "\n" - << "Additional Sig = (len=" << signature_length << ") " - << wvutil::unlimited_b2a_hex(signature) << "\n"; - } - } - return info.str(); -} } // namespace std::unique_ptr WvCdmTestBase::default_config_; @@ -412,117 +318,15 @@ WvCdmTestBase::WvCdmTestBase() } void WvCdmTestBase::Provision() { - CdmProvisioningRequest prov_request; - std::string provisioning_server_url; - CdmCertificateType cert_type = kCertificateWidevine; - std::string cert_authority; - std::string cert, wrapped_key; - - CdmSessionId session_id; + const CdmCertificateType cert_type = kCertificateWidevine; std::unique_ptr file_system(CreateTestFileSystem()); - - if (config_.provisioning_server() == "fake") { - LOGD("Using fake provisioning server."); - - TestCdmEngine cdm_engine(file_system.get(), - std::shared_ptr(new EngineMetrics)); - FakeProvisioningServer server; - CdmResponseType result = cdm_engine.GetProvisioningRequest( - cert_type, cert_authority, server.service_certificate(), kLevelDefault, - &prov_request, &provisioning_server_url); - ASSERT_EQ(NO_ERROR, result); - if (!binary_provisioning_) { - std::vector prov_request_v = - wvutil::Base64SafeDecode(prov_request); - prov_request = std::string(prov_request_v.begin(), prov_request_v.end()); - } - std::string response; - ASSERT_TRUE(server.MakeResponse(prov_request, &response)) - << "Fake provisioning server could not provision"; - result = cdm_engine.HandleProvisioningResponse(response, kLevelDefault, - &cert, &wrapped_key); - EXPECT_EQ(NO_ERROR, result); - } else { - // TODO(fredgc): provision for different SPOIDs. - TestCdmEngine cdm_engine(file_system.get(), - std::shared_ptr(new EngineMetrics)); - - CdmResponseType result = cdm_engine.GetProvisioningRequest( - cert_type, cert_authority, config_.provisioning_service_certificate(), - kLevelDefault, &prov_request, &provisioning_server_url); - ASSERT_EQ(NO_ERROR, result); - - if (binary_provisioning_) { - prov_request = wvutil::Base64SafeEncodeNoPad(prov_request); - } - - LOGV("Provisioning request: req = %s", prov_request.c_str()); - - // Ignore URL provided by CdmEngine. Use ours, as configured - // for test vs. production server. - provisioning_server_url.assign(config_.provisioning_server()); - - // Make request. - UrlRequest url_request(provisioning_server_url); - if (!url_request.is_connected()) { - LOGE("Failed to connect to provisioning server: url = %s", - provisioning_server_url.c_str()); - } - url_request.PostCertRequestInQueryString(prov_request); - - // Receive and parse response. - std::string http_message; - ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&http_message)) - << "Failed to fetch provisioning response. " - << DumpProvAttempt(provisioning_server_url, prov_request, http_message, - &cdm_engine); - - if (binary_provisioning_) { - // extract provisioning response from received message - // Extracts signed response from JSON string, result is serialized - // protobuf. - static const std::string kMessageStart = "\"signedResponse\": \""; - static const std::string kMessageEnd = "\""; - std::string protobuf_response; - const bool extract_ok = ExtractSignedMessage( - http_message, kMessageStart, kMessageEnd, &protobuf_response); - ASSERT_TRUE(extract_ok) << "Failed to extract signed serialized " - "response from JSON response"; - LOGV("Extracted response message: \n%s\n", protobuf_response.c_str()); - - ASSERT_FALSE(protobuf_response.empty()) - << "Protobuf response is unexpectedly empty"; - - // base64 decode response to yield binary protobuf - const std::vector response_vec( - wvutil::Base64SafeDecode(protobuf_response)); - ASSERT_FALSE(response_vec.empty()) - << "Failed to decode base64 of response: response = " - << protobuf_response; - - const std::string binary_protobuf_response(response_vec.begin(), - response_vec.end()); - - ASSERT_EQ(NO_ERROR, cdm_engine.HandleProvisioningResponse( - binary_protobuf_response, kLevelDefault, &cert, - &wrapped_key)) - << "Binary provisioning failed. " - << DumpProvAttempt(provisioning_server_url, prov_request, - http_message, &cdm_engine); - } else { - ASSERT_EQ(NO_ERROR, cdm_engine.HandleProvisioningResponse( - http_message, kLevelDefault, &cert, &wrapped_key)) - << "Non-binary provisioning failed. " - << DumpProvAttempt(provisioning_server_url, prov_request, - http_message, &cdm_engine); - } - } + TestCdmEngine cdm_engine(file_system.get(), + std::shared_ptr(new EngineMetrics)); + ProvisioningHolder provisioner(&cdm_engine, config_.provisioning_server(), + config_.provisioning_service_certificate()); + provisioner.Provision(cert_type, binary_provisioning_); } -// TODO(fredgc): Replace this with a pre-defined DRM certificate. We could do -// that because either the device is using a known test keybox with a known -// device key, or the device is using an OEM certificate, and we can extract -// that certificate from the provisioning request. void WvCdmTestBase::EnsureProvisioned() { CdmSessionId session_id; std::unique_ptr file_system(CreateTestFileSystem()); diff --git a/libwvdrmengine/cdm/core/test/test_base.h b/libwvdrmengine/cdm/core/test/test_base.h index 8436724f..c8d48776 100644 --- a/libwvdrmengine/cdm/core/test/test_base.h +++ b/libwvdrmengine/cdm/core/test/test_base.h @@ -88,6 +88,7 @@ class TestCdmEngine : public CdmEngine { TestCdmEngine(wvutil::FileSystem* file_system, std::shared_ptr metrics) : CdmEngine(file_system, metrics) {} + const CdmSession* GetCdmSession(std::string sessionId) const; }; class WvCdmTestBaseWithEngine : public WvCdmTestBase { diff --git a/libwvdrmengine/cdm/core/test/url_request.cpp b/libwvdrmengine/cdm/core/test/url_request.cpp index 860e350d..dc81da8d 100644 --- a/libwvdrmengine/cdm/core/test/url_request.cpp +++ b/libwvdrmengine/cdm/core/test/url_request.cpp @@ -217,8 +217,8 @@ bool UrlRequest::PostRequestWithPath(const std::string& path, const int ret = socket_.WriteAndLogErrors( request.c_str(), static_cast(request.size()), kWriteTimeoutMs); - LOGV("HTTP request: (%zu): %s", request.size(), - wvutil::b2a_hex(request).c_str()); + LOGV("HTTP request: (%zu): %s", request.size(), request.c_str()); + LOGV("HTTP request hex: %s", wvutil::b2a_hex(request).c_str()); return ret != -1; } diff --git a/libwvdrmengine/cdm/test/integration-test.mk b/libwvdrmengine/cdm/test/integration-test.mk index 5b26f540..e88872a4 100644 --- a/libwvdrmengine/cdm/test/integration-test.mk +++ b/libwvdrmengine/cdm/test/integration-test.mk @@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \ ../core/test/http_socket.cpp \ ../core/test/license_holder.cpp \ ../core/test/license_request.cpp \ + ../core/test/provisioning_holder.cpp \ ../core/test/test_base.cpp \ ../core/test/test_printers.cpp \ ../core/test/url_request.cpp \ diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 22eb3bc5..71672ec3 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -2534,33 +2534,6 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) { decryptor_->CloseSession(session_id_); } -TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) { - decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier, - nullptr, &session_id_); - std::string provisioning_server; - CdmCertificateType cert_type = kCertificateX509; - // TODO(rfrias): insert appropriate CA here - std::string cert_authority = "cast.google.com"; - std::string cert, wrapped_key; - - EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_->GetProvisioningRequest( - cert_type, cert_authority, kDefaultCdmIdentifier, - kEmptyServiceCertificate, kLevelDefault, &key_msg_, - &provisioning_server)); - EXPECT_THAT(provisioning_server, - IsSimilarUrlTo(kDefaultProvisioningServerUrl)); - - std::string response = GetCertRequestResponse(config_.provisioning_server()); - EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse( - kDefaultCdmIdentifier, response, kLevelDefault, - &cert, &wrapped_key)); - EXPECT_NE(0, static_cast(cert.size())); - EXPECT_NE(0, static_cast(wrapped_key.size())); - decryptor_->CloseSession(session_id_); -} - TEST_F(WvCdmRequestLicenseTest, ProvisioningSpoidTest) { CdmProvisioningResponse provisioning_response;