OEMCrypto unit tests for license release
Bug: 295956275 Change-Id: I3c8fc5fcadeae051cc734a64378e473492437c34
This commit is contained in:
@@ -105,6 +105,12 @@ typedef OEMCryptoResult (*L1_LoadRenewal_t)(OEMCrypto_SESSION session,
|
|||||||
size_t core_message_length,
|
size_t core_message_length,
|
||||||
const uint8_t* signature,
|
const uint8_t* signature,
|
||||||
size_t signature_length);
|
size_t signature_length);
|
||||||
|
typedef OEMCryptoResult (*L1_LoadRelease_t)(OEMCrypto_SESSION session,
|
||||||
|
const uint8_t* message,
|
||||||
|
size_t message_length,
|
||||||
|
size_t core_message_length,
|
||||||
|
const uint8_t* signature,
|
||||||
|
size_t signature_length);
|
||||||
typedef OEMCryptoResult (*L1_QueryKeyControl_t)(
|
typedef OEMCryptoResult (*L1_QueryKeyControl_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
|
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
|
||||||
uint8_t* key_control_block, size_t* key_control_block_length);
|
uint8_t* key_control_block, size_t* key_control_block_length);
|
||||||
@@ -365,6 +371,7 @@ struct FunctionPointers {
|
|||||||
L1_LoadEntitledContentKeys_t LoadEntitledContentKeys;
|
L1_LoadEntitledContentKeys_t LoadEntitledContentKeys;
|
||||||
L1_LoadEntitledContentKeys_V16_t LoadEntitledContentKeys_V16;
|
L1_LoadEntitledContentKeys_V16_t LoadEntitledContentKeys_V16;
|
||||||
L1_LoadRenewal_t LoadRenewal;
|
L1_LoadRenewal_t LoadRenewal;
|
||||||
|
L1_LoadRelease_t LoadRelease;
|
||||||
L1_QueryKeyControl_t QueryKeyControl;
|
L1_QueryKeyControl_t QueryKeyControl;
|
||||||
L1_SelectKey_t SelectKey;
|
L1_SelectKey_t SelectKey;
|
||||||
L1_DecryptCENC_V17_t DecryptCENC_V17;
|
L1_DecryptCENC_V17_t DecryptCENC_V17;
|
||||||
@@ -1078,6 +1085,7 @@ class Adapter {
|
|||||||
LOOKUP_ALL(18, EnterTestMode, OEMCrypto_EnterTestMode);
|
LOOKUP_ALL(18, EnterTestMode, OEMCrypto_EnterTestMode);
|
||||||
|
|
||||||
LOOKUP_ALL(19, SetDecryptHash, OEMCrypto_SetDecryptHash);
|
LOOKUP_ALL(19, SetDecryptHash, OEMCrypto_SetDecryptHash);
|
||||||
|
LOOKUP_ALL(19, LoadRelease, OEMCrypto_LoadRelease);
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -1119,6 +1127,7 @@ class Adapter {
|
|||||||
level3_.LoadLicense_V18 = Level3_LoadLicense;
|
level3_.LoadLicense_V18 = Level3_LoadLicense;
|
||||||
level3_.LoadEntitledContentKeys = Level3_LoadEntitledContentKeys;
|
level3_.LoadEntitledContentKeys = Level3_LoadEntitledContentKeys;
|
||||||
level3_.LoadRenewal = Level3_LoadRenewal;
|
level3_.LoadRenewal = Level3_LoadRenewal;
|
||||||
|
level3_.LoadRelease = Leve3_LoadRelease;
|
||||||
level3_.QueryKeyControl = Level3_QueryKeyControl;
|
level3_.QueryKeyControl = Level3_QueryKeyControl;
|
||||||
level3_.SelectKey = Level3_SelectKey;
|
level3_.SelectKey = Level3_SelectKey;
|
||||||
level3_.DecryptCENC_V17 = Level3_DecryptCENC_V17;
|
level3_.DecryptCENC_V17 = Level3_DecryptCENC_V17;
|
||||||
@@ -2268,6 +2277,23 @@ extern "C" OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session,
|
|||||||
signature_length);
|
signature_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_LoadRelease(OEMCrypto_SESSION session,
|
||||||
|
const uint8_t* message,
|
||||||
|
size_t message_length,
|
||||||
|
size_t core_message_length,
|
||||||
|
const uint8_t* signature,
|
||||||
|
size_t signature_length) {
|
||||||
|
if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
LevelSession pair = gAdapter->GetSession(session);
|
||||||
|
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
if (pair.fcn->LoadRelease == nullptr) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
return pair.fcn->LoadRelease(pair.session, message, message_length,
|
||||||
|
core_message_length, signature,
|
||||||
|
signature_length);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
|
extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
|
||||||
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
|
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
|
||||||
uint8_t* key_control_block, size_t* key_control_block_length) {
|
uint8_t* key_control_block, size_t* key_control_block_length) {
|
||||||
|
|||||||
@@ -732,6 +732,7 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
|
|||||||
#define OEMCrypto_PrepAndSignReleaseRequest _oecc147
|
#define OEMCrypto_PrepAndSignReleaseRequest _oecc147
|
||||||
#define OEMCrypto_GetUsageEntryInfo _oecc148
|
#define OEMCrypto_GetUsageEntryInfo _oecc148
|
||||||
#define OEMCrypto_GetBCCType _oecc149
|
#define OEMCrypto_GetBCCType _oecc149
|
||||||
|
#define OEMCrypto_LoadRelease _oecc150
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
/// @addtogroup initcontrol
|
/// @addtogroup initcontrol
|
||||||
@@ -1582,6 +1583,53 @@ OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session,
|
|||||||
const uint8_t* signature,
|
const uint8_t* signature,
|
||||||
size_t signature_length);
|
size_t signature_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the signature passes, OEMCrypto shall use the function
|
||||||
|
* ODK_ParseRelease, as described in the document "Widevine Core Message
|
||||||
|
* Serialization" to parse and verify the message. If ODK_ParseRelease
|
||||||
|
* returns an error, OEMCrypto returns the error to the CDM layer.
|
||||||
|
*
|
||||||
|
* NOTE: OEMCrypto_LoadLicense() must be called first to load the keys into
|
||||||
|
* the session.
|
||||||
|
*
|
||||||
|
* @verification
|
||||||
|
* The signature of the message shall be computed using mac_key[server], and
|
||||||
|
* the API shall verify the computed signature matches the signature passed
|
||||||
|
* in. If not, return OEMCrypto_ERROR_SIGNATURE_FAILURE. The signature
|
||||||
|
* verification shall use a constant-time algorithm (a signature mismatch
|
||||||
|
* will always take the same time as a successful comparison).
|
||||||
|
*
|
||||||
|
* @param[in] session: handle for the session to be used.
|
||||||
|
* @param[in] message: pointer to memory containing message to be verified.
|
||||||
|
* @param[in] message_length: length of the message, in bytes.
|
||||||
|
* @param[in] core_message_length: length of the core submessage, in bytes.
|
||||||
|
* @param[in] signature: pointer to memory containing the signature.
|
||||||
|
* @param[in] signature_length: length of the signature, in bytes.
|
||||||
|
*
|
||||||
|
* @retval OEMCrypto_SUCCESS success
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_SESSION
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||||
|
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||||
|
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
||||||
|
* @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
|
||||||
|
*
|
||||||
|
* @threading
|
||||||
|
* This is a "Session Function" and may be called simultaneously with session
|
||||||
|
* functions for other sessions but not simultaneously with other functions
|
||||||
|
* for this session. It will not be called simultaneously with initialization
|
||||||
|
* or usage table functions. It is as if the CDM holds a write lock for this
|
||||||
|
* session, and a read lock on the OEMCrypto system.
|
||||||
|
*
|
||||||
|
* @version
|
||||||
|
* This method is new in API version 19.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_LoadRelease(OEMCrypto_SESSION session,
|
||||||
|
const uint8_t* message,
|
||||||
|
size_t message_length,
|
||||||
|
size_t core_message_length,
|
||||||
|
const uint8_t* signature,
|
||||||
|
size_t signature_length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the decrypted key control block for the given content_key_id. This
|
* Returns the decrypted key control block for the given content_key_id. This
|
||||||
* function is for application developers to debug license server and key
|
* function is for application developers to debug license server and key
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ namespace wvoec3 {
|
|||||||
#define Level3_EnterTestMode _lcc140
|
#define Level3_EnterTestMode _lcc140
|
||||||
#define Level3_GetDeviceSignedCsrPayload _lcc141
|
#define Level3_GetDeviceSignedCsrPayload _lcc141
|
||||||
#define Level3_SetDecryptHash _lcc143
|
#define Level3_SetDecryptHash _lcc143
|
||||||
|
#define Level3_PrepAndSignReleaseRequest _lcc147
|
||||||
|
#define Level3_GetUsageEntryInfo _lcc148
|
||||||
|
#define Level3_LoadRelease _lcc150
|
||||||
#else
|
#else
|
||||||
#define Level3_Initialize _oecc01
|
#define Level3_Initialize _oecc01
|
||||||
#define Level3_Terminate _oecc02
|
#define Level3_Terminate _oecc02
|
||||||
@@ -223,6 +226,10 @@ namespace wvoec3 {
|
|||||||
#define Level3_EnterTestMode _oecc140
|
#define Level3_EnterTestMode _oecc140
|
||||||
#define Level3_GetDeviceSignedCsrPayload _oecc141
|
#define Level3_GetDeviceSignedCsrPayload _oecc141
|
||||||
#define Level3_SetDecryptHash _oecc143
|
#define Level3_SetDecryptHash _oecc143
|
||||||
|
#define Level3_PrepAndSignReleaseRequest _oecc147
|
||||||
|
#define Level3_GetUsageEntryInfo _oecc148
|
||||||
|
#define Level3_LoadRelease _oecc150
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define Level3_GetInitializationState _oecl3o01
|
#define Level3_GetInitializationState _oecl3o01
|
||||||
|
|||||||
@@ -1513,27 +1513,9 @@ void RenewalRoundTrip::FillAndVerifyCoreRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenewalRoundTrip::CreateDefaultResponse() {
|
// Nothing is needed for this function but it needs a definition since it's
|
||||||
if (is_release_) {
|
// declared as a virtual function in the RoundTrip class.
|
||||||
uint32_t control = 0;
|
void RenewalRoundTrip::CreateDefaultResponse() {}
|
||||||
uint32_t nonce = 0;
|
|
||||||
// A single key object with no key id should update all keys.
|
|
||||||
constexpr size_t index = 0;
|
|
||||||
response_data_.keys[index].key_id_length = 0;
|
|
||||||
response_data_.keys[index].key_id[0] = '\0';
|
|
||||||
const uint32_t renewal_api =
|
|
||||||
std::max<uint32_t>(core_request_.api_major_version, 15u);
|
|
||||||
std::string kcVersion = "kc" + std::to_string(renewal_api);
|
|
||||||
memcpy(response_data_.keys[index].control.verification, kcVersion.c_str(),
|
|
||||||
4);
|
|
||||||
const uint32_t duration = static_cast<uint32_t>(
|
|
||||||
license_messages_->core_response()
|
|
||||||
.timer_limits.initial_renewal_duration_seconds);
|
|
||||||
response_data_.keys[index].control.duration = htonl(duration);
|
|
||||||
response_data_.keys[index].control.nonce = htonl(nonce);
|
|
||||||
response_data_.keys[index].control.control_bits = htonl(control);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenewalRoundTrip::EncryptAndSignResponse() {
|
void RenewalRoundTrip::EncryptAndSignResponse() {
|
||||||
// Renewal messages are not encrypted.
|
// Renewal messages are not encrypted.
|
||||||
@@ -1628,6 +1610,80 @@ OEMCryptoResult RenewalRoundTrip::LoadResponse(Session* session) {
|
|||||||
response_signature_.data(), response_signature_.size());
|
response_signature_.data(), response_signature_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReleaseRoundTrip::VerifyRequestSignature(
|
||||||
|
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||||
|
size_t core_message_length) {
|
||||||
|
ASSERT_EQ(HMAC_SHA256_SIGNATURE_SIZE, generated_signature.size());
|
||||||
|
std::vector<uint8_t> expected_signature;
|
||||||
|
session()->key_deriver().ClientSignBuffer(data, &expected_signature);
|
||||||
|
ASSERT_EQ(expected_signature, generated_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseRoundTrip::FillAndVerifyCoreRequest(
|
||||||
|
const std::string& core_message_string) {
|
||||||
|
EXPECT_TRUE(
|
||||||
|
oemcrypto_core_message::deserialize::CoreReleaseRequestFromMessage(
|
||||||
|
core_message_string, &core_request_));
|
||||||
|
EXPECT_EQ(license_messages_->api_version(), core_request_.api_major_version);
|
||||||
|
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
|
||||||
|
EXPECT_EQ(license_messages_->core_request().session_id,
|
||||||
|
core_request_.session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing is needed for this function but it needs a definition since it's
|
||||||
|
// declared as a virtual function in the RoundTrip class.
|
||||||
|
void ReleaseRoundTrip::CreateDefaultResponse() {}
|
||||||
|
|
||||||
|
void ReleaseRoundTrip::EncryptAndSignResponse() {
|
||||||
|
// Release messages are not encrypted.
|
||||||
|
encrypted_response_data_ = response_data_;
|
||||||
|
// Create a core response for a call to LoadRelease.
|
||||||
|
// TODO(b/191724203): Test release server has different version from license
|
||||||
|
// server.
|
||||||
|
ASSERT_NE(license_messages_, nullptr);
|
||||||
|
CoreMessageFeatures features =
|
||||||
|
CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
|
||||||
|
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreReleaseResponse(
|
||||||
|
features, core_request_, seconds_since_license_received_,
|
||||||
|
seconds_since_first_decrypt_, &serialized_core_message_));
|
||||||
|
// Resize serialize core message to be just big enough or required core
|
||||||
|
// message size, whichever is larger.
|
||||||
|
serialized_core_message_.resize(
|
||||||
|
std::max(required_core_message_size_, serialized_core_message_.size()));
|
||||||
|
// Make the message buffer a just big enough, or the
|
||||||
|
// required size, whichever is larger.
|
||||||
|
const size_t message_size =
|
||||||
|
std::max(required_message_size_, serialized_core_message_.size() +
|
||||||
|
sizeof(encrypted_response_data_));
|
||||||
|
// Stripe the encrypted message.
|
||||||
|
encrypted_response_.resize(message_size);
|
||||||
|
for (size_t i = 0; i < encrypted_response_.size(); i++) {
|
||||||
|
encrypted_response_[i] = i % 0x100;
|
||||||
|
}
|
||||||
|
// Concatenate the core message and the response.
|
||||||
|
ASSERT_GE(encrypted_response_.size(), serialized_core_message_.size());
|
||||||
|
memcpy(encrypted_response_.data(), serialized_core_message_.data(),
|
||||||
|
serialized_core_message_.size());
|
||||||
|
ASSERT_GE(encrypted_response_.size(),
|
||||||
|
serialized_core_message_.size() + sizeof(encrypted_response_data_));
|
||||||
|
memcpy(encrypted_response_.data() + serialized_core_message_.size(),
|
||||||
|
reinterpret_cast<const uint8_t*>(&encrypted_response_data_),
|
||||||
|
sizeof(encrypted_response_data_));
|
||||||
|
session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
|
||||||
|
encrypted_response_.size(),
|
||||||
|
&response_signature_);
|
||||||
|
SetEncryptAndSignResponseLengths();
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ReleaseRoundTrip::LoadResponse(Session* session) {
|
||||||
|
// TODO(vickymin): Write corpus for oemcrypto_load_release_fuzz.
|
||||||
|
VerifyEncryptAndSignResponseLengths();
|
||||||
|
return OEMCrypto_LoadRelease(
|
||||||
|
session->session_id(), encrypted_response_.data(),
|
||||||
|
encrypted_response_.size(), serialized_core_message_.size(),
|
||||||
|
response_signature_.data(), response_signature_.size());
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<util::EccCurve, std::unique_ptr<util::EccPrivateKey>,
|
std::unordered_map<util::EccCurve, std::unique_ptr<util::EccPrivateKey>,
|
||||||
std::hash<int>>
|
std::hash<int>>
|
||||||
Session::server_ephemeral_keys_;
|
Session::server_ephemeral_keys_;
|
||||||
|
|||||||
@@ -609,6 +609,48 @@ class RenewalRoundTrip
|
|||||||
bool is_release_; // If this is a license release, and not a real renewal.
|
bool is_release_; // If this is a license release, and not a real renewal.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ReleaseRoundTrip
|
||||||
|
: public RoundTrip<
|
||||||
|
/* CoreRequest */ oemcrypto_core_message::ODK_ReleaseRequest,
|
||||||
|
OEMCrypto_PrepAndSignReleaseRequest,
|
||||||
|
// Release response info is same as request:
|
||||||
|
/* CoreResponse */ oemcrypto_core_message::ODK_ReleaseRequest,
|
||||||
|
/* ResponseData */ MessageData> {
|
||||||
|
public:
|
||||||
|
ReleaseRoundTrip(LicenseRoundTrip* license_messages)
|
||||||
|
: RoundTrip(license_messages->session()),
|
||||||
|
license_messages_(license_messages) {}
|
||||||
|
void CreateDefaultResponse() override;
|
||||||
|
void EncryptAndSignResponse() override;
|
||||||
|
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||||
|
OEMCryptoResult LoadResponse(Session* session) override;
|
||||||
|
int64_t seconds_since_license_received() const {
|
||||||
|
return seconds_since_license_received_;
|
||||||
|
}
|
||||||
|
void set_seconds_since_license_received(
|
||||||
|
int64_t seconds_since_license_received) {
|
||||||
|
seconds_since_license_received_ = seconds_since_license_received;
|
||||||
|
}
|
||||||
|
int64_t seconds_since_first_decrypt() const {
|
||||||
|
return seconds_since_first_decrypt_;
|
||||||
|
}
|
||||||
|
void set_seconds_since_first_decrypt(int64_t seconds_since_first_decrypt) {
|
||||||
|
seconds_since_first_decrypt_ = seconds_since_first_decrypt;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool RequestHasNonce() override { return false; }
|
||||||
|
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||||
|
const vector<uint8_t>& generated_signature,
|
||||||
|
size_t core_message_length) override;
|
||||||
|
// Verify the values of the core response.
|
||||||
|
virtual void FillAndVerifyCoreRequest(
|
||||||
|
const std::string& core_message_string) override;
|
||||||
|
LicenseRoundTrip* license_messages_;
|
||||||
|
int64_t seconds_since_license_received_;
|
||||||
|
int64_t seconds_since_first_decrypt_;
|
||||||
|
};
|
||||||
|
|
||||||
class EntitledMessage {
|
class EntitledMessage {
|
||||||
public:
|
public:
|
||||||
EntitledMessage(LicenseRoundTrip* license_messages)
|
EntitledMessage(LicenseRoundTrip* license_messages)
|
||||||
|
|||||||
@@ -400,6 +400,17 @@ class OEMCryptoRefreshTest : public OEMCryptoLicenseTest {
|
|||||||
ASSERT_EQ(expected_result, renewal_messages->LoadResponse());
|
ASSERT_EQ(expected_result, renewal_messages->LoadResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MakeReleaseRequest(ReleaseRoundTrip* release_messages) {
|
||||||
|
ASSERT_NO_FATAL_FAILURE(release_messages->SignAndVerifyRequest());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(release_messages->CreateDefaultResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRelease(ReleaseRoundTrip* release_messages,
|
||||||
|
OEMCryptoResult expected_result) {
|
||||||
|
ASSERT_NO_FATAL_FAILURE(release_messages->EncryptAndSignResponse());
|
||||||
|
ASSERT_EQ(expected_result, release_messages->LoadResponse());
|
||||||
|
}
|
||||||
|
|
||||||
ODK_TimerLimits timer_limits_;
|
ODK_TimerLimits timer_limits_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -651,6 +651,28 @@ TEST_P(OEMCryptoUsageTableTest, OfflineLicenseRefresh) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
|
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that an offline license can be loaded and that the license can be
|
||||||
|
// released
|
||||||
|
TEST_P(OEMCryptoUsageTableTest, OfflineLicenseReleaseAPI19) {
|
||||||
|
// License release is new in OEMCrypto v19.
|
||||||
|
if (wvoec::global_features.api_version < 19 || license_api_version_ < 19) {
|
||||||
|
GTEST_SKIP() << "Test for versions 19 and up only.";
|
||||||
|
}
|
||||||
|
LicenseWithUsageEntry entry;
|
||||||
|
entry.license_messages().set_api_version(license_api_version_);
|
||||||
|
entry.MakeAndLoad(this, wvoec::kControlNonceOrEntry);
|
||||||
|
Session& s = entry.session();
|
||||||
|
|
||||||
|
ASSERT_NO_FATAL_FAILURE(entry.TestDecryptCTR());
|
||||||
|
// License release message is signed by client and verified by the server.
|
||||||
|
ReleaseRoundTrip release_messages(&entry.license_messages());
|
||||||
|
MakeReleaseRequest(&release_messages);
|
||||||
|
LoadRelease(&release_messages, OEMCrypto_SUCCESS);
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
entry.TestDecryptCTR(true, OEMCrypto_ERROR_UNKNOWN_FAILURE));
|
||||||
|
}
|
||||||
|
|
||||||
// Test that an offline license can be reloaded in a new session.
|
// Test that an offline license can be reloaded in a new session.
|
||||||
TEST_P(OEMCryptoUsageTableTest, ReloadOfflineLicense) {
|
TEST_P(OEMCryptoUsageTableTest, ReloadOfflineLicense) {
|
||||||
LicenseWithUsageEntry entry;
|
LicenseWithUsageEntry entry;
|
||||||
|
|||||||
Reference in New Issue
Block a user