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) + ) + }; +}