From 7dd4e76c1d2d9c5d42275127758bf3511698fb0b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 16 Mar 2020 13:08:20 -0700 Subject: [PATCH] os: add rngmanager --- .../source/os/impl/os_resource_manager.hpp | 3 ++ .../source/os/impl/os_rng_manager.hpp | 25 ++++++++++++ .../source/os/impl/os_rng_manager_impl.cpp | 31 +++++++++++++++ .../source/os/impl/os_rng_manager_impl.hpp | 34 +++++++++++++++++ .../impl/os_rng_manager_impl.os.horizon.cpp | 38 +++++++++++++++++++ .../libstratosphere/source/os/os_random.cpp | 2 +- 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 libraries/libstratosphere/source/os/impl/os_rng_manager.hpp create mode 100644 libraries/libstratosphere/source/os/impl/os_rng_manager_impl.cpp create mode 100644 libraries/libstratosphere/source/os/impl/os_rng_manager_impl.hpp create mode 100644 libraries/libstratosphere/source/os/impl/os_rng_manager_impl.os.horizon.cpp diff --git a/libraries/libstratosphere/source/os/impl/os_resource_manager.hpp b/libraries/libstratosphere/source/os/impl/os_resource_manager.hpp index 4129a8846..61525e908 100644 --- a/libraries/libstratosphere/source/os/impl/os_resource_manager.hpp +++ b/libraries/libstratosphere/source/os/impl/os_resource_manager.hpp @@ -15,18 +15,21 @@ */ #pragma once #include +#include "os_rng_manager_impl.hpp" #include "os_tick_manager_impl.hpp" namespace ams::os::impl { class OsResourceManager { private: + RngManager rng_manager{}; /* TODO */ TickManager tick_manager{}; /* TODO */ public: constexpr OsResourceManager() = default; + constexpr ALWAYS_INLINE RngManager &GetRngManager() { return this->rng_manager; } constexpr ALWAYS_INLINE TickManager &GetTickManager() { return this->tick_manager; } }; diff --git a/libraries/libstratosphere/source/os/impl/os_rng_manager.hpp b/libraries/libstratosphere/source/os/impl/os_rng_manager.hpp new file mode 100644 index 000000000..7abc003f8 --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_rng_manager.hpp @@ -0,0 +1,25 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::os::impl { + + ALWAYS_INLINE RngManager &GetRngManager() { + return GetResourceManager().GetRngManager(); + } + +} diff --git a/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.cpp b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.cpp new file mode 100644 index 000000000..21edde42d --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.cpp @@ -0,0 +1,31 @@ +/* + * 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 . + */ +#include +#include "os_rng_manager_impl.hpp" + +namespace ams::os::impl { + + u64 RngManager::GenerateRandomU64() { + std::scoped_lock lk(this->lock); + + if (AMS_UNLIKELY(!this->initialized)) { + this->Initialize(); + } + + return this->mt.GenerateRandomU64(); + } + +} diff --git a/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.hpp b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.hpp new file mode 100644 index 000000000..25406633b --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.hpp @@ -0,0 +1,34 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::os::impl { + + class RngManager { + private: + util::TinyMT mt; + os::Mutex lock; + bool initialized; + private: + void Initialize(); + public: + constexpr RngManager() : mt(), lock(), initialized() { /* ... */ } + public: + u64 GenerateRandomU64(); + }; + +} diff --git a/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.os.horizon.cpp b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.os.horizon.cpp new file mode 100644 index 000000000..84a350c39 --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_rng_manager_impl.os.horizon.cpp @@ -0,0 +1,38 @@ +/* + * 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 . + */ +#include +#include "os_rng_manager_impl.hpp" + +namespace ams::os::impl { + + void RngManager::Initialize() { + /* Retrieve entropy from kernel. */ + u32 seed[4]; + static_assert(util::size(seed) == util::TinyMT::NumStateWords); + + /* Nintendo does not check the result of these invocations, but we will for safety. */ + /* Nintendo uses entropy values 0, 1 to seed the public TinyMT random, and values */ + /* 2, 3 to seed os::detail::RngManager's private TinyMT random. */ + R_ABORT_UNLESS(svcGetInfo(reinterpret_cast(&seed[0]), InfoType_RandomEntropy, INVALID_HANDLE, 2)); + R_ABORT_UNLESS(svcGetInfo(reinterpret_cast(&seed[2]), InfoType_RandomEntropy, INVALID_HANDLE, 3)); + + this->mt.Initialize(seed, util::size(seed)); + + /* Note that we've initialized. */ + this->initialized = true; + } + +} diff --git a/libraries/libstratosphere/source/os/os_random.cpp b/libraries/libstratosphere/source/os/os_random.cpp index 3498b14ae..cd3962d20 100644 --- a/libraries/libstratosphere/source/os/os_random.cpp +++ b/libraries/libstratosphere/source/os/os_random.cpp @@ -42,7 +42,7 @@ namespace ams::os { void GenerateRandomBytes(void *dst, size_t size) { std::scoped_lock lk(g_random_mutex); - if (!g_initialized_random) { + if (AMS_UNLIKELY(!g_initialized_random)) { impl::InitializeRandomImpl(&g_random); g_initialized_random = true; }