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:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user