Implement PS:GetRandomBytes and use openssl for random bytes (#7164)
This commit is contained in:
		| @@ -9,6 +9,7 @@ | |||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/service/ps/ps_ps.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/arithmetic128.h" | ||||||
| #include "core/hw/aes/key.h" | #include "core/hw/aes/key.h" | ||||||
|  |  | ||||||
| @@ -146,6 +147,20 @@ void PS_PS::EncryptDecryptAes(Kernel::HLERequestContext& ctx) { | |||||||
|     rb.PushMappedBuffer(destination); |     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) { | PS_PS::PS_PS() : ServiceFramework("ps:ps", DefaultMaxSessions) { | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         // clang-format off |         // clang-format off | ||||||
| @@ -160,7 +175,7 @@ PS_PS::PS_PS() : ServiceFramework("ps:ps", DefaultMaxSessions) { | |||||||
|         {0x000A, nullptr, "GetLocalFriendCodeSeed"}, |         {0x000A, nullptr, "GetLocalFriendCodeSeed"}, | ||||||
|         {0x000B, nullptr, "GetDeviceId"}, |         {0x000B, nullptr, "GetDeviceId"}, | ||||||
|         {0x000C, nullptr, "SeedRNG"}, |         {0x000C, nullptr, "SeedRNG"}, | ||||||
|         {0x000D, nullptr, "GenerateRandomBytes"}, |         {0x000D, &PS_PS::GenerateRandomBytes, "GenerateRandomBytes"}, | ||||||
|         {0x000E, nullptr, "InterfaceForPXI_0x04010084"}, |         {0x000E, nullptr, "InterfaceForPXI_0x04010084"}, | ||||||
|         {0x000F, nullptr, "InterfaceForPXI_0x04020082"}, |         {0x000F, nullptr, "InterfaceForPXI_0x04020082"}, | ||||||
|         {0x0010, nullptr, "InterfaceForPXI_0x04030044"}, |         {0x0010, nullptr, "InterfaceForPXI_0x04030044"}, | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <openssl/rand.h> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| @@ -16,10 +17,6 @@ void SSL_C::Initialize(Kernel::HLERequestContext& ctx) { | |||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
|     rp.PopPID(); |     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 |     // Stub, return success | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
| @@ -27,33 +24,13 @@ void SSL_C::Initialize(Kernel::HLERequestContext& ctx) { | |||||||
|  |  | ||||||
| void SSL_C::GenerateRandomData(Kernel::HLERequestContext& ctx) { | void SSL_C::GenerateRandomData(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
|     u32 size = rp.Pop<u32>(); |     const u32 size = rp.Pop<u32>(); | ||||||
|     auto buffer = rp.PopMappedBuffer(); |     auto buffer = rp.PopMappedBuffer(); | ||||||
|  |  | ||||||
|     // Fill the output buffer with random data. |     std::vector<u8> out_data(size); | ||||||
|     u32 data = 0; |     SSL::GenerateRandomData(out_data); | ||||||
|     u32 i = 0; |     buffer.Write(out_data.data(), 0, size); | ||||||
|     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(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         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); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushMappedBuffer(buffer); |     rb.PushMappedBuffer(buffer); | ||||||
| @@ -96,4 +73,9 @@ void InstallInterfaces(Core::System& system) { | |||||||
|     std::make_shared<SSL_C>()->InstallAsService(service_manager); |     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 | } // namespace Service::SSL | ||||||
|   | |||||||
| @@ -21,14 +21,13 @@ private: | |||||||
|     void Initialize(Kernel::HLERequestContext& ctx); |     void Initialize(Kernel::HLERequestContext& ctx); | ||||||
|     void GenerateRandomData(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 |     SERVICE_SERIALIZATION_SIMPLE | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void InstallInterfaces(Core::System& system); | void InstallInterfaces(Core::System& system); | ||||||
|  |  | ||||||
|  | void GenerateRandomData(std::vector<u8>& out); | ||||||
|  |  | ||||||
| } // namespace Service::SSL | } // namespace Service::SSL | ||||||
|  |  | ||||||
| BOOST_CLASS_EXPORT_KEY(Service::SSL::SSL_C) | BOOST_CLASS_EXPORT_KEY(Service::SSL::SSL_C) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user