]> Git Repo - J-linux.git/blob - net/handshake/tlshd.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / net / handshake / tlshd.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Establish a TLS session for a kernel socket consumer
4  * using the tlshd user space handler.
5  *
6  * Author: Chuck Lever <[email protected]>
7  *
8  * Copyright (c) 2021-2023, Oracle and/or its affiliates.
9  */
10
11 #include <linux/types.h>
12 #include <linux/socket.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/key.h>
17
18 #include <net/sock.h>
19 #include <net/handshake.h>
20 #include <net/genetlink.h>
21 #include <net/tls_prot.h>
22
23 #include <uapi/linux/keyctl.h>
24 #include <uapi/linux/handshake.h>
25 #include "handshake.h"
26
27 struct tls_handshake_req {
28         void                    (*th_consumer_done)(void *data, int status,
29                                                     key_serial_t peerid);
30         void                    *th_consumer_data;
31
32         int                     th_type;
33         unsigned int            th_timeout_ms;
34         int                     th_auth_mode;
35         const char              *th_peername;
36         key_serial_t            th_keyring;
37         key_serial_t            th_certificate;
38         key_serial_t            th_privkey;
39
40         unsigned int            th_num_peerids;
41         key_serial_t            th_peerid[5];
42 };
43
44 static struct tls_handshake_req *
45 tls_handshake_req_init(struct handshake_req *req,
46                        const struct tls_handshake_args *args)
47 {
48         struct tls_handshake_req *treq = handshake_req_private(req);
49
50         treq->th_timeout_ms = args->ta_timeout_ms;
51         treq->th_consumer_done = args->ta_done;
52         treq->th_consumer_data = args->ta_data;
53         treq->th_peername = args->ta_peername;
54         treq->th_keyring = args->ta_keyring;
55         treq->th_num_peerids = 0;
56         treq->th_certificate = TLS_NO_CERT;
57         treq->th_privkey = TLS_NO_PRIVKEY;
58         return treq;
59 }
60
61 static void tls_handshake_remote_peerids(struct tls_handshake_req *treq,
62                                          struct genl_info *info)
63 {
64         struct nlattr *head = nlmsg_attrdata(info->nlhdr, GENL_HDRLEN);
65         int rem, len = nlmsg_attrlen(info->nlhdr, GENL_HDRLEN);
66         struct nlattr *nla;
67         unsigned int i;
68
69         i = 0;
70         nla_for_each_attr(nla, head, len, rem) {
71                 if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH)
72                         i++;
73         }
74         if (!i)
75                 return;
76         treq->th_num_peerids = min_t(unsigned int, i,
77                                      ARRAY_SIZE(treq->th_peerid));
78
79         i = 0;
80         nla_for_each_attr(nla, head, len, rem) {
81                 if (nla_type(nla) == HANDSHAKE_A_DONE_REMOTE_AUTH)
82                         treq->th_peerid[i++] = nla_get_u32(nla);
83                 if (i >= treq->th_num_peerids)
84                         break;
85         }
86 }
87
88 /**
89  * tls_handshake_done - callback to handle a CMD_DONE request
90  * @req: socket on which the handshake was performed
91  * @status: session status code
92  * @info: full results of session establishment
93  *
94  */
95 static void tls_handshake_done(struct handshake_req *req,
96                                unsigned int status, struct genl_info *info)
97 {
98         struct tls_handshake_req *treq = handshake_req_private(req);
99
100         treq->th_peerid[0] = TLS_NO_PEERID;
101         if (info)
102                 tls_handshake_remote_peerids(treq, info);
103
104         if (!status)
105                 set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags);
106
107         treq->th_consumer_done(treq->th_consumer_data, -status,
108                                treq->th_peerid[0]);
109 }
110
111 #if IS_ENABLED(CONFIG_KEYS)
112 static int tls_handshake_private_keyring(struct tls_handshake_req *treq)
113 {
114         key_ref_t process_keyring_ref, keyring_ref;
115         int ret;
116
117         if (treq->th_keyring == TLS_NO_KEYRING)
118                 return 0;
119
120         process_keyring_ref = lookup_user_key(KEY_SPEC_PROCESS_KEYRING,
121                                               KEY_LOOKUP_CREATE,
122                                               KEY_NEED_WRITE);
123         if (IS_ERR(process_keyring_ref)) {
124                 ret = PTR_ERR(process_keyring_ref);
125                 goto out;
126         }
127
128         keyring_ref = lookup_user_key(treq->th_keyring, KEY_LOOKUP_CREATE,
129                                       KEY_NEED_LINK);
130         if (IS_ERR(keyring_ref)) {
131                 ret = PTR_ERR(keyring_ref);
132                 goto out_put_key;
133         }
134
135         ret = key_link(key_ref_to_ptr(process_keyring_ref),
136                        key_ref_to_ptr(keyring_ref));
137
138         key_ref_put(keyring_ref);
139 out_put_key:
140         key_ref_put(process_keyring_ref);
141 out:
142         return ret;
143 }
144 #else
145 static int tls_handshake_private_keyring(struct tls_handshake_req *treq)
146 {
147         return 0;
148 }
149 #endif
150
151 static int tls_handshake_put_peer_identity(struct sk_buff *msg,
152                                            struct tls_handshake_req *treq)
153 {
154         unsigned int i;
155
156         for (i = 0; i < treq->th_num_peerids; i++)
157                 if (nla_put_u32(msg, HANDSHAKE_A_ACCEPT_PEER_IDENTITY,
158                                 treq->th_peerid[i]) < 0)
159                         return -EMSGSIZE;
160         return 0;
161 }
162
163 static int tls_handshake_put_certificate(struct sk_buff *msg,
164                                          struct tls_handshake_req *treq)
165 {
166         struct nlattr *entry_attr;
167
168         if (treq->th_certificate == TLS_NO_CERT &&
169             treq->th_privkey == TLS_NO_PRIVKEY)
170                 return 0;
171
172         entry_attr = nla_nest_start(msg, HANDSHAKE_A_ACCEPT_CERTIFICATE);
173         if (!entry_attr)
174                 return -EMSGSIZE;
175
176         if (nla_put_s32(msg, HANDSHAKE_A_X509_CERT,
177                         treq->th_certificate) ||
178             nla_put_s32(msg, HANDSHAKE_A_X509_PRIVKEY,
179                         treq->th_privkey)) {
180                 nla_nest_cancel(msg, entry_attr);
181                 return -EMSGSIZE;
182         }
183
184         nla_nest_end(msg, entry_attr);
185         return 0;
186 }
187
188 /**
189  * tls_handshake_accept - callback to construct a CMD_ACCEPT response
190  * @req: handshake parameters to return
191  * @info: generic netlink message context
192  * @fd: file descriptor to be returned
193  *
194  * Returns zero on success, or a negative errno on failure.
195  */
196 static int tls_handshake_accept(struct handshake_req *req,
197                                 struct genl_info *info, int fd)
198 {
199         struct tls_handshake_req *treq = handshake_req_private(req);
200         struct nlmsghdr *hdr;
201         struct sk_buff *msg;
202         int ret;
203
204         ret = tls_handshake_private_keyring(treq);
205         if (ret < 0)
206                 goto out;
207
208         ret = -ENOMEM;
209         msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
210         if (!msg)
211                 goto out;
212         hdr = handshake_genl_put(msg, info);
213         if (!hdr)
214                 goto out_cancel;
215
216         ret = nla_put_s32(msg, HANDSHAKE_A_ACCEPT_SOCKFD, fd);
217         if (ret < 0)
218                 goto out_cancel;
219         ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type);
220         if (ret < 0)
221                 goto out_cancel;
222         if (treq->th_peername) {
223                 ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME,
224                                      treq->th_peername);
225                 if (ret < 0)
226                         goto out_cancel;
227         }
228         if (treq->th_timeout_ms) {
229                 ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms);
230                 if (ret < 0)
231                         goto out_cancel;
232         }
233
234         ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_AUTH_MODE,
235                           treq->th_auth_mode);
236         if (ret < 0)
237                 goto out_cancel;
238         switch (treq->th_auth_mode) {
239         case HANDSHAKE_AUTH_PSK:
240                 ret = tls_handshake_put_peer_identity(msg, treq);
241                 if (ret < 0)
242                         goto out_cancel;
243                 break;
244         case HANDSHAKE_AUTH_X509:
245                 ret = tls_handshake_put_certificate(msg, treq);
246                 if (ret < 0)
247                         goto out_cancel;
248                 break;
249         }
250
251         genlmsg_end(msg, hdr);
252         return genlmsg_reply(msg, info);
253
254 out_cancel:
255         genlmsg_cancel(msg, hdr);
256 out:
257         return ret;
258 }
259
260 static const struct handshake_proto tls_handshake_proto = {
261         .hp_handler_class       = HANDSHAKE_HANDLER_CLASS_TLSHD,
262         .hp_privsize            = sizeof(struct tls_handshake_req),
263         .hp_flags               = BIT(HANDSHAKE_F_PROTO_NOTIFY),
264
265         .hp_accept              = tls_handshake_accept,
266         .hp_done                = tls_handshake_done,
267 };
268
269 /**
270  * tls_client_hello_anon - request an anonymous TLS handshake on a socket
271  * @args: socket and handshake parameters for this request
272  * @flags: memory allocation control flags
273  *
274  * Return values:
275  *   %0: Handshake request enqueue; ->done will be called when complete
276  *   %-ESRCH: No user agent is available
277  *   %-ENOMEM: Memory allocation failed
278  */
279 int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t flags)
280 {
281         struct tls_handshake_req *treq;
282         struct handshake_req *req;
283
284         req = handshake_req_alloc(&tls_handshake_proto, flags);
285         if (!req)
286                 return -ENOMEM;
287         treq = tls_handshake_req_init(req, args);
288         treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
289         treq->th_auth_mode = HANDSHAKE_AUTH_UNAUTH;
290
291         return handshake_req_submit(args->ta_sock, req, flags);
292 }
293 EXPORT_SYMBOL(tls_client_hello_anon);
294
295 /**
296  * tls_client_hello_x509 - request an x.509-based TLS handshake on a socket
297  * @args: socket and handshake parameters for this request
298  * @flags: memory allocation control flags
299  *
300  * Return values:
301  *   %0: Handshake request enqueue; ->done will be called when complete
302  *   %-ESRCH: No user agent is available
303  *   %-ENOMEM: Memory allocation failed
304  */
305 int tls_client_hello_x509(const struct tls_handshake_args *args, gfp_t flags)
306 {
307         struct tls_handshake_req *treq;
308         struct handshake_req *req;
309
310         req = handshake_req_alloc(&tls_handshake_proto, flags);
311         if (!req)
312                 return -ENOMEM;
313         treq = tls_handshake_req_init(req, args);
314         treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
315         treq->th_auth_mode = HANDSHAKE_AUTH_X509;
316         treq->th_certificate = args->ta_my_cert;
317         treq->th_privkey = args->ta_my_privkey;
318
319         return handshake_req_submit(args->ta_sock, req, flags);
320 }
321 EXPORT_SYMBOL(tls_client_hello_x509);
322
323 /**
324  * tls_client_hello_psk - request a PSK-based TLS handshake on a socket
325  * @args: socket and handshake parameters for this request
326  * @flags: memory allocation control flags
327  *
328  * Return values:
329  *   %0: Handshake request enqueue; ->done will be called when complete
330  *   %-EINVAL: Wrong number of local peer IDs
331  *   %-ESRCH: No user agent is available
332  *   %-ENOMEM: Memory allocation failed
333  */
334 int tls_client_hello_psk(const struct tls_handshake_args *args, gfp_t flags)
335 {
336         struct tls_handshake_req *treq;
337         struct handshake_req *req;
338         unsigned int i;
339
340         if (!args->ta_num_peerids ||
341             args->ta_num_peerids > ARRAY_SIZE(treq->th_peerid))
342                 return -EINVAL;
343
344         req = handshake_req_alloc(&tls_handshake_proto, flags);
345         if (!req)
346                 return -ENOMEM;
347         treq = tls_handshake_req_init(req, args);
348         treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
349         treq->th_auth_mode = HANDSHAKE_AUTH_PSK;
350         treq->th_num_peerids = args->ta_num_peerids;
351         for (i = 0; i < args->ta_num_peerids; i++)
352                 treq->th_peerid[i] = args->ta_my_peerids[i];
353
354         return handshake_req_submit(args->ta_sock, req, flags);
355 }
356 EXPORT_SYMBOL(tls_client_hello_psk);
357
358 /**
359  * tls_server_hello_x509 - request a server TLS handshake on a socket
360  * @args: socket and handshake parameters for this request
361  * @flags: memory allocation control flags
362  *
363  * Return values:
364  *   %0: Handshake request enqueue; ->done will be called when complete
365  *   %-ESRCH: No user agent is available
366  *   %-ENOMEM: Memory allocation failed
367  */
368 int tls_server_hello_x509(const struct tls_handshake_args *args, gfp_t flags)
369 {
370         struct tls_handshake_req *treq;
371         struct handshake_req *req;
372
373         req = handshake_req_alloc(&tls_handshake_proto, flags);
374         if (!req)
375                 return -ENOMEM;
376         treq = tls_handshake_req_init(req, args);
377         treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO;
378         treq->th_auth_mode = HANDSHAKE_AUTH_X509;
379         treq->th_certificate = args->ta_my_cert;
380         treq->th_privkey = args->ta_my_privkey;
381
382         return handshake_req_submit(args->ta_sock, req, flags);
383 }
384 EXPORT_SYMBOL(tls_server_hello_x509);
385
386 /**
387  * tls_server_hello_psk - request a server TLS handshake on a socket
388  * @args: socket and handshake parameters for this request
389  * @flags: memory allocation control flags
390  *
391  * Return values:
392  *   %0: Handshake request enqueue; ->done will be called when complete
393  *   %-ESRCH: No user agent is available
394  *   %-ENOMEM: Memory allocation failed
395  */
396 int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flags)
397 {
398         struct tls_handshake_req *treq;
399         struct handshake_req *req;
400
401         req = handshake_req_alloc(&tls_handshake_proto, flags);
402         if (!req)
403                 return -ENOMEM;
404         treq = tls_handshake_req_init(req, args);
405         treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO;
406         treq->th_auth_mode = HANDSHAKE_AUTH_PSK;
407         treq->th_num_peerids = 1;
408         treq->th_peerid[0] = args->ta_my_peerids[0];
409
410         return handshake_req_submit(args->ta_sock, req, flags);
411 }
412 EXPORT_SYMBOL(tls_server_hello_psk);
413
414 /**
415  * tls_handshake_cancel - cancel a pending handshake
416  * @sk: socket on which there is an ongoing handshake
417  *
418  * Request cancellation races with request completion. To determine
419  * who won, callers examine the return value from this function.
420  *
421  * Return values:
422  *   %true - Uncompleted handshake request was canceled
423  *   %false - Handshake request already completed or not found
424  */
425 bool tls_handshake_cancel(struct sock *sk)
426 {
427         return handshake_req_cancel(sk);
428 }
429 EXPORT_SYMBOL(tls_handshake_cancel);
430
431 /**
432  * tls_handshake_close - send a Closure alert
433  * @sock: an open socket
434  *
435  */
436 void tls_handshake_close(struct socket *sock)
437 {
438         struct handshake_req *req;
439
440         req = handshake_req_hash_lookup(sock->sk);
441         if (!req)
442                 return;
443         if (!test_and_clear_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags))
444                 return;
445         tls_alert_send(sock, TLS_ALERT_LEVEL_WARNING,
446                        TLS_ALERT_DESC_CLOSE_NOTIFY);
447 }
448 EXPORT_SYMBOL(tls_handshake_close);
This page took 0.050326 seconds and 4 git commands to generate.