emberemu/tests/PINAuthenticator.cpp

95 lines
No EOL
2.9 KiB
C++

/*
* 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 <gtest/gtest.h>
#include <login/PINAuthenticator.h>
#include <shared/utility/Clock.h>
#include <shared/utility/HashDefines.h>
#include <array>
#include <chrono>
#include <memory>
#include <string>
#include <cstdint>
using namespace ember;
struct MockClock final : utility::ClockBase {
std::chrono::time_point<std::chrono::system_clock> 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<std::chrono::seconds>(time).time_since_epoch().count();
const auto time_s = std::chrono::seconds(curr_ts - timestamp);
timepoint = time - time_s;
}
virtual std::chrono::time_point<std::chrono::system_clock> 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<std::uint8_t, hash_sizes::sha160> 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<std::uint8_t, 20> 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));
}