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 <crypto/skcipher.h>
14 #include <linux/module.h>
15 #include <linux/net.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(sizeof(*token), GFP_KERNEL);
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 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
270 nomem_yrxgk:
271 kfree(token->rxgk);
272 nomem_token:
273 kfree(token);
274 nomem:
275 return -ENOMEM;
276 reject_token:
277 kfree(token);
278 reject:
279 return -EKEYREJECTED;
280 expired:
281 kfree(token->rxgk);
282 kfree(token);
283 return -EKEYEXPIRED;
284 }
285
286 /*
287 * attempt to parse the data as the XDR format
288 * - the caller guarantees we have more than 7 words
289 */
rxrpc_preparse_xdr(struct key_preparsed_payload * prep)290 static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
291 {
292 const __be32 *xdr = prep->data, *token, *p;
293 const char *cp;
294 unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
295 size_t datalen = prep->datalen;
296 int ret, ret2;
297
298 _enter(",{%x,%x,%x,%x},%zu",
299 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
300 prep->datalen);
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;
320 paddedlen = (len + 3) & ~3;
321 if (paddedlen > datalen)
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;
328 for (; loop < paddedlen; loop++)
329 if (cp[loop])
330 goto not_xdr;
331 _debug("cellname: [%u/%u] '%*.*s'",
332 len, paddedlen, len, len, (const char *) xdr);
333 datalen -= paddedlen;
334 xdr += paddedlen >> 2;
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 */
346 p = xdr;
347 loop = ntoken;
348 do {
349 if (datalen < 8)
350 goto not_xdr;
351 toklen = ntohl(*p++);
352 sec_ix = ntohl(*p);
353 datalen -= 4;
354 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
355 paddedlen = (toklen + 3) & ~3;
356 if (toklen < 20 || toklen > datalen || paddedlen > datalen)
357 goto not_xdr;
358 datalen -= paddedlen;
359 p += paddedlen >> 2;
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 */
370 ret = -EPROTONOSUPPORT;
371 do {
372 toklen = ntohl(*xdr++);
373 token = xdr;
374 xdr += (toklen + 3) / 4;
375
376 sec_ix = ntohl(*token++);
377 toklen -= 4;
378
379 _debug("TOKEN type=%x len=%x", sec_ix, toklen);
380
381 switch (sec_ix) {
382 case RXRPC_SECURITY_RXKAD:
383 ret2 = rxrpc_preparse_xdr_rxkad(prep, datalen, token, toklen);
384 break;
385 case RXRPC_SECURITY_YFS_RXGK:
386 ret2 = rxrpc_preparse_xdr_yfs_rxgk(prep, datalen, token, toklen);
387 break;
388 default:
389 ret2 = -EPROTONOSUPPORT;
390 break;
391 }
392
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;
403 default:
404 ret = ret2;
405 goto error;
406 }
407
408 } while (--ntoken > 0);
409
410 error:
411 _leave(" = %d", ret);
412 return ret;
413
414 not_xdr:
415 _leave(" = -EPROTO");
416 return -EPROTO;
417 }
418
419 /*
420 * Preparse an rxrpc defined key.
421 *
422 * Data should be of the form:
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 */
rxrpc_preparse(struct key_preparsed_payload * prep)434 static int rxrpc_preparse(struct key_preparsed_payload *prep)
435 {
436 const struct rxrpc_key_data_v1 *v1;
437 struct rxrpc_key_token *token, **pp;
438 time64_t expiry;
439 size_t plen;
440 u32 kver;
441 int ret;
442
443 _enter("%zu", prep->datalen);
444
445 /* handle a no-security key */
446 if (!prep->data && prep->datalen == 0)
447 return 0;
448
449 /* determine if the XDR payload format is being used */
450 if (prep->datalen > 7 * 4) {
451 ret = rxrpc_preparse_xdr(prep);
452 if (ret != -EPROTO)
453 return ret;
454 }
455
456 /* get the key interface version number */
457 ret = -EINVAL;
458 if (prep->datalen <= 4 || !prep->data)
459 goto error;
460 memcpy(&kver, prep->data, sizeof(kver));
461 prep->data += sizeof(kver);
462 prep->datalen -= sizeof(kver);
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;
472 if (prep->datalen < sizeof(*v1))
473 goto error;
474
475 v1 = prep->data;
476 if (prep->datalen != sizeof(*v1) + v1->ticket_length)
477 goto error;
478
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);
483 _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
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)
489 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
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]);
494
495 ret = -EPROTONOSUPPORT;
496 if (v1->security_index != RXRPC_SECURITY_RXKAD)
497 goto error;
498
499 plen = sizeof(*token->kad) + v1->ticket_length;
500 prep->quotalen = plen + sizeof(*token);
501
502 ret = -ENOMEM;
503 token = kzalloc(sizeof(*token), GFP_KERNEL);
504 if (!token)
505 goto error;
506 token->kad = kzalloc(plen, GFP_KERNEL);
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);
516
517 /* count the number of tokens attached */
518 prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
519
520 /* attach the data */
521 pp = (struct rxrpc_key_token **)&prep->payload.data[0];
522 while (*pp)
523 pp = &(*pp)->next;
524 *pp = token;
525 expiry = rxrpc_u32_to_time64(token->kad->expiry);
526 if (expiry < prep->expiry)
527 prep->expiry = expiry;
528 token = NULL;
529 ret = 0;
530
531 error_free:
532 kfree(token);
533 error:
534 return ret;
535 }
536
537 /*
538 * Free token list.
539 */
rxrpc_free_token_list(struct rxrpc_key_token * token)540 static 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;
550 case RXRPC_SECURITY_YFS_RXGK:
551 kfree(token->rxgk->ticket.data);
552 kfree(token->rxgk);
553 break;
554 default:
555 pr_err("Unknown token type %x on rxrpc key\n",
556 token->security_index);
557 BUG();
558 }
559
560 kfree(token);
561 }
562 }
563
564 /*
565 * Clean up preparse data.
566 */
rxrpc_free_preparse(struct key_preparsed_payload * prep)567 static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
568 {
569 rxrpc_free_token_list(prep->payload.data[0]);
570 }
571
572 /*
573 * dispose of the data dangling from the corpse of a rxrpc key
574 */
rxrpc_destroy(struct key * key)575 static void rxrpc_destroy(struct key *key)
576 {
577 rxrpc_free_token_list(key->payload.data[0]);
578 }
579
580 /*
581 * describe the rxrpc key
582 */
rxrpc_describe(const struct key * key,struct seq_file * m)583 static void rxrpc_describe(const struct key *key, struct seq_file *m)
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;
597 case RXRPC_SECURITY_YFS_RXGK:
598 seq_puts(m, "ygk");
599 break;
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
609 /*
610 * grab the security key for a socket
611 */
rxrpc_request_key(struct rxrpc_sock * rx,sockptr_t optval,int optlen)612 int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
613 {
614 struct key *key;
615 char *description;
616
617 _enter("");
618
619 if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
620 return -EINVAL;
621
622 description = memdup_sockptr_nul(optval, optlen);
623 if (IS_ERR(description))
624 return PTR_ERR(description);
625
626 key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
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
639 /*
640 * generate a server data key
641 */
rxrpc_get_server_data_key(struct rxrpc_connection * conn,const void * session_key,time64_t expiry,u32 kvno)642 int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
643 const void *session_key,
644 time64_t expiry,
645 u32 kvno)
646 {
647 const struct cred *cred = current_cred();
648 struct key *key;
649 int ret;
650
651 struct {
652 u32 kver;
653 struct rxrpc_key_data_v1 v1;
654 } data;
655
656 _enter("");
657
658 key = key_alloc(&key_type_rxrpc, "x",
659 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
660 KEY_ALLOC_NOT_IN_QUOTA, NULL);
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;
669 data.v1.security_index = RXRPC_SECURITY_RXKAD;
670 data.v1.ticket_length = 0;
671 data.v1.expiry = rxrpc_time64_to_u32(expiry);
672 data.v1.kvno = 0;
673
674 memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
675
676 ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
677 if (ret < 0)
678 goto error;
679
680 conn->key = key;
681 _leave(" = 0 [%d]", key_serial(key));
682 return 0;
683
684 error:
685 key_revoke(key);
686 key_put(key);
687 _leave(" = -ENOMEM [ins %d]", ret);
688 return -ENOMEM;
689 }
690 EXPORT_SYMBOL(rxrpc_get_server_data_key);
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.
698 *
699 * Return: The new key or a negative error code.
700 */
rxrpc_get_null_key(const char * keyname)701 struct key *rxrpc_get_null_key(const char *keyname)
702 {
703 const struct cred *cred = current_cred();
704 struct key *key;
705 int ret;
706
707 key = key_alloc(&key_type_rxrpc, keyname,
708 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
709 KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
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 }
722 EXPORT_SYMBOL(rxrpc_get_null_key);
723
724 /*
725 * read the contents of an rxrpc key
726 * - this returns the result in XDR form
727 */
rxrpc_read(const struct key * key,char * buffer,size_t buflen)728 static long rxrpc_read(const struct key *key,
729 char *buffer, size_t buflen)
730 {
731 const struct rxrpc_key_token *token;
732 size_t size;
733 __be32 *xdr, *oldxdr;
734 u32 cnlen, toksize, ntoks, tok, zero;
735 u16 toksizes[AFSTOKEN_MAX];
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
744 #define RND(X) (((X) + 3) & ~3)
745
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 */
749 size += RND(cnlen); /* cellname */
750 size += 1 * 4; /* token count */
751
752 ntoks = 0;
753 for (token = key->payload.data[0]; token; token = token->next) {
754 toksize = 4; /* sec index */
755
756 switch (token->security_index) {
757 case RXRPC_SECURITY_RXKAD:
758 toksize += 8 * 4; /* viceid, kvno, key*2, begin,
759 * end, primary, tktlen */
760 if (!token->no_leak_key)
761 toksize += RND(token->kad->ticket_len);
762 break;
763
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
771 default: /* we have a ticket we can't encode */
772 pr_err("Unsupported key token type (%u)\n",
773 token->security_index);
774 return -ENOPKG;
775 }
776
777 _debug("token[%u]: toksize=%u", ntoks, toksize);
778 if (WARN_ON(toksize > AFSTOKEN_LENGTH_MAX))
779 return -EIO;
780
781 toksizes[ntoks++] = toksize;
782 size += toksize + 4; /* each token has a length word */
783 }
784
785 #undef RND
786
787 if (!buffer || buflen < size)
788 return size;
789
790 xdr = (__be32 *)buffer;
791 zero = 0;
792 #define ENCODE(x) \
793 do { \
794 *xdr++ = htonl(x); \
795 } while(0)
796 #define ENCODE_DATA(l, s) \
797 do { \
798 u32 _l = (l); \
799 ENCODE(l); \
800 memcpy(xdr, (s), _l); \
801 if (_l & 3) \
802 memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
803 xdr += (_l + 3) >> 2; \
804 } while(0)
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)
813 #define ENCODE64(x) \
814 do { \
815 __be64 y = cpu_to_be64(x); \
816 memcpy(xdr, &y, 8); \
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)
824
825 ENCODE(0); /* flags */
826 ENCODE_DATA(cnlen, key->description + 4); /* cellname */
827 ENCODE(ntoks);
828
829 tok = 0;
830 for (token = key->payload.data[0]; token; token = token->next) {
831 toksize = toksizes[tok++];
832 ENCODE(toksize);
833 oldxdr = xdr;
834 ENCODE(token->security_index);
835
836 switch (token->security_index) {
837 case RXRPC_SECURITY_RXKAD:
838 ENCODE(token->kad->vice_id);
839 ENCODE(token->kad->kvno);
840 ENCODE_BYTES(8, token->kad->session_key);
841 ENCODE(token->kad->start);
842 ENCODE(token->kad->expiry);
843 ENCODE(token->kad->primary_flag);
844 if (token->no_leak_key)
845 ENCODE(0);
846 else
847 ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
848 break;
849
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
864 default:
865 pr_err("Unsupported key token type (%u)\n",
866 token->security_index);
867 return -ENOPKG;
868 }
869
870 if (WARN_ON((unsigned long)xdr - (unsigned long)oldxdr !=
871 toksize))
872 return -EIO;
873 }
874
875 #undef ENCODE_STR
876 #undef ENCODE_DATA
877 #undef ENCODE64
878 #undef ENCODE
879
880 if (WARN_ON(tok != ntoks))
881 return -EIO;
882 if (WARN_ON((unsigned long)xdr - (unsigned long)buffer != size))
883 return -EIO;
884 _leave(" = %zu", size);
885 return size;
886 }
887