Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
2832-Rewrite-set_ktls-for-better-error-checking...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2832-Rewrite-set_ktls-for-better-error-checking.patch of Package erlang
From c46bb39a02f6e4032199d00867022488cf919903 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen <raimo@erlang.org> Date: Thu, 11 Aug 2022 20:58:26 +0200 Subject: [PATCH 02/11] Rewrite set_ktls for better error checking --- lib/ssl/src/inet_tls_dist.erl | 249 ++++++++++++++++++++++---------- lib/ssl/test/ssl_dist_SUITE.erl | 63 ++++---- 2 files changed, 199 insertions(+), 113 deletions(-) diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 89db0bab11..638eca2339 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -330,37 +330,23 @@ accept_one(Driver, Kernel, Socket) -> net_kernel:connecttime()) of {ok, #sslsocket{pid = [Receiver, Sender| _]} = SslSocket} -> - DistCtrl = case KTLS of + case KTLS of true -> {ok, KtlsInfo} = ssl_gen_statem:ktls_handover(Receiver), - set_ktls(KtlsInfo), - Socket; - false -> - Sender - end, - trace( - Kernel ! - {accept, self(), DistCtrl, - Driver:family(), tls}), - receive - {Kernel, controller, Pid} -> - ChangeOwner = case KTLS of - true -> - inet_tcp:controlling_process(Socket, Pid); - false -> - ssl:controlling_process(SslSocket, Pid) - end, - case ChangeOwner of + case set_ktls(KtlsInfo) of ok -> - trace(Pid ! {self(), controller}); - Error -> - trace(Pid ! {self(), exit}), + accept_one( + Driver, Kernel, Socket, KTLS, Socket); + {error, KtlsReason} -> ?LOG_ERROR( - "Cannot control TLS distribution connection: ~p~n", - [Error]) + [{slogan, set_ktls_failed}, + {reason, KtlsReason}, + {pid, self()}]), + gen_tcp:close(Socket), + trace({ktls_error, KtlsReason}) end; - {Kernel, unsupported_protocol} -> - trace(unsupported_protocol) + false -> + accept_one(Driver, Kernel, SslSocket, KTLS, Sender) end; {error, {options, _}} = Error -> %% Bad options: that's probably our fault. @@ -374,6 +360,31 @@ accept_one(Driver, Kernel, Socket) -> gen_tcp:close(Socket), trace(Other) end. +%% +accept_one(Driver, Kernel, DistSocket, KTLS, DistCtrl) -> + trace(Kernel ! {accept, self(), DistCtrl, Driver:family(), tls}), + receive + {Kernel, controller, Pid} -> + case + case KTLS of + true -> + inet_tcp:controlling_process(DistSocket, Pid); + false -> + ssl:controlling_process(DistSocket, Pid) + end + of + ok -> + trace(Pid ! {self(), controller}); + {error, Reason} -> + trace(Pid ! {self(), exit}), + ?LOG_ERROR( + [{slogan, controlling_process_failed}, + {reason, Reason}, + {pid, self()}]) + end; + {Kernel, unsupported_protocol} -> + trace(unsupported_protocol) + end. %% {verify_fun,{fun ?MODULE:verify_client/3,_}} is used @@ -655,27 +666,36 @@ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNo net_kernel:connecttime() ) of {ok, #sslsocket{pid = [Receiver, Sender| _]} = SslSocket} -> - HSData0 = case KTLS of - true -> - {ok, KtlsInfo} = ssl_gen_statem:ktls_handover(Receiver), - set_ktls(KtlsInfo), - #{socket := Socket} = KtlsInfo, - hs_data_common(Socket); - false -> - _ = monitor_pid(Sender), - ok = ssl:controlling_process(SslSocket, self()), - link(Sender), - hs_data_common(SslSocket) - end, + DistSocket = + case KTLS of + true -> + {ok, KtlsInfo} = + ssl_gen_statem:ktls_handover(Receiver), + case set_ktls(KtlsInfo) of + ok -> + #{socket := Socket} = KtlsInfo, + Socket; + {error, KtlsReason} -> + ?shutdown2( + Node, + trace({set_ktls_falied, KtlsReason})) + end; + false -> + _ = monitor_pid(Sender), + ok = ssl:controlling_process(SslSocket, self()), + link(Sender), + SslSocket + end, HSData = - HSData0#hs_data{ - kernel_pid = Kernel, - other_node = Node, - this_node = MyNode, - timer = Timer, - this_flags = 0, - other_version = Version, - request_type = Type}, + (hs_data_common(DistSocket)) + #hs_data{ + kernel_pid = Kernel, + other_node = Node, + this_node = MyNode, + timer = Timer, + this_flags = 0, + other_version = Version, + request_type = Type}, dist_util:handshake_we_started(trace(HSData)); Other -> %% Other Node may have closed since @@ -972,38 +992,111 @@ verify_fun(Value) -> error(malformed_ssl_dist_opt, [Value]) end. -set_ktls(#{ - socket := Socket, - tls_version := {3, 4}, - cipher_suite := ?TLS_AES_256_GCM_SHA384, - socket_options := #socket_options{ - mode = _Mode, - packet = Packet, - packet_size = PacketSize, - header = Header, - active = Active - }, - write_state := #cipher_state{ - iv = <<WriteSalt:4/bytes, WriteIV:8/bytes>>, key = WriteKey - }, - write_seq := WriteSeq, - read_state := #cipher_state{ - iv = <<ReadSalt:4/bytes, ReadIV:8/bytes>>, key = ReadKey - }, - read_seq := ReadSeq -}) -> - % SOL_TCP = 6, TCP_ULP = 31 - inet:setopts(Socket, [{raw, 6, 31, <<"tls">>}]), - % SOL_TLS = 282, TLS_TX = 1, TLS_RX = 2, TLS_1_3_VERSION = <<4, 3>>, TLS_CIPHER_AES_GCM_256 = <<52, 0>> - inet:setopts(Socket, [ - {raw, 282, 1, <<4, 3, 52, 0, WriteIV/binary, WriteKey/binary, WriteSalt/binary, WriteSeq:64>>} - ]), - inet:setopts(Socket, [ - {raw, 282, 2, <<4, 3, 52, 0, ReadIV/binary, ReadKey/binary, ReadSalt/binary, ReadSeq:64>>} - ]), - inet:setopts(Socket, [ - list, {packet, Packet}, {packet_size, PacketSize}, {header, Header}, {active, Active} - ]). +set_ktls(#{socket := Socket} = KtlsInfo) -> + %% Check OS support + case {os:type(), os:version()} of + {{unix,linux}, {Major,Minor,_}} + when 5 == Major, 2 =< Minor; + 5 < Major -> + set_ktls(KtlsInfo, Socket); + OsTypeVersion -> + {error, {ktls_invalid_os, OsTypeVersion}} + end. +%% +%% Check TLS version and cipher suite +set_ktls( + #{tls_version := {3,4}, % 'tlsv1.3' + cipher_suite := CipherSuite} = KtlsInfo, + Socket) + when CipherSuite =:= ?TLS_AES_256_GCM_SHA384 -> + %% + %% See include/netinet/tcp.h + %% + SOL_TCP = 6, + TCP_ULP = 31, + _ = inet:setopts(Socket, [{raw, SOL_TCP, TCP_ULP, <<"tls">>}]), + set_ktls( + KtlsInfo, Socket, + inet:getopts(Socket, [{raw, SOL_TCP, TCP_ULP, 4}]), + {raw, SOL_TCP, TCP_ULP, <<"tls",0>>}); +set_ktls( + #{tls_version := TLSVersion, cipher_suite := CipherSuite}, + _Socket) -> + {error, {ktls_invalid_cipher, TLSVersion, CipherSuite}}. +%% +%% Check if kernel module loaded, +%% i.e if getopts SOL_TCP,TCP_ULP returned "tls" +set_ktls( + KtlsInfo, Socket, + {ok, [ULP]}, + ULP) -> + #{write_state := + #cipher_state{ + key = <<WriteKey:32/bytes>>, + iv = <<WriteSalt:4/bytes, WriteIV:8/bytes>> + }, + write_seq := WriteSeq, + read_state := + #cipher_state{ + key = <<ReadKey:32/bytes>>, + iv = <<ReadSalt:4/bytes, ReadIV:8/bytes>> + }, + read_seq := ReadSeq, + socket_options := SocketOptions} = KtlsInfo, + %% + %% See include/linux/tls.h + %% + TLS_1_3_VERSION_MAJOR = 3, + TLS_1_3_VERSION_MINOR = 4, + TLS_1_3_VERSION = + (TLS_1_3_VERSION_MAJOR bsl 8) bor TLS_1_3_VERSION_MINOR, + TLS_CIPHER_AES_GCM_256 = 52, + TLS_crypto_info_TX = + <<TLS_1_3_VERSION:16/native, + TLS_CIPHER_AES_GCM_256:16/native, + WriteIV/bytes, WriteKey/bytes, + WriteSalt/bytes, WriteSeq:64/native>>, + TLS_crypto_info_RX = + <<TLS_1_3_VERSION:16/native, + TLS_CIPHER_AES_GCM_256:16/native, + ReadIV/bytes, ReadKey/bytes, + ReadSalt/bytes, ReadSeq:64/native>>, + SOL_TLS = 282, + TLS_TX = 1, + TLS_RX = 2, + RawOptTX = {raw, SOL_TLS, TLS_TX, TLS_crypto_info_TX}, + RawOptRX = {raw, SOL_TLS, TLS_RX, TLS_crypto_info_RX}, + _ = inet:setopts(Socket, [RawOptTX]), + _ = inet:setopts(Socket, [RawOptRX]), + %% + %% Check if cipher could be set + case + inet:getopts( + Socket, [{raw, SOL_TLS, TLS_TX, byte_size(TLS_crypto_info_TX)}]) + of + {ok, [RawOptTX]} -> + #socket_options{ + mode = _Mode, + packet = Packet, + packet_size = PacketSize, + header = Header, + active = Active + } = SocketOptions, + case + inet:setopts( + Socket, + [list, {packet, Packet}, {packet_size, PacketSize}, + {header, Header}, {active, Active}]) + of + ok -> ok; + {error, SetoptError} -> + {error, {ktls_setopt_failed, SetoptError}} + end; + Other -> + {error, {ktls_set_cipher_failed, Other}} + end; +set_ktls(_KtlsInfo, _Socket, BadGetoptULP, _ULP) -> + {error, {ktls_not_supported, BadGetoptULP}}. %% ------------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 767f37d875..b7abc3afad 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -158,41 +158,34 @@ init_per_testcase(plain_verify_options = Case, Config) when is_list(Config) -> common_init(Case, [{old_flags, Flags} | Config]); init_per_testcase(ktls_basic = Case, Config) when is_list(Config) -> - try - {ok, Listen} = gen_tcp:listen(0, [{active, false}]), - {ok, Port} = inet:port(Listen), - {ok, Client} = gen_tcp:connect("localhost", Port, [{active, false}]), - {ok, Server} = gen_tcp:accept(Listen), - ServerTx = <<4,3,52,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,0,0,0,0,0,0,0,0>>, - ServerRx = <<4,3,52,0,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,0,0,0,0,0,0,0,0>>, - ClientTx = ServerRx, - ClientRx = ServerTx, - inet:setopts(Server, [{raw, 6, 31, <<"tls">>}]), - inet:setopts(Server, [{raw, 282, 1, ServerTx}]), - inet:setopts(Server, [{raw, 282, 2, ServerRx}]), - inet:setopts(Client, [{raw, 6, 31, <<"tls">>}]), - inet:setopts(Client, [{raw, 282, 1, ClientTx}]), - inet:setopts(Client, [{raw, 282, 2, ClientRx}]), - {ok, [{raw, 6, 31, <<"tls">>}]} = inet:getopts(Server, [{raw, 6, 31, 3}]), - {ok, [{raw, 282, 1, ServerTx}]} = inet:getopts(Server, [{raw, 282, 1, 56}]), - {ok, [{raw, 6, 31, <<"tls">>}]} = inet:getopts(Client, [{raw, 6, 31, 3}]), - {ok, [{raw, 282, 1, ClientTx}]} = inet:getopts(Client, [{raw, 282, 1, 56}]), - ok = gen_tcp:send(Client, "client"), - {ok, "client"} = gen_tcp:recv(Server, 6, 1000), - ok = gen_tcp:send(Server, "server"), - {ok, "server"} = gen_tcp:recv(Client, 6, 1000), - gen_tcp:close(Server), - gen_tcp:close(Client), - gen_tcp:close(Listen), - common_init(Case, Config) - catch - Class:Reason:Stacktrace -> - {skip, lists:flatten(io_lib:format( - "ktls not supported, ~p:~p:~0p", - [Class, Reason, Stacktrace] - ))} + case {os:type(), os:version()} of + {{unix,linux}, {Major,Minor,_}} + when 5 == Major, 2 =< Minor; + 5 < Major -> + {ok, Listen} = gen_tcp:listen(0, [{active, false}]), + {ok, Port} = inet:port(Listen), + {ok, Client} = + gen_tcp:connect({127,0,0,1}, Port, [{active, false}]), + {ok, Server} = gen_tcp:accept(Listen), + %% + _ = inet:setopts(Server, [{raw, 6, 31, <<"tls">>}]), + Result = inet:getopts(Server, [{raw, 6, 31, 4}]), + %% + _ = gen_tcp:close(Server), + _ = gen_tcp:close(Client), + _ = gen_tcp:close(Listen), + case Result of + {ok, [{raw, 6, 31, <<"tls",0>>}]} -> + common_init(Case, Config); + Other -> + {skip, + lists:flatten( + io_lib:format("kTLS not supported, ~p", [Other]))} + end; + OS -> + {skip, + lists:flatten( + io_lib:format("kTLS not supported by OS: ~p", [OS]))} end; init_per_testcase(Case, Config) when is_list(Config) -> -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor