OEMCrypto v16.3
There were no new changes to the OEMCrypto code. However, the ODK library changed, so we rolled the minor version number to 3. The ODK library was updated to support a nonce-free offline license. An offline license would not require a nonce if, for example, it is preloaded onto the device and does not have an entry in the usage table. Also, the following unit tests have been updated: 1. Various tests: Keys are not derived if they are not used. This is more in line with the “OEMCrypto state” diagram below. 2. The decrypt hash is not verified when there are multiple samples or no key is selected. 3. LoadKeyWithNoRequest. A nonce-free license is loaded in a session that did not sign the request. (Requires 16.3 ODK library) 4. RefreshLargeBuffer. The renewal message was set to the large size. Previously, only the license request was set to the larger size. 5. OEMCryptoGenericCryptoTest.*LargeBuffer. The correct buffer size is now being used. 6. ShrinkOverOpenSessions: The correct error code OEMCrypto_ERROR_ENTRY_IN_USE is now verified. 7. TimeRollbackPrevention: The test was refactored and fixed. Comments were added.
This commit is contained in:
@@ -4,16 +4,26 @@
|
||||
|
||||
#include "test_sleep.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "clock.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
bool TestSleep::real_sleep_ = true;
|
||||
TestSleep::CallBack* TestSleep::callback_ = nullptr;
|
||||
int TestSleep::total_clock_rollback_ = 0;
|
||||
|
||||
void TestSleep::Sleep(unsigned int seconds) {
|
||||
int64_t milliseconds = 1000 * seconds;
|
||||
@@ -23,10 +33,10 @@ void TestSleep::Sleep(unsigned int seconds) {
|
||||
// total since the start, and then compare to a running total of sleep
|
||||
// calls. We sleep for approximately x second, and then advance the clock by
|
||||
// the amount of time that has actually passed.
|
||||
static auto start_real = std::chrono::steady_clock().now();
|
||||
static auto start_real = std::chrono::system_clock().now();
|
||||
static int64_t fake_clock = 0;
|
||||
sleep(seconds);
|
||||
auto now_real = std::chrono::steady_clock().now();
|
||||
auto now_real = std::chrono::system_clock().now();
|
||||
int64_t total_real = (now_real - start_real) / std::chrono::milliseconds(1);
|
||||
// We want to advance the fake clock by the difference between the real
|
||||
// clock, and the previous value on the fake clock.
|
||||
@@ -41,4 +51,98 @@ void TestSleep::SyncFakeClock() {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
bool TestSleep::RollbackSystemTime(int seconds) {
|
||||
if (real_sleep_) {
|
||||
#ifdef _WIN32
|
||||
// See remarks from this for why this series is used.
|
||||
// https://msdn.microsoft.com/en-us/f77cdf86-0f97-4a89-b565-95b46fa7d65b
|
||||
SYSTEMTIME time;
|
||||
GetSystemTime(&time);
|
||||
FILETIME file_time;
|
||||
if (!SystemTimeToFileTime(time, &file_time)) return false;
|
||||
uint64_t long_time =
|
||||
static_cast<uint64_t>(file_time.dwLowDateTime) |
|
||||
(static_cast<uint64_t>(file_time.dwHighDateTime) << 32);
|
||||
long_time += static_cast<uint64_t>(delta_seconds) *
|
||||
1e7; // long_time is in 100-nanosecond intervals.
|
||||
file_time.dwLowDateTime = long_time & ((1ull << 32) - 1);
|
||||
file_time.dwHighDateTime = long_time >> 32;
|
||||
if (!FileTimeToSystemTime(&file_time, &time)) return false;
|
||||
if (!SetSystemTime(&time)) return false;
|
||||
#else
|
||||
auto time = std::chrono::system_clock::now();
|
||||
auto modified_time = time - std::chrono::seconds(seconds);
|
||||
;
|
||||
timespec time_spec;
|
||||
time_spec.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
modified_time.time_since_epoch())
|
||||
.count();
|
||||
time_spec.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
modified_time.time_since_epoch())
|
||||
.count() %
|
||||
(1000 * 1000 * 1000);
|
||||
if (clock_settime(CLOCK_REALTIME, &time_spec)) {
|
||||
LOGE("Error setting clock: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // end if(real_sleep_)...
|
||||
|
||||
// For both real and fake sleep we still update the callback and we still keep
|
||||
// track of the total amount of time slept.
|
||||
total_clock_rollback_ += seconds;
|
||||
if (callback_ != nullptr) callback_->ElapseTime(-1000 * seconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestSleep::CanChangeSystemTime() {
|
||||
// If we are using a fake clock, then we can move the clock backwards by
|
||||
// just going backwards.
|
||||
// ElapseTime.
|
||||
if (!real_sleep_) {
|
||||
return true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
LUID desired_id;
|
||||
if (!LookupPrivilegeValue(nullptr, SE_SYSTEMTIME_NAME, &desired_id)) {
|
||||
LOGE("Win32 time rollback: no SYSTEMTIME permission.");
|
||||
return false;
|
||||
}
|
||||
HANDLE token;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) {
|
||||
LOGE("Win32 time rollback: cannot access process token.");
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<void, decltype(&CloseHandle)> safe_token(token, &CloseHandle);
|
||||
|
||||
// This queries all the permissions given to the token to determine if we can
|
||||
// change the system time. Note this is subtly different from PrivilegeCheck
|
||||
// as that only checks "enabled" privileges; even with admin rights, the
|
||||
// privilege is default disabled, even when granted.
|
||||
|
||||
DWORD size = 0;
|
||||
// Determine how big we need to allocate first.
|
||||
GetTokenInformation(token, TokenPrivileges, nullptr, 0, &size);
|
||||
// Since TOKEN_PRIVILEGES uses a variable-length array, we need to use malloc
|
||||
std::unique_ptr<TOKEN_PRIVILEGES, decltype(&free)> privileges(
|
||||
(TOKEN_PRIVILEGES*)malloc(size), &free);
|
||||
if (privileges && GetTokenInformation(token, TokenPrivileges,
|
||||
privileges.get(), size, &size)) {
|
||||
for (int i = 0; i < privileges->PrivilegeCount; i++) {
|
||||
if (privileges->Privileges[i].Luid.HighPart == desired_id.HighPart &&
|
||||
privileges->Privileges[i].Luid.LowPart == desired_id.LowPart) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGE("Win32 time rollback: cannot set system time.");
|
||||
return false;
|
||||
#else
|
||||
// Otherwise, the test needs to be run as root.
|
||||
const uid_t uid = getuid();
|
||||
if (uid == 0) return true;
|
||||
LOGE("Unix time rollback: not running as root (uid=%u.", uid);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -22,8 +22,9 @@ class TestSleep {
|
||||
virtual ~CallBack(){};
|
||||
};
|
||||
|
||||
// If real_sleep_ is true, then this sleeps for |seconds| of time.
|
||||
// If the callback exists, this calls the callback.
|
||||
// If real_sleep_ is true, then this sleeps for |seconds| of time. If
|
||||
// real_sleep_ is false, then the fake clock is advanced by |seconds|. If the
|
||||
// callback exists, this calls the callback.
|
||||
static void Sleep(unsigned int seconds);
|
||||
|
||||
// If we are using a real clock and a fake clock, then the real clock advances
|
||||
@@ -33,8 +34,30 @@ class TestSleep {
|
||||
// failing due to this drift.
|
||||
static void SyncFakeClock();
|
||||
|
||||
static void set_real_sleep(bool real_sleep) { real_sleep_ = real_sleep; }
|
||||
// Roll the system clock back by |seconds|. Returns true on success. A well
|
||||
// mannered test will call CanChangeSystemTime before attempting to call this
|
||||
// function and then assert that this is true. This function should *NOT* roll
|
||||
// back the clock used by OEMCrypto -- in fact, there are several tests that
|
||||
// verify this function does not roll back the clock used by OEMCrypto.
|
||||
static bool RollbackSystemTime(int seconds);
|
||||
|
||||
// Roll the system clock forward to undo all previous calls to
|
||||
// RollBackSystemTime. Returns true on success.
|
||||
static bool ResetRollback() {
|
||||
return total_clock_rollback_ == 0 ||
|
||||
RollbackSystemTime(-total_clock_rollback_);
|
||||
}
|
||||
|
||||
// Returns true if the system time can be rolled back. This is true on some
|
||||
// devices if the tests are run as root. It is also true when using a fake
|
||||
// clock with the reference version of OEMCrypto. This function is about the
|
||||
// system clock, *NOT* the clock used by OEMCrypto.
|
||||
static bool CanChangeSystemTime();
|
||||
|
||||
static void set_real_sleep(bool real_sleep) { real_sleep_ = real_sleep; }
|
||||
static bool real_sleep() { return real_sleep_; }
|
||||
|
||||
// The callback is notified whenever sleep is called.
|
||||
static void set_callback(CallBack* callback) { callback_ = callback; }
|
||||
|
||||
private:
|
||||
@@ -42,6 +65,9 @@ class TestSleep {
|
||||
static bool real_sleep_;
|
||||
// Called when the clock should advance.
|
||||
static CallBack* callback_;
|
||||
// The sum of all calls to RollBackSystemTime. Kept so we can undo all changes
|
||||
// at the end of a test.
|
||||
static int total_clock_rollback_;
|
||||
};
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user