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