From a1895e7e2e6da4e35fc618bc6cf027da04d50545 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Fri, 19 Jun 2015 16:14:40 -0700 Subject: [PATCH] Allow interspersed provisioning attempts to succeed. merge of http://go/wvgerrit/14807 from the widevine repo. The mediaDrm API only allows for a single provisioning attempt at a time. If concurrent provisioning attempts occur, resources are released from all but the last request, in order to allow at least that one to be successful. Any provisioning responses received before one from the last request will be rejected. A side-effect was that all provisioning resources would then be released. This caused a provisioning response from the last attempt to be rejected as well. This CL corrects this behavior and releases resources only if a provisioning attempt is successful. The side-effect is that, if the response to the last request is not received or failure occurs while processing, a crypto session may be held until the next provisioning attempt. In other cases of concurrency, provisioning responses to requests other than the last which are received after the last response will be declared successful. b/21879484 Change-Id: I3a840ceda1a16ee6adb40c2dbca6c4adf3da12c3 --- libwvdrmengine/cdm/core/src/cdm_engine.cpp | 6 ++- .../cdm/test/request_license_test.cpp | 40 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index b504d054..f0e50681 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -595,7 +595,11 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( } CdmResponseType ret = cert_provisioning_->HandleProvisioningResponse( origin, response, cert, wrapped_key); - cert_provisioning_.reset(NULL); // Release resources. + // Release resources only on success. It is possible that a provisioning + // attempt was made after this one was requested but before the response was + // received, which will cause this attempt to fail. Not releasing will + // allow for the possibility that the later attempt succeeds. + if (NO_ERROR == ret) cert_provisioning_.reset(NULL); return ret; } diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 8e5057aa..acbe9f2d 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -824,7 +824,7 @@ TEST_F(WvCdmRequestLicenseTest, UnprovisionTest) { &wrapped_private_key)); } -TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) { +TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) { decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_); std::string provisioning_server_url; CdmCertificateType cert_type = kCertificateWidevine; @@ -861,6 +861,44 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) { decryptor_.CloseSession(session_id_); } +TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) { + decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_); + std::string provisioning_server_url; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + std::string key_msg1, key_msg2; + + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest( + cert_type, cert_authority, EMPTY_ORIGIN, + &key_msg1, &provisioning_server_url)); + EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); + + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest( + cert_type, cert_authority, EMPTY_ORIGIN, + &key_msg2, &provisioning_server_url)); + EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); + + key_msg_ = key_msg1; + std::string response = + GetCertRequestResponse(g_config->provisioning_server_url()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_6, + decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, + &wrapped_key)); + EXPECT_EQ(0, static_cast(cert.size())); + EXPECT_EQ(0, static_cast(wrapped_key.size())); + + key_msg_ = key_msg2; + response = GetCertRequestResponse(g_config->provisioning_server_url()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); + EXPECT_EQ(0, static_cast(cert.size())); + EXPECT_EQ(0, static_cast(wrapped_key.size())); + + decryptor_.CloseSession(session_id_); +} + TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) { decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_); std::string provisioning_server_url;