Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/handshake/tlshd.c
49979 views
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
if (treq->th_keyring) {
234
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_KEYRING,
235
treq->th_keyring);
236
if (ret < 0)
237
goto out_cancel;
238
}
239
240
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_AUTH_MODE,
241
treq->th_auth_mode);
242
if (ret < 0)
243
goto out_cancel;
244
switch (treq->th_auth_mode) {
245
case HANDSHAKE_AUTH_PSK:
246
ret = tls_handshake_put_peer_identity(msg, treq);
247
if (ret < 0)
248
goto out_cancel;
249
break;
250
case HANDSHAKE_AUTH_X509:
251
ret = tls_handshake_put_certificate(msg, treq);
252
if (ret < 0)
253
goto out_cancel;
254
break;
255
}
256
257
genlmsg_end(msg, hdr);
258
return genlmsg_reply(msg, info);
259
260
out_cancel:
261
genlmsg_cancel(msg, hdr);
262
nlmsg_free(msg);
263
out:
264
return ret;
265
}
266
267
static const struct handshake_proto tls_handshake_proto = {
268
.hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD,
269
.hp_privsize = sizeof(struct tls_handshake_req),
270
.hp_flags = BIT(HANDSHAKE_F_PROTO_NOTIFY),
271
272
.hp_accept = tls_handshake_accept,
273
.hp_done = tls_handshake_done,
274
};
275
276
/**
277
* tls_client_hello_anon - request an anonymous TLS handshake on a socket
278
* @args: socket and handshake parameters for this request
279
* @flags: memory allocation control flags
280
*
281
* Return values:
282
* %0: Handshake request enqueue; ->done will be called when complete
283
* %-ESRCH: No user agent is available
284
* %-ENOMEM: Memory allocation failed
285
*/
286
int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t flags)
287
{
288
struct tls_handshake_req *treq;
289
struct handshake_req *req;
290
291
req = handshake_req_alloc(&tls_handshake_proto, flags);
292
if (!req)
293
return -ENOMEM;
294
treq = tls_handshake_req_init(req, args);
295
treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
296
treq->th_auth_mode = HANDSHAKE_AUTH_UNAUTH;
297
298
return handshake_req_submit(args->ta_sock, req, flags);
299
}
300
EXPORT_SYMBOL(tls_client_hello_anon);
301
302
/**
303
* tls_client_hello_x509 - request an x.509-based TLS handshake on a socket
304
* @args: socket and handshake parameters for this request
305
* @flags: memory allocation control flags
306
*
307
* Return values:
308
* %0: Handshake request enqueue; ->done will be called when complete
309
* %-ESRCH: No user agent is available
310
* %-ENOMEM: Memory allocation failed
311
*/
312
int tls_client_hello_x509(const struct tls_handshake_args *args, gfp_t flags)
313
{
314
struct tls_handshake_req *treq;
315
struct handshake_req *req;
316
317
req = handshake_req_alloc(&tls_handshake_proto, flags);
318
if (!req)
319
return -ENOMEM;
320
treq = tls_handshake_req_init(req, args);
321
treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
322
treq->th_auth_mode = HANDSHAKE_AUTH_X509;
323
treq->th_certificate = args->ta_my_cert;
324
treq->th_privkey = args->ta_my_privkey;
325
326
return handshake_req_submit(args->ta_sock, req, flags);
327
}
328
EXPORT_SYMBOL(tls_client_hello_x509);
329
330
/**
331
* tls_client_hello_psk - request a PSK-based TLS handshake on a socket
332
* @args: socket and handshake parameters for this request
333
* @flags: memory allocation control flags
334
*
335
* Return values:
336
* %0: Handshake request enqueue; ->done will be called when complete
337
* %-EINVAL: Wrong number of local peer IDs
338
* %-ESRCH: No user agent is available
339
* %-ENOMEM: Memory allocation failed
340
*/
341
int tls_client_hello_psk(const struct tls_handshake_args *args, gfp_t flags)
342
{
343
struct tls_handshake_req *treq;
344
struct handshake_req *req;
345
unsigned int i;
346
347
if (!args->ta_num_peerids ||
348
args->ta_num_peerids > ARRAY_SIZE(treq->th_peerid))
349
return -EINVAL;
350
351
req = handshake_req_alloc(&tls_handshake_proto, flags);
352
if (!req)
353
return -ENOMEM;
354
treq = tls_handshake_req_init(req, args);
355
treq->th_type = HANDSHAKE_MSG_TYPE_CLIENTHELLO;
356
treq->th_auth_mode = HANDSHAKE_AUTH_PSK;
357
treq->th_num_peerids = args->ta_num_peerids;
358
for (i = 0; i < args->ta_num_peerids; i++)
359
treq->th_peerid[i] = args->ta_my_peerids[i];
360
361
return handshake_req_submit(args->ta_sock, req, flags);
362
}
363
EXPORT_SYMBOL(tls_client_hello_psk);
364
365
/**
366
* tls_server_hello_x509 - request a server TLS handshake on a socket
367
* @args: socket and handshake parameters for this request
368
* @flags: memory allocation control flags
369
*
370
* Return values:
371
* %0: Handshake request enqueue; ->done will be called when complete
372
* %-ESRCH: No user agent is available
373
* %-ENOMEM: Memory allocation failed
374
*/
375
int tls_server_hello_x509(const struct tls_handshake_args *args, gfp_t flags)
376
{
377
struct tls_handshake_req *treq;
378
struct handshake_req *req;
379
380
req = handshake_req_alloc(&tls_handshake_proto, flags);
381
if (!req)
382
return -ENOMEM;
383
treq = tls_handshake_req_init(req, args);
384
treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO;
385
treq->th_auth_mode = HANDSHAKE_AUTH_X509;
386
treq->th_certificate = args->ta_my_cert;
387
treq->th_privkey = args->ta_my_privkey;
388
389
return handshake_req_submit(args->ta_sock, req, flags);
390
}
391
EXPORT_SYMBOL(tls_server_hello_x509);
392
393
/**
394
* tls_server_hello_psk - request a server TLS handshake on a socket
395
* @args: socket and handshake parameters for this request
396
* @flags: memory allocation control flags
397
*
398
* Return values:
399
* %0: Handshake request enqueue; ->done will be called when complete
400
* %-ESRCH: No user agent is available
401
* %-ENOMEM: Memory allocation failed
402
*/
403
int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flags)
404
{
405
struct tls_handshake_req *treq;
406
struct handshake_req *req;
407
408
req = handshake_req_alloc(&tls_handshake_proto, flags);
409
if (!req)
410
return -ENOMEM;
411
treq = tls_handshake_req_init(req, args);
412
treq->th_type = HANDSHAKE_MSG_TYPE_SERVERHELLO;
413
treq->th_auth_mode = HANDSHAKE_AUTH_PSK;
414
treq->th_num_peerids = 1;
415
treq->th_peerid[0] = args->ta_my_peerids[0];
416
417
return handshake_req_submit(args->ta_sock, req, flags);
418
}
419
EXPORT_SYMBOL(tls_server_hello_psk);
420
421
/**
422
* tls_handshake_cancel - cancel a pending handshake
423
* @sk: socket on which there is an ongoing handshake
424
*
425
* Request cancellation races with request completion. To determine
426
* who won, callers examine the return value from this function.
427
*
428
* Return values:
429
* %true - Uncompleted handshake request was canceled
430
* %false - Handshake request already completed or not found
431
*/
432
bool tls_handshake_cancel(struct sock *sk)
433
{
434
return handshake_req_cancel(sk);
435
}
436
EXPORT_SYMBOL(tls_handshake_cancel);
437
438
/**
439
* tls_handshake_close - send a Closure alert
440
* @sock: an open socket
441
*
442
*/
443
void tls_handshake_close(struct socket *sock)
444
{
445
struct handshake_req *req;
446
447
req = handshake_req_hash_lookup(sock->sk);
448
if (!req)
449
return;
450
if (!test_and_clear_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags))
451
return;
452
tls_alert_send(sock, TLS_ALERT_LEVEL_WARNING,
453
TLS_ALERT_DESC_CLOSE_NOTIFY);
454
}
455
EXPORT_SYMBOL(tls_handshake_close);
456
457