]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/rxrpc/ar-key.c
RxRPC: Allow RxRPC keys to be read
[karo-tx-linux.git] / net / rxrpc / ar-key.c
1 /* RxRPC key management
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  *
11  * RxRPC keys should have a description of describing their purpose:
12  *      "afs@CAMBRIDGE.REDHAT.COM>
13  */
14
15 #include <linux/module.h>
16 #include <linux/net.h>
17 #include <linux/skbuff.h>
18 #include <linux/key-type.h>
19 #include <linux/crypto.h>
20 #include <linux/ctype.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_instantiate(struct key *, const void *, size_t);
28 static int rxrpc_instantiate_s(struct key *, const void *, size_t);
29 static void rxrpc_destroy(struct key *);
30 static void rxrpc_destroy_s(struct key *);
31 static void rxrpc_describe(const struct key *, struct seq_file *);
32 static long rxrpc_read(const struct key *, char __user *, size_t);
33
34 /*
35  * rxrpc defined keys take an arbitrary string as the description and an
36  * arbitrary blob of data as the payload
37  */
38 struct key_type key_type_rxrpc = {
39         .name           = "rxrpc",
40         .instantiate    = rxrpc_instantiate,
41         .match          = user_match,
42         .destroy        = rxrpc_destroy,
43         .describe       = rxrpc_describe,
44         .read           = rxrpc_read,
45 };
46 EXPORT_SYMBOL(key_type_rxrpc);
47
48 /*
49  * rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
50  * description and an 8-byte decryption key as the payload
51  */
52 struct key_type key_type_rxrpc_s = {
53         .name           = "rxrpc_s",
54         .instantiate    = rxrpc_instantiate_s,
55         .match          = user_match,
56         .destroy        = rxrpc_destroy_s,
57         .describe       = rxrpc_describe,
58 };
59
60 /*
61  * parse an RxKAD type XDR format token
62  * - the caller guarantees we have at least 4 words
63  */
64 static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
65                                        unsigned toklen)
66 {
67         struct rxrpc_key_token *token;
68         size_t plen;
69         u32 tktlen;
70         int ret;
71
72         _enter(",{%x,%x,%x,%x},%u",
73                ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
74                toklen);
75
76         if (toklen <= 8 * 4)
77                 return -EKEYREJECTED;
78         tktlen = ntohl(xdr[7]);
79         _debug("tktlen: %x", tktlen);
80         if (tktlen > AFSTOKEN_RK_TIX_MAX)
81                 return -EKEYREJECTED;
82         if (8 * 4 + tktlen != toklen)
83                 return -EKEYREJECTED;
84
85         plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
86         ret = key_payload_reserve(key, key->datalen + plen);
87         if (ret < 0)
88                 return ret;
89
90         plen -= sizeof(*token);
91         token = kmalloc(sizeof(*token), GFP_KERNEL);
92         if (!token)
93                 return -ENOMEM;
94
95         token->kad = kmalloc(plen, GFP_KERNEL);
96         if (!token->kad) {
97                 kfree(token);
98                 return -ENOMEM;
99         }
100
101         token->security_index   = RXRPC_SECURITY_RXKAD;
102         token->kad->ticket_len  = tktlen;
103         token->kad->vice_id     = ntohl(xdr[0]);
104         token->kad->kvno        = ntohl(xdr[1]);
105         token->kad->start       = ntohl(xdr[4]);
106         token->kad->expiry      = ntohl(xdr[5]);
107         token->kad->primary_flag = ntohl(xdr[6]);
108         memcpy(&token->kad->session_key, &xdr[2], 8);
109         memcpy(&token->kad->ticket, &xdr[8], tktlen);
110
111         _debug("SCIX: %u", token->security_index);
112         _debug("TLEN: %u", token->kad->ticket_len);
113         _debug("EXPY: %x", token->kad->expiry);
114         _debug("KVNO: %u", token->kad->kvno);
115         _debug("PRIM: %u", token->kad->primary_flag);
116         _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
117                token->kad->session_key[0], token->kad->session_key[1],
118                token->kad->session_key[2], token->kad->session_key[3],
119                token->kad->session_key[4], token->kad->session_key[5],
120                token->kad->session_key[6], token->kad->session_key[7]);
121         if (token->kad->ticket_len >= 8)
122                 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
123                        token->kad->ticket[0], token->kad->ticket[1],
124                        token->kad->ticket[2], token->kad->ticket[3],
125                        token->kad->ticket[4], token->kad->ticket[5],
126                        token->kad->ticket[6], token->kad->ticket[7]);
127
128         /* count the number of tokens attached */
129         key->type_data.x[0]++;
130
131         /* attach the data */
132         token->next = key->payload.data;
133         key->payload.data = token;
134         if (token->kad->expiry < key->expiry)
135                 key->expiry = token->kad->expiry;
136
137         _leave(" = 0");
138         return 0;
139 }
140
141 /*
142  * attempt to parse the data as the XDR format
143  * - the caller guarantees we have more than 7 words
144  */
145 static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen)
146 {
147         const __be32 *xdr = data, *token;
148         const char *cp;
149         unsigned len, tmp, loop, ntoken, toklen, sec_ix;
150         int ret;
151
152         _enter(",{%x,%x,%x,%x},%zu",
153                ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
154                datalen);
155
156         if (datalen > AFSTOKEN_LENGTH_MAX)
157                 goto not_xdr;
158
159         /* XDR is an array of __be32's */
160         if (datalen & 3)
161                 goto not_xdr;
162
163         /* the flags should be 0 (the setpag bit must be handled by
164          * userspace) */
165         if (ntohl(*xdr++) != 0)
166                 goto not_xdr;
167         datalen -= 4;
168
169         /* check the cell name */
170         len = ntohl(*xdr++);
171         if (len < 1 || len > AFSTOKEN_CELL_MAX)
172                 goto not_xdr;
173         datalen -= 4;
174         tmp = (len + 3) & ~3;
175         if (tmp > datalen)
176                 goto not_xdr;
177
178         cp = (const char *) xdr;
179         for (loop = 0; loop < len; loop++)
180                 if (!isprint(cp[loop]))
181                         goto not_xdr;
182         if (len < tmp)
183                 for (; loop < tmp; loop++)
184                         if (cp[loop])
185                                 goto not_xdr;
186         _debug("cellname: [%u/%u] '%*.*s'",
187                len, tmp, len, len, (const char *) xdr);
188         datalen -= tmp;
189         xdr += tmp >> 2;
190
191         /* get the token count */
192         if (datalen < 12)
193                 goto not_xdr;
194         ntoken = ntohl(*xdr++);
195         datalen -= 4;
196         _debug("ntoken: %x", ntoken);
197         if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
198                 goto not_xdr;
199
200         /* check each token wrapper */
201         token = xdr;
202         loop = ntoken;
203         do {
204                 if (datalen < 8)
205                         goto not_xdr;
206                 toklen = ntohl(*xdr++);
207                 sec_ix = ntohl(*xdr);
208                 datalen -= 4;
209                 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
210                 if (toklen < 20 || toklen > datalen)
211                         goto not_xdr;
212                 datalen -= (toklen + 3) & ~3;
213                 xdr += (toklen + 3) >> 2;
214
215         } while (--loop > 0);
216
217         _debug("remainder: %zu", datalen);
218         if (datalen != 0)
219                 goto not_xdr;
220
221         /* okay: we're going to assume it's valid XDR format
222          * - we ignore the cellname, relying on the key to be correctly named
223          */
224         do {
225                 xdr = token;
226                 toklen = ntohl(*xdr++);
227                 token = xdr + ((toklen + 3) >> 2);
228                 sec_ix = ntohl(*xdr++);
229                 toklen -= 4;
230
231                 switch (sec_ix) {
232                 case RXRPC_SECURITY_RXKAD:
233                         ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
234                         if (ret != 0)
235                                 goto error;
236                         break;
237
238                 default:
239                         ret = -EPROTONOSUPPORT;
240                         goto error;
241                 }
242
243         } while (--ntoken > 0);
244
245         _leave(" = 0");
246         return 0;
247
248 not_xdr:
249         _leave(" = -EPROTO");
250         return -EPROTO;
251 error:
252         _leave(" = %d", ret);
253         return ret;
254 }
255
256 /*
257  * instantiate an rxrpc defined key
258  * data should be of the form:
259  *      OFFSET  LEN     CONTENT
260  *      0       4       key interface version number
261  *      4       2       security index (type)
262  *      6       2       ticket length
263  *      8       4       key expiry time (time_t)
264  *      12      4       kvno
265  *      16      8       session key
266  *      24      [len]   ticket
267  *
268  * if no data is provided, then a no-security key is made
269  */
270 static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
271 {
272         const struct rxrpc_key_data_v1 *v1;
273         struct rxrpc_key_token *token, **pp;
274         size_t plen;
275         u32 kver;
276         int ret;
277
278         _enter("{%x},,%zu", key_serial(key), datalen);
279
280         /* handle a no-security key */
281         if (!data && datalen == 0)
282                 return 0;
283
284         /* determine if the XDR payload format is being used */
285         if (datalen > 7 * 4) {
286                 ret = rxrpc_instantiate_xdr(key, data, datalen);
287                 if (ret != -EPROTO)
288                         return ret;
289         }
290
291         /* get the key interface version number */
292         ret = -EINVAL;
293         if (datalen <= 4 || !data)
294                 goto error;
295         memcpy(&kver, data, sizeof(kver));
296         data += sizeof(kver);
297         datalen -= sizeof(kver);
298
299         _debug("KEY I/F VERSION: %u", kver);
300
301         ret = -EKEYREJECTED;
302         if (kver != 1)
303                 goto error;
304
305         /* deal with a version 1 key */
306         ret = -EINVAL;
307         if (datalen < sizeof(*v1))
308                 goto error;
309
310         v1 = data;
311         if (datalen != sizeof(*v1) + v1->ticket_length)
312                 goto error;
313
314         _debug("SCIX: %u", v1->security_index);
315         _debug("TLEN: %u", v1->ticket_length);
316         _debug("EXPY: %x", v1->expiry);
317         _debug("KVNO: %u", v1->kvno);
318         _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
319                v1->session_key[0], v1->session_key[1],
320                v1->session_key[2], v1->session_key[3],
321                v1->session_key[4], v1->session_key[5],
322                v1->session_key[6], v1->session_key[7]);
323         if (v1->ticket_length >= 8)
324                 _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
325                        v1->ticket[0], v1->ticket[1],
326                        v1->ticket[2], v1->ticket[3],
327                        v1->ticket[4], v1->ticket[5],
328                        v1->ticket[6], v1->ticket[7]);
329
330         ret = -EPROTONOSUPPORT;
331         if (v1->security_index != RXRPC_SECURITY_RXKAD)
332                 goto error;
333
334         plen = sizeof(*token->kad) + v1->ticket_length;
335         ret = key_payload_reserve(key, plen + sizeof(*token));
336         if (ret < 0)
337                 goto error;
338
339         ret = -ENOMEM;
340         token = kmalloc(sizeof(*token), GFP_KERNEL);
341         if (!token)
342                 goto error;
343         token->kad = kmalloc(plen, GFP_KERNEL);
344         if (!token->kad)
345                 goto error_free;
346
347         token->security_index           = RXRPC_SECURITY_RXKAD;
348         token->kad->ticket_len          = v1->ticket_length;
349         token->kad->expiry              = v1->expiry;
350         token->kad->kvno                = v1->kvno;
351         memcpy(&token->kad->session_key, &v1->session_key, 8);
352         memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
353
354         /* attach the data */
355         key->type_data.x[0]++;
356
357         pp = (struct rxrpc_key_token **)&key->payload.data;
358         while (*pp)
359                 pp = &(*pp)->next;
360         *pp = token;
361         if (token->kad->expiry < key->expiry)
362                 key->expiry = token->kad->expiry;
363         token = NULL;
364         ret = 0;
365
366 error_free:
367         kfree(token);
368 error:
369         return ret;
370 }
371
372 /*
373  * instantiate a server secret key
374  * data should be a pointer to the 8-byte secret key
375  */
376 static int rxrpc_instantiate_s(struct key *key, const void *data,
377                                size_t datalen)
378 {
379         struct crypto_blkcipher *ci;
380
381         _enter("{%x},,%zu", key_serial(key), datalen);
382
383         if (datalen != 8)
384                 return -EINVAL;
385
386         memcpy(&key->type_data, data, 8);
387
388         ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
389         if (IS_ERR(ci)) {
390                 _leave(" = %ld", PTR_ERR(ci));
391                 return PTR_ERR(ci);
392         }
393
394         if (crypto_blkcipher_setkey(ci, data, 8) < 0)
395                 BUG();
396
397         key->payload.data = ci;
398         _leave(" = 0");
399         return 0;
400 }
401
402 /*
403  * dispose of the data dangling from the corpse of a rxrpc key
404  */
405 static void rxrpc_destroy(struct key *key)
406 {
407         struct rxrpc_key_token *token;
408
409         while ((token = key->payload.data)) {
410                 key->payload.data = token->next;
411                 switch (token->security_index) {
412                 case RXRPC_SECURITY_RXKAD:
413                         kfree(token->kad);
414                         break;
415                 default:
416                         printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
417                                token->security_index);
418                         BUG();
419                 }
420
421                 kfree(token);
422         }
423 }
424
425 /*
426  * dispose of the data dangling from the corpse of a rxrpc key
427  */
428 static void rxrpc_destroy_s(struct key *key)
429 {
430         if (key->payload.data) {
431                 crypto_free_blkcipher(key->payload.data);
432                 key->payload.data = NULL;
433         }
434 }
435
436 /*
437  * describe the rxrpc key
438  */
439 static void rxrpc_describe(const struct key *key, struct seq_file *m)
440 {
441         seq_puts(m, key->description);
442 }
443
444 /*
445  * grab the security key for a socket
446  */
447 int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen)
448 {
449         struct key *key;
450         char *description;
451
452         _enter("");
453
454         if (optlen <= 0 || optlen > PAGE_SIZE - 1)
455                 return -EINVAL;
456
457         description = kmalloc(optlen + 1, GFP_KERNEL);
458         if (!description)
459                 return -ENOMEM;
460
461         if (copy_from_user(description, optval, optlen)) {
462                 kfree(description);
463                 return -EFAULT;
464         }
465         description[optlen] = 0;
466
467         key = request_key(&key_type_rxrpc, description, NULL);
468         if (IS_ERR(key)) {
469                 kfree(description);
470                 _leave(" = %ld", PTR_ERR(key));
471                 return PTR_ERR(key);
472         }
473
474         rx->key = key;
475         kfree(description);
476         _leave(" = 0 [key %x]", key->serial);
477         return 0;
478 }
479
480 /*
481  * grab the security keyring for a server socket
482  */
483 int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval,
484                          int optlen)
485 {
486         struct key *key;
487         char *description;
488
489         _enter("");
490
491         if (optlen <= 0 || optlen > PAGE_SIZE - 1)
492                 return -EINVAL;
493
494         description = kmalloc(optlen + 1, GFP_KERNEL);
495         if (!description)
496                 return -ENOMEM;
497
498         if (copy_from_user(description, optval, optlen)) {
499                 kfree(description);
500                 return -EFAULT;
501         }
502         description[optlen] = 0;
503
504         key = request_key(&key_type_keyring, description, NULL);
505         if (IS_ERR(key)) {
506                 kfree(description);
507                 _leave(" = %ld", PTR_ERR(key));
508                 return PTR_ERR(key);
509         }
510
511         rx->securities = key;
512         kfree(description);
513         _leave(" = 0 [key %x]", key->serial);
514         return 0;
515 }
516
517 /*
518  * generate a server data key
519  */
520 int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
521                               const void *session_key,
522                               time_t expiry,
523                               u32 kvno)
524 {
525         const struct cred *cred = current_cred();
526         struct key *key;
527         int ret;
528
529         struct {
530                 u32 kver;
531                 struct rxrpc_key_data_v1 v1;
532         } data;
533
534         _enter("");
535
536         key = key_alloc(&key_type_rxrpc, "x", 0, 0, cred, 0,
537                         KEY_ALLOC_NOT_IN_QUOTA);
538         if (IS_ERR(key)) {
539                 _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
540                 return -ENOMEM;
541         }
542
543         _debug("key %d", key_serial(key));
544
545         data.kver = 1;
546         data.v1.security_index = RXRPC_SECURITY_RXKAD;
547         data.v1.ticket_length = 0;
548         data.v1.expiry = expiry;
549         data.v1.kvno = 0;
550
551         memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
552
553         ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
554         if (ret < 0)
555                 goto error;
556
557         conn->key = key;
558         _leave(" = 0 [%d]", key_serial(key));
559         return 0;
560
561 error:
562         key_revoke(key);
563         key_put(key);
564         _leave(" = -ENOMEM [ins %d]", ret);
565         return -ENOMEM;
566 }
567 EXPORT_SYMBOL(rxrpc_get_server_data_key);
568
569 /**
570  * rxrpc_get_null_key - Generate a null RxRPC key
571  * @keyname: The name to give the key.
572  *
573  * Generate a null RxRPC key that can be used to indicate anonymous security is
574  * required for a particular domain.
575  */
576 struct key *rxrpc_get_null_key(const char *keyname)
577 {
578         const struct cred *cred = current_cred();
579         struct key *key;
580         int ret;
581
582         key = key_alloc(&key_type_rxrpc, keyname, 0, 0, cred,
583                         KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
584         if (IS_ERR(key))
585                 return key;
586
587         ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
588         if (ret < 0) {
589                 key_revoke(key);
590                 key_put(key);
591                 return ERR_PTR(ret);
592         }
593
594         return key;
595 }
596 EXPORT_SYMBOL(rxrpc_get_null_key);
597
598 /*
599  * read the contents of an rxrpc key
600  * - this returns the result in XDR form
601  */
602 static long rxrpc_read(const struct key *key,
603                        char __user *buffer, size_t buflen)
604 {
605         struct rxrpc_key_token *token;
606         size_t size, toksize;
607         __be32 __user *xdr;
608         u32 cnlen, tktlen, ntoks, zero;
609
610         _enter("");
611
612         /* we don't know what form we should return non-AFS keys in */
613         if (memcmp(key->description, "afs@", 4) != 0)
614                 return -EOPNOTSUPP;
615         cnlen = strlen(key->description + 4);
616
617         /* AFS keys we return in XDR form, so we need to work out the size of
618          * the XDR */
619         size = 2 * 4;   /* flags, cellname len */
620         size += (cnlen + 3) & ~3;       /* cellname */
621         size += 1 * 4;  /* token count */
622
623         ntoks = 0;
624         for (token = key->payload.data; token; token = token->next) {
625                 switch (token->security_index) {
626                 case RXRPC_SECURITY_RXKAD:
627                         size += 2 * 4;  /* length, security index (switch ID) */
628                         size += 8 * 4;  /* viceid, kvno, key*2, begin, end,
629                                          * primary, tktlen */
630                         size += (token->kad->ticket_len + 3) & ~3; /* ticket */
631                         ntoks++;
632                         break;
633
634                 default: /* can't encode */
635                         break;
636                 }
637         }
638
639         if (!buffer || buflen < size)
640                 return size;
641
642         xdr = (__be32 __user *) buffer;
643         zero = 0;
644 #define ENCODE(x)                               \
645         do {                                    \
646                 __be32 y = htonl(x);            \
647                 if (put_user(y, xdr++) < 0)     \
648                         goto fault;             \
649         } while(0)
650
651         ENCODE(0);      /* flags */
652         ENCODE(cnlen);  /* cellname length */
653         if (copy_to_user(xdr, key->description + 4, cnlen) != 0)
654                 goto fault;
655         if (cnlen & 3 &&
656             copy_to_user((u8 *)xdr + cnlen, &zero, 4 - (cnlen & 3)) != 0)
657                 goto fault;
658         xdr += (cnlen + 3) >> 2;
659         ENCODE(ntoks);  /* token count */
660
661         for (token = key->payload.data; token; token = token->next) {
662                 toksize = 1 * 4;        /* sec index */
663
664                 switch (token->security_index) {
665                 case RXRPC_SECURITY_RXKAD:
666                         toksize += 8 * 4;
667                         toksize += (token->kad->ticket_len + 3) & ~3;
668                         ENCODE(toksize);
669                         ENCODE(token->security_index);
670                         ENCODE(token->kad->vice_id);
671                         ENCODE(token->kad->kvno);
672                         if (copy_to_user(xdr, token->kad->session_key, 8) != 0)
673                                 goto fault;
674                         xdr += 8 >> 2;
675                         ENCODE(token->kad->start);
676                         ENCODE(token->kad->expiry);
677                         ENCODE(token->kad->primary_flag);
678                         tktlen = token->kad->ticket_len;
679                         ENCODE(tktlen);
680                         if (copy_to_user(xdr, token->kad->ticket, tktlen) != 0)
681                                 goto fault;
682                         if (tktlen & 3 &&
683                             copy_to_user((u8 *)xdr + tktlen, &zero,
684                                          4 - (tktlen & 3)) != 0)
685                                 goto fault;
686                         xdr += (tktlen + 3) >> 2;
687                         break;
688
689                 default:
690                         break;
691                 }
692         }
693
694 #undef ENCODE
695
696         ASSERTCMP((char __user *) xdr - buffer, ==, size);
697         _leave(" = %zu", size);
698         return size;
699
700 fault:
701         _leave(" = -EFAULT");
702         return -EFAULT;
703 }