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;