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