diff --git a/hmac_utils.cpp b/hmac_utils.cpp index da3fc2d..3ff1722 100644 --- a/hmac_utils.cpp +++ b/hmac_utils.cpp @@ -26,7 +26,7 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } - std::time_t rounded = (now / interval_sec) * interval_sec; + std::time_t rounded = now - (now % interval_sec); return get_hmac(key, std::to_string(rounded), hash_type); } @@ -39,7 +39,7 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } - std::time_t rounded = (now / interval_sec) * interval_sec; + std::time_t rounded = now - (now % interval_sec); if (constant_time_equals(token, get_hmac(key, std::to_string(rounded), 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; @@ -59,7 +59,7 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } - std::time_t rounded = (now / interval_sec) * interval_sec; + std::time_t rounded = now - (now % interval_sec); std::string payload = std::to_string(rounded) + "|" + fingerprint; return get_hmac(key, payload, hash_type); } @@ -73,7 +73,7 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } - std::time_t rounded = (now / interval_sec) * interval_sec; + std::time_t rounded = now - (now % interval_sec); 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; @@ -154,6 +154,9 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } + if (now < 0) { + throw std::runtime_error("std::time returned negative value"); + } uint64_t timestamp = static_cast(now); return get_totp_code_at(key_ptr, key_len, timestamp, period, digits, hash_type); } @@ -203,6 +206,9 @@ namespace hmac { if (now == static_cast(-1) && errno != 0) { throw std::runtime_error("std::time failed"); } + if (now < 0) { + throw std::runtime_error("std::time returned negative value"); + } uint64_t timestamp = static_cast(now); uint64_t counter = timestamp / period; if (token == get_hotp_code(key_ptr, key_len, counter, digits, hash_type)) return true; diff --git a/test_all.cpp b/test_all.cpp index 0ca6002..b5d4cd7 100644 --- a/test_all.cpp +++ b/test_all.cpp @@ -215,16 +215,16 @@ TEST(TimeErrorTest, MinusOneWithErrno) { mock_time_value = 0; } -TEST(TotpTimeErrorTest, MinusOneNoErrno) { +TEST(TotpTimeErrorTest, NegativeTimeThrows) { const std::string key = "12345"; mock_time_value = static_cast(-1); mock_errno_value = 0; - EXPECT_NO_THROW(hmac::get_totp_code(key)); + EXPECT_THROW(hmac::get_totp_code(key), std::runtime_error); mock_time_value = 0; mock_errno_value = 0; } -TEST(TotpTimeErrorTest, MinusOneWithErrno) { +TEST(TotpTimeErrorTest, NegativeTimeThrowsErrno) { const std::string key = "12345"; mock_time_value = static_cast(-1); mock_errno_value = EINVAL; @@ -233,6 +233,17 @@ TEST(TotpTimeErrorTest, MinusOneWithErrno) { mock_time_value = 0; } +TEST(TotpTimeErrorTest, ValidityNegativeTimeThrows) { + const std::string key = "12345"; + mock_time_value = static_cast(-1); + mock_errno_value = 0; + EXPECT_THROW( + hmac::is_totp_token_valid(0, key.data(), key.size(), 30, 6, hmac::TypeHash::SHA1), + std::runtime_error); + mock_time_value = 0; + mock_errno_value = 0; +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();