Changed Prov4.0 handler to accept only recent requests.
[ Cherry-pick of v19 http://go/wvgerrit/219291 ] [ Merge of http://go/wvgerrit/219432 ] If the same app/origin generates multiple provisioning 4.0 requests it is possible that a mismatch between the OEM/DRM certificate and the wrapped OEM/DRM private key occurs. The CDM would use the OEM/DRM certificate of the first response one received, and the wrapped private key of the last request generated. To avoid this issue, the public key from the most recent request is cached and checked against the responses received. If the keys match, that response is accepted; if the keys don't match than the response is assumed "stale" and the response is dropped. In an attempt to maintain existing behavior of the CDM, "stale" responses will return NO_ERROR to the app. Note: This was tested using both RSA and ECC cert key types. VIC-specific: Needed to add implementation of StringContains() and StringEndsWith(). Bug: 391469176 Test: run_prov40_tests Change-Id: Id45d40d9af355c46a61c3cc2c19c252cf17c7489
This commit is contained in:
@@ -279,4 +279,539 @@ TEST_F(CoreIntegrationTest, NeedKeyBeforeLicenseLoad) {
|
||||
EXPECT_EQ(NEED_KEY, holder.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
class Prov40IntegrationTest : public WvCdmTestBaseWithEngine {
|
||||
public:
|
||||
void SetUp() override {
|
||||
WvCdmTestBaseWithEngine::SetUp();
|
||||
// Ensure CDM is operating using Provisioning 4.0.
|
||||
std::string prov_model;
|
||||
CdmResponseType status = cdm_engine_.QueryStatus(
|
||||
kLevelDefault, QUERY_KEY_PROVISIONING_MODEL, &prov_model);
|
||||
ASSERT_EQ(status, NO_ERROR) << "Failed to determine provisioning model";
|
||||
if (prov_model != QUERY_VALUE_BOOT_CERTIFICATE_CHAIN) {
|
||||
GTEST_SKIP() << "Test is for Prov4.0 only";
|
||||
return;
|
||||
}
|
||||
// Ensure CDM is not provisioned.
|
||||
if (IsProvisioned()) {
|
||||
status = cdm_engine_.Unprovision(kSecurityLevelL1);
|
||||
ASSERT_EQ(status, NO_ERROR) << "Failed to unprovision DRM cert";
|
||||
status = cdm_engine_.UnprovisionOemCert(kSecurityLevelL1);
|
||||
ASSERT_EQ(status, NO_ERROR) << "Failed to unprovision OEM cert";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning);
|
||||
}
|
||||
}
|
||||
|
||||
CdmProvisioningStatus GetProvisioningStatus() {
|
||||
return cdm_engine_.GetProvisioningStatus(kSecurityLevelL1);
|
||||
}
|
||||
|
||||
bool IsProvisioned() { return cdm_engine_.IsProvisioned(kSecurityLevelL1); }
|
||||
|
||||
void PreDrmProvisioningCheck() {
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning)
|
||||
<< "Not in valid state for pre DRM provisioning check";
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// OEM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning attempt failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning)
|
||||
<< "OEM Certificate provisioning was not completed";
|
||||
}
|
||||
|
||||
void PostIncompleteOemProvisioningCheck() {
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning)
|
||||
<< "Not in valid state for post incomplete OEM provisioning check";
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// OEM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning attempt failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning)
|
||||
<< "OEM Certificate provisioning was not completed";
|
||||
// DRM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning attempt failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kProvisioned)
|
||||
<< "DRM Certificate provisioning was not completed";
|
||||
// Remaining is the same as post DRM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck())
|
||||
<< "Failed post incomplete OEM provisioning check after DRM "
|
||||
"provisioning";
|
||||
}
|
||||
|
||||
void PostOemProvisioningCheck() {
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning)
|
||||
<< "Not in valid state for post OEM provisioning check";
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kProvisioned)
|
||||
<< "DRM Certificate provisioning was not completed";
|
||||
// Remaining is the same as post DRM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck())
|
||||
<< "Failed post OEM provisioning check after DRM provisioning";
|
||||
}
|
||||
|
||||
void PostIncompleteDrmProvisioningCheck() {
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning)
|
||||
<< "Not in valid state for post incomplete DRM provisioning check";
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kProvisioned)
|
||||
<< "DRM Certificate provisioning was not completed";
|
||||
// Remaining is the same as post DRM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck())
|
||||
<< "Failed post incomplete DRM provisioning check after DRM "
|
||||
"provisioning";
|
||||
}
|
||||
|
||||
void PostDrmProvisioningCheck() {
|
||||
ASSERT_EQ(GetProvisioningStatus(), kProvisioned)
|
||||
<< "Not in valid state for post DRM provisioning check";
|
||||
LicenseHolder holder("CDM_Streaming", &cdm_engine_, config_);
|
||||
ASSERT_NO_FATAL_FAILURE(holder.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
}; // class Prov40IntegrationTest
|
||||
|
||||
// Expected flow of an app; 1 OEM request-response, 1 DRM request-response.
|
||||
//
|
||||
// Case: OemReq1, OemResp1, DrmReq1, DrmResp1
|
||||
//
|
||||
// Notes:
|
||||
// This is Widevine's expected behavior by an app.
|
||||
//
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UsualOrder_LoadOem1_LoadDrm1) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning);
|
||||
|
||||
// Round 1 - OEM provisioning (OemReq1, OemResp1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Round 2 - DRM provisioning (DrmReq1, DrmResp1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kProvisioned);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp1 (OemResp2 is never acquired)
|
||||
// Expectation:
|
||||
// CDM handles OemResp1, but does not complete OEM
|
||||
// provisioning.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Apps that encounter this situation are likely generating many
|
||||
// provisioning requests and loading them in whatever order they
|
||||
// arrive.
|
||||
//
|
||||
// Post-Case: OEM provisioning, DRM provisioning, load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_DropOem2_LoadOem1) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// OEM provisioning.
|
||||
// Generate first request (OemReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request1 = provisioner.request();
|
||||
|
||||
// Generate second request (OemReq2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
// Never send for the second request.
|
||||
|
||||
// Use first request for fetching/loading response (OemResp1).
|
||||
// CDM may or may not return an error, but OEM provisioning is still
|
||||
// needed.
|
||||
provisioner.set_request(oem_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostIncompleteOemProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp2 (OemResp1 is never acquired)
|
||||
// Expectation:
|
||||
// CDM handles OemReq2 (NO_ERROR), and OEM provisioning is
|
||||
// completed.
|
||||
//
|
||||
// Notes:
|
||||
// This is OK behavior by the app.
|
||||
// Only the OEM response from the most recent OEM request will
|
||||
// complete provisioning.
|
||||
//
|
||||
// Post-Case: OEM provisioning, DRM provisioning, load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_DropOem1_LoadOem2) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// OEM provisioning.
|
||||
// Generate first request (OemReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
// Never send for the first request.
|
||||
|
||||
// Generate, fetch and load second request (OemReq2, OemResp2).
|
||||
// This should complete OEM provisioning.
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostOemProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp1, OemResp2
|
||||
// Expectation:
|
||||
// OemResp1 is handled by the CDM, but does not complete
|
||||
// provisioning. OemResp2 is accepted by the CDM
|
||||
// and completes provisioning.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Only the OEM response from the most recent OEM request will
|
||||
// complete provisioning.
|
||||
//
|
||||
// Post-Case: DRM provisioning, load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadOem1_LoadOem2) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// OEM provisioning.
|
||||
// Generate first request, store it for later (OemReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request1 = provisioner.request();
|
||||
|
||||
// Generate second request, store it for later (OemReq2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request2 = provisioner.request();
|
||||
|
||||
// Use first request for fetching/loading response (OemResp1).
|
||||
// CDM may or may not return an error, but OEM provisioning is still
|
||||
// needed.
|
||||
provisioner.set_request(oem_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsOemCertProvisioning);
|
||||
|
||||
// Use second request for fetching/loading response (OemResp2).
|
||||
// CDM should accept the second response as valid (so long as
|
||||
// a third was not generated).
|
||||
provisioner.set_request(oem_request2);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.LoadResponse(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning failed";
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostOemProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp2, OemResp1
|
||||
// Expectation:
|
||||
// OemResp2 is accepted by the CDM and comletes OEM provisioning.
|
||||
// OemResp1 does not cause the CDM to be corrupted.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, cannot be handle
|
||||
// by the CDM.
|
||||
// In single-staged provisioning, the CDM silently drops
|
||||
// any additional provisioning responses; but in two-stage
|
||||
// this cannot easily by determine that the response is a
|
||||
// late OEM response.
|
||||
//
|
||||
// Post-Case: DRM provisioning, load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadOem2_LoadOem1) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// OEM provisioning.
|
||||
// Generate first request, store it for later (OemReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request1 = provisioner.request();
|
||||
|
||||
// Generate, fetch and load second request (OemReq2, OemResp2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "OEM Certificate provisioning failed";
|
||||
// Provisioning should be complete.
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Use first request for fetching/loading response (OemResp1).
|
||||
// CDM may or may not return an error, but DRM provisioning
|
||||
// should still be allowed after.
|
||||
provisioner.set_request(oem_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
// Should not effect existing provisioning state.
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning)
|
||||
<< "Late OEM Certificate response invalidated original response";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostOemProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: DrmReq1, DrmReq2, DrmResp1, (DrmResp2 is never acquired)
|
||||
// Expectation:
|
||||
// DrmResp1 is handled by the CDM, but does not complete
|
||||
// provisioning.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Apps that encounter this situation are likely generating many
|
||||
// provisioning requests and loading them in whatever order they
|
||||
// arrive.
|
||||
// For single-stage, this situation usually returns a signature
|
||||
// failure.
|
||||
//
|
||||
// Pre-Case: OEM provisioning
|
||||
// Post-Case: DRM provisioning, load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_DropDrm2_LoadDrm1) {
|
||||
ASSERT_NO_FATAL_FAILURE(PreDrmProvisioningCheck());
|
||||
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// DRM provisioning.
|
||||
// Generate first request, store it for later (DrmReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string drm_request1 = provisioner.request();
|
||||
|
||||
// Generate second request (DrmReq2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
// Never send for the second request.
|
||||
|
||||
// Use first request for fetching/loading response (DrmResp1).
|
||||
// CDM may or may not return an error, but DRM provisioning is still
|
||||
// needed.
|
||||
provisioner.set_request(drm_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostIncompleteDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: DrmReq1, DrmReq2, DrmResp2 (DrmResp1 is never acquired)
|
||||
// Expectation:
|
||||
// CDM accepts DrmReq2 (NO_ERROR), and DRM provisioning is
|
||||
// completed.
|
||||
//
|
||||
// Notes:
|
||||
// This is OK behavior by the app.
|
||||
// Only the DRM response from the most recent DRM request will
|
||||
// complete provisioning.
|
||||
//
|
||||
// Pre-Case: OEM provisioning
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_DropDrm1_LoadDrm2) {
|
||||
ASSERT_NO_FATAL_FAILURE(PreDrmProvisioningCheck());
|
||||
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// DRM provisioning.
|
||||
// Generate first request (DrmReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
// Never send for the first request.
|
||||
|
||||
// Generate, fetch and load second request (DrmReq2, DrmResp2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_TRUE(IsProvisioned());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: DrmReq1, DrmReq2, DrmResp1, DrmResp2
|
||||
// Expectation:
|
||||
// DrmResp1 is handled by the CDM, but does not complete
|
||||
// provisioning. DrmResp2 is accepted by the CDM and
|
||||
// completes provisioning.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Only the DRM response from the most recent DRM request will
|
||||
// complete provisioning.
|
||||
//
|
||||
// Pre-Case: OEM provisioning
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadDrm1_LoadDrm2) {
|
||||
ASSERT_NO_FATAL_FAILURE(PreDrmProvisioningCheck());
|
||||
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// DRM provisioning.
|
||||
// Generate first request, store it for later (DrmReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string drm_request1 = provisioner.request();
|
||||
|
||||
// Generate second request, store it for later (DrmReq2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string drm_request2 = provisioner.request();
|
||||
|
||||
// Use first request for fetching/loading response (DrmResp1).
|
||||
// CDM may or may not return an error, but DRM provisioning is still
|
||||
// needed.
|
||||
provisioner.set_request(drm_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Use second request for fetching/loading response (DrmResp2).
|
||||
// CDM should accept the second response as valid (so long as
|
||||
// a third was not generated).
|
||||
provisioner.set_request(drm_request2);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.LoadResponse(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_TRUE(IsProvisioned());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: DrmReq1, DrmReq2, DrmResp2, DrmResp1
|
||||
// Expectation:
|
||||
// DrmResp2 is accepted by the CDM (NO_ERROR) and completes
|
||||
// provisioning. DrmResp1 is handled by the CDM, but is dropped
|
||||
// without causing issues with existing certificates.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
//
|
||||
// Pre-Case: OEM provisioning
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadDrm2_LoadDrm1) {
|
||||
ASSERT_NO_FATAL_FAILURE(PreDrmProvisioningCheck());
|
||||
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
// DRM provisioning.
|
||||
// Generate first request, store it for later (DrmReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string drm_request1 = provisioner.request();
|
||||
|
||||
// Generate, fetch and load second request (DrmReq2, DrmResp2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_))
|
||||
<< "DRM Certificate provisioning failed";
|
||||
ASSERT_TRUE(IsProvisioned());
|
||||
|
||||
// Use first request for fetching/loading response (DrmResp1).
|
||||
// CDM may or may not return an error, and the CDM should still
|
||||
// be considered provisioned.
|
||||
provisioner.set_request(drm_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
// Should not effect existing provisioning state.
|
||||
ASSERT_TRUE(IsProvisioned())
|
||||
<< "Late DRM Certificate response invalidated original response";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp2, DrmReq1, OemResp1, DrmResp1
|
||||
// Expectation:
|
||||
// OemResp2 will complete OEM provisioning, allowing the
|
||||
// creation of DrmReq1.
|
||||
// OemResp1 (being received after OEM provisioning is completed,
|
||||
// and DRM provisioning initiated) is handled by the CDM
|
||||
// and does not prevent the completion of DRM provisioning.
|
||||
//
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Stale OEM responses should not interrupt DRM provisioning in
|
||||
// progress.
|
||||
//
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadOem2_LoadDrm1_LoadOem1AsDrm) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// Round 1 - OEM provisioning.
|
||||
// Generated and stored first OEM request (OemReq1)
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request1 = provisioner.request();
|
||||
|
||||
// Complete provisioning on the second attempt (OemReq2, OemResp2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_));
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Round 2 - DRM provisioning.
|
||||
// Generate DRM certificate request (DrmReq1).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string drm_request1 = provisioner.request();
|
||||
|
||||
// Use OEM request 1 to get an OEM response (OemResp1).
|
||||
// CDM should detect that the OEM response is no longer needed
|
||||
// and should drop the response with or without errors.
|
||||
provisioner.set_request(oem_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
// Should not effect existing provisioning state.
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Use DRM request 1 to get a DRM response (DrmResp1).
|
||||
provisioner.set_request(drm_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.LoadResponse(binary_provisioning_))
|
||||
<< "Real DRM Certificate provisioning failed";
|
||||
ASSERT_TRUE(IsProvisioned());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
|
||||
// Case: OemReq1, OemReq2, OemResp2, DrmReq1, DrmResp1, OemResp1
|
||||
// Expectation:
|
||||
// OemResp2 will complete OEM provisioning, allowing the
|
||||
// creation of DrmReq1.
|
||||
// DrmResp1 will complete DRM provisioning.
|
||||
// OemResp1 (being received after OEM provisioning is completed,
|
||||
// and after DRM provisioning is complete) is handled by the CDM
|
||||
// and does not cause any other issue.
|
||||
//
|
||||
// Notes:
|
||||
// This is undesirable behavior by the app, but can be partially
|
||||
// handle by the CDM.
|
||||
// Any provisioning response received after DRM provisioning
|
||||
// is completed is ignored.
|
||||
//
|
||||
// Post-Case: Load license
|
||||
TEST_F(Prov40IntegrationTest, UnusualOrder_LoadOem2_LoadOem1AsDrm_LoadDrm1) {
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_);
|
||||
|
||||
// Round 1 - OEM provisioning.
|
||||
// Generated and stored first OEM request (OemReq1)
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.GenerateRequest(binary_provisioning_));
|
||||
const std::string oem_request1 = provisioner.request();
|
||||
|
||||
// Complete provisioning on the second attempt (OemReq2, OemResp2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_));
|
||||
ASSERT_EQ(GetProvisioningStatus(), kNeedsDrmCertProvisioning);
|
||||
|
||||
// Round 2 - DRM provisioning (DrmReq1, DrmReq2).
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.Provision(binary_provisioning_));
|
||||
ASSERT_TRUE(IsProvisioned());
|
||||
|
||||
// Use OEM request 1 to get an OEM response (OemResp2).
|
||||
// CDM should detect that CDM is fully provisioned and should drop
|
||||
// the response with or without errors.
|
||||
provisioner.set_request(oem_request1);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioner.FetchResponse());
|
||||
// Do not enforce any particular error (including NO_ERROR).
|
||||
provisioner.LoadResponseReturnStatus(binary_provisioning_);
|
||||
// Should not effect existing provisioning state.
|
||||
ASSERT_TRUE(IsProvisioned())
|
||||
<< "Late OEM Certificate response invalidated DRM certificate";
|
||||
;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(PostDrmProvisioningCheck());
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user