/* * Copyright (c) 2021 - 2026 Ember * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include using namespace ember; struct MockClock final : utility::ClockBase { std::chrono::time_point timepoint; explicit MockClock(const std::uint64_t timestamp) { set_timestamp(timestamp); } void set_timestamp(const std::uint64_t timestamp) { const auto time = std::chrono::system_clock::now(); const auto curr_ts = std::chrono::time_point_cast(time).time_since_epoch().count(); const auto time_s = std::chrono::seconds(curr_ts - timestamp); timepoint = time - time_s; } virtual std::chrono::time_point now() const override { return timepoint; } }; /* * Tests static PIN functionality using replayed protocol values * from a known good authentication session */ TEST(PINAuthenticator, StaticPIN) { const auto pin = 456801u; const PINAuthenticator::SaltBytes client_salt { 0x79, 0xf3, 0xbd, 0x81, 0x15, 0xbf, 0x0e, 0xe9, 0x80, 0xfc, 0xa7, 0x8b, 0x7d, 0xd5, 0x4c, 0x65 }; const PINAuthenticator::SaltBytes server_salt { 0x64, 0x65, 0x03, 0xbd, 0x6d, 0xc0, 0xfc, 0x04, 0x3d, 0x6a, 0x91, 0xb2, 0xb6, 0x47, 0xe2, 0xc2 }; std::array client_hash { 0x0b, 0xae, 0x6c, 0x91, 0x70, 0xc3, 0x7d, 0x11, 0x1e, 0x33, 0x02, 0x76, 0x6f, 0x97, 0x18, 0x98, 0x39, 0xa8, 0xcb, 0x77 }; const std::uint32_t grid_seed = 0x3a0442e3u; PINAuthenticator pin_auth(grid_seed); EXPECT_TRUE(pin_auth.validate_pin(server_salt, client_salt, client_hash, pin)); } /* * Tests TOTP implementation using replayed protocol values * from a known good authentication session, with the PIN * having been generated by a third-party TOTP app */ TEST(PINAuthenticator, TOTPPin) { MockClock clock(1622781613); const std::string secret("JBSWY3DPEHPK3PXP"); const PINAuthenticator::SaltBytes client_salt { 0x0c, 0x9b, 0x72, 0xe5, 0x95, 0x83, 0x9a, 0xef, 0xc6, 0x70, 0x80, 0x46, 0x1c, 0x96, 0x9f, 0x3f }; const PINAuthenticator::SaltBytes server_salt { 0x76, 0x2b, 0x52, 0x2f, 0x4b, 0x21, 0xf8, 0xb9, 0x33, 0x21, 0xd8, 0x9b, 0xd5, 0x75, 0x77, 0xdb }; std::array client_hash{ 0x8d, 0xf8, 0x3c, 0x1f, 0x5f, 0x2d, 0xcc, 0x6d, 0xdd, 0xb9, 0xdc, 0x79, 0xea, 0x66, 0x88, 0xc9, 0x00, 0xba, 0xc6, 0x4c }; const std::uint32_t grid_seed = 0xddcfd808; PINAuthenticator auth(grid_seed); const auto pin = PINAuthenticator::generate_totp_pin(secret, 0, clock); ASSERT_EQ(pin, 598290) << "PINs did not match"; EXPECT_TRUE(auth.validate_pin(server_salt, client_salt, client_hash, pin)); }