Update ODK Library and add license release unit test

Merge from Widevine repo of two CLs.

Merge from Widevine repo of http://go/wvgerrit/94743

A license release should not have a core message. This CL adjusts the
existing unit tests to verify this. There is also a new unit test called
SecureStop that explicitly tests sending a secure stop in a new
session without first loading the license.

Merge from Widevine repo of http://go/wvgerrit/94865

This CL has the following changes copied from google3:
http://cr/298871728 Remove odk_static_assert for Message size temporarily
http://cr/298755935 Fix a compiling error during macro expansion
http://cr/298481745 Add missing header for android
http://cr/298448142 Fix odk_test gyp file
http://cr/298419641 Remove header from Android.bp
http://cr/298402053 Separate sizeOf(args) bytes in fuzz tests
http://cr/297730316 No core messages for license release
http://cr/297714346 Add copybara_test and piper_sot_to_gerrit
http://cr/297636713 Adding some comments around boolean conversion code
http://cr/297420679 Autofuzzer when ran with address sanitizer ...
http://cr/296513584 Minor fix with fuzzing odk clock values
http://cr/296322024 Fixing errors in code with how request ...
http://cr/296313159 Fuzzing ODK clock values by setting aside ...
http://cr/295763207 Add more odk tests and move helper functions to test helper
http://cr/294524098 Adding a Build Rule for ODK_KDO_Fuzzer and updating
http://cr/294492213 Address a few review comments of ODK
http://cr/293674368 odk_fuzz: add TODOs & comments
http://cr/293492806 Fix spelling

Bug: 150243585
Bug: 150020278
Bug: 150095506
Bug: 147297226
Bug: 148290294
Bug: 148907684
Bug: 150608451
Test: unit tests
Change-Id: I25fd406f29f4eba40f5cb27e9a1317dce4ffc2f5
This commit is contained in:
Fred Gylys-Colwell
2020-02-28 12:03:28 -08:00
committed by Jeff Tinker
parent 0947bd185b
commit c5b7a01ab5
17 changed files with 1528 additions and 866 deletions

View File

@@ -826,8 +826,8 @@ void RenewalRoundTrip::VerifyRequestSignature(
void RenewalRoundTrip::FillAndVerifyCoreRequest(
const std::string& core_message_string) {
if (license_messages_->api_version() < kCoreMessagesAPI) {
// For v15, we expect that no core request was created.
if (license_messages_->api_version() < kCoreMessagesAPI || is_release_) {
// For v15 or for a release, we expect that no core request was created.
EXPECT_FALSE(
oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage(
core_message_string, &core_request_));
@@ -837,13 +837,9 @@ void RenewalRoundTrip::FillAndVerifyCoreRequest(
core_message_string, &core_request_));
EXPECT_EQ(license_messages_->core_request().api_major_version,
core_request_.api_major_version);
if (!is_release_) {
// For a license release, we do not expect the nonce to be correct. That
// is because a release might be sent without loading the license first.
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
EXPECT_EQ(license_messages_->core_request().session_id,
core_request_.session_id);
}
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
EXPECT_EQ(license_messages_->core_request().session_id,
core_request_.session_id);
}
}
@@ -1397,13 +1393,6 @@ void Session::UpdateUsageEntry(std::vector<uint8_t>* header_buffer) {
encrypted_usage_entry_.data(), &entry_buffer_length));
}
void Session::DeactivateUsageEntry(const std::string& pst) {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_DeactivateUsageEntry(
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()),
pst.length()));
}
void Session::LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer) {
usage_entry_number_ = index;
encrypted_usage_entry_ = buffer;

View File

@@ -527,8 +527,6 @@ class Session {
void ReloadUsageEntry() { LoadUsageEntry(*this); }
// Update the usage entry and save the header to the specified buffer.
void UpdateUsageEntry(std::vector<uint8_t>* header_buffer);
// Deactivate this session's usage entry.
void DeactivateUsageEntry(const std::string& pst);
// 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; }

View File

@@ -15,9 +15,9 @@
#include <stdint.h>
#ifdef _WIN32
# include <windows.h>
# include <windows.h>
#else
# include <sys/time.h>
# include <sys/time.h>
#endif
#include <gtest/gtest.h>
@@ -46,9 +46,9 @@
using ::testing::Bool;
using ::testing::Combine;
using ::testing::Range;
using ::testing::tuple;
using ::testing::Values;
using ::testing::WithParamInterface;
using ::testing::tuple;
using namespace std;
namespace std { // GTest wants PrintTo to be in the std namespace.
@@ -92,11 +92,11 @@ constexpr size_t MiB = 1024 * 1024;
// depending on the resource rating reported by OEMCrypto. This function looks
// up the required value for the specified resource for the target OEMCrypto
// library.
template<typename T, size_t N>
template <typename T, size_t N>
T GetResourceValue(T (&resource_values)[N]) {
if (global_features.resource_rating < 1) return resource_values[0];
if (global_features.resource_rating > N) return resource_values[N-1];
return resource_values[global_features.resource_rating-1];
if (global_features.resource_rating > N) return resource_values[N - 1];
return resource_values[global_features.resource_rating - 1];
}
// After API 16, we require 300 entries in the usage table. Before API 16, we
@@ -124,8 +124,8 @@ const size_t kLargeMessageSize[] = { 8*KiB, 8*KiB, 16*KiB, 32*KiB};
/** @return The Unix time of the given time point. */
template <typename Duration>
uint64_t UnixTime(const std::chrono::time_point<std::chrono::system_clock,
Duration>& point) {
uint64_t UnixTime(
const std::chrono::time_point<std::chrono::system_clock, Duration>& point) {
return point.time_since_epoch() / std::chrono::seconds(1);
}
@@ -143,7 +143,8 @@ void AddNativeTime(int64_t delta_seconds, NativeTime* time) {
ASSERT_TRUE(SystemTimeToFileTime(time, &file_time));
uint64_t long_time = static_cast<uint64_t>(file_time.dwLowDateTime) |
(static_cast<uint64_t>(file_time.dwHighDateTime) << 32);
long_time += delta_seconds * 1e7; // long_time is in 100-nanosecond intervals.
long_time +=
delta_seconds * 1e7; // long_time is in 100-nanosecond intervals.
file_time.dwLowDateTime = long_time & ((1ull << 32) - 1);
file_time.dwHighDateTime = long_time >> 32;
ASSERT_TRUE(FileTimeToSystemTime(&file_time, time));
@@ -344,8 +345,7 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenCloseAPI10) {
ASSERT_GE(max_sessions, required_number);
// We allow GetMaxNumberOfSessions to return an estimate. This tests with a
// pad of 5%. Even if it's just an estimate, we still require 8 sessions.
size_t max_sessions_with_pad =
max(max_sessions * 19 / 20, required_number);
size_t max_sessions_with_pad = max(max_sessions * 19 / 20, required_number);
vector<OEMCrypto_SESSION> sessions;
// Limit the number of sessions for testing.
const size_t kMaxNumberOfSessionsForTesting = 0x100u;
@@ -631,7 +631,7 @@ TEST_F(OEMCryptoKeyboxTest, GenerateDerivedKeysFromKeyboxLargeBuffer) {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GenerateDerivedKeys(
s.session_id(), mac_context.data(), mac_context.size(),
enc_context.data(),enc_context.size()));
enc_context.data(), enc_context.size()));
}
// This class is for tests that have an OEM Certificate instead of a keybox.
@@ -660,7 +660,6 @@ TEST_F(OEMCryptoProv30Test, GetDeviceId) {
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
// The OEM certificate must be valid.
TEST_F(OEMCryptoProv30Test, CertValidAPI15) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxOrOEMCertValid());
@@ -2843,12 +2842,12 @@ TEST_F(OEMCryptoLoadsCertificate, LoadWrappedRSAKey) {
TEST_F(OEMCryptoLoadsCertificate, TestLargeRSAKey3072) {
encoded_rsa_key_.assign(kTestRSAPKCS8PrivateKeyInfo3_3072,
kTestRSAPKCS8PrivateKeyInfo3_3072 +
sizeof(kTestRSAPKCS8PrivateKeyInfo3_3072));
sizeof(kTestRSAPKCS8PrivateKeyInfo3_3072));
CreateWrappedRSAKey();
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s.InstallRSASessionTestKey(wrapped_rsa_key_));
LicenseRoundTrip license_messages(&s);
@@ -2869,8 +2868,8 @@ TEST_F(OEMCryptoLoadsCertificate, TestCarmichaelRSAKey) {
CreateWrappedRSAKey();
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s.InstallRSASessionTestKey(wrapped_rsa_key_));
LicenseRoundTrip license_messages(&s);
@@ -2888,8 +2887,8 @@ TEST_F(OEMCryptoLoadsCertificate, TestMultipleRSAKeys) {
Session s1; // Session s1 loads the default rsa key, but doesn't use it
// until after s2 uses its key.
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(s1.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s1.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadDeviceRSAKey(s1.session_id(), wrapped_rsa_key_.data(),
wrapped_rsa_key_.size()));
@@ -2900,8 +2899,8 @@ TEST_F(OEMCryptoLoadsCertificate, TestMultipleRSAKeys) {
sizeof(kTestRSAPKCS8PrivateKeyInfo4_2048));
CreateWrappedRSAKey();
ASSERT_NO_FATAL_FAILURE(s2.open());
ASSERT_NO_FATAL_FAILURE(s2.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s2.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s2.InstallRSASessionTestKey(wrapped_rsa_key_));
LicenseRoundTrip license_messages2(&s2);
ASSERT_NO_FATAL_FAILURE(s2.GenerateNonce());
@@ -3006,8 +3005,8 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) {
wrapped_rsa_key_.size()));
vector<uint8_t> session_key;
vector<uint8_t> enc_session_key;
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_TRUE(s.GenerateRSASessionKey(&session_key, &enc_session_key));
vector<uint8_t> mac_context;
vector<uint8_t> enc_context;
@@ -3035,10 +3034,9 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) {
while (clock.now() - start_time < kTestDuration) {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_DeriveKeysFromSessionKey(
s.session_id(),
enc_session_key.data(), enc_session_key.size(),
mac_context.data(), mac_context.size(),
enc_context.data(), enc_context.size()));
s.session_id(), enc_session_key.data(),
enc_session_key.size(), mac_context.data(),
mac_context.size(), enc_context.data(), enc_context.size()));
count++;
}
delta_time = clock.now() - start_time;
@@ -3068,9 +3066,8 @@ TEST_F(OEMCryptoUsesCertificate, GenerateDerivedKeysLargeBuffer) {
}
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_DeriveKeysFromSessionKey(
session_.session_id(),
enc_session_key.data(), enc_session_key.size(),
mac_context.data(), mac_context.size(),
session_.session_id(), enc_session_key.data(),
enc_session_key.size(), mac_context.data(), mac_context.size(),
enc_context.data(), enc_context.size()));
}
@@ -3090,19 +3087,16 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
GetRandBytes(licenseRequest.data(), licenseRequest.size());
size_t signature_length = 256;
vector<uint8_t> signature(signature_length);
sts = OEMCrypto_GenerateRSASignature(s.session_id(), licenseRequest.data(),
licenseRequest.size(),
signature.data(), &signature_length,
scheme);
sts = OEMCrypto_GenerateRSASignature(
s.session_id(), licenseRequest.data(), licenseRequest.size(),
signature.data(), &signature_length, scheme);
// Allow OEMCrypto to request a full buffer.
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
ASSERT_NE(static_cast<size_t>(0), signature_length);
signature.assign(signature_length, 0);
sts = OEMCrypto_GenerateRSASignature(s.session_id(),
licenseRequest.data(),
licenseRequest.size(),
signature.data(), &signature_length,
scheme);
sts = OEMCrypto_GenerateRSASignature(
s.session_id(), licenseRequest.data(), licenseRequest.size(),
signature.data(), &signature_length, scheme);
}
EXPECT_NE(OEMCrypto_SUCCESS, sts)
@@ -3137,8 +3131,8 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
ASSERT_EQ(OEMCrypto_SUCCESS, sts)
<< "Failed to sign with padding scheme=" << (int)scheme
<< ", size=" << (int)size;
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(licenseRequest, signature,
signature_length, scheme));
delete[] signature;
@@ -3154,8 +3148,8 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate {
s.GenerateNonce();
vector<uint8_t> session_key;
vector<uint8_t> enc_session_key;
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
ASSERT_TRUE(s.GenerateRSASessionKey(&session_key, &enc_session_key));
vector<uint8_t> mac_context;
vector<uint8_t> enc_context;
@@ -3359,7 +3353,7 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
"01" // 1
"05" // null object. (field=parameter?)
"00" // size of null object
);
);
vector<uint8_t> pkey = wvcdm::a2b_hex("020100"); // integer, version = 0.
pkey = concat(pkey, field_n);
@@ -3416,8 +3410,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
ASSERT_EQ(OEMCrypto_SUCCESS, sts)
<< "Failed to sign with padding scheme=" << (int)scheme
<< ", size=" << (int)message.size();
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(encoded_rsa_key_.data(),
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(
s.PreparePublicKey(encoded_rsa_key_.data(), encoded_rsa_key_.size()));
// Verify that the signature matches the official test vector.
ASSERT_EQ(correct_signature.size(), signature_length);
@@ -3426,8 +3420,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
// Also verify that our verification algorithm agrees. This is not needed
// to test OEMCrypto, but it does verify that this test is valid.
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(
digest, signature.data(), signature_length, scheme));
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(digest, signature.data(),
signature_length, scheme));
ASSERT_NO_FATAL_FAILURE(s.VerifyRSASignature(
digest, correct_signature.data(), correct_signature.size(), scheme));
}
@@ -3435,7 +3429,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
// CAST Receivers should report that they support cast certificates.
TEST_F(OEMCryptoCastReceiverTest, SupportsCertificatesAPI13) {
ASSERT_NE(0u, OEMCrypto_Supports_RSA_CAST & OEMCrypto_SupportedCertificates());
ASSERT_NE(0u,
OEMCrypto_Supports_RSA_CAST & OEMCrypto_SupportedCertificates());
}
// # PKCS#1 v1.5 Signature Example 15.1
@@ -4215,10 +4210,9 @@ class OEMCryptoGenericCryptoTest : public OEMCryptoRefreshTest {
OEMCrypto_CipherMode_CTR);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
vector<uint8_t> encrypted(buffer_length);
sts =
OEMCrypto_Generic_Encrypt(session_.session_id(), clear_buffer_.data(),
buffer_length, iv_, algorithm,
encrypted.data());
sts = OEMCrypto_Generic_Encrypt(session_.session_id(), clear_buffer_.data(),
buffer_length, iv_, algorithm,
encrypted.data());
EXPECT_NE(OEMCrypto_SUCCESS, sts);
expected_encrypted.resize(buffer_length);
EXPECT_NE(encrypted, expected_encrypted);
@@ -4237,10 +4231,9 @@ class OEMCryptoGenericCryptoTest : public OEMCryptoRefreshTest {
OEMCrypto_CipherMode_CTR);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
vector<uint8_t> resultant(encrypted.size());
sts =
OEMCrypto_Generic_Decrypt(session_.session_id(), encrypted.data(),
buffer_length, iv_, algorithm,
resultant.data());
sts = OEMCrypto_Generic_Decrypt(session_.session_id(), encrypted.data(),
buffer_length, iv_, algorithm,
resultant.data());
EXPECT_NE(OEMCrypto_SUCCESS, sts);
EXPECT_NE(clear_buffer_, resultant);
}
@@ -4310,11 +4303,11 @@ TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncrypt) {
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
vector<uint8_t> encrypted(clear_buffer_.size());
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING,
encrypted.data()));
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(), clear_buffer_.size(),
iv_, OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data()));
ASSERT_EQ(expected_encrypted, encrypted);
}
@@ -4346,8 +4339,8 @@ TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptSameBufferAPI12) {
vector<uint8_t> buffer = clear_buffer_;
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), buffer.data(), buffer.size(),
iv_, OEMCrypto_AES_CBC_128_NO_PADDING, buffer.data()));
session_.session_id(), buffer.data(), buffer.size(), iv_,
OEMCrypto_AES_CBC_128_NO_PADDING, buffer.data()));
ASSERT_EQ(expected_encrypted, buffer);
}
@@ -4474,11 +4467,10 @@ TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerify) {
session_.license().keys[key_index].key_id,
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(),
signature.size()));
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256,
signature.data(), signature.size()));
}
// Test that the Generic_Verify function fails when not allowed.
@@ -4507,11 +4499,11 @@ TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptLargeBuffer) {
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
vector<uint8_t> encrypted(clear_buffer_.size());
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING,
encrypted.data()));
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(), clear_buffer_.size(),
iv_, OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data()));
ASSERT_EQ(expected_encrypted, encrypted);
}
@@ -4579,11 +4571,10 @@ TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerifyLargeBuffer) {
session_.license().keys[key_index].key_id,
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(),
signature.size()));
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256,
signature.data(), signature.size()));
}
// Test Generic_Encrypt when the key duration has expired.
@@ -4604,11 +4595,11 @@ TEST_P(OEMCryptoGenericCryptoTest, KeyDurationEncrypt) {
session_.license().keys[key_index].key_id,
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING,
encrypted.data()));
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_Generic_Encrypt(
session_.session_id(), clear_buffer_.data(), clear_buffer_.size(),
iv_, OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data()));
ASSERT_EQ(expected_encrypted, encrypted);
wvcdm::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key.
@@ -4709,11 +4700,10 @@ TEST_P(OEMCryptoGenericCryptoTest, KeyDurationVerify) {
session_.license().keys[key_index].key_id,
session_.license().keys[key_index].key_id_length,
OEMCrypto_CipherMode_CTR));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(),
signature.size()));
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Generic_Verify(
session_.session_id(), clear_buffer_.data(),
clear_buffer_.size(), OEMCrypto_HMAC_SHA256,
signature.data(), signature.size()));
wvcdm::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key.
OEMCryptoResult status = OEMCrypto_Generic_Verify(
@@ -4827,7 +4817,8 @@ class LicenseWithUsageEntry {
generic_crypto_(false),
time_license_received_(0),
time_first_decrypt_(0),
time_last_decrypt_(0) {
time_last_decrypt_(0),
active_(true) {
license_messages_.set_pst(pst);
}
@@ -4888,6 +4879,15 @@ class LicenseWithUsageEntry {
if (time_first_decrypt_ == 0) time_first_decrypt_ = time_last_decrypt_;
}
void DeactivateUsageEntry() {
active_ = false;
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_DeactivateUsageEntry(
session_.session_id(),
reinterpret_cast<const uint8_t*>(pst().c_str()), pst().length()));
}
void GenerateVerifyReport(OEMCrypto_Usage_Entry_Status status) {
ASSERT_NO_FATAL_FAILURE(session_.GenerateReport(pst()));
Test_PST_Report expected(pst(), status);
@@ -4897,7 +4897,7 @@ class LicenseWithUsageEntry {
// The PST report was signed above. Below we verify that the entire message
// that is sent to the server will be signed by the right mac keys.
RenewalRoundTrip renewal_messages(&license_messages_);
renewal_messages.set_is_release(true);
renewal_messages.set_is_release(!active_);
ASSERT_NO_FATAL_FAILURE(renewal_messages.SignAndVerifyRequest());
}
@@ -4921,6 +4921,7 @@ class LicenseWithUsageEntry {
int64_t time_license_received_;
int64_t time_first_decrypt_;
int64_t time_last_decrypt_;
bool active_;
};
class OEMCryptoUsageTableTest : public OEMCryptoGenericCryptoTest {
@@ -4973,7 +4974,7 @@ TEST_P(OEMCryptoUsageTableTest, OnlineLicense) {
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
// Flag the entry as inactive.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
@@ -4982,7 +4983,7 @@ TEST_P(OEMCryptoUsageTableTest, OnlineLicense) {
entry.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
// We could call DeactivateUsageEntry multiple times. The state should not
// change.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
@@ -4999,7 +5000,7 @@ TEST_P(OEMCryptoUsageTableTest, OnlineLicenseUnused) {
// No decrypt. We do not use this license.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kUnused));
// Flag the entry as inactive.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUnused));
@@ -5008,7 +5009,7 @@ TEST_P(OEMCryptoUsageTableTest, OnlineLicenseUnused) {
entry.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
// We could call DeactivateUsageEntry multiple times. The state should not
// change.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUnused));
@@ -5031,7 +5032,7 @@ TEST_P(OEMCryptoUsageTableTest, ForbidReportWithNoUpdate) {
// Now it's OK.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
// Flag the entry as inactive.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
// Cannot generate a report without first updating the file.
ASSERT_NO_FATAL_FAILURE(
s.GenerateReport(entry.pst(), OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE));
@@ -5201,7 +5202,7 @@ TEST_P(OEMCryptoUsageTableTest, GenericCryptoEncrypt) {
EXPECT_EQ(expected_encrypted, encrypted);
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
encrypted.assign(clear_buffer_.size(), 0);
@@ -5236,7 +5237,7 @@ TEST_P(OEMCryptoUsageTableTest, GenericCryptoDecrypt) {
EXPECT_EQ(clear_buffer_, resultant);
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
resultant.assign(encrypted.size(), 0);
@@ -5279,7 +5280,7 @@ TEST_P(OEMCryptoUsageTableTest, GenericCryptoSign) {
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
signature.assign(SHA256_DIGEST_LENGTH, 0);
@@ -5314,7 +5315,7 @@ TEST_P(OEMCryptoUsageTableTest, GenericCryptoVerify) {
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
sts = OEMCrypto_Generic_Verify(s.session_id(), clear_buffer_.data(),
@@ -5505,8 +5506,7 @@ TEST_P(OEMCryptoUsageTableTest, DeactivateOfflineLicense) {
ASSERT_NO_FATAL_FAILURE(entry.OpenAndReload(this));
ASSERT_NO_FATAL_FAILURE(
entry.TestDecryptCTR()); // Should be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
s.DeactivateUsageEntry(entry.pst())); // Then deactivate.
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry()); // Then deactivate.
// After deactivate, should not be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
entry.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
@@ -5531,7 +5531,7 @@ TEST_P(OEMCryptoUsageTableTest, DeactivateOfflineLicense) {
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
// We could call DeactivateUsageEntry multiple times. The state should not
// change.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
}
@@ -5545,8 +5545,7 @@ TEST_P(OEMCryptoUsageTableTest, DeactivateOfflineLicenseUnused) {
Session& s = entry.session();
// No Decrypt. This license is unused.
ASSERT_NO_FATAL_FAILURE(entry.OpenAndReload(this));
ASSERT_NO_FATAL_FAILURE(
s.DeactivateUsageEntry(entry.pst())); // Then deactivate.
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry()); // Then deactivate.
// After deactivate, should not be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
entry.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
@@ -5571,11 +5570,30 @@ TEST_P(OEMCryptoUsageTableTest, DeactivateOfflineLicenseUnused) {
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUnused));
// We could call DeactivateUsageEntry multiple times. The state should not
// change.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUnused));
}
TEST_P(OEMCryptoUsageTableTest, SecureStop) {
LicenseWithUsageEntry entry;
entry.license_messages().set_api_version(license_api_version_);
entry.MakeAndLoadOnline(this);
Session& s = entry.session();
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.TestDecryptCTR());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s.close());
// When we generate a secure stop without loading the license first, it
// should assume the server does not support core messages.
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(entry.ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
}
// Test update usage table fails when passed a null pointer.
TEST_P(OEMCryptoUsageTableTest, UpdateFailsWithNullPtr) {
LicenseWithUsageEntry entry;
@@ -5638,8 +5656,7 @@ class OEMCryptoUsageTableDefragTest : public OEMCryptoUsageTableTest {
ASSERT_LT(0u, header_buffer_length);
encrypted_usage_header_.resize(header_buffer_length);
sts = OEMCrypto_ShrinkUsageTableHeader(
new_size, encrypted_usage_header_.data(),
&header_buffer_length);
new_size, encrypted_usage_header_.data(), &header_buffer_length);
ASSERT_EQ(expected_result, sts);
}
};
@@ -5895,26 +5912,23 @@ TEST_P(OEMCryptoUsageTableTest, ReloadUsageTableWithSkew) {
nullptr, old_usage_header_2_.size()));
ASSERT_NO_FATAL_FAILURE(s.open());
// Cannot load an entry if header didn't load.
ASSERT_EQ(
OEMCrypto_ERROR_UNKNOWN_FAILURE,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_EQ(OEMCrypto_ERROR_UNKNOWN_FAILURE,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_NO_FATAL_FAILURE(s.close());
// Modified header generates error.
vector<uint8_t> bad_header = encrypted_usage_header_;
bad_header[3] ^= 42;
ASSERT_NE(OEMCrypto_SUCCESS,
OEMCrypto_LoadUsageTableHeader(bad_header.data(),
bad_header.size()));
ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_LoadUsageTableHeader(
bad_header.data(), bad_header.size()));
ASSERT_NO_FATAL_FAILURE(s.open());
// Cannot load an entry if header didn't load.
ASSERT_EQ(
OEMCrypto_ERROR_UNKNOWN_FAILURE,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_EQ(OEMCrypto_ERROR_UNKNOWN_FAILURE,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_NO_FATAL_FAILURE(s.close());
// Old by 2 generation numbers is error.
@@ -5923,11 +5937,10 @@ TEST_P(OEMCryptoUsageTableTest, ReloadUsageTableWithSkew) {
old_usage_header_2_.size()));
ASSERT_NO_FATAL_FAILURE(s.open());
// Cannot load an entry if header didn't load.
ASSERT_NE(
OEMCrypto_SUCCESS,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_NE(OEMCrypto_SUCCESS,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_NO_FATAL_FAILURE(s.close());
// Old by 1 generation numbers is just warning.
@@ -5936,11 +5949,10 @@ TEST_P(OEMCryptoUsageTableTest, ReloadUsageTableWithSkew) {
old_usage_header_1_.size()));
// Everything else should still work. Skew by 1 is just a warning.
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_EQ(
OEMCrypto_WARNING_GENERATION_SKEW,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_EQ(OEMCrypto_WARNING_GENERATION_SKEW,
OEMCrypto_LoadUsageEntry(s.session_id(), s.usage_entry_number(),
s.encrypted_usage_entry().data(),
s.encrypted_usage_entry().size()));
ASSERT_NO_FATAL_FAILURE(InstallTestRSAKey(&s));
ASSERT_EQ(OEMCrypto_SUCCESS, entry.license_messages().LoadResponse());
}
@@ -5952,8 +5964,8 @@ TEST_P(OEMCryptoUsageTableTest, GenerateReportWrongPST) {
entry.MakeAndLoadOnline(this);
Session& s = entry.session();
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s.GenerateReport("wrong_pst",
OEMCrypto_ERROR_WRONG_PST));
ASSERT_NO_FATAL_FAILURE(
s.GenerateReport("wrong_pst", OEMCrypto_ERROR_WRONG_PST));
}
// Test usage table timing.
@@ -5992,7 +6004,7 @@ TEST_P(OEMCryptoUsageTableTest, TimingTest) {
ASSERT_NO_FATAL_FAILURE(entry2.TestDecryptCTR());
wvcdm::TestSleep::Sleep(kLongSleep);
ASSERT_NO_FATAL_FAILURE(s1.DeactivateUsageEntry(entry1.pst()));
ASSERT_NO_FATAL_FAILURE(entry1.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s2.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s1.close());
@@ -6105,7 +6117,7 @@ TEST_P(OEMCryptoUsageTableTest, VerifyUsageTimes) {
// |<------------------------------------| = seconds_since_license_received
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kActive));
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(entry.pst()));
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(entry.GenerateVerifyReport(kInactiveUsed));
ASSERT_NO_FATAL_FAILURE(
@@ -6195,8 +6207,8 @@ TEST_P(OEMCryptoUsageTableTestWallClock, TimeRollbackPrevention) {
// Rollback the wall clock time.
cout << "Rolling the system time back..." << endl;
ASSERT_NO_FATAL_FAILURE(SetWallTimeDelta(
-static_cast<int64_t>(kLongDuration) * 10));
ASSERT_NO_FATAL_FAILURE(
SetWallTimeDelta(-static_cast<int64_t>(kLongDuration) * 10));
// Try to playback again.
ASSERT_NO_FATAL_FAILURE(entry.OpenAndReload(this));
@@ -6210,8 +6222,8 @@ TEST_P(OEMCryptoUsageTableTestWallClock, TimeRollbackPrevention) {
// not report negative times.
const auto test_duration = third_decrypt_monotonic - first_decrypt_monotonic;
cout << "Rolling the system time forward to the absolute time..." << endl;
ASSERT_NO_FATAL_FAILURE(SetWallTimeDelta(
test_duration / std::chrono::seconds(1)));
ASSERT_NO_FATAL_FAILURE(
SetWallTimeDelta(test_duration / std::chrono::seconds(1)));
// Need to update time created since the verification checks the time of PST
// report creation.
expected.time_created = UnixTime(wall_clock.now());
@@ -6232,8 +6244,7 @@ TEST_P(OEMCryptoUsageTableTest, PSTLargeBuffer) {
ASSERT_NO_FATAL_FAILURE(entry.OpenAndReload(this));
ASSERT_NO_FATAL_FAILURE(
entry.TestDecryptCTR()); // Should be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
s.DeactivateUsageEntry(entry.pst())); // Then deactivate.
ASSERT_NO_FATAL_FAILURE(entry.DeactivateUsageEntry()); // Then deactivate.
// After deactivate, should not be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
entry.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));