OEMCrypto Backwards Compatible Usage Table

Merge from widevine of http://go/wvgerrit/23283

This CL adds the backwards compatiblity functions to the new usage
tables in the oemcrypto mock reference code.

b/31458046
b/32554171

Change-Id: I04901d95aceb8910406f7c514c26c29c2c575322
This commit is contained in:
Fred Gylys-Colwell
2017-01-27 15:22:55 -08:00
parent d06fa606c7
commit 9e153438db
14 changed files with 1151 additions and 350 deletions

View File

@@ -332,6 +332,7 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
license_.keys[i].cipher_mode = OEMCrypto_CipherMode_CTR;
}
memcpy(license_.pst, pst.c_str(), min(sizeof(license_.pst), pst.length()));
pst_ = pst;
}
void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
@@ -857,6 +858,20 @@ void Session::LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer) {
OEMCrypto_LoadUsageEntry(session_id(), index, &buffer[0], buffer.size()));
}
void Session::MoveUsageEntry(uint32_t new_index,
std::vector<uint8_t>* header_buffer,
OEMCryptoResult expect_result) {
ASSERT_NO_FATAL_FAILURE(open());
ASSERT_NO_FATAL_FAILURE(ReloadUsageEntry());
ASSERT_EQ(expect_result, OEMCrypto_MoveEntry(session_id(), new_index));
if (expect_result == OEMCrypto_SUCCESS) {
usage_entry_number_ = new_index;
ASSERT_NO_FATAL_FAILURE(UpdateUsageEntry(header_buffer));
}
ASSERT_NO_FATAL_FAILURE(close());
}
void Session::GenerateReport(const std::string& pst, bool expect_success,
Session* other) {
ASSERT_TRUE(open_);
@@ -897,6 +912,84 @@ void Session::GenerateReport(const std::string& pst, bool expect_success,
EXPECT_EQ(0, memcmp(pst.c_str(), pst_report().pst(), pst.length()));
}
void Session::VerifyPST(const Test_PST_Report& expected) {
wvcdm::Unpacked_PST_Report computed = pst_report();
EXPECT_EQ(expected.status, computed.status());
char* pst_ptr = reinterpret_cast<char *>(computed.pst());
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
ASSERT_EQ(expected.pst, computed_pst);
EXPECT_NEAR(expected.seconds_since_license_received,
computed.seconds_since_license_received(),
kLicenseReceivedTimeTolerance);
// Decrypt times only valid on licenses that have been active.
if (expected.status == kActive || expected.status == kInactiveUsed) {
EXPECT_NEAR(expected.seconds_since_first_decrypt,
computed.seconds_since_first_decrypt(),
kUsageTableTimeTolerance);
EXPECT_NEAR(expected.seconds_since_last_decrypt,
computed.seconds_since_last_decrypt(),
kUsageTableTimeTolerance);
}
std::vector<uint8_t> signature(SHA_DIGEST_LENGTH);
unsigned int md_len = SHA_DIGEST_LENGTH;
if (!HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),
&pst_report_buffer_[0] + SHA_DIGEST_LENGTH,
pst_report_buffer_.size() - SHA_DIGEST_LENGTH,
&signature[0], &md_len)) {
cout << "Error computing HMAC.\n";
dump_openssl_error();
}
EXPECT_EQ(0, memcmp(computed.signature(), &signature[0],
SHA_DIGEST_LENGTH));
}
static int64_t MaybeAdjustTime(int64_t t, time_t now) {
int64_t k10Minutes = 60 * 10; // in seconds.
if (t > k10Minutes) return now - t;
return t;
}
void Session::GenerateVerifyReport(const std::string& pst,
OEMCrypto_Usage_Entry_Status status,
int64_t time_license_received,
int64_t time_first_decrypt,
int64_t time_last_decrypt) {
ASSERT_NO_FATAL_FAILURE(GenerateReport(pst));
Test_PST_Report expected(pst, status);
time_t now = time(NULL);
expected.seconds_since_license_received =
MaybeAdjustTime(time_license_received, now);
expected.seconds_since_first_decrypt =
MaybeAdjustTime(time_first_decrypt, now);
expected.seconds_since_last_decrypt = MaybeAdjustTime(time_last_decrypt, now);
ASSERT_NO_FATAL_FAILURE(VerifyPST(expected));
}
void Session::CreateOldEntry(const Test_PST_Report& report) {
OEMCryptoResult result = OEMCrypto_CreateOldUsageEntry(
report.seconds_since_license_received,
report.seconds_since_first_decrypt,
report.seconds_since_last_decrypt,
report.status, &mac_key_server_[0],
&mac_key_client_[0],
reinterpret_cast<const uint8_t*>(report.pst.c_str()),
report.pst.length());
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) return;
ASSERT_EQ(OEMCrypto_SUCCESS, result);
}
void Session::CopyAndVerifyOldEntry(const Test_PST_Report& report,
std::vector<uint8_t>* header_buffer) {
ASSERT_NO_FATAL_FAILURE(CreateNewUsageEntry());
OEMCryptoResult result = OEMCrypto_CopyOldUsageEntry(
session_id(), reinterpret_cast<const uint8_t*>(report.pst.c_str()),
report.pst.length());
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) return;
ASSERT_NO_FATAL_FAILURE(UpdateUsageEntry(header_buffer));
ASSERT_NO_FATAL_FAILURE(GenerateReport(report.pst));
ASSERT_NO_FATAL_FAILURE(VerifyPST(report));
}
const uint8_t* Session::message_ptr() {
return reinterpret_cast<const uint8_t*>(&encrypted_license());
}

View File

@@ -51,6 +51,8 @@ const int kLongSleep = 2 * kSpeedMultiplier;
const uint32_t kDuration = 2 * kSpeedMultiplier;
const uint32_t kLongDuration = 5 * kSpeedMultiplier;
const int32_t kTimeTolerance = 3 * kSpeedMultiplier;
const int kLicenseReceivedTimeTolerance = kSpeedMultiplier;
const time_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
} // namespace
typedef struct {
@@ -102,6 +104,18 @@ struct RSAPrivateKeyMessage {
uint32_t nonce;
};
struct Test_PST_Report {
Test_PST_Report(const std::string& pst_in,
OEMCrypto_Usage_Entry_Status status_in)
: pst(pst_in), status(status_in) {}
OEMCrypto_Usage_Entry_Status status;
int64_t seconds_since_license_received;
int64_t seconds_since_first_decrypt;
int64_t seconds_since_last_decrypt;
std::string pst;
};
// Increment counter for AES-CTR. The CENC spec specifies we increment only
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
// is different from the OpenSSL implementation, so we implement the CTR loop
@@ -267,6 +281,7 @@ class Session {
OEMCryptoResult expect_result = OEMCrypto_SUCCESS);
// The usage entry number for this session's usage entry.
uint32_t usage_entry_number() const { return usage_entry_number_; }
void set_usage_entry_number(uint32_t v) { usage_entry_number_ = v; }
// The encrypted buffer holding the recently updated and saved usage entry.
const vector<uint8_t>& encrypted_usage_entry() const {
return encrypted_usage_entry_;
@@ -277,11 +292,32 @@ class Session {
// order to verify signatures.
void GenerateReport(const std::string& pst, bool expect_success = true,
Session* other = 0);
// Move this usage entry to a new index.
void MoveUsageEntry(uint32_t new_index, std::vector<uint8_t>* header_buffer,
OEMCryptoResult expect_result = OEMCrypto_SUCCESS);
// PST used in FillSimpleMesage.
string pst() const { return pst_; }
// Returns a pointer-like thing to the usage report generated by the previous
// call to GenerateReport.
wvcdm::Unpacked_PST_Report pst_report() {
return wvcdm::Unpacked_PST_Report(&pst_report_buffer_[0]);
}
// Verify the PST report.
void VerifyPST(const Test_PST_Report& report);
// Generate and Verify the Usage Report. If any time is greater than 10
// minutes, it is assumed to be an absolute time, and time_since will be
// computed relative to now.
void GenerateVerifyReport(const std::string& pst,
OEMCrypto_Usage_Entry_Status status,
int64_t time_license_received = 0,
int64_t time_first_decrypt = 0,
int64_t time_last_decrypt = 0);
// Create an entry in the old usage table based on the given report.
void CreateOldEntry(const Test_PST_Report &report);
// Create a new entry and copy the old entry into it. Then very the report
// is right.
void CopyAndVerifyOldEntry(const Test_PST_Report &report,
std::vector<uint8_t>* header_buffer);
// The unencrypted license response or license renewal response.
MessageData& license() { return license_; }
@@ -329,6 +365,7 @@ class Session {
int num_keys_;
vector<uint8_t> encrypted_usage_entry_;
uint32_t usage_entry_number_;
string pst_;
};
} // namespace wvoec

File diff suppressed because it is too large Load Diff

View File

@@ -130,4 +130,12 @@ TEST_F(OEMCryptoAndroidNYCTest, MinVersionNumber11) {
ASSERT_GE(version, 11u);
}
// These tests are required for O Android devices.
class OEMCryptoAndroidOCTest : public OEMCryptoAndroidNYCTest {};
TEST_F(OEMCryptoAndroidOCTest, MinVersionNumber13) {
uint32_t version = OEMCrypto_APIVersion();
ASSERT_GE(version, 13u);
}
} // namespace wvoec