Accept a security level to be specified during provisioning
[ Merge of http://go/wvgerrit/98694 and http://go/ag/11052323 ] 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) Change-Id: I8d9234eec2b23a9c913e77a709943b431e25e43e
This commit is contained in:
@@ -453,6 +453,8 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
|
||||
|
||||
SecurityLevel mapSecurityLevel(const std::string& level);
|
||||
|
||||
wvcdm::SecurityLevel getRequestedSecurityLevel() const;
|
||||
|
||||
Status openSessionCommon(std::vector<uint8_t>& sessionId);
|
||||
|
||||
bool initDataResemblesPSSH(const std::vector<uint8_t>& initData);
|
||||
|
||||
@@ -371,10 +371,15 @@ status_t WVDrmPlugin::getProvisionRequest(const String8& cert_type,
|
||||
|
||||
string cdmCertAuthority = cert_authority.string();
|
||||
|
||||
wvcdm::SecurityLevel requested_security_level =
|
||||
mPropertySet.security_level().compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
|
||||
CdmResponseType res = mCDM->GetProvisioningRequest(
|
||||
cdmCertType, cdmCertAuthority, mCdmIdentifier,
|
||||
mProvisioningServiceCertificate, &cdmProvisionRequest,
|
||||
&cdmDefaultUrl);
|
||||
mProvisioningServiceCertificate, requested_security_level,
|
||||
&cdmProvisionRequest, &cdmDefaultUrl);
|
||||
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
request = ToVector(cdmProvisionRequest);
|
||||
@@ -401,10 +406,15 @@ status_t WVDrmPlugin::provideProvisionResponse(
|
||||
} else {
|
||||
string cdmCertificate;
|
||||
string cdmWrappedKey;
|
||||
CdmResponseType res = mCDM->HandleProvisioningResponse(mCdmIdentifier,
|
||||
cdmResponse,
|
||||
&cdmCertificate,
|
||||
&cdmWrappedKey);
|
||||
wvcdm::SecurityLevel requested_security_level =
|
||||
mPropertySet.security_level()
|
||||
.compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
CdmResponseType res =
|
||||
mCDM->HandleProvisioningResponse(mCdmIdentifier, cdmResponse,
|
||||
requested_security_level,
|
||||
&cdmCertificate, &cdmWrappedKey);
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
certificate = ToVector(cdmCertificate);
|
||||
wrapped_key = ToVector(cdmWrappedKey);
|
||||
|
||||
@@ -719,7 +719,8 @@ Return<void> WVDrmPlugin::getProvisionRequest_1_2(
|
||||
|
||||
CdmResponseType res = mCDM->GetProvisioningRequest(
|
||||
cdmCertType, cdmCertAuthority, identifier,
|
||||
mProvisioningServiceCertificate, &cdmProvisionRequest, &cdmDefaultUrl);
|
||||
mProvisioningServiceCertificate, getRequestedSecurityLevel(),
|
||||
&cdmProvisionRequest, &cdmDefaultUrl);
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
request = StrToVector(cdmProvisionRequest);
|
||||
defaultUrl.clear();
|
||||
@@ -765,7 +766,8 @@ Return<void> WVDrmPlugin::provideProvisionResponse(
|
||||
std::string cdmCertificate;
|
||||
std::string cdmWrappedKey;
|
||||
CdmResponseType res = mCDM->HandleProvisioningResponse(
|
||||
identifier, cdmResponse, &cdmCertificate, &cdmWrappedKey);
|
||||
identifier, cdmResponse, getRequestedSecurityLevel(), &cdmCertificate,
|
||||
&cdmWrappedKey);
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
certificate = StrToVector(cdmCertificate);
|
||||
wrappedKey = StrToVector(cdmWrappedKey);
|
||||
@@ -1951,12 +1953,7 @@ void WVDrmPlugin::OnSessionLostState(const CdmSessionId& cdmSessionId) {
|
||||
|
||||
Status WVDrmPlugin::queryProperty(const std::string& property,
|
||||
std::string& stringValue) const {
|
||||
wvcdm::SecurityLevel securityLevel =
|
||||
mPropertySet.security_level().compare(
|
||||
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0
|
||||
? wvcdm::kLevel3
|
||||
: wvcdm::kLevelDefault;
|
||||
return queryProperty(securityLevel, property, stringValue);
|
||||
return queryProperty(getRequestedSecurityLevel(), property, stringValue);
|
||||
}
|
||||
|
||||
Status WVDrmPlugin::queryProperty(wvcdm::SecurityLevel securityLevel,
|
||||
@@ -2047,6 +2044,13 @@ Status WVDrmPlugin::mapOEMCryptoResult(OEMCryptoResult res) {
|
||||
}
|
||||
}
|
||||
|
||||
wvcdm::SecurityLevel WVDrmPlugin::getRequestedSecurityLevel() const {
|
||||
return mPropertySet.security_level().compare(
|
||||
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0
|
||||
? wvcdm::kLevel3
|
||||
: wvcdm::kLevelDefault;
|
||||
}
|
||||
|
||||
bool WVDrmPlugin::initDataResemblesPSSH(const std::vector<uint8_t>& initData) {
|
||||
const uint8_t* const initDataArray = initData.data();
|
||||
|
||||
|
||||
@@ -7,25 +7,26 @@
|
||||
#define LOG_TAG "WVDrmPluginTest"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <ostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm_client_property_set.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "media/stagefright/foundation/ABase.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
|
||||
#include "HidlTypes.h"
|
||||
#include "TypeConvert.h"
|
||||
#include "WVDrmPlugin.h"
|
||||
#include "WVErrors.h"
|
||||
#include "cdm_client_property_set.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/foundation/ABase.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
|
||||
namespace wvdrm {
|
||||
namespace hardware {
|
||||
@@ -174,16 +175,17 @@ class MockCDM : public WvContentDecryptionModule {
|
||||
MOCK_METHOD2(QueryOemCryptoSessionId, CdmResponseType(const CdmSessionId&,
|
||||
CdmQueryMap*));
|
||||
|
||||
MOCK_METHOD6(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
|
||||
MOCK_METHOD7(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
|
||||
const std::string&,
|
||||
const CdmIdentifier&,
|
||||
const std::string&,
|
||||
wvcdm::SecurityLevel,
|
||||
CdmProvisioningRequest*,
|
||||
std::string*));
|
||||
|
||||
MOCK_METHOD4(HandleProvisioningResponse,
|
||||
MOCK_METHOD5(HandleProvisioningResponse,
|
||||
CdmResponseType(const CdmIdentifier&, CdmProvisioningResponse&,
|
||||
std::string*, std::string*));
|
||||
wvcdm::SecurityLevel, std::string*, std::string*));
|
||||
|
||||
MOCK_METHOD2(Unprovision, CdmResponseType(CdmSecurityLevel,
|
||||
const CdmIdentifier&));
|
||||
@@ -838,13 +840,27 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
|
||||
|
||||
static const char* kDefaultUrl = "http://google.com/";
|
||||
|
||||
EXPECT_CALL(*cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(),
|
||||
HasOrigin(EMPTY_ORIGIN), IsEmpty(),
|
||||
_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(cdmRequest),
|
||||
SetArgPointee<5>(kDefaultUrl),
|
||||
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
|
||||
testing::Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// The first and the third invocation should be at default security level,
|
||||
// while the second one should be L3
|
||||
EXPECT_CALL(*cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(),
|
||||
HasOrigin(EMPTY_ORIGIN), IsEmpty(),
|
||||
wvcdm::kLevelDefault, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(DoAll(SetArgPointee<5>(cdmRequest),
|
||||
SetArgPointee<6>(kDefaultUrl),
|
||||
testing::Return(wvcdm::NO_ERROR)));
|
||||
EXPECT_CALL(*cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(),
|
||||
HasOrigin(EMPTY_ORIGIN), IsEmpty(),
|
||||
wvcdm::kLevel3, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<5>(cdmRequest),
|
||||
SetArgPointee<6>(kDefaultUrl),
|
||||
testing::Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Make 3 provisioning requests at security level default then L3 then L1
|
||||
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
|
||||
plugin.getProvisionRequest(
|
||||
hidl_string(""), hidl_string(""),
|
||||
@@ -855,6 +871,34 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
|
||||
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
|
||||
EXPECT_STREQ(kDefaultUrl, defaultUrl.c_str());
|
||||
});
|
||||
|
||||
// Set L3 security level
|
||||
Status status = plugin.setPropertyString(hidl_string("securityLevel"),
|
||||
hidl_string("L3"));
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
plugin.getProvisionRequest(
|
||||
hidl_string(""), hidl_string(""),
|
||||
[&](Status status, hidl_vec<uint8_t> hRequest, hidl_string defaultUrl) {
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
|
||||
std::vector<uint8_t> request(hRequest);
|
||||
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
|
||||
EXPECT_STREQ(kDefaultUrl, defaultUrl.c_str());
|
||||
});
|
||||
|
||||
// Reset security level to L1
|
||||
status = plugin.setPropertyString(hidl_string("securityLevel"),
|
||||
hidl_string("L1"));
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
plugin.getProvisionRequest(
|
||||
hidl_string(""), hidl_string(""),
|
||||
[&](Status status, hidl_vec<uint8_t> hRequest, hidl_string defaultUrl) {
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
|
||||
std::vector<uint8_t> request(hRequest);
|
||||
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
|
||||
EXPECT_STREQ(kDefaultUrl, defaultUrl.c_str());
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
|
||||
@@ -871,15 +915,27 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
|
||||
std::vector<uint8_t> response;
|
||||
response.assign(responseRaw, responseRaw + kResponseSize);
|
||||
|
||||
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
|
||||
testing::Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// The first and the third invocation should be at default security level,
|
||||
// while the second one should be L3
|
||||
EXPECT_CALL(*cdm, HandleProvisioningResponse(HasOrigin(EMPTY_ORIGIN),
|
||||
ElementsAreArray(responseRaw,
|
||||
kResponseSize),
|
||||
_, _))
|
||||
wvcdm::kLevelDefault, _, _))
|
||||
.Times(2);
|
||||
EXPECT_CALL(*cdm, HandleProvisioningResponse(HasOrigin(EMPTY_ORIGIN),
|
||||
ElementsAreArray(responseRaw,
|
||||
kResponseSize),
|
||||
wvcdm::kLevel3, _, _))
|
||||
.Times(1);
|
||||
|
||||
std::vector<uint8_t> cert;
|
||||
std::vector<uint8_t> key;
|
||||
|
||||
// Process 3 provisioning responses at security level default then L3 then L1
|
||||
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
|
||||
plugin.provideProvisionResponse(
|
||||
toHidlVec(response),
|
||||
@@ -887,6 +943,26 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
|
||||
hidl_vec<uint8_t> /* key */) {
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
});
|
||||
|
||||
// Set L3 security level
|
||||
Status status = plugin.setPropertyString(hidl_string("securityLevel"),
|
||||
hidl_string("L3"));
|
||||
plugin.provideProvisionResponse(
|
||||
toHidlVec(response),
|
||||
[&](Status status, hidl_vec<uint8_t> /* cert */,
|
||||
hidl_vec<uint8_t> /* key */) {
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
});
|
||||
|
||||
// Reset security level to L1
|
||||
status = plugin.setPropertyString(hidl_string("securityLevel"),
|
||||
hidl_string("L1"));
|
||||
plugin.provideProvisionResponse(
|
||||
toHidlVec(response),
|
||||
[&](Status status, hidl_vec<uint8_t> /* cert */,
|
||||
hidl_vec<uint8_t> /* key */) {
|
||||
ASSERT_EQ(Status::OK, status);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, UnprovisionsDevice) {
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
// License Agreement.
|
||||
//
|
||||
|
||||
#include <ostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "WVDrmPlugin.h"
|
||||
#include "WVErrors.h"
|
||||
#include "cdm_client_property_set.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/foundation/ABase.h"
|
||||
#include "media/stagefright/foundation/AString.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
#include "WVDrmPlugin.h"
|
||||
#include "WVErrors.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace std;
|
||||
@@ -85,16 +85,17 @@ class MockCDM : public WvContentDecryptionModule {
|
||||
MOCK_METHOD2(QueryOemCryptoSessionId, CdmResponseType(const CdmSessionId&,
|
||||
CdmQueryMap*));
|
||||
|
||||
MOCK_METHOD6(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
|
||||
MOCK_METHOD7(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
|
||||
const std::string&,
|
||||
const CdmIdentifier&,
|
||||
const std::string&,
|
||||
SecurityLevel,
|
||||
CdmProvisioningRequest*,
|
||||
std::string*));
|
||||
|
||||
MOCK_METHOD4(HandleProvisioningResponse,
|
||||
MOCK_METHOD5(HandleProvisioningResponse,
|
||||
CdmResponseType(const CdmIdentifier&, CdmProvisioningResponse&,
|
||||
std::string*, std::string*));
|
||||
SecurityLevel, std::string*, std::string*));
|
||||
|
||||
MOCK_METHOD2(Unprovision, CdmResponseType(CdmSecurityLevel,
|
||||
const CdmIdentifier&));
|
||||
@@ -607,9 +608,9 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
|
||||
|
||||
EXPECT_CALL(*cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(),
|
||||
HasOrigin(EMPTY_ORIGIN), IsEmpty(),
|
||||
_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(cdmRequest),
|
||||
SetArgPointee<5>(kDefaultUrl),
|
||||
wvcdm::kLevelDefault, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<5>(cdmRequest),
|
||||
SetArgPointee<6>(kDefaultUrl),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
Vector<uint8_t> request;
|
||||
@@ -640,7 +641,7 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
|
||||
EXPECT_CALL(*cdm, HandleProvisioningResponse(HasOrigin(EMPTY_ORIGIN),
|
||||
ElementsAreArray(responseRaw,
|
||||
kResponseSize),
|
||||
_, _))
|
||||
wvcdm::kLevelDefault, _, _))
|
||||
.Times(1);
|
||||
|
||||
Vector<uint8_t> cert;
|
||||
|
||||
Reference in New Issue
Block a user