diff --git a/hmac_utils.cpp b/hmac_utils.cpp index da4ee8d..fd0c9a7 100644 --- a/hmac_utils.cpp +++ b/hmac_utils.cpp @@ -36,8 +36,12 @@ namespace hmac { } std::time_t rounded = (now / interval_sec) * interval_sec; if (constant_time_equals(token, get_hmac(key, std::to_string(rounded), hash_type))) return true; - if (constant_time_equals(token, get_hmac(key, std::to_string(rounded - interval_sec), hash_type))) return true; - if (constant_time_equals(token, get_hmac(key, std::to_string(rounded + interval_sec), hash_type))) return true; + if (rounded >= std::numeric_limits::min() + interval_sec) { + if (constant_time_equals(token, get_hmac(key, std::to_string(rounded - interval_sec), hash_type))) return true; + } + if (rounded <= std::numeric_limits::max() - interval_sec) { + if (constant_time_equals(token, get_hmac(key, std::to_string(rounded + interval_sec), hash_type))) return true; + } return false; } @@ -66,10 +70,14 @@ namespace hmac { std::string prefix = "|" + fingerprint; std::string payload = std::to_string(rounded) + prefix; if (constant_time_equals(token, get_hmac(key, payload, hash_type))) return true; - payload = std::to_string(rounded - interval_sec) + prefix; - if (constant_time_equals(token, get_hmac(key, payload, hash_type))) return true; - payload = std::to_string(rounded + interval_sec) + prefix; - if (constant_time_equals(token, get_hmac(key, payload, hash_type))) return true; + if (rounded >= std::numeric_limits::min() + interval_sec) { + payload = std::to_string(rounded - interval_sec) + prefix; + if (constant_time_equals(token, get_hmac(key, payload, hash_type))) return true; + } + if (rounded <= std::numeric_limits::max() - interval_sec) { + payload = std::to_string(rounded + interval_sec) + prefix; + if (constant_time_equals(token, get_hmac(key, payload, hash_type))) return true; + } return false; } diff --git a/test_all.cpp b/test_all.cpp index 91e8777..fb61991 100644 --- a/test_all.cpp +++ b/test_all.cpp @@ -1,9 +1,16 @@ #include #include #include +#include #include "hmac.hpp" #include "hmac_utils.hpp" +static std::time_t mock_time_value = 0; +extern "C" std::time_t time(std::time_t* t) { + if (t) *t = mock_time_value; + return mock_time_value; +} + TEST(HashTest, SHA1) { EXPECT_EQ(hmac_hash::sha1("grape"), "bc8a2f8cdedb005b5c787692853709b060db75ff"); @@ -65,6 +72,56 @@ TEST(TokenTest, InvalidInterval) { EXPECT_THROW(hmac::is_token_valid(token, key, 0), std::invalid_argument); } +TEST(TokenBoundaryTest, MaxTime) { + const std::string key = "12345"; + const int interval = 30; + mock_time_value = std::numeric_limits::max(); + std::string token = hmac::generate_time_token(key, interval); + EXPECT_TRUE(hmac::is_token_valid(token, key, interval)); + mock_time_value = std::numeric_limits::max() - interval; + std::string token_prev = hmac::generate_time_token(key, interval); + mock_time_value = std::numeric_limits::max(); + EXPECT_TRUE(hmac::is_token_valid(token_prev, key, interval)); +} + +TEST(TokenBoundaryTest, MinTime) { + const std::string key = "12345"; + const int interval = 30; + mock_time_value = std::numeric_limits::min(); + std::string token = hmac::generate_time_token(key, interval); + EXPECT_TRUE(hmac::is_token_valid(token, key, interval)); + mock_time_value = std::numeric_limits::min() + interval; + std::string token_next = hmac::generate_time_token(key, interval); + mock_time_value = std::numeric_limits::min(); + EXPECT_TRUE(hmac::is_token_valid(token_next, key, interval)); +} + +TEST(TokenBoundaryFingerprintTest, MaxTime) { + const std::string key = "12345"; + const std::string fingerprint = "fp"; + const int interval = 30; + mock_time_value = std::numeric_limits::max(); + std::string token = hmac::generate_time_token(key, fingerprint, interval); + EXPECT_TRUE(hmac::is_token_valid(token, key, fingerprint, interval)); + mock_time_value = std::numeric_limits::max() - interval; + std::string token_prev = hmac::generate_time_token(key, fingerprint, interval); + mock_time_value = std::numeric_limits::max(); + EXPECT_TRUE(hmac::is_token_valid(token_prev, key, fingerprint, interval)); +} + +TEST(TokenBoundaryFingerprintTest, MinTime) { + const std::string key = "12345"; + const std::string fingerprint = "fp"; + const int interval = 30; + mock_time_value = std::numeric_limits::min(); + std::string token = hmac::generate_time_token(key, fingerprint, interval); + EXPECT_TRUE(hmac::is_token_valid(token, key, fingerprint, interval)); + mock_time_value = std::numeric_limits::min() + interval; + std::string token_next = hmac::generate_time_token(key, fingerprint, interval); + mock_time_value = std::numeric_limits::min(); + EXPECT_TRUE(hmac::is_token_valid(token_next, key, fingerprint, interval)); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();