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:
Fred Gylys-Colwell
2017-01-27 15:23:56 -08:00
parent 49a61f6270
commit e4231fea3b
5 changed files with 46 additions and 17 deletions

View File

@@ -948,7 +948,6 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
// TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key.
const std::vector<uint8_t> context(
wrapped->context, wrapped->context + sizeof(wrapped->context));
// 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));
}
}
// TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key.
if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID;

View File

@@ -116,7 +116,7 @@ void UsageTableEntry::Deactivate(const std::vector<uint8_t>& pst) {
} else if (data_.status == kActive) {
data_.status = kInactiveUsed;
}
forbid_report_ = false;
forbid_report_ = true;
data_.generation_number++;
usage_table_->IncrementGeneration();
}
@@ -130,13 +130,13 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
pst.size() != data_.pst_length) {
LOGE("ReportUsage: bad pst length = %d, should be %d.",
pst.size(), data_.pst_length);
return OEMCrypto_ERROR_INVALID_CONTEXT;
return OEMCrypto_ERROR_WRONG_PST;
}
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
LOGE("ReportUsage: wrong pst %s, should be %s.",
wvcdm::b2a_hex(pst).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());
if (*buffer_length < length_needed) {
@@ -658,7 +658,6 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
if (or_make_new_one) {
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
sizeof(int64_t));
master_generation_number_ = 0; // TODO(fredgc): remove after debugging.
return true;
}
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());

View File

@@ -872,7 +872,8 @@ void Session::MoveUsageEntry(uint32_t new_index,
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) {
ASSERT_TRUE(open_);
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(
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()), pst.length(),
&pst_report_buffer_[0], &length);
if (expect_success) {
if (expected_result == OEMCrypto_SUCCESS) {
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
}
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(),
reinterpret_cast<const uint8_t*>(pst.c_str()),
pst.length(), &pst_report_buffer_[0], &length);
if (!expect_success) {
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(expected_result, sts);
if (expected_result != OEMCrypto_SUCCESS) {
return;
}
ASSERT_EQ(pst_report_buffer_.size(), length);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
unsigned int sig_len = SHA_DIGEST_LENGTH;
HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),

View File

@@ -286,11 +286,12 @@ class Session {
const vector<uint8_t>& encrypted_usage_entry() const {
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
// checks. If other is not null, then the mac keys are copied from other in
// 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);
// Move this usage entry to a new index.
void MoveUsageEntry(uint32_t new_index, std::vector<uint8_t>* header_buffer,

View File

@@ -4386,6 +4386,36 @@ TEST_P(UsageTableTestWithMAC, OnlineLicense) {
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) {
std::string pst = "my_pst";
Session s;
@@ -4802,7 +4832,7 @@ TEST_P(UsageTableTestWithMAC, ReloadOfflineLicenseWithTerminate) {
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
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());
}
@@ -4934,7 +4964,7 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
ASSERT_NO_FATAL_FAILURE(s3.open());
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
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());
}
@@ -5265,7 +5295,8 @@ TEST_F(UsageTableTest, GenerateReportWrongPST) {
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.GenerateReport("wrong_pst", false));
ASSERT_NO_FATAL_FAILURE(s.GenerateReport("wrong_pst",
OEMCrypto_ERROR_WRONG_PST));
}
TEST_F(UsageTableTest, TimingTest) {
@@ -5548,7 +5579,7 @@ TEST_F(UsageTableTest, PSTLargeBuffer) {
ASSERT_NO_FATAL_FAILURE(s3.open());
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s));
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());
}