xref: /openbmc/linux/net/handshake/tlshd.c (revision 476ec641)
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);
427