diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index e7e50db2..6b3c792c 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -102,7 +102,6 @@ class CdmEngine : public TimerHandler { bool CancelSessions(); void CleanupProvisioningSession(const CdmSessionId& cdm_session_id); void ComposeJsonRequest(const std::string& message, - const std::string& signature, CdmProvisioningRequest* request); // Parse a blob of multiple concatenated PSSH atoms to extract the first diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index a53f90a9..2a5c5493 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -22,7 +22,9 @@ namespace { const std::string kDefaultProvisioningServerUrl = - "http://www-googleapis-test.sandbox.google.com/certificateprovisioning/v1/devicecertificates/create"; + "http://www-googleapis-test.sandbox.google.com/" + "certificateprovisioning/v1/devicecertificates/create" + "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; } namespace wvcdm { @@ -340,38 +342,29 @@ void CdmEngine::CleanupProvisioningSession(const CdmSessionId& cdm_session_id) { } /* - * This function converts message and signature into base64 format. + * This function converts SignedProvisioningRequest into base64 format. * It then wraps it in JSON format expected by the Apiary frontend. * Apiary requires the base64 encoding to replace '+' with minus '-', * and '/' with underscore '_'; opposite to stubby's. * * Returns the JSON formated string in *request. * The JSON formated request takes the following format: - * { - * 'signedRequest': { - * 'message': 'base64 encoded message', - * 'signature': 'base64 encoded signature' - * } - * } + * + * {'signedRequest':'base64 encoded message'} */ void CdmEngine::ComposeJsonRequest( const std::string& message, - const std::string& signature, CdmProvisioningRequest* request) { // performs base64 encoding for message std::vector message_vector(message.begin(), message.end()); std::string message_b64 = Base64SafeEncode(message_vector); - // performs base64 encoding for signature - std::vector signature_vector(signature.begin(), signature.end()); - std::string signature_b64 = Base64SafeEncode(signature_vector); - - request->assign("{'signedRequest':{'message':'"); + request->assign("{'signedRequest':'"); request->append(message_b64); - request->append("','signature':'"); - request->append(signature_b64); - request->append("'}}"); + request->append("'}"); + + LOGD("json request:\r\n%s", request->c_str()); } /* @@ -458,27 +451,33 @@ CdmResponseType CdmEngine::GetProvisioningRequest( std::string the_nonce(reinterpret_cast(&nonce), sizeof(nonce)); provisioning_request.set_nonce(the_nonce); - // Serializes the provisioning request. - std::string serialized_request; - provisioning_request.SerializeToString(&serialized_request); + std::string serialized_message; + provisioning_request.SerializeToString(&serialized_message); // Derives signing and encryption keys and constructs signature. std::string request_signature; - if (!crypto_session->PrepareRequest(serialized_request, + if (!crypto_session->PrepareRequest(serialized_message, &request_signature, true)) { request->clear(); CleanupProvisioningSession(cdm_session_id); return UNKNOWN_ERROR; } - if (request_signature.empty()) { - request->clear(); - CleanupProvisioningSession(cdm_session_id); - return UNKNOWN_ERROR; + request->clear(); + CleanupProvisioningSession(cdm_session_id); + return UNKNOWN_ERROR; } + SignedProvisioningMessage signed_provisioning_msg; + signed_provisioning_msg.set_message(serialized_message); + signed_provisioning_msg.set_signature(request_signature); + + std::string serialized_request; + signed_provisioning_msg.SerializeToString(&serialized_request); + // converts request into JSON string - ComposeJsonRequest(serialized_request, request_signature, request); + ComposeJsonRequest(serialized_request, request); + return NO_ERROR; } @@ -527,26 +526,18 @@ bool CdmEngine::ParseJsonResponse( CdmResponseType CdmEngine::HandleProvisioningResponse( CdmProvisioningResponse& response) { if (response.empty()) { - LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response."); + LOGE("Empty provisioning response."); return UNKNOWN_ERROR; } //--------------------------------------------------------------------------- - // Extracts response from JSON string, decodes base64 signed message - const std::string kMessageStart = "\"message\": \""; - const std::string kMessageEnd = "\","; - std::string signed_message; - if (!ParseJsonResponse(response, kMessageStart, kMessageEnd, &signed_message)) { - LOGE("Fails to extract signed message from JSON response"); - return UNKNOWN_ERROR; - } - - // Extracts signature from JSON string, decodes base64 signature - const std::string kSignatureStart = "\"signature\": \""; - const std::string kSignatureEnd = "\""; - std::string signature; - if (!ParseJsonResponse(response, kSignatureStart, kSignatureEnd, &signature)) { - LOGE("Fails to extract signature from JSON response"); + // Extracts signed response from JSON string, decodes base64 signed response + const std::string kMessageStart = "\"signedResponse\": \""; + const std::string kMessageEnd = "\""; + std::string serialized_signed_response; + if (!ParseJsonResponse(response, kMessageStart, kMessageEnd, + &serialized_signed_response)) { + LOGE("Fails to extract signed serialized response from JSON response"); return UNKNOWN_ERROR; } @@ -568,7 +559,8 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( CdmSessionId cdm_session_id = provisioning_session_->session_id(); CryptoSession* crypto_session = crypto_engine->FindSession(cdm_session_id); if (!crypto_session) { - LOGE("HandleProvisioningResponse: fails to find %s", cdm_session_id.c_str()); + LOGE("HandleProvisioningResponse: fails to find %s", + cdm_session_id.c_str()); return UNKNOWN_ERROR; } @@ -576,23 +568,38 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( // Authenticates provisioning response using D1s (server key derived from // the provisioing request's input). Validate provisioning response and // stores private device RSA key and certificate. + SignedProvisioningMessage signed_response; + if (!signed_response.ParseFromString(serialized_signed_response)) { + LOGE("Fails to parse signed serialized response"); + CleanupProvisioningSession(cdm_session_id); + return UNKNOWN_ERROR; + } + + if (!signed_response.has_signature() || !signed_response.has_message()) { + LOGE("Invalid response - signature or message not found"); + CleanupProvisioningSession(cdm_session_id); + return UNKNOWN_ERROR; + } + + const std::string& signed_message = signed_response.message(); ProvisioningResponse provisioning_response; if (!provisioning_response.ParseFromString(signed_message)) { - LOGE("HandleProvisioningResponse: fails to parse signed message"); + LOGE("Fails to parse signed message"); CleanupProvisioningSession(cdm_session_id); return UNKNOWN_ERROR; } if (!provisioning_response.has_device_rsa_key()) { - LOGE("HandleProvisioningResponse: invalid response - key not found"); + LOGE("Invalid response - key not found"); CleanupProvisioningSession(cdm_session_id); return UNKNOWN_ERROR; } const std::string& enc_rsa_key = provisioning_response.device_rsa_key(); - const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv(); const std::string& nonce = provisioning_response.nonce(); + const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv(); + const std::string& signature = signed_response.signature(); std::string wrapped_rsa_key; if (!crypto_session->RewrapDeviceRSAKey(signed_message, diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index e363c321..9abab09e 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -25,7 +25,9 @@ wvcdm::KeyId g_wrong_key_id; int g_use_full_path = 0; // cannot use boolean in getopt_long const std::string kDefaultProvisioningServerUrl = - "http://www-googleapis-test.sandbox.google.com/certificateprovisioning/v1/devicecertificates/create"; + "http://www-googleapis-test.sandbox.google.com/" + "certificateprovisioning/v1/devicecertificates/create" + "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; } // namespace namespace wvcdm { @@ -56,7 +58,7 @@ class WvCdmRequestLicenseTest : public testing::Test { app_parameters, &key_msg_, &server_url), wvcdm::KEY_MESSAGE); - EXPECT_EQ((size_t)0, server_url.size()); + EXPECT_EQ(0, static_cast(server_url.size())); } void GenerateRenewalRequest(const std::string& key_system, @@ -71,7 +73,7 @@ class WvCdmRequestLicenseTest : public testing::Test { app_parameters, &key_msg_, &server_url), wvcdm::KEY_MESSAGE); - EXPECT_NE((size_t)0, server_url.size()); + EXPECT_NE(0, static_cast(server_url.size())); } // posts a request and extracts the drm message from the response @@ -122,9 +124,11 @@ class WvCdmRequestLicenseTest : public testing::Test { url_request.PostCertRequest(key_msg_); std::string response; int resp_bytes = url_request.GetResponse(response); - LOGD("size=%u, response start: %s", response.size(), - response.substr(0, 1024).c_str()); - LOGD("end: %s", response.substr(response.size() - 256).c_str()); + if (resp_bytes) { + LOGD("size=%u, response start:\t\rn%s", response.size(), + response.substr(0, 1024).c_str()); + LOGD("end:\r\n%s", response.substr(response.size() - 256).c_str()); + } LOGD("end %d bytes response dump", resp_bytes); // Youtube server returns 400 for invalid message while play server returns