Save and retrieve key information from licenses and usage records

[ Merge of http://go/wvgerrit/120512 ]

Wrapped DRM private keys are loaded when a key request is made or when
offline/usage sessions are restored. They were earlier loaded when a
session was opened.

For streaming sessions, key material will be fetched from the default
or legacy certificates and loaded when a key request is made.

For offline and usage sessions, key material may be retrieved from
license or usage records if available. If not available, information
associated with the legacy certificate will be loaded.

Certificate and wrapped keys are also written out when an offline
license or usage record is saved.

Bug: 169740403
Test: WV unit/integration tests
      WvCdmRequestLicenseTest.ProvisioningWithExpiringCertTest
      WvCdmRequestLicenseTest.StreamingWithExpiringCertTest
      WvCdmRequestLicenseTest.RestoreOfflineKeysWithExpiringCertTest
Change-Id: Ice0154c632170c46da171cbbb23a97380c610a98
This commit is contained in:
Rahul Frias
2021-03-23 13:06:55 -07:00
parent 30ebbefb40
commit e538c96131
9 changed files with 412 additions and 253 deletions

View File

@@ -120,6 +120,7 @@ class MockDeviceFiles : public DeviceFiles {
DeviceFiles::CertificateState(bool, std::string*,
CryptoWrappedKey*, std::string*,
uint32_t*));
MOCK_METHOD1(HasCertificate, bool(bool));
};
class MockUsageTableHeader : public UsageTableHeader {
@@ -169,8 +170,8 @@ class MockCdmLicense : public CdmLicense {
public:
MockCdmLicense(const CdmSessionId& session_id) : CdmLicense(session_id) {}
MOCK_METHOD6(Init, bool(const std::string&, CdmClientTokenType, bool,
const std::string&, CryptoSession*, PolicyEngine*));
MOCK_METHOD4(Init,
bool(bool, const std::string&, CryptoSession*, PolicyEngine*));
MOCK_METHOD0(provider_session_token, std::string());
};
@@ -218,19 +219,10 @@ TEST_F(CdmSessionTest, InitWithBuiltInCertificate) {
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
.WillOnce(Return(kClientTokenDrmCert));
EXPECT_CALL(*file_handle_,
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*license_parser_,
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
@@ -245,19 +237,10 @@ TEST_F(CdmSessionTest, InitWithCertificate) {
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
.WillOnce(Return(kClientTokenKeybox));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_,
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*license_parser_,
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
@@ -272,19 +255,10 @@ TEST_F(CdmSessionTest, ReInitFail) {
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
.WillOnce(Return(kClientTokenKeybox));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_,
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*license_parser_,
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
@@ -298,25 +272,6 @@ TEST_F(CdmSessionTest, InitFailCryptoError) {
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init(nullptr));
}
TEST_F(CdmSessionTest, InitNeedsProvisioning) {
Sequence crypto_session_seq;
CdmSecurityLevel level = kSecurityLevelL1;
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
.WillOnce(Return(kClientTokenKeybox));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_,
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
.WillOnce(Return(DeviceFiles::kCertificateInvalid));
ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init(nullptr));
}
TEST_F(CdmSessionTest, UpdateUsageEntry) {
// Setup common expectations for initializing the CdmSession object.
Sequence crypto_session_seq;
@@ -327,21 +282,12 @@ TEST_F(CdmSessionTest, UpdateUsageEntry) {
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
.WillOnce(Return(kClientTokenKeybox));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_,
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(DeviceFiles::kCertificateValid)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
.InSequence(crypto_session_seq)
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
EXPECT_CALL(*crypto_session_, GetUsageTableHeader())
.WillOnce(Return(&usage_table_header_));
EXPECT_CALL(*license_parser_,
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
Eq(crypto_session_), Eq(policy_engine_)))
.WillOnce(Return(true));
// Set up mocks and expectations for the UpdateUsageEntryInformation call.

View File

@@ -250,22 +250,13 @@ TEST_F(CdmLicenseTest, InitSuccess) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
kEmptyServiceCertificate, crypto_session_,
policy_engine_));
}
TEST_F(CdmLicenseTest, InitFail_EmptyToken) {
CreateCdmLicense();
EXPECT_FALSE(cdm_license_->Init("", kClientTokenDrmCert, false,
kEmptyServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(false, kEmptyServiceCertificate,
crypto_session_, policy_engine_));
}
TEST_F(CdmLicenseTest, InitFail_CryptoSessionNull) {
CreateCdmLicense();
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
kEmptyServiceCertificate, nullptr,
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate, nullptr,
policy_engine_));
}
@@ -273,36 +264,32 @@ TEST_F(CdmLicenseTest, InitFail_PolicyEngineNull) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
CreateCdmLicense();
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
kEmptyServiceCertificate, crypto_session_,
nullptr));
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate,
crypto_session_, nullptr));
}
TEST_F(CdmLicenseTest, InitWithEmptyServiceCert) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kEmptyServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(true, kEmptyServiceCertificate,
crypto_session_, policy_engine_));
}
TEST_F(CdmLicenseTest, InitWithInvalidServiceCert) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
CreateCdmLicense();
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kInvalidServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_FALSE(cdm_license_->Init(true, kInvalidServiceCertificate,
crypto_session_, policy_engine_));
}
TEST_F(CdmLicenseTest, InitWithServiceCert) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kDefaultServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
crypto_session_, policy_engine_));
}
TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
@@ -335,16 +322,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
Return(NO_ERROR)));
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kDefaultServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
crypto_session_, policy_engine_));
CdmAppParameterMap app_parameters;
CdmKeyMessage signed_request;
std::string server_url;
EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming,
app_parameters, &signed_request,
&server_url),
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
&signed_request, &server_url),
KEY_MESSAGE);
EXPECT_TRUE(!signed_request.empty());
@@ -460,16 +446,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
Return(NO_ERROR)));
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kDefaultServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
crypto_session_, policy_engine_));
CdmAppParameterMap app_parameters;
CdmKeyMessage signed_request;
std::string server_url;
EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming,
app_parameters, &signed_request,
&server_url),
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
&signed_request, &server_url),
KEY_MESSAGE);
EXPECT_TRUE(!signed_request.empty());
@@ -601,9 +586,8 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) {
// Set up the CdmLicense with the mocks and fake entitlement key
CreateCdmLicense();
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
kDefaultServiceCertificate, crypto_session_,
policy_engine_));
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
crypto_session_, policy_engine_));
cdm_license_->set_entitlement_keys(entitlement_license);
// Call the function under test and check its return value