Merge tag 'pm-6.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[linux-block.git] / net / rxrpc / key.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
17926a79
DH
2/* RxRPC key management
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
17926a79 7 * RxRPC keys should have a description of describing their purpose:
177b8989 8 * "afs@example.com"
17926a79
DH
9 */
10
9b6d5398
JP
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
1afe593b 13#include <crypto/skcipher.h>
17926a79
DH
14#include <linux/module.h>
15#include <linux/net.h>
16#include <linux/skbuff.h>
76181c13 17#include <linux/key-type.h>
33941284 18#include <linux/ctype.h>
5a0e3ad6 19#include <linux/slab.h>
17926a79
DH
20#include <net/sock.h>
21#include <net/af_rxrpc.h>
22#include <keys/rxrpc-type.h>
23#include <keys/user-type.h>
24#include "ar-internal.h"
25
8a7a3eb4 26static int rxrpc_preparse(struct key_preparsed_payload *);
8a7a3eb4 27static void rxrpc_free_preparse(struct key_preparsed_payload *);
17926a79 28static void rxrpc_destroy(struct key *);
17926a79 29static void rxrpc_describe(const struct key *, struct seq_file *);
d3ec10aa 30static long rxrpc_read(const struct key *, char *, size_t);
17926a79
DH
31
32/*
33 * rxrpc defined keys take an arbitrary string as the description and an
34 * arbitrary blob of data as the payload
35 */
36struct key_type key_type_rxrpc = {
37 .name = "rxrpc",
9b242610 38 .flags = KEY_TYPE_NET_DOMAIN,
8a7a3eb4
DH
39 .preparse = rxrpc_preparse,
40 .free_preparse = rxrpc_free_preparse,
41 .instantiate = generic_key_instantiate,
17926a79
DH
42 .destroy = rxrpc_destroy,
43 .describe = rxrpc_describe,
ed6dd18b 44 .read = rxrpc_read,
17926a79 45};
17926a79
DH
46EXPORT_SYMBOL(key_type_rxrpc);
47
33941284
DH
48/*
49 * parse an RxKAD type XDR format token
50 * - the caller guarantees we have at least 4 words
51 */
8a7a3eb4
DH
52static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
53 size_t datalen,
54 const __be32 *xdr, unsigned int toklen)
33941284 55{
99455153 56 struct rxrpc_key_token *token, **pptoken;
10674a03 57 time64_t expiry;
33941284
DH
58 size_t plen;
59 u32 tktlen;
33941284
DH
60
61 _enter(",{%x,%x,%x,%x},%u",
62 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
63 toklen);
64
65 if (toklen <= 8 * 4)
66 return -EKEYREJECTED;
67 tktlen = ntohl(xdr[7]);
68 _debug("tktlen: %x", tktlen);
69 if (tktlen > AFSTOKEN_RK_TIX_MAX)
70 return -EKEYREJECTED;
fde0133b 71 if (toklen < 8 * 4 + tktlen)
33941284
DH
72 return -EKEYREJECTED;
73
74 plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
8a7a3eb4 75 prep->quotalen = datalen + plen;
33941284
DH
76
77 plen -= sizeof(*token);
0a93ea2e 78 token = kzalloc(sizeof(*token), GFP_KERNEL);
33941284
DH
79 if (!token)
80 return -ENOMEM;
81
0a93ea2e 82 token->kad = kzalloc(plen, GFP_KERNEL);
33941284
DH
83 if (!token->kad) {
84 kfree(token);
85 return -ENOMEM;
86 }
87
88 token->security_index = RXRPC_SECURITY_RXKAD;
89 token->kad->ticket_len = tktlen;
90 token->kad->vice_id = ntohl(xdr[0]);
91 token->kad->kvno = ntohl(xdr[1]);
92 token->kad->start = ntohl(xdr[4]);
93 token->kad->expiry = ntohl(xdr[5]);
94 token->kad->primary_flag = ntohl(xdr[6]);
95 memcpy(&token->kad->session_key, &xdr[2], 8);
96 memcpy(&token->kad->ticket, &xdr[8], tktlen);
97
98 _debug("SCIX: %u", token->security_index);
99 _debug("TLEN: %u", token->kad->ticket_len);
100 _debug("EXPY: %x", token->kad->expiry);
101 _debug("KVNO: %u", token->kad->kvno);
102 _debug("PRIM: %u", token->kad->primary_flag);
103 _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
104 token->kad->session_key[0], token->kad->session_key[1],
105 token->kad->session_key[2], token->kad->session_key[3],
106 token->kad->session_key[4], token->kad->session_key[5],
107 token->kad->session_key[6], token->kad->session_key[7]);
108 if (token->kad->ticket_len >= 8)
109 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
110 token->kad->ticket[0], token->kad->ticket[1],
111 token->kad->ticket[2], token->kad->ticket[3],
112 token->kad->ticket[4], token->kad->ticket[5],
113 token->kad->ticket[6], token->kad->ticket[7]);
114
115 /* count the number of tokens attached */
146aa8b1 116 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
33941284
DH
117
118 /* attach the data */
146aa8b1 119 for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
99455153
DH
120 *pptoken;
121 pptoken = &(*pptoken)->next)
122 continue;
123 *pptoken = token;
10674a03
BW
124 expiry = rxrpc_u32_to_time64(token->kad->expiry);
125 if (expiry < prep->expiry)
126 prep->expiry = expiry;
99455153
DH
127
128 _leave(" = 0");
129 return 0;
130}
131
0ca100ff
DH
132static u64 xdr_dec64(const __be32 *xdr)
133{
134 return (u64)ntohl(xdr[0]) << 32 | (u64)ntohl(xdr[1]);
135}
136
137static time64_t rxrpc_s64_to_time64(s64 time_in_100ns)
138{
139 bool neg = false;
140 u64 tmp = time_in_100ns;
141
142 if (time_in_100ns < 0) {
143 tmp = -time_in_100ns;
144 neg = true;
145 }
146 do_div(tmp, 10000000);
147 return neg ? -tmp : tmp;
148}
149
150/*
151 * Parse a YFS-RxGK type XDR format token
152 * - the caller guarantees we have at least 4 words
153 *
154 * struct token_rxgk {
155 * opr_time begintime;
156 * opr_time endtime;
157 * afs_int64 level;
158 * afs_int64 lifetime;
159 * afs_int64 bytelife;
160 * afs_int64 enctype;
161 * opaque key<>;
162 * opaque ticket<>;
163 * };
164 */
165static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
166 size_t datalen,
167 const __be32 *xdr, unsigned int toklen)
168{
169 struct rxrpc_key_token *token, **pptoken;
170 time64_t expiry;
171 size_t plen;
172 const __be32 *ticket, *key;
173 s64 tmp;
174 u32 tktlen, keylen;
175
176 _enter(",{%x,%x,%x,%x},%x",
177 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
178 toklen);
179
180 if (6 * 2 + 2 > toklen / 4)
181 goto reject;
182
183 key = xdr + (6 * 2 + 1);
184 keylen = ntohl(key[-1]);
185 _debug("keylen: %x", keylen);
186 keylen = round_up(keylen, 4);
187 if ((6 * 2 + 2) * 4 + keylen > toklen)
188 goto reject;
189
190 ticket = xdr + (6 * 2 + 1 + (keylen / 4) + 1);
191 tktlen = ntohl(ticket[-1]);
192 _debug("tktlen: %x", tktlen);
193 tktlen = round_up(tktlen, 4);
194 if ((6 * 2 + 2) * 4 + keylen + tktlen != toklen) {
195 kleave(" = -EKEYREJECTED [%x!=%x, %x,%x]",
196 (6 * 2 + 2) * 4 + keylen + tktlen, toklen,
197 keylen, tktlen);
198 goto reject;
199 }
200
201 plen = sizeof(*token) + sizeof(*token->rxgk) + tktlen + keylen;
202 prep->quotalen = datalen + plen;
203
204 plen -= sizeof(*token);
205 token = kzalloc(sizeof(*token), GFP_KERNEL);
206 if (!token)
207 goto nomem;
208
209 token->rxgk = kzalloc(sizeof(*token->rxgk) + keylen, GFP_KERNEL);
210 if (!token->rxgk)
211 goto nomem_token;
212
213 token->security_index = RXRPC_SECURITY_YFS_RXGK;
214 token->rxgk->begintime = xdr_dec64(xdr + 0 * 2);
215 token->rxgk->endtime = xdr_dec64(xdr + 1 * 2);
216 token->rxgk->level = tmp = xdr_dec64(xdr + 2 * 2);
217 if (tmp < -1LL || tmp > RXRPC_SECURITY_ENCRYPT)
218 goto reject_token;
219 token->rxgk->lifetime = xdr_dec64(xdr + 3 * 2);
220 token->rxgk->bytelife = xdr_dec64(xdr + 4 * 2);
221 token->rxgk->enctype = tmp = xdr_dec64(xdr + 5 * 2);
222 if (tmp < 0 || tmp > UINT_MAX)
223 goto reject_token;
224 token->rxgk->key.len = ntohl(key[-1]);
225 token->rxgk->key.data = token->rxgk->_key;
226 token->rxgk->ticket.len = ntohl(ticket[-1]);
227
228 if (token->rxgk->endtime != 0) {
229 expiry = rxrpc_s64_to_time64(token->rxgk->endtime);
230 if (expiry < 0)
231 goto expired;
232 if (expiry < prep->expiry)
233 prep->expiry = expiry;
234 }
235
236 memcpy(token->rxgk->key.data, key, token->rxgk->key.len);
237
238 /* Pad the ticket so that we can use it directly in XDR */
239 token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
240 GFP_KERNEL);
241 if (!token->rxgk->ticket.data)
242 goto nomem_yrxgk;
243 memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
244
245 _debug("SCIX: %u", token->security_index);
246 _debug("EXPY: %llx", token->rxgk->endtime);
247 _debug("LIFE: %llx", token->rxgk->lifetime);
248 _debug("BYTE: %llx", token->rxgk->bytelife);
249 _debug("ENC : %u", token->rxgk->enctype);
250 _debug("LEVL: %u", token->rxgk->level);
251 _debug("KLEN: %u", token->rxgk->key.len);
252 _debug("TLEN: %u", token->rxgk->ticket.len);
253 _debug("KEY0: %*phN", token->rxgk->key.len, token->rxgk->key.data);
254 _debug("TICK: %*phN",
255 min_t(u32, token->rxgk->ticket.len, 32), token->rxgk->ticket.data);
256
257 /* count the number of tokens attached */
258 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
259
260 /* attach the data */
261 for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
262 *pptoken;
263 pptoken = &(*pptoken)->next)
264 continue;
265 *pptoken = token;
266
267 _leave(" = 0");
268 return 0;
269
270nomem_yrxgk:
271 kfree(token->rxgk);
272nomem_token:
273 kfree(token);
274nomem:
275 return -ENOMEM;
276reject_token:
277 kfree(token);
278reject:
279 return -EKEYREJECTED;
280expired:
281 kfree(token->rxgk);
282 kfree(token);
283 return -EKEYEXPIRED;
284}
285
33941284
DH
286/*
287 * attempt to parse the data as the XDR format
288 * - the caller guarantees we have more than 7 words
289 */
8a7a3eb4 290static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
33941284 291{
4c20c333 292 const __be32 *xdr = prep->data, *token, *p;
33941284 293 const char *cp;
5f2f9765 294 unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
8a7a3eb4 295 size_t datalen = prep->datalen;
9a0e6464 296 int ret, ret2;
33941284
DH
297
298 _enter(",{%x,%x,%x,%x},%zu",
299 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
8a7a3eb4 300 prep->datalen);
33941284
DH
301
302 if (datalen > AFSTOKEN_LENGTH_MAX)
303 goto not_xdr;
304
305 /* XDR is an array of __be32's */
306 if (datalen & 3)
307 goto not_xdr;
308
309 /* the flags should be 0 (the setpag bit must be handled by
310 * userspace) */
311 if (ntohl(*xdr++) != 0)
312 goto not_xdr;
313 datalen -= 4;
314
315 /* check the cell name */
316 len = ntohl(*xdr++);
317 if (len < 1 || len > AFSTOKEN_CELL_MAX)
318 goto not_xdr;
319 datalen -= 4;
5f2f9765
DH
320 paddedlen = (len + 3) & ~3;
321 if (paddedlen > datalen)
33941284
DH
322 goto not_xdr;
323
324 cp = (const char *) xdr;
325 for (loop = 0; loop < len; loop++)
326 if (!isprint(cp[loop]))
327 goto not_xdr;
5f2f9765
DH
328 for (; loop < paddedlen; loop++)
329 if (cp[loop])
330 goto not_xdr;
33941284 331 _debug("cellname: [%u/%u] '%*.*s'",
5f2f9765
DH
332 len, paddedlen, len, len, (const char *) xdr);
333 datalen -= paddedlen;
334 xdr += paddedlen >> 2;
33941284
DH
335
336 /* get the token count */
337 if (datalen < 12)
338 goto not_xdr;
339 ntoken = ntohl(*xdr++);
340 datalen -= 4;
341 _debug("ntoken: %x", ntoken);
342 if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
343 goto not_xdr;
344
345 /* check each token wrapper */
4c20c333 346 p = xdr;
33941284
DH
347 loop = ntoken;
348 do {
349 if (datalen < 8)
350 goto not_xdr;
4c20c333
DH
351 toklen = ntohl(*p++);
352 sec_ix = ntohl(*p);
33941284
DH
353 datalen -= 4;
354 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
5f2f9765
DH
355 paddedlen = (toklen + 3) & ~3;
356 if (toklen < 20 || toklen > datalen || paddedlen > datalen)
33941284 357 goto not_xdr;
5f2f9765 358 datalen -= paddedlen;
4c20c333 359 p += paddedlen >> 2;
33941284
DH
360
361 } while (--loop > 0);
362
363 _debug("remainder: %zu", datalen);
364 if (datalen != 0)
365 goto not_xdr;
366
367 /* okay: we're going to assume it's valid XDR format
368 * - we ignore the cellname, relying on the key to be correctly named
369 */
9a0e6464 370 ret = -EPROTONOSUPPORT;
33941284 371 do {
33941284 372 toklen = ntohl(*xdr++);
4c20c333
DH
373 token = xdr;
374 xdr += (toklen + 3) / 4;
375
376 sec_ix = ntohl(*token++);
33941284
DH
377 toklen -= 4;
378
4c20c333 379 _debug("TOKEN type=%x len=%x", sec_ix, toklen);
99455153 380
33941284
DH
381 switch (sec_ix) {
382 case RXRPC_SECURITY_RXKAD:
9a0e6464 383 ret2 = rxrpc_preparse_xdr_rxkad(prep, datalen, token, toklen);
33941284 384 break;
0ca100ff
DH
385 case RXRPC_SECURITY_YFS_RXGK:
386 ret2 = rxrpc_preparse_xdr_yfs_rxgk(prep, datalen, token, toklen);
387 break;
9a0e6464
DH
388 default:
389 ret2 = -EPROTONOSUPPORT;
390 break;
391 }
33941284 392
9a0e6464
DH
393 switch (ret2) {
394 case 0:
395 ret = 0;
396 break;
397 case -EPROTONOSUPPORT:
398 break;
399 case -ENOPKG:
400 if (ret != 0)
401 ret = -ENOPKG;
402 break;
33941284 403 default:
9a0e6464 404 ret = ret2;
33941284
DH
405 goto error;
406 }
407
408 } while (--ntoken > 0);
409
9a0e6464
DH
410error:
411 _leave(" = %d", ret);
412 return ret;
33941284
DH
413
414not_xdr:
415 _leave(" = -EPROTO");
416 return -EPROTO;
33941284
DH
417}
418
17926a79 419/*
8a7a3eb4
DH
420 * Preparse an rxrpc defined key.
421 *
422 * Data should be of the form:
17926a79
DH
423 * OFFSET LEN CONTENT
424 * 0 4 key interface version number
425 * 4 2 security index (type)
426 * 6 2 ticket length
427 * 8 4 key expiry time (time_t)
428 * 12 4 kvno
429 * 16 8 session key
430 * 24 [len] ticket
431 *
432 * if no data is provided, then a no-security key is made
433 */
8a7a3eb4 434static int rxrpc_preparse(struct key_preparsed_payload *prep)
17926a79 435{
33941284
DH
436 const struct rxrpc_key_data_v1 *v1;
437 struct rxrpc_key_token *token, **pp;
10674a03 438 time64_t expiry;
17926a79
DH
439 size_t plen;
440 u32 kver;
441 int ret;
442
8a7a3eb4 443 _enter("%zu", prep->datalen);
17926a79
DH
444
445 /* handle a no-security key */
cf7f601c 446 if (!prep->data && prep->datalen == 0)
17926a79
DH
447 return 0;
448
33941284 449 /* determine if the XDR payload format is being used */
cf7f601c 450 if (prep->datalen > 7 * 4) {
8a7a3eb4 451 ret = rxrpc_preparse_xdr(prep);
33941284
DH
452 if (ret != -EPROTO)
453 return ret;
454 }
455
17926a79
DH
456 /* get the key interface version number */
457 ret = -EINVAL;
cf7f601c 458 if (prep->datalen <= 4 || !prep->data)
17926a79 459 goto error;
cf7f601c
DH
460 memcpy(&kver, prep->data, sizeof(kver));
461 prep->data += sizeof(kver);
462 prep->datalen -= sizeof(kver);
17926a79
DH
463
464 _debug("KEY I/F VERSION: %u", kver);
465
466 ret = -EKEYREJECTED;
467 if (kver != 1)
468 goto error;
469
470 /* deal with a version 1 key */
471 ret = -EINVAL;
cf7f601c 472 if (prep->datalen < sizeof(*v1))
17926a79
DH
473 goto error;
474
cf7f601c
DH
475 v1 = prep->data;
476 if (prep->datalen != sizeof(*v1) + v1->ticket_length)
17926a79
DH
477 goto error;
478
33941284
DH
479 _debug("SCIX: %u", v1->security_index);
480 _debug("TLEN: %u", v1->ticket_length);
481 _debug("EXPY: %x", v1->expiry);
482 _debug("KVNO: %u", v1->kvno);
17926a79 483 _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
33941284
DH
484 v1->session_key[0], v1->session_key[1],
485 v1->session_key[2], v1->session_key[3],
486 v1->session_key[4], v1->session_key[5],
487 v1->session_key[6], v1->session_key[7]);
488 if (v1->ticket_length >= 8)
17926a79 489 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
33941284
DH
490 v1->ticket[0], v1->ticket[1],
491 v1->ticket[2], v1->ticket[3],
492 v1->ticket[4], v1->ticket[5],
493 v1->ticket[6], v1->ticket[7]);
17926a79
DH
494
495 ret = -EPROTONOSUPPORT;
33941284 496 if (v1->security_index != RXRPC_SECURITY_RXKAD)
17926a79
DH
497 goto error;
498
33941284 499 plen = sizeof(*token->kad) + v1->ticket_length;
8a7a3eb4 500 prep->quotalen = plen + sizeof(*token);
17926a79
DH
501
502 ret = -ENOMEM;
0a93ea2e 503 token = kzalloc(sizeof(*token), GFP_KERNEL);
33941284 504 if (!token)
17926a79 505 goto error;
0a93ea2e 506 token->kad = kzalloc(plen, GFP_KERNEL);
33941284
DH
507 if (!token->kad)
508 goto error_free;
509
510 token->security_index = RXRPC_SECURITY_RXKAD;
511 token->kad->ticket_len = v1->ticket_length;
512 token->kad->expiry = v1->expiry;
513 token->kad->kvno = v1->kvno;
514 memcpy(&token->kad->session_key, &v1->session_key, 8);
515 memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
17926a79 516
8a7a3eb4 517 /* count the number of tokens attached */
146aa8b1 518 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
33941284 519
8a7a3eb4 520 /* attach the data */
146aa8b1 521 pp = (struct rxrpc_key_token **)&prep->payload.data[0];
33941284
DH
522 while (*pp)
523 pp = &(*pp)->next;
524 *pp = token;
10674a03
BW
525 expiry = rxrpc_u32_to_time64(token->kad->expiry);
526 if (expiry < prep->expiry)
527 prep->expiry = expiry;
33941284 528 token = NULL;
17926a79
DH
529 ret = 0;
530
33941284
DH
531error_free:
532 kfree(token);
17926a79
DH
533error:
534 return ret;
535}
536
537/*
8a7a3eb4 538 * Free token list.
17926a79 539 */
8a7a3eb4
DH
540static void rxrpc_free_token_list(struct rxrpc_key_token *token)
541{
542 struct rxrpc_key_token *next;
543
544 for (; token; token = next) {
545 next = token->next;
546 switch (token->security_index) {
547 case RXRPC_SECURITY_RXKAD:
548 kfree(token->kad);
549 break;
0ca100ff
DH
550 case RXRPC_SECURITY_YFS_RXGK:
551 kfree(token->rxgk->ticket.data);
552 kfree(token->rxgk);
553 break;
8a7a3eb4 554 default:
9b6d5398 555 pr_err("Unknown token type %x on rxrpc key\n",
8a7a3eb4
DH
556 token->security_index);
557 BUG();
558 }
559
560 kfree(token);
561 }
562}
563
564/*
565 * Clean up preparse data.
566 */
567static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
568{
146aa8b1 569 rxrpc_free_token_list(prep->payload.data[0]);
8a7a3eb4
DH
570}
571
17926a79
DH
572/*
573 * dispose of the data dangling from the corpse of a rxrpc key
574 */
575static void rxrpc_destroy(struct key *key)
576{
146aa8b1 577 rxrpc_free_token_list(key->payload.data[0]);
17926a79
DH
578}
579
17926a79
DH
580/*
581 * describe the rxrpc key
582 */
583static void rxrpc_describe(const struct key *key, struct seq_file *m)
0727d3ec
DH
584{
585 const struct rxrpc_key_token *token;
586 const char *sep = ": ";
587
588 seq_puts(m, key->description);
589
590 for (token = key->payload.data[0]; token; token = token->next) {
591 seq_puts(m, sep);
592
593 switch (token->security_index) {
594 case RXRPC_SECURITY_RXKAD:
595 seq_puts(m, "ka");
596 break;
0ca100ff
DH
597 case RXRPC_SECURITY_YFS_RXGK:
598 seq_puts(m, "ygk");
599 break;
0727d3ec
DH
600 default: /* we have a ticket we can't encode */
601 seq_printf(m, "%u", token->security_index);
602 break;
603 }
604
605 sep = " ";
606 }
607}
608
17926a79
DH
609/*
610 * grab the security key for a socket
611 */
a7b75c5a 612int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
17926a79
DH
613{
614 struct key *key;
615 char *description;
616
617 _enter("");
618
38b1dc47 619 if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
17926a79
DH
620 return -EINVAL;
621
a7b75c5a 622 description = memdup_sockptr_nul(optval, optlen);
16e5c1fc
AV
623 if (IS_ERR(description))
624 return PTR_ERR(description);
17926a79 625
028db3e2 626 key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
17926a79
DH
627 if (IS_ERR(key)) {
628 kfree(description);
629 _leave(" = %ld", PTR_ERR(key));
630 return PTR_ERR(key);
631 }
632
633 rx->key = key;
634 kfree(description);
635 _leave(" = 0 [key %x]", key->serial);
636 return 0;
637}
638
17926a79
DH
639/*
640 * generate a server data key
641 */
642int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
643 const void *session_key,
10674a03 644 time64_t expiry,
17926a79
DH
645 u32 kvno)
646{
d84f4f99 647 const struct cred *cred = current_cred();
17926a79
DH
648 struct key *key;
649 int ret;
650
651 struct {
652 u32 kver;
33941284 653 struct rxrpc_key_data_v1 v1;
17926a79
DH
654 } data;
655
656 _enter("");
657
c6089735 658 key = key_alloc(&key_type_rxrpc, "x",
028db3e2 659 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
5ac7eace 660 KEY_ALLOC_NOT_IN_QUOTA, NULL);
17926a79
DH
661 if (IS_ERR(key)) {
662 _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
663 return -ENOMEM;
664 }
665
666 _debug("key %d", key_serial(key));
667
668 data.kver = 1;
33941284
DH
669 data.v1.security_index = RXRPC_SECURITY_RXKAD;
670 data.v1.ticket_length = 0;
10674a03 671 data.v1.expiry = rxrpc_time64_to_u32(expiry);
33941284 672 data.v1.kvno = 0;
17926a79 673
33941284 674 memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
17926a79
DH
675
676 ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
677 if (ret < 0)
678 goto error;
679
2cc80086 680 conn->key = key;
17926a79
DH
681 _leave(" = 0 [%d]", key_serial(key));
682 return 0;
683
684error:
685 key_revoke(key);
686 key_put(key);
687 _leave(" = -ENOMEM [ins %d]", ret);
688 return -ENOMEM;
689}
17926a79 690EXPORT_SYMBOL(rxrpc_get_server_data_key);
76181c13
DH
691
692/**
693 * rxrpc_get_null_key - Generate a null RxRPC key
694 * @keyname: The name to give the key.
695 *
696 * Generate a null RxRPC key that can be used to indicate anonymous security is
697 * required for a particular domain.
28a79fc9
DH
698 *
699 * Return: The new key or a negative error code.
76181c13
DH
700 */
701struct key *rxrpc_get_null_key(const char *keyname)
702{
d84f4f99 703 const struct cred *cred = current_cred();
76181c13
DH
704 struct key *key;
705 int ret;
706
c6089735
EB
707 key = key_alloc(&key_type_rxrpc, keyname,
708 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
028db3e2 709 KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
76181c13
DH
710 if (IS_ERR(key))
711 return key;
712
713 ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
714 if (ret < 0) {
715 key_revoke(key);
716 key_put(key);
717 return ERR_PTR(ret);
718 }
719
720 return key;
721}
722EXPORT_SYMBOL(rxrpc_get_null_key);
ed6dd18b
DH
723
724/*
725 * read the contents of an rxrpc key
726 * - this returns the result in XDR form
727 */
728static long rxrpc_read(const struct key *key,
d3ec10aa 729 char *buffer, size_t buflen)
ed6dd18b 730{
99455153 731 const struct rxrpc_key_token *token;
99455153 732 size_t size;
d3ec10aa 733 __be32 *xdr, *oldxdr;
99455153
DH
734 u32 cnlen, toksize, ntoks, tok, zero;
735 u16 toksizes[AFSTOKEN_MAX];
ed6dd18b
DH
736
737 _enter("");
738
739 /* we don't know what form we should return non-AFS keys in */
740 if (memcmp(key->description, "afs@", 4) != 0)
741 return -EOPNOTSUPP;
742 cnlen = strlen(key->description + 4);
743
99455153
DH
744#define RND(X) (((X) + 3) & ~3)
745
ed6dd18b
DH
746 /* AFS keys we return in XDR form, so we need to work out the size of
747 * the XDR */
748 size = 2 * 4; /* flags, cellname len */
99455153 749 size += RND(cnlen); /* cellname */
ed6dd18b
DH
750 size += 1 * 4; /* token count */
751
752 ntoks = 0;
146aa8b1 753 for (token = key->payload.data[0]; token; token = token->next) {
99455153
DH
754 toksize = 4; /* sec index */
755
ed6dd18b
DH
756 switch (token->security_index) {
757 case RXRPC_SECURITY_RXKAD:
56305118 758 toksize += 8 * 4; /* viceid, kvno, key*2, begin,
99455153 759 * end, primary, tktlen */
d2ae4e91
DH
760 if (!token->no_leak_key)
761 toksize += RND(token->kad->ticket_len);
ed6dd18b
DH
762 break;
763
0ca100ff
DH
764 case RXRPC_SECURITY_YFS_RXGK:
765 toksize += 6 * 8 + 2 * 4;
766 if (!token->no_leak_key)
767 toksize += RND(token->rxgk->key.len);
768 toksize += RND(token->rxgk->ticket.len);
769 break;
770
99455153 771 default: /* we have a ticket we can't encode */
9a059cd5
DH
772 pr_err("Unsupported key token type (%u)\n",
773 token->security_index);
d52e419a 774 return -ENOPKG;
ed6dd18b 775 }
99455153
DH
776
777 _debug("token[%u]: toksize=%u", ntoks, toksize);
84924aac
DH
778 if (WARN_ON(toksize > AFSTOKEN_LENGTH_MAX))
779 return -EIO;
99455153
DH
780
781 toksizes[ntoks++] = toksize;
782 size += toksize + 4; /* each token has a length word */
ed6dd18b
DH
783 }
784
99455153
DH
785#undef RND
786
ed6dd18b
DH
787 if (!buffer || buflen < size)
788 return size;
789
d3ec10aa 790 xdr = (__be32 *)buffer;
ed6dd18b
DH
791 zero = 0;
792#define ENCODE(x) \
793 do { \
d3ec10aa 794 *xdr++ = htonl(x); \
ed6dd18b 795 } while(0)
99455153
DH
796#define ENCODE_DATA(l, s) \
797 do { \
798 u32 _l = (l); \
799 ENCODE(l); \
d3ec10aa
WL
800 memcpy(xdr, (s), _l); \
801 if (_l & 3) \
802 memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
99455153
DH
803 xdr += (_l + 3) >> 2; \
804 } while(0)
56305118
MD
805#define ENCODE_BYTES(l, s) \
806 do { \
807 u32 _l = (l); \
808 memcpy(xdr, (s), _l); \
809 if (_l & 3) \
810 memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
811 xdr += (_l + 3) >> 2; \
812 } while(0)
99455153
DH
813#define ENCODE64(x) \
814 do { \
815 __be64 y = cpu_to_be64(x); \
d3ec10aa 816 memcpy(xdr, &y, 8); \
99455153
DH
817 xdr += 8 >> 2; \
818 } while(0)
819#define ENCODE_STR(s) \
820 do { \
821 const char *_s = (s); \
822 ENCODE_DATA(strlen(_s), _s); \
823 } while(0)
ed6dd18b 824
99455153
DH
825 ENCODE(0); /* flags */
826 ENCODE_DATA(cnlen, key->description + 4); /* cellname */
827 ENCODE(ntoks);
ed6dd18b 828
99455153 829 tok = 0;
146aa8b1 830 for (token = key->payload.data[0]; token; token = token->next) {
99455153
DH
831 toksize = toksizes[tok++];
832 ENCODE(toksize);
833 oldxdr = xdr;
834 ENCODE(token->security_index);
ed6dd18b
DH
835
836 switch (token->security_index) {
837 case RXRPC_SECURITY_RXKAD:
ed6dd18b
DH
838 ENCODE(token->kad->vice_id);
839 ENCODE(token->kad->kvno);
56305118 840 ENCODE_BYTES(8, token->kad->session_key);
ed6dd18b
DH
841 ENCODE(token->kad->start);
842 ENCODE(token->kad->expiry);
843 ENCODE(token->kad->primary_flag);
d2ae4e91
DH
844 if (token->no_leak_key)
845 ENCODE(0);
846 else
847 ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
99455153
DH
848 break;
849
0ca100ff
DH
850 case RXRPC_SECURITY_YFS_RXGK:
851 ENCODE64(token->rxgk->begintime);
852 ENCODE64(token->rxgk->endtime);
853 ENCODE64(token->rxgk->level);
854 ENCODE64(token->rxgk->lifetime);
855 ENCODE64(token->rxgk->bytelife);
856 ENCODE64(token->rxgk->enctype);
857 if (token->no_leak_key)
858 ENCODE(0);
859 else
860 ENCODE_DATA(token->rxgk->key.len, token->rxgk->key.data);
861 ENCODE_DATA(token->rxgk->ticket.len, token->rxgk->ticket.data);
862 break;
863
ed6dd18b 864 default:
d52e419a
DH
865 pr_err("Unsupported key token type (%u)\n",
866 token->security_index);
867 return -ENOPKG;
ed6dd18b 868 }
99455153 869
fadfc57c 870 if (WARN_ON((unsigned long)xdr - (unsigned long)oldxdr !=
84924aac
DH
871 toksize))
872 return -EIO;
ed6dd18b
DH
873 }
874
99455153
DH
875#undef ENCODE_STR
876#undef ENCODE_DATA
877#undef ENCODE64
ed6dd18b
DH
878#undef ENCODE
879
84924aac
DH
880 if (WARN_ON(tok != ntoks))
881 return -EIO;
882 if (WARN_ON((unsigned long)xdr - (unsigned long)buffer != size))
883 return -EIO;
ed6dd18b
DH
884 _leave(" = %zu", size);
885 return size;
ed6dd18b 886}