csrng service implementation

Implements the 'csrng:' service using C++ <random>'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.
This commit is contained in:
sspacelynx 2021-08-16 10:10:07 +02:00 committed by ◱ Mark
parent 9d4aee57a5
commit 10d43c88c9
6 changed files with 62 additions and 1 deletions

View File

@ -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

View File

@ -22,6 +22,7 @@
#include <memory>
#include <compare>
#include <variant>
#include <random>
#include <sys/mman.h>
#include <fmt/format.h>
#include <frozen/unordered_map.h>
@ -338,6 +339,21 @@ namespace skyline {
constexpr std::size_t Hash(std::string_view view) {
return frz::elsa<frz::string>{}(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<typename T> requires (std::is_integral_v<T>)
void FillRandomBytes(std::span<T> in) {
std::independent_bits_engine<std::mt19937_64, std::numeric_limits<T>::digits, T> gen(detail::generator);
std::generate(in.begin(), in.end(), gen);
}
}
/**

View File

@ -1,4 +1,3 @@
#include <random>
#include "uuid.h"
namespace skyline {

View File

@ -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")

View File

@ -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 <common.h>
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 {};
}
}

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <services/base_service.h>
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)
)
};
}