Accept a security level to be specified during provisioning
[ Merge of http://go/wvgerrit/97267 ] In earlier releases, provisioning would occur based on a cached security level. If an open session call returned a NotProvisionedException the security level would be cached for use with any future provisioning call. An app would have to set the security level, then call openSession, have it fail and then request provisioning. This fits the normal flow of most apps. Still on occasion, an app might change requested security level after an openSession call failed. Using the cached security level would result in unexpected behavior. This change allows provisioning to occur at the last security level that was set. Bug: 129356527 Test: wv unit/integration tests, GTS tests (GtsMediaTestCases) Merged-In: I8d9234eec2b23a9c913e77a709943b431e25e43e Change-Id: I8d9234eec2b23a9c913e77a709943b431e25e43e
This commit is contained in:
@@ -179,12 +179,14 @@ class CdmEngine {
|
||||
// Generate and return a valid provisioning request.
|
||||
virtual CdmResponseType GetProvisioningRequest(
|
||||
CdmCertificateType cert_type, const std::string& cert_authority,
|
||||
const std::string& service_certificate, CdmProvisioningRequest* request,
|
||||
const std::string& service_certificate,
|
||||
SecurityLevel requested_security_level, CdmProvisioningRequest* request,
|
||||
std::string* default_url);
|
||||
|
||||
// Verify and process a provisioning response.
|
||||
virtual CdmResponseType HandleProvisioningResponse(
|
||||
const CdmProvisioningResponse& response, std::string* cert,
|
||||
const CdmProvisioningResponse& response,
|
||||
SecurityLevel requested_security_level, std::string* cert,
|
||||
std::string* wrapped_key);
|
||||
|
||||
// Return true if there is a device certificate on the current
|
||||
@@ -388,7 +390,6 @@ class CdmEngine {
|
||||
CdmSessionMap session_map_;
|
||||
CdmReleaseKeySetMap release_key_sets_;
|
||||
std::unique_ptr<CertificateProvisioning> cert_provisioning_;
|
||||
SecurityLevel cert_provisioning_requested_security_level_;
|
||||
FileSystem* file_system_;
|
||||
Clock clock_;
|
||||
std::string spoid_;
|
||||
|
||||
@@ -156,21 +156,24 @@ class CdmEngineMetricsImpl : public T {
|
||||
CdmResponseType GetProvisioningRequest(CdmCertificateType cert_type,
|
||||
const std::string& cert_authority,
|
||||
const std::string& service_certificate,
|
||||
SecurityLevel requested_security_level,
|
||||
CdmProvisioningRequest* request,
|
||||
std::string* default_url) override {
|
||||
CdmResponseType sts;
|
||||
M_TIME(sts = T::GetProvisioningRequest(cert_type, cert_authority,
|
||||
service_certificate, request,
|
||||
default_url),
|
||||
M_TIME(sts = T::GetProvisioningRequest(
|
||||
cert_type, cert_authority, service_certificate,
|
||||
requested_security_level, request, default_url),
|
||||
metrics_, cdm_engine_get_provisioning_request_, sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType HandleProvisioningResponse(
|
||||
const CdmProvisioningResponse& response, std::string* cert,
|
||||
const CdmProvisioningResponse& response,
|
||||
SecurityLevel requested_security_level, std::string* cert,
|
||||
std::string* wrapped_key) override {
|
||||
CdmResponseType sts;
|
||||
M_TIME(sts = T::HandleProvisioningResponse(response, cert, wrapped_key),
|
||||
M_TIME(sts = T::HandleProvisioningResponse(
|
||||
response, requested_security_level, cert, wrapped_key),
|
||||
metrics_, cdm_engine_handle_provisioning_response_, sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ CdmEngine::CdmEngine(FileSystem* file_system,
|
||||
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||
: metrics_(metrics),
|
||||
cert_provisioning_(),
|
||||
cert_provisioning_requested_security_level_(kLevelDefault),
|
||||
file_system_(file_system),
|
||||
spoid_(EMPTY_SPOID),
|
||||
usage_session_(),
|
||||
@@ -136,8 +135,6 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
|
||||
new_session->Init(property_set, forced_session_id, event_listener);
|
||||
if (sts != NO_ERROR) {
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
new_session->GetRequestedSecurityLevel();
|
||||
// Reserve a session ID so the CDM can return success.
|
||||
if (session_id) *session_id = new_session->GenerateSessionId();
|
||||
} else {
|
||||
@@ -294,10 +291,6 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
if (KEY_ADDED == sts) {
|
||||
return sts;
|
||||
} else if (KEY_MESSAGE != sts) {
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
session->GetRequestedSecurityLevel();
|
||||
}
|
||||
LOGE("Key request generation failed, status = %d", static_cast<int>(sts));
|
||||
return sts;
|
||||
}
|
||||
@@ -414,10 +407,6 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
&error_detail);
|
||||
session->GetMetrics()->cdm_session_restore_offline_session_.Increment(
|
||||
sts, error_detail);
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
session->GetRequestedSecurityLevel();
|
||||
}
|
||||
if (sts != KEY_ADDED && sts != GET_RELEASED_LICENSE_ERROR) {
|
||||
LOGE("Restore offline session failed: status = %d", static_cast<int>(sts));
|
||||
}
|
||||
@@ -895,7 +884,8 @@ bool CdmEngine::IsSecurityLevelSupported(CdmSecurityLevel level) {
|
||||
*/
|
||||
CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
CdmCertificateType cert_type, const std::string& cert_authority,
|
||||
const std::string& service_certificate, CdmProvisioningRequest* request,
|
||||
const std::string& service_certificate,
|
||||
SecurityLevel requested_security_level, CdmProvisioningRequest* request,
|
||||
std::string* default_url) {
|
||||
LOGI("Getting provisioning request");
|
||||
if (!request) {
|
||||
@@ -915,7 +905,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
if (status != NO_ERROR) return status;
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
|
||||
cert_provisioning_requested_security_level_, cert_type, cert_authority,
|
||||
requested_security_level, cert_type, cert_authority,
|
||||
file_system_->origin(), spoid_, request, default_url);
|
||||
if (ret != NO_ERROR) {
|
||||
cert_provisioning_.reset(); // Release resources.
|
||||
@@ -931,7 +921,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
* Returns NO_ERROR for success and CdmResponseType error code if fails.
|
||||
*/
|
||||
CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
const CdmProvisioningResponse& response, std::string* cert,
|
||||
const CdmProvisioningResponse& response,
|
||||
SecurityLevel requested_security_level, std::string* cert,
|
||||
std::string* wrapped_key) {
|
||||
LOGI("Handling provision request");
|
||||
if (response.empty()) {
|
||||
@@ -955,10 +946,9 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
std::unique_ptr<CryptoSession> crypto_session(
|
||||
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
|
||||
CdmResponseType status;
|
||||
M_TIME(status = crypto_session->Open(
|
||||
cert_provisioning_requested_security_level_),
|
||||
M_TIME(status = crypto_session->Open(requested_security_level),
|
||||
metrics_->GetCryptoMetrics(), crypto_session_open_, status,
|
||||
cert_provisioning_requested_security_level_);
|
||||
requested_security_level);
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("Provisioning object missing and crypto session open failed");
|
||||
return EMPTY_PROVISIONING_CERTIFICATE_2;
|
||||
|
||||
@@ -76,13 +76,13 @@ class MockCdmEngineImpl : public CdmEngine {
|
||||
MOCK_METHOD1(RemoveKeys, CdmResponseType(const CdmSessionId&));
|
||||
MOCK_METHOD2(QueryKeyStatus,
|
||||
CdmResponseType(const CdmSessionId&, CdmQueryMap*));
|
||||
MOCK_METHOD5(GetProvisioningRequest,
|
||||
MOCK_METHOD6(GetProvisioningRequest,
|
||||
CdmResponseType(CdmCertificateType, const std::string&,
|
||||
const std::string&, CdmProvisioningRequest*,
|
||||
std::string*));
|
||||
MOCK_METHOD3(HandleProvisioningResponse,
|
||||
CdmResponseType(const CdmProvisioningResponse&, std::string*,
|
||||
std::string*));
|
||||
const std::string&, SecurityLevel,
|
||||
CdmProvisioningRequest*, std::string*));
|
||||
MOCK_METHOD4(HandleProvisioningResponse,
|
||||
CdmResponseType(const CdmProvisioningResponse&, SecurityLevel,
|
||||
std::string*, std::string*));
|
||||
MOCK_METHOD1(Unprovision, CdmResponseType(CdmSecurityLevel));
|
||||
MOCK_METHOD4(ListUsageIds,
|
||||
CdmResponseType(const std::string&, CdmSecurityLevel,
|
||||
@@ -311,16 +311,17 @@ TEST_F(WvCdmEngineMetricsImplTest, GetProvisioningRequest) {
|
||||
std::string default_url;
|
||||
|
||||
EXPECT_CALL(*test_cdm_metrics_engine_,
|
||||
GetProvisioningRequest(Eq(kCertificateX509),
|
||||
Eq("fake certificate authority"),
|
||||
Eq("fake service certificate"),
|
||||
Eq(&request), Eq(&default_url)))
|
||||
GetProvisioningRequest(
|
||||
Eq(kCertificateX509), Eq("fake certificate authority"),
|
||||
Eq("fake service certificate"), Eq(wvcdm::kLevelDefault),
|
||||
Eq(&request), Eq(&default_url)))
|
||||
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
|
||||
|
||||
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
|
||||
test_cdm_metrics_engine_->GetProvisioningRequest(
|
||||
kCertificateX509, "fake certificate authority",
|
||||
"fake service certificate", &request, &default_url));
|
||||
"fake service certificate", wvcdm::kLevelDefault, &request,
|
||||
&default_url));
|
||||
|
||||
drm_metrics::WvCdmMetrics metrics_proto;
|
||||
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
|
||||
@@ -340,12 +341,14 @@ TEST_F(WvCdmEngineMetricsImplTest, HandleProvisioningResponse) {
|
||||
|
||||
EXPECT_CALL(*test_cdm_metrics_engine_,
|
||||
HandleProvisioningResponse(Eq("fake provisioning response"),
|
||||
Eq(&cert), Eq(&wrapped_key)))
|
||||
Eq(wvcdm::kLevelDefault), Eq(&cert),
|
||||
Eq(&wrapped_key)))
|
||||
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
|
||||
|
||||
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
|
||||
test_cdm_metrics_engine_->HandleProvisioningResponse(
|
||||
"fake provisioning response", &cert, &wrapped_key));
|
||||
"fake provisioning response", wvcdm::kLevelDefault, &cert,
|
||||
&wrapped_key));
|
||||
|
||||
drm_metrics::WvCdmMetrics metrics_proto;
|
||||
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
|
||||
|
||||
@@ -294,8 +294,8 @@ void WvCdmTestBase::Provision() {
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
FakeProvisioningServer server;
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, server.service_certificate(), &prov_request,
|
||||
&provisioning_server_url);
|
||||
cert_type, cert_authority, server.service_certificate(), kLevelDefault,
|
||||
&prov_request, &provisioning_server_url);
|
||||
ASSERT_EQ(NO_ERROR, result);
|
||||
if (!binary_provisioning_) {
|
||||
std::vector<uint8_t> prov_request_v = Base64SafeDecode(prov_request);
|
||||
@@ -304,8 +304,8 @@ void WvCdmTestBase::Provision() {
|
||||
std::string response;
|
||||
ASSERT_TRUE(server.MakeResponse(prov_request, &response))
|
||||
<< "Fake provisioning server could not provision";
|
||||
result =
|
||||
cdm_engine.HandleProvisioningResponse(response, &cert, &wrapped_key);
|
||||
result = cdm_engine.HandleProvisioningResponse(response, kLevelDefault,
|
||||
&cert, &wrapped_key);
|
||||
EXPECT_EQ(NO_ERROR, result);
|
||||
} else {
|
||||
// TODO(fredgc): provision for different SPOIDs.
|
||||
@@ -314,7 +314,7 @@ void WvCdmTestBase::Provision() {
|
||||
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
||||
&prov_request, &provisioning_server_url);
|
||||
kLevelDefault, &prov_request, &provisioning_server_url);
|
||||
ASSERT_EQ(NO_ERROR, result);
|
||||
|
||||
if (binary_provisioning_) {
|
||||
@@ -385,14 +385,15 @@ void WvCdmTestBase::Provision() {
|
||||
std::string binary_protobuf_response(response_vec.begin(),
|
||||
response_vec.end());
|
||||
|
||||
if (cdm_engine.HandleProvisioningResponse(
|
||||
binary_protobuf_response, &cert, &wrapped_key) != NO_ERROR) {
|
||||
if (cdm_engine.HandleProvisioningResponse(binary_protobuf_response,
|
||||
kLevelDefault, &cert,
|
||||
&wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle provisioning response");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (cdm_engine.HandleProvisioningResponse(http_message, &cert,
|
||||
&wrapped_key) != NO_ERROR) {
|
||||
if (cdm_engine.HandleProvisioningResponse(
|
||||
http_message, kLevelDefault, &cert, &wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle binary provisioning response");
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user