rxrpc: Split the server key type (rxrpc_s) into its own file
[linux-block.git] / net / rxrpc / key.c
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@CAMBRIDGE.REDHAT.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  */
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
132 /*
133  * attempt to parse the data as the XDR format
134  * - the caller guarantees we have more than 7 words
135  */
136 static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
137 {
138         const __be32 *xdr = prep->data, *token;
139         const char *cp;
140         unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
141         size_t datalen = prep->datalen;
142         int ret;
143
144         _enter(",{%x,%x,%x,%x},%zu",
145                ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
146                prep->datalen);
147
148         if (datalen > AFSTOKEN_LENGTH_MAX)
149                 goto not_xdr;
150
151         /* XDR is an array of __be32's */
152         if (datalen & 3)
153                 goto not_xdr;
154
155         /* the flags should be 0 (the setpag bit must be handled by
156          * userspace) */
157         if (ntohl(*xdr++) != 0)
158                 goto not_xdr;
159         datalen -= 4;
160
161         /* check the cell name */
162         len = ntohl(*xdr++);
163         if (len < 1 || len > AFSTOKEN_CELL_MAX)
164                 goto not_xdr;
165         datalen -= 4;
166         paddedlen = (len + 3) & ~3;
167         if (paddedlen > datalen)
168                 goto not_xdr;
169
170         cp = (const char *) xdr;
171         for (loop = 0; loop < len; loop++)
172                 if (!isprint(cp[loop]))
173                         goto not_xdr;
174         for (; loop < paddedlen; loop++)
175                 if (cp[loop])
176                         goto not_xdr;
177         _debug("cellname: [%u/%u] '%*.*s'",
178                len, paddedlen, len, len, (const char *) xdr);
179         datalen -= paddedlen;
180         xdr += paddedlen >> 2;
181
182         /* get the token count */
183         if (datalen < 12)
184                 goto not_xdr;
185         ntoken = ntohl(*xdr++);
186         datalen -= 4;
187         _debug("ntoken: %x", ntoken);
188         if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
189                 goto not_xdr;
190
191         /* check each token wrapper */
192         token = xdr;
193         loop = ntoken;
194         do {
195                 if (datalen < 8)
196                         goto not_xdr;
197                 toklen = ntohl(*xdr++);
198                 sec_ix = ntohl(*xdr);
199                 datalen -= 4;
200                 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
201                 paddedlen = (toklen + 3) & ~3;
202                 if (toklen < 20 || toklen > datalen || paddedlen > datalen)
203                         goto not_xdr;
204                 datalen -= paddedlen;
205                 xdr += paddedlen >> 2;
206
207         } while (--loop > 0);
208
209         _debug("remainder: %zu", datalen);
210         if (datalen != 0)
211                 goto not_xdr;
212
213         /* okay: we're going to assume it's valid XDR format
214          * - we ignore the cellname, relying on the key to be correctly named
215          */
216         do {
217                 xdr = token;
218                 toklen = ntohl(*xdr++);
219                 token = xdr + ((toklen + 3) >> 2);
220                 sec_ix = ntohl(*xdr++);
221                 toklen -= 4;
222
223                 _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
224
225                 switch (sec_ix) {
226                 case RXRPC_SECURITY_RXKAD:
227                         ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, toklen);
228                         if (ret != 0)
229                                 goto error;
230                         break;
231
232                 default:
233                         ret = -EPROTONOSUPPORT;
234                         goto error;
235                 }
236
237         } while (--ntoken > 0);
238
239         _leave(" = 0");
240         return 0;
241
242 not_xdr:
243         _leave(" = -EPROTO");
244         return -EPROTO;
245 error:
246         _leave(" = %d", ret);
247         return ret;
248 }
249
250 /*
251  * Preparse an rxrpc defined key.
252  *
253  * Data should be of the form:
254  *      OFFSET  LEN     CONTENT
255  *      0       4       key interface version number
256  *      4       2       security index (type)
257  *      6       2       ticket length
258  *      8       4       key expiry time (time_t)
259  *      12      4       kvno
260  *      16      8       session key
261  *      24      [len]   ticket
262  *
263  * if no data is provided, then a no-security key is made
264  */
265 static int rxrpc_preparse(struct key_preparsed_payload *prep)
266 {
267         const struct rxrpc_key_data_v1 *v1;
268         struct rxrpc_key_token *token, **pp;
269         time64_t expiry;
270         size_t plen;
271         u32 kver;
272         int ret;
273
274         _enter("%zu", prep->datalen);
275
276         /* handle a no-security key */
277         if (!prep->data && prep->datalen == 0)
278                 return 0;
279
280         /* determine if the XDR payload format is being used */
281         if (prep->datalen > 7 * 4) {
282                 ret = rxrpc_preparse_xdr(prep);
283                 if (ret != -EPROTO)
284                         return ret;
285         }
286
287         /* get the key interface version number */
288         ret = -EINVAL;
289         if (prep->datalen <= 4 || !prep->data)
290                 goto error;
291         memcpy(&kver, prep->data, sizeof(kver));
292         prep->data += sizeof(kver);
293         prep->datalen -= sizeof(kver);
294
295         _debug("KEY I/F VERSION: %u", kver);
296
297         ret = -EKEYREJECTED;
298         if (kver != 1)
299                 goto error;
300
301         /* deal with a version 1 key */
302         ret = -EINVAL;
303         if (prep->datalen < sizeof(*v1))
304                 goto error;
305
306         v1 = prep->data;
307         if (prep->datalen != sizeof(*v1) + v1->ticket_length)
308                 goto error;
309
310         _debug("SCIX: %u", v1->security_index);
311         _debug("TLEN: %u", v1->ticket_length);
312         _debug("EXPY: %x", v1->expiry);
313         _debug("KVNO: %u", v1->kvno);
314         _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
315                v1->session_key[0], v1->session_key[1],
316                v1->session_key[2], v1->session_key[3],
317                v1->session_key[4], v1->session_key[5],
318                v1->session_key[6], v1->session_key[7]);
319         if (v1->ticket_length >= 8)
320                 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
321                        v1->ticket[0], v1->ticket[1],
322                        v1->ticket[2], v1->ticket[3],
323                        v1->ticket[4], v1->ticket[5],
324                        v1->ticket[6], v1->ticket[7]);
325
326         ret = -EPROTONOSUPPORT;
327         if (v1->security_index != RXRPC_SECURITY_RXKAD)
328                 goto error;
329
330         plen = sizeof(*token->kad) + v1->ticket_length;
331         prep->quotalen = plen + sizeof(*token);
332
333         ret = -ENOMEM;
334         token = kzalloc(sizeof(*token), GFP_KERNEL);
335         if (!token)
336                 goto error;
337         token->kad = kzalloc(plen, GFP_KERNEL);
338         if (!token->kad)
339                 goto error_free;
340
341         token->security_index           = RXRPC_SECURITY_RXKAD;
342         token->kad->ticket_len          = v1->ticket_length;
343         token->kad->expiry              = v1->expiry;
344         token->kad->kvno                = v1->kvno;
345         memcpy(&token->kad->session_key, &v1->session_key, 8);
346         memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
347
348         /* count the number of tokens attached */
349         prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
350
351         /* attach the data */
352         pp = (struct rxrpc_key_token **)&prep->payload.data[0];
353         while (*pp)
354                 pp = &(*pp)->next;
355         *pp = token;
356         expiry = rxrpc_u32_to_time64(token->kad->expiry);
357         if (expiry < prep->expiry)
358                 prep->expiry = expiry;
359         token = NULL;
360         ret = 0;
361
362 error_free:
363         kfree(token);
364 error:
365         return ret;
366 }
367
368 /*
369  * Free token list.
370  */
371 static void rxrpc_free_token_list(struct rxrpc_key_token *token)
372 {
373         struct rxrpc_key_token *next;
374
375         for (; token; token = next) {
376                 next = token->next;
377                 switch (token->security_index) {
378                 case RXRPC_SECURITY_RXKAD:
379                         kfree(token->kad);
380                         break;
381                 default:
382                         pr_err("Unknown token type %x on rxrpc key\n",
383                                token->security_index);
384                         BUG();
385                 }
386
387                 kfree(token);
388         }
389 }
390
391 /*
392  * Clean up preparse data.
393  */
394 static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
395 {
396         rxrpc_free_token_list(prep->payload.data[0]);
397 }
398
399 /*
400  * dispose of the data dangling from the corpse of a rxrpc key
401  */
402 static void rxrpc_destroy(struct key *key)
403 {
404         rxrpc_free_token_list(key->payload.data[0]);
405 }
406
407 /*
408  * describe the rxrpc key
409  */
410 static void rxrpc_describe(const struct key *key, struct seq_file *m)
411 {
412         const struct rxrpc_key_token *token;
413         const char *sep = ": ";
414
415         seq_puts(m, key->description);
416
417         for (token = key->payload.data[0]; token; token = token->next) {
418                 seq_puts(m, sep);
419
420                 switch (token->security_index) {
421                 case RXRPC_SECURITY_RXKAD:
422                         seq_puts(m, "ka");
423                         break;
424                 default: /* we have a ticket we can't encode */
425                         seq_printf(m, "%u", token->security_index);
426                         break;
427                 }
428
429                 sep = " ";
430         }
431 }
432
433 /*
434  * grab the security key for a socket
435  */
436 int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
437 {
438         struct key *key;
439         char *description;
440
441         _enter("");
442
443         if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
444                 return -EINVAL;
445
446         description = memdup_sockptr_nul(optval, optlen);
447         if (IS_ERR(description))
448                 return PTR_ERR(description);
449
450         key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
451         if (IS_ERR(key)) {
452                 kfree(description);
453                 _leave(" = %ld", PTR_ERR(key));
454                 return PTR_ERR(key);
455         }
456
457         rx->key = key;
458         kfree(description);
459         _leave(" = 0 [key %x]", key->serial);
460         return 0;
461 }
462
463 /*
464  * generate a server data key
465  */
466 int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
467                               const void *session_key,
468                               time64_t expiry,
469                               u32 kvno)
470 {
471         const struct cred *cred = current_cred();
472         struct key *key;
473         int ret;
474
475         struct {
476                 u32 kver;
477                 struct rxrpc_key_data_v1 v1;
478         } data;
479
480         _enter("");
481
482         key = key_alloc(&key_type_rxrpc, "x",
483                         GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
484                         KEY_ALLOC_NOT_IN_QUOTA, NULL);
485         if (IS_ERR(key)) {
486                 _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
487                 return -ENOMEM;
488         }
489
490         _debug("key %d", key_serial(key));
491
492         data.kver = 1;
493         data.v1.security_index = RXRPC_SECURITY_RXKAD;
494         data.v1.ticket_length = 0;
495         data.v1.expiry = rxrpc_time64_to_u32(expiry);
496         data.v1.kvno = 0;
497
498         memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
499
500         ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
501         if (ret < 0)
502                 goto error;
503
504         conn->params.key = key;
505         _leave(" = 0 [%d]", key_serial(key));
506         return 0;
507
508 error:
509         key_revoke(key);
510         key_put(key);
511         _leave(" = -ENOMEM [ins %d]", ret);
512         return -ENOMEM;
513 }
514 EXPORT_SYMBOL(rxrpc_get_server_data_key);
515
516 /**
517  * rxrpc_get_null_key - Generate a null RxRPC key
518  * @keyname: The name to give the key.
519  *
520  * Generate a null RxRPC key that can be used to indicate anonymous security is
521  * required for a particular domain.
522  */
523 struct key *rxrpc_get_null_key(const char *keyname)
524 {
525         const struct cred *cred = current_cred();
526         struct key *key;
527         int ret;
528
529         key = key_alloc(&key_type_rxrpc, keyname,
530                         GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
531                         KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
532         if (IS_ERR(key))
533                 return key;
534
535         ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
536         if (ret < 0) {
537                 key_revoke(key);
538                 key_put(key);
539                 return ERR_PTR(ret);
540         }
541
542         return key;
543 }
544 EXPORT_SYMBOL(rxrpc_get_null_key);
545
546 /*
547  * read the contents of an rxrpc key
548  * - this returns the result in XDR form
549  */
550 static long rxrpc_read(const struct key *key,
551                        char *buffer, size_t buflen)
552 {
553         const struct rxrpc_key_token *token;
554         size_t size;
555         __be32 *xdr, *oldxdr;
556         u32 cnlen, toksize, ntoks, tok, zero;
557         u16 toksizes[AFSTOKEN_MAX];
558
559         _enter("");
560
561         /* we don't know what form we should return non-AFS keys in */
562         if (memcmp(key->description, "afs@", 4) != 0)
563                 return -EOPNOTSUPP;
564         cnlen = strlen(key->description + 4);
565
566 #define RND(X) (((X) + 3) & ~3)
567
568         /* AFS keys we return in XDR form, so we need to work out the size of
569          * the XDR */
570         size = 2 * 4;   /* flags, cellname len */
571         size += RND(cnlen);     /* cellname */
572         size += 1 * 4;  /* token count */
573
574         ntoks = 0;
575         for (token = key->payload.data[0]; token; token = token->next) {
576                 toksize = 4;    /* sec index */
577
578                 switch (token->security_index) {
579                 case RXRPC_SECURITY_RXKAD:
580                         toksize += 8 * 4;       /* viceid, kvno, key*2, begin,
581                                                  * end, primary, tktlen */
582                         toksize += RND(token->kad->ticket_len);
583                         break;
584
585                 default: /* we have a ticket we can't encode */
586                         pr_err("Unsupported key token type (%u)\n",
587                                token->security_index);
588                         continue;
589                 }
590
591                 _debug("token[%u]: toksize=%u", ntoks, toksize);
592                 ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
593
594                 toksizes[ntoks++] = toksize;
595                 size += toksize + 4; /* each token has a length word */
596         }
597
598 #undef RND
599
600         if (!buffer || buflen < size)
601                 return size;
602
603         xdr = (__be32 *)buffer;
604         zero = 0;
605 #define ENCODE(x)                               \
606         do {                                    \
607                 *xdr++ = htonl(x);              \
608         } while(0)
609 #define ENCODE_DATA(l, s)                                               \
610         do {                                                            \
611                 u32 _l = (l);                                           \
612                 ENCODE(l);                                              \
613                 memcpy(xdr, (s), _l);                                   \
614                 if (_l & 3)                                             \
615                         memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));    \
616                 xdr += (_l + 3) >> 2;                                   \
617         } while(0)
618 #define ENCODE_BYTES(l, s)                                              \
619         do {                                                            \
620                 u32 _l = (l);                                           \
621                 memcpy(xdr, (s), _l);                                   \
622                 if (_l & 3)                                             \
623                         memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));    \
624                 xdr += (_l + 3) >> 2;                                   \
625         } while(0)
626 #define ENCODE64(x)                                     \
627         do {                                            \
628                 __be64 y = cpu_to_be64(x);              \
629                 memcpy(xdr, &y, 8);                     \
630                 xdr += 8 >> 2;                          \
631         } while(0)
632 #define ENCODE_STR(s)                           \
633         do {                                    \
634                 const char *_s = (s);           \
635                 ENCODE_DATA(strlen(_s), _s);    \
636         } while(0)
637
638         ENCODE(0);                                      /* flags */
639         ENCODE_DATA(cnlen, key->description + 4);       /* cellname */
640         ENCODE(ntoks);
641
642         tok = 0;
643         for (token = key->payload.data[0]; token; token = token->next) {
644                 toksize = toksizes[tok++];
645                 ENCODE(toksize);
646                 oldxdr = xdr;
647                 ENCODE(token->security_index);
648
649                 switch (token->security_index) {
650                 case RXRPC_SECURITY_RXKAD:
651                         ENCODE(token->kad->vice_id);
652                         ENCODE(token->kad->kvno);
653                         ENCODE_BYTES(8, token->kad->session_key);
654                         ENCODE(token->kad->start);
655                         ENCODE(token->kad->expiry);
656                         ENCODE(token->kad->primary_flag);
657                         ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
658                         break;
659
660                 default:
661                         break;
662                 }
663
664                 ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
665                           toksize);
666         }
667
668 #undef ENCODE_STR
669 #undef ENCODE_DATA
670 #undef ENCODE64
671 #undef ENCODE
672
673         ASSERTCMP(tok, ==, ntoks);
674         ASSERTCMP((char __user *) xdr - buffer, ==, size);
675         _leave(" = %zu", size);
676         return size;
677 }