citra-emu
/
citra-canary
Archived
1
0
Fork 0

Implement PS:GetRandomBytes and use openssl for random bytes (#7164)

This commit is contained in:
PabloMK7 2023-11-15 01:15:50 +01:00 committed by GitHub
parent e9936e01c2
commit de40153fa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 32 deletions

View File

@ -9,6 +9,7 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/ps/ps_ps.h"
#include "core/hle/service/ssl/ssl_c.h"
#include "core/hw/aes/arithmetic128.h"
#include "core/hw/aes/key.h"
@ -146,6 +147,20 @@ void PS_PS::EncryptDecryptAes(Kernel::HLERequestContext& ctx) {
rb.PushMappedBuffer(destination);
}
void PS_PS::GenerateRandomBytes(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 size = rp.Pop<u32>();
auto buffer = rp.PopMappedBuffer();
std::vector<u8> out_data(size);
SSL::GenerateRandomData(out_data);
buffer.Write(out_data.data(), 0, size);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS);
rb.PushMappedBuffer(buffer);
}
PS_PS::PS_PS() : ServiceFramework("ps:ps", DefaultMaxSessions) {
static const FunctionInfo functions[] = {
// clang-format off
@ -160,7 +175,7 @@ PS_PS::PS_PS() : ServiceFramework("ps:ps", DefaultMaxSessions) {
{0x000A, nullptr, "GetLocalFriendCodeSeed"},
{0x000B, nullptr, "GetDeviceId"},
{0x000C, nullptr, "SeedRNG"},
{0x000D, nullptr, "GenerateRandomBytes"},
{0x000D, &PS_PS::GenerateRandomBytes, "GenerateRandomBytes"},
{0x000E, nullptr, "InterfaceForPXI_0x04010084"},
{0x000F, nullptr, "InterfaceForPXI_0x04020082"},
{0x0010, nullptr, "InterfaceForPXI_0x04030044"},

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <openssl/rand.h>
#include "common/archives.h"
#include "common/common_types.h"
#include "core/core.h"
@ -16,10 +17,6 @@ void SSL_C::Initialize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
rp.PopPID();
// Seed random number generator when the SSL service is initialized
std::random_device rand_device;
rand_gen.seed(rand_device());
// Stub, return success
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
@ -27,33 +24,13 @@ void SSL_C::Initialize(Kernel::HLERequestContext& ctx) {
void SSL_C::GenerateRandomData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 size = rp.Pop<u32>();
const u32 size = rp.Pop<u32>();
auto buffer = rp.PopMappedBuffer();
// Fill the output buffer with random data.
u32 data = 0;
u32 i = 0;
while (i < size) {
if ((i % 4) == 0) {
// The random number generator returns 4 bytes worth of data, so generate new random
// data when i == 0 and when i is divisible by 4
data = rand_gen();
}
std::vector<u8> out_data(size);
SSL::GenerateRandomData(out_data);
buffer.Write(out_data.data(), 0, size);
if (size > 4) {
// Use up the entire 4 bytes of the random data for as long as possible
buffer.Write(&data, i, 4);
i += 4;
} else if (size == 2) {
buffer.Write(&data, i, 2);
i += 2;
} else {
buffer.Write(&data, i, 1);
i++;
}
}
// Stub, return success
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS);
rb.PushMappedBuffer(buffer);
@ -96,4 +73,9 @@ void InstallInterfaces(Core::System& system) {
std::make_shared<SSL_C>()->InstallAsService(service_manager);
}
void GenerateRandomData(std::vector<u8>& out) {
// Fill the output buffer with random data.
RAND_bytes(out.data(), static_cast<int>(out.size()));
}
} // namespace Service::SSL

View File

@ -21,14 +21,13 @@ private:
void Initialize(Kernel::HLERequestContext& ctx);
void GenerateRandomData(Kernel::HLERequestContext& ctx);
// TODO: Implement a proper CSPRNG in the future when actual security is needed
std::mt19937 rand_gen;
SERVICE_SERIALIZATION_SIMPLE
};
void InstallInterfaces(Core::System& system);
void GenerateRandomData(std::vector<u8>& out);
} // namespace Service::SSL
BOOST_CLASS_EXPORT_KEY(Service::SSL::SSL_C)