Adjust provisioning retry

Merge from Widevine repo of http://go/wvgerrit/94243

When generating a second provisioning request, a new session should be
opened because a session can only have one nonce for v16.

For Provisioning 3.0 devices, the OEM Cert's private key must be
loaded in the new session.

Test: WvCdmRequestLicenseTest.ProvisioningInterposedRetryTest
Bug: 135288420 Nonce reuse
Bug: 141655126 Cert reload
Change-Id: I8a96566142c4d4380e2bdd571e8d363a7a1f74d4
This commit is contained in:
Fred Gylys-Colwell
2020-02-18 14:29:05 -08:00
parent 3708c4d53f
commit 18da273c42
3 changed files with 41 additions and 66 deletions

View File

@@ -2303,6 +2303,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
kEmptyServiceCertificate, &key_msg2, &provisioning_server));
EXPECT_EQ(provisioning_server, kDefaultProvisioningServerUrl);
// Second message should succeed.
key_msg_ = key_msg2;
std::string response = GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
@@ -2312,6 +2313,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
// First message is ignored because second already succeeded.
key_msg_ = key_msg1;
response = GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
@@ -2330,68 +2332,39 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
std::string provisioning_model;
CdmKeyMessage key_msg1, key_msg2;
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_->QueryStatus(kLevelDefault,
wvcdm::QUERY_KEY_PROVISIONING_MODEL,
&provisioning_model));
decryptor_->GetProvisioningRequest(
cert_type, cert_authority, kDefaultCdmIdentifier,
kEmptyServiceCertificate, &key_msg1, &provisioning_server));
EXPECT_EQ(provisioning_server, kDefaultProvisioningServerUrl);
std::string value;
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_->QueryStatus(
kLevelDefault, wvcdm::QUERY_KEY_OEMCRYPTO_API_VERSION, &value));
std::istringstream ss(value);
uint32_t api_version;
ss >> api_version;
ASSERT_FALSE(ss.fail());
EXPECT_TRUE(ss.eof());
decryptor_->GetProvisioningRequest(
cert_type, cert_authority, kDefaultCdmIdentifier,
kEmptyServiceCertificate, &key_msg2, &provisioning_server));
EXPECT_EQ(provisioning_server, kDefaultProvisioningServerUrl);
if (provisioning_model == wvcdm::QUERY_VALUE_KEYBOX ||
(provisioning_model == wvcdm::QUERY_VALUE_OEM_CERTIFICATE &&
api_version >= 15)) {
// From OEMCrypto v15.2 onwards, the nonce table size is fixed. We can't
// test this for API versions before that if they use OEM certificates.
std::vector<std::string> key_msgs;
// First request expected to fail, because only one message may be active.
key_msg_ = key_msg1;
std::string response = GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(LOAD_PROVISIONING_ERROR,
decryptor_->HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
// TODO(b/135288420): There can be only one request per OEMCrypto session.
// This code must change.
wvcdm::CdmResponseType first_request_error;
// For keyboxes we use derived keys as part of the provisioning request.
// These get updated each request, therefore any request before the latest
// fails, so we only need 2 requests.
key_msgs.resize(2);
first_request_error = wvcdm::REWRAP_DEVICE_RSA_KEY_ERROR;
for (size_t i = 0; i < key_msgs.size(); i++) {
EXPECT_EQ(
wvcdm::NO_ERROR,
decryptor_->GetProvisioningRequest(
cert_type, cert_authority, kDefaultCdmIdentifier,
kEmptyServiceCertificate, &key_msgs[i], &provisioning_server));
EXPECT_EQ(provisioning_server, kDefaultProvisioningServerUrl);
}
// First request that we expect to fail.
key_msg_ = key_msgs[0];
std::string response =
GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(first_request_error,
decryptor_->HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
// Second request that we expect to succeed.
key_msg_ = key_msgs[1];
response = GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_->HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
}
// Second message should succeed.
key_msg_ = key_msg2;
response = GetCertRequestResponse(config_.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_->HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_->CloseSession(session_id_);
}
@@ -3981,7 +3954,7 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
FileSystem file_system;
DeviceFiles handle(&file_system);
EXPECT_TRUE(handle.Init(security_level));
ASSERT_TRUE(handle.Init(security_level));
std::vector<std::string> psts;
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(""), &psts));