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