diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 67e37e0823..406c65b2ca 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -41,6 +41,8 @@ enum class IoMode : u32 { enum class OptionType : u32 { DoNotCloseSocket = 0, GetServerCertChain = 1, + SkipDefaultVerify = 2, + EnableAlpn = 3, }; // This is nn::ssl::sf::SslVersion @@ -61,6 +63,12 @@ struct SslContextSharedData { u32 connection_count = 0; }; +struct Parameters { + ContextOption option; + s32 value; +}; +static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); + class ISslConnection final : public ServiceFramework { public: explicit ISslConnection(Core::System& system_in, SslVersion ssl_version_in, @@ -96,8 +104,8 @@ public: {23, nullptr, "GetOption"}, {24, nullptr, "GetVerifyCertErrors"}, {25, nullptr, "GetCipherInfo"}, - {26, nullptr, "SetNextAlpnProto"}, - {27, nullptr, "GetNextAlpnProto"}, + {26, &ISslConnection::SetNextAlpnProto, "SetNextAlpnProto"}, + {27, &ISslConnection::GetNextAlpnProto, "GetNextAlpnProto"}, {28, nullptr, "SetDtlsSocketDescriptor"}, {29, nullptr, "GetDtlsHandshakeTimeout"}, {30, nullptr, "SetPrivateOption"}, @@ -140,7 +148,10 @@ private: std::optional fd_to_close; bool do_not_close_socket = false; bool get_server_cert_chain = false; + bool skip_default_verify = false; + bool enable_alpn = false; std::shared_ptr socket; + std::vector next_alpn_proto; bool did_handshake = false; Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { @@ -381,6 +392,12 @@ private: case OptionType::GetServerCertChain: get_server_cert_chain = static_cast(parameters.value); break; + case OptionType::SkipDefaultVerify: + skip_default_verify = static_cast(parameters.value); + break; + case OptionType::EnableAlpn: + enable_alpn = static_cast(parameters.value); + break; default: LOG_WARNING(Service_SSL, "Unknown option={}, value={}", parameters.option, parameters.value); @@ -389,6 +406,31 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } + + void SetNextAlpnProto(HLERequestContext& ctx) { + const auto data = ctx.ReadBuffer(0); + next_alpn_proto.assign(data.begin(), data.end()); + + LOG_DEBUG(Service_SSL, "SetNextAlpnProto called, size={}", next_alpn_proto.size()); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void GetNextAlpnProto(HLERequestContext& ctx) { + const size_t writable = ctx.GetWriteBufferSize(); + const size_t to_write = std::min(next_alpn_proto.size(), writable); + + if (to_write != 0) { + ctx.WriteBuffer(std::span(next_alpn_proto.data(), to_write)); + } + + LOG_DEBUG(Service_SSL, "GetNextAlpnProto called, size={}", to_write); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast(to_write)); + } }; class ISslContext final : public ServiceFramework { @@ -398,7 +440,7 @@ public: shared_data{std::make_shared()} { static const FunctionInfo functions[] = { {0, &ISslContext::SetOption, "SetOption"}, - {1, nullptr, "GetOption"}, + {1, &ISslContext::GetOption, "GetOption"}, {2, &ISslContext::CreateConnection, "CreateConnection"}, {3, &ISslContext::GetConnectionCount, "GetConnectionCount"}, {4, &ISslContext::ImportServerPki, "ImportServerPki"}, @@ -420,17 +462,18 @@ private: std::shared_ptr shared_data; 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(); + 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 GetOption(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto parameters = rp.PopRaw(); + + LOG_WARNING(Service_SSL, "(STUBBED) called. option={}", parameters); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess);