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