From 10d43c88c97cc2433db71fd841a852725f7bf7af Mon Sep 17 00:00:00 2001 From: sspacelynx <37104290+sspacelynx@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:10:07 +0200 Subject: [PATCH] csrng service implementation Implements the 'csrng:' service using C++ 's Mersenne Twister, this does make it insecure for cryptographic purposes but it is pointless to attempt to do this regardless as we cannot ensure that the guest will run in a secure environment which cannot be mutated by an attacker. Used by Prison Princess, Pokemon Cafe Mix, Paint your Pet and more. --- app/CMakeLists.txt | 1 + app/src/main/cpp/skyline/common.h | 16 ++++++++++++ app/src/main/cpp/skyline/common/uuid.cpp | 1 - .../main/cpp/skyline/services/serviceman.cpp | 2 ++ .../skyline/services/spl/IRandomInterface.cpp | 17 ++++++++++++ .../skyline/services/spl/IRandomInterface.h | 26 +++++++++++++++++++ 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 app/src/main/cpp/skyline/services/spl/IRandomInterface.cpp create mode 100644 app/src/main/cpp/skyline/services/spl/IRandomInterface.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 8ec46660..837f7a31 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -217,6 +217,7 @@ add_library(skyline SHARED ${source_DIR}/skyline/services/nifm/IGeneralService.cpp ${source_DIR}/skyline/services/nifm/IRequest.cpp ${source_DIR}/skyline/services/socket/bsd/IClient.cpp + ${source_DIR}/skyline/services/spl/IRandomInterface.cpp ${source_DIR}/skyline/services/ssl/ISslService.cpp ${source_DIR}/skyline/services/ssl/ISslContext.cpp ${source_DIR}/skyline/services/prepo/IPrepoService.cpp diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index 61a63da7..359de46c 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -338,6 +339,21 @@ namespace skyline { constexpr std::size_t Hash(std::string_view view) { return frz::elsa{}(frz::string(view.data(), view.size()), 0); } + + namespace detail { + static thread_local std::mt19937_64 generator{GetTimeTicks()}; + } + + /** + * @brief Fills an array with random data from a Mersenne Twister pseudo-random generator + * @note The generator is seeded with the the current time in ticks + */ + template requires (std::is_integral_v) + void FillRandomBytes(std::span in) { + std::independent_bits_engine::digits, T> gen(detail::generator); + + std::generate(in.begin(), in.end(), gen); + } } /** diff --git a/app/src/main/cpp/skyline/common/uuid.cpp b/app/src/main/cpp/skyline/common/uuid.cpp index 4cc2ca79..6006578a 100644 --- a/app/src/main/cpp/skyline/common/uuid.cpp +++ b/app/src/main/cpp/skyline/common/uuid.cpp @@ -1,4 +1,3 @@ -#include #include "uuid.h" namespace skyline { diff --git a/app/src/main/cpp/skyline/services/serviceman.cpp b/app/src/main/cpp/skyline/services/serviceman.cpp index e86e436f..3b63eef5 100644 --- a/app/src/main/cpp/skyline/services/serviceman.cpp +++ b/app/src/main/cpp/skyline/services/serviceman.cpp @@ -32,6 +32,7 @@ #include "nfp/IUserManager.h" #include "nifm/IStaticService.h" #include "socket/bsd/IClient.h" +#include "spl/IRandomInterface.h" #include "ssl/ISslService.h" #include "prepo/IPrepoService.h" #include "mmnv/IRequest.h" @@ -95,6 +96,7 @@ namespace skyline::service { SERVICE_CASE(nfp::IUserManager, "nfp:user") SERVICE_CASE(nifm::IStaticService, "nifm:u") SERVICE_CASE(socket::IClient, "bsd:u") + SERVICE_CASE(spl::IRandomInterface, "csrng") SERVICE_CASE(ssl::ISslService, "ssl") SERVICE_CASE(prepo::IPrepoService, "prepo:u") SERVICE_CASE(mmnv::IRequest, "mm:u") diff --git a/app/src/main/cpp/skyline/services/spl/IRandomInterface.cpp b/app/src/main/cpp/skyline/services/spl/IRandomInterface.cpp new file mode 100644 index 00000000..e23bbab4 --- /dev/null +++ b/app/src/main/cpp/skyline/services/spl/IRandomInterface.cpp @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include "IRandomInterface.h" + +#include + +namespace skyline::service::spl { + IRandomInterface::IRandomInterface(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {} + + Result IRandomInterface::GetRandomBytes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto &outBuf{request.outputBuf.at(0)}; + + util::FillRandomBytes(outBuf); + return {}; + } +} diff --git a/app/src/main/cpp/skyline/services/spl/IRandomInterface.h b/app/src/main/cpp/skyline/services/spl/IRandomInterface.h new file mode 100644 index 00000000..ee0131e3 --- /dev/null +++ b/app/src/main/cpp/skyline/services/spl/IRandomInterface.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include + +namespace skyline::service::spl { + /** + * @brief csrng provides cryptographically secure random number generation + * @url https://switchbrew.org/wiki/SPL_services#csrng + */ + class IRandomInterface : public BaseService { + public: + IRandomInterface(const DeviceState &state, ServiceManager &manager); + + /** + * @brief Fills an output buffer with random bytes + */ + Result GetRandomBytes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + SERVICE_DECL( + SFUNC(0x0, IRandomInterface, GetRandomBytes) + ) + }; +}