More OEMCrypto Usage Table Unit Tests
Merge from widevine repo of http://go/wvgerrit/23421 This CL adds some more unit tests for big usage tables, and corrects a problem found in the reference code. Change-Id: Iae9a4406d79a13362223c2b4da7365b845d92382
This commit is contained in:
@@ -948,7 +948,6 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
|
|||||||
LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed.");
|
LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed.");
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
// TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key.
|
|
||||||
const std::vector<uint8_t> context(
|
const std::vector<uint8_t> context(
|
||||||
wrapped->context, wrapped->context + sizeof(wrapped->context));
|
wrapped->context, wrapped->context + sizeof(wrapped->context));
|
||||||
// Generate mac and encryption keys for encrypting the signature.
|
// Generate mac and encryption keys for encrypting the signature.
|
||||||
@@ -1157,7 +1156,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
|
|||||||
dump_hex("iv", wrapped->iv, sizeof(wrapped->iv));
|
dump_hex("iv", wrapped->iv, sizeof(wrapped->iv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key.
|
|
||||||
if (!crypto_engine->ValidRootOfTrust()) {
|
if (!crypto_engine->ValidRootOfTrust()) {
|
||||||
LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]");
|
LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]");
|
||||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void UsageTableEntry::Deactivate(const std::vector<uint8_t>& pst) {
|
|||||||
} else if (data_.status == kActive) {
|
} else if (data_.status == kActive) {
|
||||||
data_.status = kInactiveUsed;
|
data_.status = kInactiveUsed;
|
||||||
}
|
}
|
||||||
forbid_report_ = false;
|
forbid_report_ = true;
|
||||||
data_.generation_number++;
|
data_.generation_number++;
|
||||||
usage_table_->IncrementGeneration();
|
usage_table_->IncrementGeneration();
|
||||||
}
|
}
|
||||||
@@ -130,13 +130,13 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
|||||||
pst.size() != data_.pst_length) {
|
pst.size() != data_.pst_length) {
|
||||||
LOGE("ReportUsage: bad pst length = %d, should be %d.",
|
LOGE("ReportUsage: bad pst length = %d, should be %d.",
|
||||||
pst.size(), data_.pst_length);
|
pst.size(), data_.pst_length);
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_WRONG_PST;
|
||||||
}
|
}
|
||||||
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
|
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
|
||||||
LOGE("ReportUsage: wrong pst %s, should be %s.",
|
LOGE("ReportUsage: wrong pst %s, should be %s.",
|
||||||
wvcdm::b2a_hex(pst).c_str(),
|
wvcdm::b2a_hex(pst).c_str(),
|
||||||
wvcdm::HexEncode(data_.pst, data_.pst_length).c_str());
|
wvcdm::HexEncode(data_.pst, data_.pst_length).c_str());
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_WRONG_PST;
|
||||||
}
|
}
|
||||||
size_t length_needed = wvcdm::Unpacked_PST_Report::report_size(pst.size());
|
size_t length_needed = wvcdm::Unpacked_PST_Report::report_size(pst.size());
|
||||||
if (*buffer_length < length_needed) {
|
if (*buffer_length < length_needed) {
|
||||||
@@ -658,7 +658,6 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
|
|||||||
if (or_make_new_one) {
|
if (or_make_new_one) {
|
||||||
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
|
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
|
||||||
sizeof(int64_t));
|
sizeof(int64_t));
|
||||||
master_generation_number_ = 0; // TODO(fredgc): remove after debugging.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());
|
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());
|
||||||
|
|||||||
@@ -872,7 +872,8 @@ void Session::MoveUsageEntry(uint32_t new_index,
|
|||||||
ASSERT_NO_FATAL_FAILURE(close());
|
ASSERT_NO_FATAL_FAILURE(close());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::GenerateReport(const std::string& pst, bool expect_success,
|
void Session::GenerateReport(const std::string& pst,
|
||||||
|
OEMCryptoResult expected_result,
|
||||||
Session* other) {
|
Session* other) {
|
||||||
ASSERT_TRUE(open_);
|
ASSERT_TRUE(open_);
|
||||||
if (other) { // If other is specified, copy mac keys.
|
if (other) { // If other is specified, copy mac keys.
|
||||||
@@ -883,7 +884,7 @@ void Session::GenerateReport(const std::string& pst, bool expect_success,
|
|||||||
OEMCryptoResult sts = OEMCrypto_ReportUsage(
|
OEMCryptoResult sts = OEMCrypto_ReportUsage(
|
||||||
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()), pst.length(),
|
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()), pst.length(),
|
||||||
&pst_report_buffer_[0], &length);
|
&pst_report_buffer_[0], &length);
|
||||||
if (expect_success) {
|
if (expected_result == OEMCrypto_SUCCESS) {
|
||||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||||
}
|
}
|
||||||
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
|
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||||
@@ -893,12 +894,11 @@ void Session::GenerateReport(const std::string& pst, bool expect_success,
|
|||||||
sts = OEMCrypto_ReportUsage(session_id(),
|
sts = OEMCrypto_ReportUsage(session_id(),
|
||||||
reinterpret_cast<const uint8_t*>(pst.c_str()),
|
reinterpret_cast<const uint8_t*>(pst.c_str()),
|
||||||
pst.length(), &pst_report_buffer_[0], &length);
|
pst.length(), &pst_report_buffer_[0], &length);
|
||||||
if (!expect_success) {
|
ASSERT_EQ(expected_result, sts);
|
||||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
if (expected_result != OEMCrypto_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT_EQ(pst_report_buffer_.size(), length);
|
ASSERT_EQ(pst_report_buffer_.size(), length);
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
|
||||||
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
|
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
|
||||||
unsigned int sig_len = SHA_DIGEST_LENGTH;
|
unsigned int sig_len = SHA_DIGEST_LENGTH;
|
||||||
HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),
|
HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),
|
||||||
|
|||||||
@@ -286,11 +286,12 @@ class Session {
|
|||||||
const vector<uint8_t>& encrypted_usage_entry() const {
|
const vector<uint8_t>& encrypted_usage_entry() const {
|
||||||
return encrypted_usage_entry_;
|
return encrypted_usage_entry_;
|
||||||
}
|
}
|
||||||
// Generates a usage report for the specified pst. If expect_success is true,
|
// Generates a usage report for the specified pst. If there is success,
|
||||||
// the report's signature is verified, and several fields are given sanity
|
// the report's signature is verified, and several fields are given sanity
|
||||||
// checks. If other is not null, then the mac keys are copied from other in
|
// checks. If other is not null, then the mac keys are copied from other in
|
||||||
// order to verify signatures.
|
// order to verify signatures.
|
||||||
void GenerateReport(const std::string& pst, bool expect_success = true,
|
void GenerateReport(const std::string& pst,
|
||||||
|
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||||
Session* other = 0);
|
Session* other = 0);
|
||||||
// Move this usage entry to a new index.
|
// Move this usage entry to a new index.
|
||||||
void MoveUsageEntry(uint32_t new_index, std::vector<uint8_t>* header_buffer,
|
void MoveUsageEntry(uint32_t new_index, std::vector<uint8_t>* header_buffer,
|
||||||
|
|||||||
@@ -4386,6 +4386,36 @@ TEST_P(UsageTableTestWithMAC, OnlineLicense) {
|
|||||||
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
|
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(UsageTableTestWithMAC, ForbidReportWithNoUpdate) {
|
||||||
|
std::string pst = "my_pst";
|
||||||
|
Session s;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(
|
||||||
|
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceRequired,
|
||||||
|
s.get_nonce(), pst));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.CreateNewUsageEntry());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
|
||||||
|
// Cannot generate a report without first updating the file.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
s.GenerateReport(pst, OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
|
// Now it's OK.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kActive));
|
||||||
|
// Flag the entry as inactive.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(pst));
|
||||||
|
// Cannot generate a report without first updating the file.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
s.GenerateReport(pst, OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE));
|
||||||
|
// Decrypt should fail.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(UsageTableTestWithMAC, OnlineLicenseWithRefresh) {
|
TEST_P(UsageTableTestWithMAC, OnlineLicenseWithRefresh) {
|
||||||
std::string pst = "my_pst";
|
std::string pst = "my_pst";
|
||||||
Session s;
|
Session s;
|
||||||
@@ -4802,7 +4832,7 @@ TEST_P(UsageTableTestWithMAC, ReloadOfflineLicenseWithTerminate) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
|
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
|
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst, kActive));
|
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kActive));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4934,7 +4964,7 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s3.open());
|
ASSERT_NO_FATAL_FAILURE(s3.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
|
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.UpdateUsageEntry(&encrypted_usage_header_));
|
ASSERT_NO_FATAL_FAILURE(s3.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, true, &s));
|
ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, OEMCrypto_SUCCESS, &s));
|
||||||
EXPECT_EQ(kInactiveUsed, s3.pst_report().status());
|
EXPECT_EQ(kInactiveUsed, s3.pst_report().status());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5265,7 +5295,8 @@ TEST_F(UsageTableTest, GenerateReportWrongPST) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s.CreateNewUsageEntry());
|
ASSERT_NO_FATAL_FAILURE(s.CreateNewUsageEntry());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
|
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.GenerateReport("wrong_pst", false));
|
ASSERT_NO_FATAL_FAILURE(s.GenerateReport("wrong_pst",
|
||||||
|
OEMCrypto_ERROR_WRONG_PST));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsageTableTest, TimingTest) {
|
TEST_F(UsageTableTest, TimingTest) {
|
||||||
@@ -5548,7 +5579,7 @@ TEST_F(UsageTableTest, PSTLargeBuffer) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s3.open());
|
ASSERT_NO_FATAL_FAILURE(s3.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
|
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.UpdateUsageEntry(&encrypted_usage_header_));
|
ASSERT_NO_FATAL_FAILURE(s3.UpdateUsageEntry(&encrypted_usage_header_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, true, &s));
|
ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, OEMCrypto_SUCCESS, &s));
|
||||||
EXPECT_EQ(kInactiveUsed, s3.pst_report().status());
|
EXPECT_EQ(kInactiveUsed, s3.pst_report().status());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user