Skip to content

Commit a5962e0

Browse files
committed
Merge branch 'another-crack-at-a-handshake-upcall-mechanism'
Chuck Lever says: ==================== Another crack at a handshake upcall mechanism Here is v10 of a series to add generic support for transport layer security handshake on behalf of kernel socket consumers (user space consumers use a security library directly, of course). A summary of the purpose of these patches is archived here: https://lore.kernel.org/netdev/1DE06BB1-6BA9-4DB4-B2AA-07DE532963D6@oracle.com/ The first patch in the series applies to the top-level .gitignore file to address the build warnings reported a few days ago. I intend to submit that separately. I'd like you to consider taking the rest of this series for v6.4. The full patch set to support SunRPC with TLSv1.3 is available in the topic-rpc-with-tls-upcall branch here, based on net-next/main: https://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git This patch set includes support for in-transit confidentiality and peer authentication for both the Linux NFS client and server. A user space handshake agent for TLSv1.3 to go along with the kernel patches is available in the "main" branch here: https://github.com/oracle/ktls-utils ==================== Link: https://lore.kernel.org/r/168174169259.9520.1911007910797225963.stgit@91.116.238.104.host.secureserver.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents f1836a4 + 88232ec commit a5962e0

20 files changed

Lines changed: 2467 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ modules.order
105105
!.gitignore
106106
!.mailmap
107107
!.rustfmt.toml
108+
!.kunitconfig
108109

109110
#
110111
# Generated include files
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+
#
3+
# Author: Chuck Lever <chuck.lever@oracle.com>
4+
#
5+
# Copyright (c) 2023, Oracle and/or its affiliates.
6+
#
7+
8+
name: handshake
9+
10+
protocol: genetlink
11+
12+
doc: Netlink protocol to request a transport layer security handshake.
13+
14+
definitions:
15+
-
16+
type: enum
17+
name: handler-class
18+
value-start: 0
19+
entries: [ none, tlshd, max ]
20+
-
21+
type: enum
22+
name: msg-type
23+
value-start: 0
24+
entries: [ unspec, clienthello, serverhello ]
25+
-
26+
type: enum
27+
name: auth
28+
value-start: 0
29+
entries: [ unspec, unauth, psk, x509 ]
30+
31+
attribute-sets:
32+
-
33+
name: x509
34+
attributes:
35+
-
36+
name: cert
37+
type: u32
38+
-
39+
name: privkey
40+
type: u32
41+
-
42+
name: accept
43+
attributes:
44+
-
45+
name: sockfd
46+
type: u32
47+
-
48+
name: handler-class
49+
type: u32
50+
enum: handler-class
51+
-
52+
name: message-type
53+
type: u32
54+
enum: msg-type
55+
-
56+
name: timeout
57+
type: u32
58+
-
59+
name: auth-mode
60+
type: u32
61+
enum: auth
62+
-
63+
name: peer-identity
64+
type: u32
65+
multi-attr: true
66+
-
67+
name: certificate
68+
type: nest
69+
nested-attributes: x509
70+
multi-attr: true
71+
-
72+
name: done
73+
attributes:
74+
-
75+
name: status
76+
type: u32
77+
-
78+
name: sockfd
79+
type: u32
80+
-
81+
name: remote-auth
82+
type: u32
83+
multi-attr: true
84+
85+
operations:
86+
list:
87+
-
88+
name: ready
89+
doc: Notify handlers that a new handshake request is waiting
90+
notify: accept
91+
-
92+
name: accept
93+
doc: Handler retrieves next queued handshake request
94+
attribute-set: accept
95+
flags: [ admin-perm ]
96+
do:
97+
request:
98+
attributes:
99+
- handler-class
100+
reply:
101+
attributes:
102+
- sockfd
103+
- message-type
104+
- timeout
105+
- auth-mode
106+
- peer-identity
107+
- certificate
108+
-
109+
name: done
110+
doc: Handler reports handshake completion
111+
attribute-set: done
112+
do:
113+
request:
114+
attributes:
115+
- status
116+
- sockfd
117+
- remote-auth
118+
119+
mcast-groups:
120+
list:
121+
-
122+
name: none
123+
-
124+
name: tlshd

Documentation/networking/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Contents:
3636
scaling
3737
tls
3838
tls-offload
39+
tls-handshake
3940
nfc
4041
6lowpan
4142
6pack
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
=======================
4+
In-Kernel TLS Handshake
5+
=======================
6+
7+
Overview
8+
========
9+
10+
Transport Layer Security (TLS) is a Upper Layer Protocol (ULP) that runs
11+
over TCP. TLS provides end-to-end data integrity and confidentiality in
12+
addition to peer authentication.
13+
14+
The kernel's kTLS implementation handles the TLS record subprotocol, but
15+
does not handle the TLS handshake subprotocol which is used to establish
16+
a TLS session. Kernel consumers can use the API described here to
17+
request TLS session establishment.
18+
19+
There are several possible ways to provide a handshake service in the
20+
kernel. The API described here is designed to hide the details of those
21+
implementations so that in-kernel TLS consumers do not need to be
22+
aware of how the handshake gets done.
23+
24+
25+
User handshake agent
26+
====================
27+
28+
As of this writing, there is no TLS handshake implementation in the
29+
Linux kernel. To provide a handshake service, a handshake agent
30+
(typically in user space) is started in each network namespace where a
31+
kernel consumer might require a TLS handshake. Handshake agents listen
32+
for events sent from the kernel that indicate a handshake request is
33+
waiting.
34+
35+
An open socket is passed to a handshake agent via a netlink operation,
36+
which creates a socket descriptor in the agent's file descriptor table.
37+
If the handshake completes successfully, the handshake agent promotes
38+
the socket to use the TLS ULP and sets the session information using the
39+
SOL_TLS socket options. The handshake agent returns the socket to the
40+
kernel via a second netlink operation.
41+
42+
43+
Kernel Handshake API
44+
====================
45+
46+
A kernel TLS consumer initiates a client-side TLS handshake on an open
47+
socket by invoking one of the tls_client_hello() functions. First, it
48+
fills in a structure that contains the parameters of the request:
49+
50+
.. code-block:: c
51+
52+
struct tls_handshake_args {
53+
struct socket *ta_sock;
54+
tls_done_func_t ta_done;
55+
void *ta_data;
56+
unsigned int ta_timeout_ms;
57+
key_serial_t ta_keyring;
58+
key_serial_t ta_my_cert;
59+
key_serial_t ta_my_privkey;
60+
unsigned int ta_num_peerids;
61+
key_serial_t ta_my_peerids[5];
62+
};
63+
64+
The @ta_sock field references an open and connected socket. The consumer
65+
must hold a reference on the socket to prevent it from being destroyed
66+
while the handshake is in progress. The consumer must also have
67+
instantiated a struct file in sock->file.
68+
69+
70+
@ta_done contains a callback function that is invoked when the handshake
71+
has completed. Further explanation of this function is in the "Handshake
72+
Completion" sesction below.
73+
74+
The consumer can fill in the @ta_timeout_ms field to force the servicing
75+
handshake agent to exit after a number of milliseconds. This enables the
76+
socket to be fully closed once both the kernel and the handshake agent
77+
have closed their endpoints.
78+
79+
Authentication material such as x.509 certificates, private certificate
80+
keys, and pre-shared keys are provided to the handshake agent in keys
81+
that are instantiated by the consumer before making the handshake
82+
request. The consumer can provide a private keyring that is linked into
83+
the handshake agent's process keyring in the @ta_keyring field to prevent
84+
access of those keys by other subsystems.
85+
86+
To request an x.509-authenticated TLS session, the consumer fills in
87+
the @ta_my_cert and @ta_my_privkey fields with the serial numbers of
88+
keys containing an x.509 certificate and the private key for that
89+
certificate. Then, it invokes this function:
90+
91+
.. code-block:: c
92+
93+
ret = tls_client_hello_x509(args, gfp_flags);
94+
95+
The function returns zero when the handshake request is under way. A
96+
zero return guarantees the callback function @ta_done will be invoked
97+
for this socket. The function returns a negative errno if the handshake
98+
could not be started. A negative errno guarantees the callback function
99+
@ta_done will not be invoked on this socket.
100+
101+
102+
To initiate a client-side TLS handshake with a pre-shared key, use:
103+
104+
.. code-block:: c
105+
106+
ret = tls_client_hello_psk(args, gfp_flags);
107+
108+
However, in this case, the consumer fills in the @ta_my_peerids array
109+
with serial numbers of keys containing the peer identities it wishes
110+
to offer, and the @ta_num_peerids field with the number of array
111+
entries it has filled in. The other fields are filled in as above.
112+
113+
114+
To initiate an anonymous client-side TLS handshake use:
115+
116+
.. code-block:: c
117+
118+
ret = tls_client_hello_anon(args, gfp_flags);
119+
120+
The handshake agent presents no peer identity information to the remote
121+
during this type of handshake. Only server authentication (ie the client
122+
verifies the server's identity) is performed during the handshake. Thus
123+
the established session uses encryption only.
124+
125+
126+
Consumers that are in-kernel servers use:
127+
128+
.. code-block:: c
129+
130+
ret = tls_server_hello_x509(args, gfp_flags);
131+
132+
or
133+
134+
.. code-block:: c
135+
136+
ret = tls_server_hello_psk(args, gfp_flags);
137+
138+
The argument structure is filled in as above.
139+
140+
141+
If the consumer needs to cancel the handshake request, say, due to a ^C
142+
or other exigent event, the consumer can invoke:
143+
144+
.. code-block:: c
145+
146+
bool tls_handshake_cancel(sock);
147+
148+
This function returns true if the handshake request associated with
149+
@sock has been canceled. The consumer's handshake completion callback
150+
will not be invoked. If this function returns false, then the consumer's
151+
completion callback has already been invoked.
152+
153+
154+
Handshake Completion
155+
====================
156+
157+
When the handshake agent has completed processing, it notifies the
158+
kernel that the socket may be used by the consumer again. At this point,
159+
the consumer's handshake completion callback, provided in the @ta_done
160+
field in the tls_handshake_args structure, is invoked.
161+
162+
The synopsis of this function is:
163+
164+
.. code-block:: c
165+
166+
typedef void (*tls_done_func_t)(void *data, int status,
167+
key_serial_t peerid);
168+
169+
The consumer provides a cookie in the @ta_data field of the
170+
tls_handshake_args structure that is returned in the @data parameter of
171+
this callback. The consumer uses the cookie to match the callback to the
172+
thread waiting for the handshake to complete.
173+
174+
The success status of the handshake is returned via the @status
175+
parameter:
176+
177+
+------------+----------------------------------------------+
178+
| status | meaning |
179+
+============+==============================================+
180+
| 0 | TLS session established successfully |
181+
+------------+----------------------------------------------+
182+
| -EACCESS | Remote peer rejected the handshake or |
183+
| | authentication failed |
184+
+------------+----------------------------------------------+
185+
| -ENOMEM | Temporary resource allocation failure |
186+
+------------+----------------------------------------------+
187+
| -EINVAL | Consumer provided an invalid argument |
188+
+------------+----------------------------------------------+
189+
| -ENOKEY | Missing authentication material |
190+
+------------+----------------------------------------------+
191+
| -EIO | An unexpected fault occurred |
192+
+------------+----------------------------------------------+
193+
194+
The @peerid parameter contains the serial number of a key containing the
195+
remote peer's identity or the value TLS_NO_PEERID if the session is not
196+
authenticated.
197+
198+
A best practice is to close and destroy the socket immediately if the
199+
handshake failed.
200+
201+
202+
Other considerations
203+
--------------------
204+
205+
While a handshake is under way, the kernel consumer must alter the
206+
socket's sk_data_ready callback function to ignore all incoming data.
207+
Once the handshake completion callback function has been invoked, normal
208+
receive operation can be resumed.
209+
210+
Once a TLS session is established, the consumer must provide a buffer
211+
for and then examine the control message (CMSG) that is part of every
212+
subsequent sock_recvmsg(). Each control message indicates whether the
213+
received message data is TLS record data or session metadata.
214+
215+
See tls.rst for details on how a kTLS consumer recognizes incoming
216+
(decrypted) application data, alerts, and handshake packets once the
217+
socket has been promoted to use the TLS ULP.

MAINTAINERS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8947,6 +8947,17 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
89478947
T: git git://linuxtv.org/anttip/media_tree.git
89488948
F: drivers/media/usb/hackrf/
89498949

8950+
HANDSHAKE UPCALL FOR TRANSPORT LAYER SECURITY
8951+
M: Chuck Lever <chuck.lever@oracle.com>
8952+
L: kernel-tls-handshake@lists.linux.dev
8953+
L: netdev@vger.kernel.org
8954+
S: Maintained
8955+
F: Documentation/netlink/specs/handshake.yaml
8956+
F: Documentation/networking/tls-handshake.rst
8957+
F: include/net/handshake.h
8958+
F: include/trace/events/handshake.h
8959+
F: net/handshake/
8960+
89508961
HANTRO VPU CODEC DRIVER
89518962
M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
89528963
M: Philipp Zabel <p.zabel@pengutronix.de>

0 commit comments

Comments
 (0)