diff options
author | Alex Klyubin <klyubin@google.com> | 2015-06-23 09:44:45 -0700 |
---|---|---|
committer | Alex Klyubin <klyubin@google.com> | 2015-06-23 11:14:32 -0700 |
commit | 53752414eab95d31d76db4bb088ac1d5499b5aae (patch) | |
tree | 23934b1a1531e080f44fbd26c452932b12a6d0b5 | |
parent | 9221bff2f13451ef330135bb32ea96de2a8b09cc (diff) | |
download | android_system_security-53752414eab95d31d76db4bb088ac1d5499b5aae.tar.gz android_system_security-53752414eab95d31d76db4bb088ac1d5499b5aae.tar.bz2 android_system_security-53752414eab95d31d76db4bb088ac1d5499b5aae.zip |
Fully support uint64 key validity dates.
This fixes the issue where, on 32-bit platforms, keys expiring after
about 2^31 - 1 seconds since epoch (Jan 19 2038) might be treated as
already expired.
The issue was caused by using time_t (signed 32-bit on 32-bit
platforms) as current time and downcasting uint64 activation and
expiration time instants to time_t to compare them to current time.
This downcasting could make future time instants appear to be in the
past on 32-bit platforms.
Bug: 22015107
Change-Id: Iae12019c3c019beb92d791fda80b622fa5c4ac4e
-rw-r--r-- | keystore/keystore_keymaster_enforcement.h | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h index 904bf66..f7703eb 100644 --- a/keystore/keystore_keymaster_enforcement.h +++ b/keystore/keystore_keymaster_enforcement.h @@ -38,15 +38,38 @@ class KeystoreKeymasterEnforcement : public keymaster::KeymasterEnforcement { } bool activation_date_valid(uint64_t activation_date) const override { - // Convert java date to time_t, non-portably. - time_t activation_time = activation_date / 1000; - return difftime(time(NULL), activation_time) >= 0; + time_t now = time(NULL); + if (now == static_cast<time_t>(-1)) { + // Failed to obtain current time -- fail safe: activation_date hasn't yet occurred. + return false; + } else if (now < 0) { + // Current time is prior to start of the epoch -- activation_date hasn't yet occurred. + return false; + } + + // time(NULL) returns seconds since epoch and "loses" milliseconds information. We thus add + // 999 ms to now_date to avoid a situation where an activation_date of up to 999ms in the + // past may still be considered to still be in the future. This can be removed once + // time(NULL) is replaced by a millisecond-precise source of time. + uint64_t now_date = static_cast<uint64_t>(now) * 1000 + 999; + return now_date >= activation_date; } bool expiration_date_passed(uint64_t expiration_date) const override { - // Convert jave date to time_t, non-portably. - time_t expiration_time = expiration_date / 1000; - return difftime(time(NULL), expiration_time) > 0; + time_t now = time(NULL); + if (now == static_cast<time_t>(-1)) { + // Failed to obtain current time -- fail safe: expiration_date has passed. + return true; + } else if (now < 0) { + // Current time is prior to start of the epoch: expiration_date hasn't yet occurred. + return false; + } + + // time(NULL) returns seconds since epoch and "loses" milliseconds information. As a result, + // expiration_date of up to 999 ms in the past may still be considered in the future. This + // is OK. + uint64_t now_date = static_cast<uint64_t>(now) * 1000; + return now_date > expiration_date; } bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const { |