// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/ssl/ssl.h" namespace Service::SSL { // This is nn::ssl::sf::CertificateFormat enum class CertificateFormat : u32 { Pem = 1, Der = 2, }; // This is nn::ssl::sf::ContextOption enum class ContextOption : u32 { None = 0, CrlImportDateCheckEnable = 1, }; // This is nn::ssl::sf::SslVersion struct SslVersion { union { u32 raw{}; BitField<0, 1, u32> tls_auto; BitField<3, 1, u32> tls_v10; BitField<4, 1, u32> tls_v11; BitField<5, 1, u32> tls_v12; BitField<6, 1, u32> tls_v13; BitField<24, 7, u32> api_version; }; }; class ISslConnection final : public ServiceFramework { public: explicit ISslConnection(Core::System& system_, SslVersion version) : ServiceFramework{system_, "ISslConnection"}, ssl_version{version} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetSocketDescriptor"}, {1, nullptr, "SetHostName"}, {2, nullptr, "SetVerifyOption"}, {3, nullptr, "SetIoMode"}, {4, nullptr, "GetSocketDescriptor"}, {5, nullptr, "GetHostName"}, {6, nullptr, "GetVerifyOption"}, {7, nullptr, "GetIoMode"}, {8, nullptr, "DoHandshake"}, {9, nullptr, "DoHandshakeGetServerCert"}, {10, nullptr, "Read"}, {11, nullptr, "Write"}, {12, nullptr, "Pending"}, {13, nullptr, "Peek"}, {14, nullptr, "Poll"}, {15, nullptr, "GetVerifyCertError"}, {16, nullptr, "GetNeededServerCertBufferSize"}, {17, nullptr, "SetSessionCacheMode"}, {18, nullptr, "GetSessionCacheMode"}, {19, nullptr, "FlushSessionCache"}, {20, nullptr, "SetRenegotiationMode"}, {21, nullptr, "GetRenegotiationMode"}, {22, nullptr, "SetOption"}, {23, nullptr, "GetOption"}, {24, nullptr, "GetVerifyCertErrors"}, {25, nullptr, "GetCipherInfo"}, {26, nullptr, "SetNextAlpnProto"}, {27, nullptr, "GetNextAlpnProto"}, {28, nullptr, "SetDtlsSocketDescriptor"}, {29, nullptr, "GetDtlsHandshakeTimeout"}, {30, nullptr, "SetPrivateOption"}, {31, nullptr, "SetSrtpCiphers"}, {32, nullptr, "GetSrtpCipher"}, {33, nullptr, "ExportKeyingMaterial"}, {34, nullptr, "SetIoTimeout"}, {35, nullptr, "GetIoTimeout"}, }; // clang-format on RegisterHandlers(functions); } private: SslVersion ssl_version; }; class ISslContext final : public ServiceFramework { public: explicit ISslContext(Core::System& system_, SslVersion version) : ServiceFramework{system_, "ISslContext"}, ssl_version{version} { static const FunctionInfo functions[] = { {0, &ISslContext::SetOption, "SetOption"}, {1, nullptr, "GetOption"}, {2, &ISslContext::CreateConnection, "CreateConnection"}, {3, nullptr, "GetConnectionCount"}, {4, &ISslContext::ImportServerPki, "ImportServerPki"}, {5, &ISslContext::ImportClientPki, "ImportClientPki"}, {6, nullptr, "RemoveServerPki"}, {7, nullptr, "RemoveClientPki"}, {8, nullptr, "RegisterInternalPki"}, {9, nullptr, "AddPolicyOid"}, {10, nullptr, "ImportCrl"}, {11, nullptr, "RemoveCrl"}, {12, nullptr, "ImportClientCertKeyPki"}, {13, nullptr, "GeneratePrivateKeyAndCert"}, }; RegisterHandlers(functions); } private: SslVersion ssl_version; void SetOption(HLERequestContext& ctx) { struct Parameters { ContextOption option; s32 value; }; static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); IPC::RequestParser rp{ctx}; const auto parameters = rp.PopRaw(); LOG_WARNING(Service_SSL, "(STUBBED) called. option={}, value={}", parameters.option, parameters.value); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void CreateConnection(HLERequestContext& ctx) { LOG_WARNING(Service_SSL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface(system, ssl_version); } void ImportServerPki(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto certificate_format = rp.PopEnum(); [[maybe_unused]] const auto pkcs_12_certificates = ctx.ReadBuffer(0); constexpr u64 server_id = 0; LOG_WARNING(Service_SSL, "(STUBBED) called, certificate_format={}", certificate_format); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(server_id); } void ImportClientPki(HLERequestContext& ctx) { [[maybe_unused]] const auto pkcs_12_certificate = ctx.ReadBuffer(0); [[maybe_unused]] const auto ascii_password = [&ctx] { if (ctx.CanReadBuffer(1)) { return ctx.ReadBuffer(1); } return std::span{}; }(); constexpr u64 client_id = 0; LOG_WARNING(Service_SSL, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(client_id); } }; class ISslService final : public ServiceFramework { public: explicit ISslService(Core::System& system_) : ServiceFramework{system_, "ssl"} { // clang-format off static const FunctionInfo functions[] = { {0, &ISslService::CreateContext, "CreateContext"}, {1, nullptr, "GetContextCount"}, {2, nullptr, "GetCertificates"}, {3, nullptr, "GetCertificateBufSize"}, {4, nullptr, "DebugIoctl"}, {5, &ISslService::SetInterfaceVersion, "SetInterfaceVersion"}, {6, nullptr, "FlushSessionCache"}, {7, nullptr, "SetDebugOption"}, {8, nullptr, "GetDebugOption"}, {8, nullptr, "ClearTls12FallbackFlag"}, }; // clang-format on RegisterHandlers(functions); } private: void CreateContext(HLERequestContext& ctx) { struct Parameters { SslVersion ssl_version; INSERT_PADDING_BYTES(0x4); u64 pid_placeholder; }; static_assert(sizeof(Parameters) == 0x10, "Parameters is an invalid size"); IPC::RequestParser rp{ctx}; const auto parameters = rp.PopRaw(); LOG_WARNING(Service_SSL, "(STUBBED) called, api_version={}, pid_placeholder={}", parameters.ssl_version.api_version, parameters.pid_placeholder); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface(system, parameters.ssl_version); } void SetInterfaceVersion(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u32 ssl_version = rp.Pop(); LOG_DEBUG(Service_SSL, "called, ssl_version={}", ssl_version); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } }; void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); server_manager->RegisterNamedService("ssl", std::make_shared(system)); ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::SSL