kern: use TinyMT instead of mt19937_t

This commit is contained in:
Michael Scire 2020-02-13 22:37:30 -08:00
parent 364b04b68a
commit ea0011d572
6 changed files with 418 additions and 206 deletions

View file

@ -24,9 +24,11 @@ namespace ams::kern {
bool g_call_smc_on_panic;
/* Global variables for randomness. */
/* Incredibly, N really does use std:: randomness... */
/* Nintendo uses std::mt19937_t for randomness. */
/* To save space (and because mt19337_t isn't secure anyway), */
/* We will use TinyMT. */
bool g_initialized_random_generator;
std::mt19937 g_random_generator;
util::TinyMT g_random_generator;
KSpinLock g_random_lock;
ALWAYS_INLINE size_t GetRealMemorySizeForInit() {
@ -73,6 +75,27 @@ namespace ams::kern {
return value;
}
ALWAYS_INLINE u64 GenerateRandomU64FromGenerator() {
return g_random_generator.GenerateRandomU64();
}
template<typename F>
ALWAYS_INLINE u64 GenerateUniformRange(u64 min, u64 max, F f) {
/* Handle the case where the difference is too large to represent. */
if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
return f();
}
/* Iterate until we get a value in range. */
const u64 range_size = ((max + 1) - min);
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
while (true) {
if (const u64 rnd = f(); rnd < effective_max) {
return min + (rnd % range_size);
}
}
}
ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) {
u64 value;
smc::GetConfig(&value, 1, which);
@ -168,13 +191,7 @@ namespace ams::kern {
}
u64 KSystemControl::Init::GenerateRandomRange(u64 min, u64 max) {
const u64 range_size = ((max + 1) - min);
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
while (true) {
if (const u64 rnd = GenerateRandomU64ForInit(); rnd < effective_max) {
return min + (rnd % range_size);
}
}
return GenerateUniformRange(min, max, GenerateRandomU64ForInit);
}
/* System Initialization. */
@ -250,11 +267,11 @@ namespace ams::kern {
if (AMS_UNLIKELY(!g_initialized_random_generator)) {
u64 seed;
GenerateRandomBytes(&seed, sizeof(seed));
g_random_generator.seed(seed);
g_random_generator.Initialize(reinterpret_cast<u32*>(&seed), sizeof(seed) / sizeof(u32));
g_initialized_random_generator = true;
}
return (std::uniform_int_distribution<u64>(min, max))(g_random_generator);
return GenerateUniformRange(min, max, GenerateRandomU64FromGenerator);
}
void KSystemControl::StopSystem() {

View file

@ -1,28 +0,0 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
void operator delete (void *deleted) throw() {
MESOSPHERE_PANIC("operator delete(void *) was called: %p", deleted);
}
void operator delete (void *deleted, size_t size) throw() {
MESOSPHERE_PANIC("operator delete(void *, size_t) was called: %p %zu", deleted, size);
}
void abort() {
MESOSPHERE_PANIC("abort() was called");
}