mirror of
https://github.com/EmberEmu/Ember
synced 2026-08-14 22:32:05 -04:00
95 lines
No EOL
2.9 KiB
C++
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));
|
|
} |