linux/net/rxrpc/ar-key.c
<<
>>
Prefs
   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
  27static int rxrpc_instantiate(struct key *, const void *, size_t);
  28static int rxrpc_instantiate_s(struct key *, const void *, size_t);
  29static void rxrpc_destroy(struct key *);
  30static void rxrpc_destroy_s(struct key *);
  31static void rxrpc_describe(const struct key *, struct seq_file *);
  32static 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 */
  38struct 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};
  46EXPORT_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 */
  52struct 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 */
  64static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
  65                                       unsigned toklen)
  66{
  67        struct rxrpc_key_token *token, **pptoken;
  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        for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
 133             *pptoken;
 134             pptoken = &(*pptoken)->next)
 135                continue;
 136        *pptoken = token;
 137        if (token->kad->expiry < key->expiry)
 138                key->expiry = token->kad->expiry;
 139
 140        _leave(" = 0");
 141        return 0;
 142}
 143
 144static void rxrpc_free_krb5_principal(struct krb5_principal *princ)
 145{
 146        int loop;
 147
 148        if (princ->name_parts) {
 149                for (loop = princ->n_name_parts - 1; loop >= 0; loop--)
 150                        kfree(princ->name_parts[loop]);
 151                kfree(princ->name_parts);
 152        }
 153        kfree(princ->realm);
 154}
 155
 156static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td)
 157{
 158        kfree(td->data);
 159}
 160
 161/*
 162 * free up an RxK5 token
 163 */
 164static void rxrpc_rxk5_free(struct rxk5_key *rxk5)
 165{
 166        int loop;
 167
 168        rxrpc_free_krb5_principal(&rxk5->client);
 169        rxrpc_free_krb5_principal(&rxk5->server);
 170        rxrpc_free_krb5_tagged(&rxk5->session);
 171
 172        if (rxk5->addresses) {
 173                for (loop = rxk5->n_addresses - 1; loop >= 0; loop--)
 174                        rxrpc_free_krb5_tagged(&rxk5->addresses[loop]);
 175                kfree(rxk5->addresses);
 176        }
 177        if (rxk5->authdata) {
 178                for (loop = rxk5->n_authdata - 1; loop >= 0; loop--)
 179                        rxrpc_free_krb5_tagged(&rxk5->authdata[loop]);
 180                kfree(rxk5->authdata);
 181        }
 182
 183        kfree(rxk5->ticket);
 184        kfree(rxk5->ticket2);
 185        kfree(rxk5);
 186}
 187
 188/*
 189 * extract a krb5 principal
 190 */
 191static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
 192                                       const __be32 **_xdr,
 193                                       unsigned *_toklen)
 194{
 195        const __be32 *xdr = *_xdr;
 196        unsigned toklen = *_toklen, n_parts, loop, tmp;
 197
 198        /* there must be at least one name, and at least #names+1 length
 199         * words */
 200        if (toklen <= 12)
 201                return -EINVAL;
 202
 203        _enter(",{%x,%x,%x},%u",
 204               ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), toklen);
 205
 206        n_parts = ntohl(*xdr++);
 207        toklen -= 4;
 208        if (n_parts <= 0 || n_parts > AFSTOKEN_K5_COMPONENTS_MAX)
 209                return -EINVAL;
 210        princ->n_name_parts = n_parts;
 211
 212        if (toklen <= (n_parts + 1) * 4)
 213                return -EINVAL;
 214
 215        princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL);
 216        if (!princ->name_parts)
 217                return -ENOMEM;
 218
 219        for (loop = 0; loop < n_parts; loop++) {
 220                if (toklen < 4)
 221                        return -EINVAL;
 222                tmp = ntohl(*xdr++);
 223                toklen -= 4;
 224                if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
 225                        return -EINVAL;
 226                if (tmp > toklen)
 227                        return -EINVAL;
 228                princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
 229                if (!princ->name_parts[loop])
 230                        return -ENOMEM;
 231                memcpy(princ->name_parts[loop], xdr, tmp);
 232                princ->name_parts[loop][tmp] = 0;
 233                tmp = (tmp + 3) & ~3;
 234                toklen -= tmp;
 235                xdr += tmp >> 2;
 236        }
 237
 238        if (toklen < 4)
 239                return -EINVAL;
 240        tmp = ntohl(*xdr++);
 241        toklen -= 4;
 242        if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
 243                return -EINVAL;
 244        if (tmp > toklen)
 245                return -EINVAL;
 246        princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
 247        if (!princ->realm)
 248                return -ENOMEM;
 249        memcpy(princ->realm, xdr, tmp);
 250        princ->realm[tmp] = 0;
 251        tmp = (tmp + 3) & ~3;
 252        toklen -= tmp;
 253        xdr += tmp >> 2;
 254
 255        _debug("%s/...@%s", princ->name_parts[0], princ->realm);
 256
 257        *_xdr = xdr;
 258        *_toklen = toklen;
 259        _leave(" = 0 [toklen=%u]", toklen);
 260        return 0;
 261}
 262
 263/*
 264 * extract a piece of krb5 tagged data
 265 */
 266static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
 267                                         size_t max_data_size,
 268                                         const __be32 **_xdr,
 269                                         unsigned *_toklen)
 270{
 271        const __be32 *xdr = *_xdr;
 272        unsigned toklen = *_toklen, len;
 273
 274        /* there must be at least one tag and one length word */
 275        if (toklen <= 8)
 276                return -EINVAL;
 277
 278        _enter(",%zu,{%x,%x},%u",
 279               max_data_size, ntohl(xdr[0]), ntohl(xdr[1]), toklen);
 280
 281        td->tag = ntohl(*xdr++);
 282        len = ntohl(*xdr++);
 283        toklen -= 8;
 284        if (len > max_data_size)
 285                return -EINVAL;
 286        td->data_len = len;
 287
 288        if (len > 0) {
 289                td->data = kmalloc(len, GFP_KERNEL);
 290                if (!td->data)
 291                        return -ENOMEM;
 292                memcpy(td->data, xdr, len);
 293                len = (len + 3) & ~3;
 294                toklen -= len;
 295                xdr += len >> 2;
 296        }
 297
 298        _debug("tag %x len %x", td->tag, td->data_len);
 299
 300        *_xdr = xdr;
 301        *_toklen = toklen;
 302        _leave(" = 0 [toklen=%u]", toklen);
 303        return 0;
 304}
 305
 306/*
 307 * extract an array of tagged data
 308 */
 309static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
 310                                          u8 *_n_elem,
 311                                          u8 max_n_elem,
 312                                          size_t max_elem_size,
 313                                          const __be32 **_xdr,
 314                                          unsigned *_toklen)
 315{
 316        struct krb5_tagged_data *td;
 317        const __be32 *xdr = *_xdr;
 318        unsigned toklen = *_toklen, n_elem, loop;
 319        int ret;
 320
 321        /* there must be at least one count */
 322        if (toklen < 4)
 323                return -EINVAL;
 324
 325        _enter(",,%u,%zu,{%x},%u",
 326               max_n_elem, max_elem_size, ntohl(xdr[0]), toklen);
 327
 328        n_elem = ntohl(*xdr++);
 329        toklen -= 4;
 330        if (n_elem < 0 || n_elem > max_n_elem)
 331                return -EINVAL;
 332        *_n_elem = n_elem;
 333        if (n_elem > 0) {
 334                if (toklen <= (n_elem + 1) * 4)
 335                        return -EINVAL;
 336
 337                _debug("n_elem %d", n_elem);
 338
 339                td = kcalloc(sizeof(struct krb5_tagged_data), n_elem,
 340                             GFP_KERNEL);
 341                if (!td)
 342                        return -ENOMEM;
 343                *_td = td;
 344
 345                for (loop = 0; loop < n_elem; loop++) {
 346                        ret = rxrpc_krb5_decode_tagged_data(&td[loop],
 347                                                            max_elem_size,
 348                                                            &xdr, &toklen);
 349                        if (ret < 0)
 350                                return ret;
 351                }
 352        }
 353
 354        *_xdr = xdr;
 355        *_toklen = toklen;
 356        _leave(" = 0 [toklen=%u]", toklen);
 357        return 0;
 358}
 359
 360/*
 361 * extract a krb5 ticket
 362 */
 363static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
 364                                    const __be32 **_xdr, unsigned *_toklen)
 365{
 366        const __be32 *xdr = *_xdr;
 367        unsigned toklen = *_toklen, len;
 368
 369        /* there must be at least one length word */
 370        if (toklen <= 4)
 371                return -EINVAL;
 372
 373        _enter(",{%x},%u", ntohl(xdr[0]), toklen);
 374
 375        len = ntohl(*xdr++);
 376        toklen -= 4;
 377        if (len > AFSTOKEN_K5_TIX_MAX)
 378                return -EINVAL;
 379        *_tktlen = len;
 380
 381        _debug("ticket len %u", len);
 382
 383        if (len > 0) {
 384                *_ticket = kmalloc(len, GFP_KERNEL);
 385                if (!*_ticket)
 386                        return -ENOMEM;
 387                memcpy(*_ticket, xdr, len);
 388                len = (len + 3) & ~3;
 389                toklen -= len;
 390                xdr += len >> 2;
 391        }
 392
 393        *_xdr = xdr;
 394        *_toklen = toklen;
 395        _leave(" = 0 [toklen=%u]", toklen);
 396        return 0;
 397}
 398
 399/*
 400 * parse an RxK5 type XDR format token
 401 * - the caller guarantees we have at least 4 words
 402 */
 403static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
 404                                      unsigned toklen)
 405{
 406        struct rxrpc_key_token *token, **pptoken;
 407        struct rxk5_key *rxk5;
 408        const __be32 *end_xdr = xdr + (toklen >> 2);
 409        int ret;
 410
 411        _enter(",{%x,%x,%x,%x},%u",
 412               ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
 413               toklen);
 414
 415        /* reserve some payload space for this subkey - the length of the token
 416         * is a reasonable approximation */
 417        ret = key_payload_reserve(key, key->datalen + toklen);
 418        if (ret < 0)
 419                return ret;
 420
 421        token = kzalloc(sizeof(*token), GFP_KERNEL);
 422        if (!token)
 423                return -ENOMEM;
 424
 425        rxk5 = kzalloc(sizeof(*rxk5), GFP_KERNEL);
 426        if (!rxk5) {
 427                kfree(token);
 428                return -ENOMEM;
 429        }
 430
 431        token->security_index = RXRPC_SECURITY_RXK5;
 432        token->k5 = rxk5;
 433
 434        /* extract the principals */
 435        ret = rxrpc_krb5_decode_principal(&rxk5->client, &xdr, &toklen);
 436        if (ret < 0)
 437                goto error;
 438        ret = rxrpc_krb5_decode_principal(&rxk5->server, &xdr, &toklen);
 439        if (ret < 0)
 440                goto error;
 441
 442        /* extract the session key and the encoding type (the tag field ->
 443         * ENCTYPE_xxx) */
 444        ret = rxrpc_krb5_decode_tagged_data(&rxk5->session, AFSTOKEN_DATA_MAX,
 445                                            &xdr, &toklen);
 446        if (ret < 0)
 447                goto error;
 448
 449        if (toklen < 4 * 8 + 2 * 4)
 450                goto inval;
 451        rxk5->authtime  = be64_to_cpup((const __be64 *) xdr);
 452        xdr += 2;
 453        rxk5->starttime = be64_to_cpup((const __be64 *) xdr);
 454        xdr += 2;
 455        rxk5->endtime   = be64_to_cpup((const __be64 *) xdr);
 456        xdr += 2;
 457        rxk5->renew_till = be64_to_cpup((const __be64 *) xdr);
 458        xdr += 2;
 459        rxk5->is_skey = ntohl(*xdr++);
 460        rxk5->flags = ntohl(*xdr++);
 461        toklen -= 4 * 8 + 2 * 4;
 462
 463        _debug("times: a=%llx s=%llx e=%llx rt=%llx",
 464               rxk5->authtime, rxk5->starttime, rxk5->endtime,
 465               rxk5->renew_till);
 466        _debug("is_skey=%x flags=%x", rxk5->is_skey, rxk5->flags);
 467
 468        /* extract the permitted client addresses */
 469        ret = rxrpc_krb5_decode_tagged_array(&rxk5->addresses,
 470                                             &rxk5->n_addresses,
 471                                             AFSTOKEN_K5_ADDRESSES_MAX,
 472                                             AFSTOKEN_DATA_MAX,
 473                                             &xdr, &toklen);
 474        if (ret < 0)
 475                goto error;
 476
 477        ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
 478
 479        /* extract the tickets */
 480        ret = rxrpc_krb5_decode_ticket(&rxk5->ticket, &rxk5->ticket_len,
 481                                       &xdr, &toklen);
 482        if (ret < 0)
 483                goto error;
 484        ret = rxrpc_krb5_decode_ticket(&rxk5->ticket2, &rxk5->ticket2_len,
 485                                       &xdr, &toklen);
 486        if (ret < 0)
 487                goto error;
 488
 489        ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
 490
 491        /* extract the typed auth data */
 492        ret = rxrpc_krb5_decode_tagged_array(&rxk5->authdata,
 493                                             &rxk5->n_authdata,
 494                                             AFSTOKEN_K5_AUTHDATA_MAX,
 495                                             AFSTOKEN_BDATALN_MAX,
 496                                             &xdr, &toklen);
 497        if (ret < 0)
 498                goto error;
 499
 500        ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
 501
 502        if (toklen != 0)
 503                goto inval;
 504
 505        /* attach the payload to the key */
 506        for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
 507             *pptoken;
 508             pptoken = &(*pptoken)->next)
 509                continue;
 510        *pptoken = token;
 511        if (token->kad->expiry < key->expiry)
 512                key->expiry = token->kad->expiry;
 513
 514        _leave(" = 0");
 515        return 0;
 516
 517inval:
 518        ret = -EINVAL;
 519error:
 520        rxrpc_rxk5_free(rxk5);
 521        kfree(token);
 522        _leave(" = %d", ret);
 523        return ret;
 524}
 525
 526/*
 527 * attempt to parse the data as the XDR format
 528 * - the caller guarantees we have more than 7 words
 529 */
 530static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen)
 531{
 532        const __be32 *xdr = data, *token;
 533        const char *cp;
 534        unsigned len, tmp, loop, ntoken, toklen, sec_ix;
 535        int ret;
 536
 537        _enter(",{%x,%x,%x,%x},%zu",
 538               ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
 539               datalen);
 540
 541        if (datalen > AFSTOKEN_LENGTH_MAX)
 542                goto not_xdr;
 543
 544        /* XDR is an array of __be32's */
 545        if (datalen & 3)
 546                goto not_xdr;
 547
 548        /* the flags should be 0 (the setpag bit must be handled by
 549         * userspace) */
 550        if (ntohl(*xdr++) != 0)
 551                goto not_xdr;
 552        datalen -= 4;
 553
 554        /* check the cell name */
 555        len = ntohl(*xdr++);
 556        if (len < 1 || len > AFSTOKEN_CELL_MAX)
 557                goto not_xdr;
 558        datalen -= 4;
 559        tmp = (len + 3) & ~3;
 560        if (tmp > datalen)
 561                goto not_xdr;
 562
 563        cp = (const char *) xdr;
 564        for (loop = 0; loop < len; loop++)
 565                if (!isprint(cp[loop]))
 566                        goto not_xdr;
 567        if (len < tmp)
 568                for (; loop < tmp; loop++)
 569                        if (cp[loop])
 570                                goto not_xdr;
 571        _debug("cellname: [%u/%u] '%*.*s'",
 572               len, tmp, len, len, (const char *) xdr);
 573        datalen -= tmp;
 574        xdr += tmp >> 2;
 575
 576        /* get the token count */
 577        if (datalen < 12)
 578                goto not_xdr;
 579        ntoken = ntohl(*xdr++);
 580        datalen -= 4;
 581        _debug("ntoken: %x", ntoken);
 582        if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
 583                goto not_xdr;
 584
 585        /* check each token wrapper */
 586        token = xdr;
 587        loop = ntoken;
 588        do {
 589                if (datalen < 8)
 590                        goto not_xdr;
 591                toklen = ntohl(*xdr++);
 592                sec_ix = ntohl(*xdr);
 593                datalen -= 4;
 594                _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
 595                if (toklen < 20 || toklen > datalen)
 596                        goto not_xdr;
 597                datalen -= (toklen + 3) & ~3;
 598                xdr += (toklen + 3) >> 2;
 599
 600        } while (--loop > 0);
 601
 602        _debug("remainder: %zu", datalen);
 603        if (datalen != 0)
 604                goto not_xdr;
 605
 606        /* okay: we're going to assume it's valid XDR format
 607         * - we ignore the cellname, relying on the key to be correctly named
 608         */
 609        do {
 610                xdr = token;
 611                toklen = ntohl(*xdr++);
 612                token = xdr + ((toklen + 3) >> 2);
 613                sec_ix = ntohl(*xdr++);
 614                toklen -= 4;
 615
 616                _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
 617
 618                switch (sec_ix) {
 619                case RXRPC_SECURITY_RXKAD:
 620                        ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
 621                        if (ret != 0)
 622                                goto error;
 623                        break;
 624
 625                case RXRPC_SECURITY_RXK5:
 626                        ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen);
 627                        if (ret != 0)
 628                                goto error;
 629                        break;
 630
 631                default:
 632                        ret = -EPROTONOSUPPORT;
 633                        goto error;
 634                }
 635
 636        } while (--ntoken > 0);
 637
 638        _leave(" = 0");
 639        return 0;
 640
 641not_xdr:
 642        _leave(" = -EPROTO");
 643        return -EPROTO;
 644error:
 645        _leave(" = %d", ret);
 646        return ret;
 647}
 648
 649/*
 650 * instantiate an rxrpc defined key
 651 * data should be of the form:
 652 *      OFFSET  LEN     CONTENT
 653 *      0       4       key interface version number
 654 *      4       2       security index (type)
 655 *      6       2       ticket length
 656 *      8       4       key expiry time (time_t)
 657 *      12      4       kvno
 658 *      16      8       session key
 659 *      24      [len]   ticket
 660 *
 661 * if no data is provided, then a no-security key is made
 662 */
 663static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
 664{
 665        const struct rxrpc_key_data_v1 *v1;
 666        struct rxrpc_key_token *token, **pp;
 667        size_t plen;
 668        u32 kver;
 669        int ret;
 670
 671        _enter("{%x},,%zu", key_serial(key), datalen);
 672
 673        /* handle a no-security key */
 674        if (!data && datalen == 0)
 675                return 0;
 676
 677        /* determine if the XDR payload format is being used */
 678        if (datalen > 7 * 4) {
 679                ret = rxrpc_instantiate_xdr(key, data, datalen);
 680                if (ret != -EPROTO)
 681                        return ret;
 682        }
 683
 684        /* get the key interface version number */
 685        ret = -EINVAL;
 686        if (datalen <= 4 || !data)
 687                goto error;
 688        memcpy(&kver, data, sizeof(kver));
 689        data += sizeof(kver);
 690        datalen -= sizeof(kver);
 691
 692        _debug("KEY I/F VERSION: %u", kver);
 693
 694        ret = -EKEYREJECTED;
 695        if (kver != 1)
 696                goto error;
 697
 698        /* deal with a version 1 key */
 699        ret = -EINVAL;
 700        if (datalen < sizeof(*v1))
 701                goto error;
 702
 703        v1 = data;
 704        if (datalen != sizeof(*v1) + v1->ticket_length)
 705                goto error;
 706
 707        _debug("SCIX: %u", v1->security_index);
 708        _debug("TLEN: %u", v1->ticket_length);
 709        _debug("EXPY: %x", v1->expiry);
 710        _debug("KVNO: %u", v1->kvno);
 711        _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
 712               v1->session_key[0], v1->session_key[1],
 713               v1->session_key[2], v1->session_key[3],
 714               v1->session_key[4], v1->session_key[5],
 715               v1->session_key[6], v1->session_key[7]);
 716        if (v1->ticket_length >= 8)
 717                _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
 718                       v1->ticket[0], v1->ticket[1],
 719                       v1->ticket[2], v1->ticket[3],
 720                       v1->ticket[4], v1->ticket[5],
 721                       v1->ticket[6], v1->ticket[7]);
 722
 723        ret = -EPROTONOSUPPORT;
 724        if (v1->security_index != RXRPC_SECURITY_RXKAD)
 725                goto error;
 726
 727        plen = sizeof(*token->kad) + v1->ticket_length;
 728        ret = key_payload_reserve(key, plen + sizeof(*token));
 729        if (ret < 0)
 730                goto error;
 731
 732        ret = -ENOMEM;
 733        token = kmalloc(sizeof(*token), GFP_KERNEL);
 734        if (!token)
 735                goto error;
 736        token->kad = kmalloc(plen, GFP_KERNEL);
 737        if (!token->kad)
 738                goto error_free;
 739
 740        token->security_index           = RXRPC_SECURITY_RXKAD;
 741        token->kad->ticket_len          = v1->ticket_length;
 742        token->kad->expiry              = v1->expiry;
 743        token->kad->kvno                = v1->kvno;
 744        memcpy(&token->kad->session_key, &v1->session_key, 8);
 745        memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
 746
 747        /* attach the data */
 748        key->type_data.x[0]++;
 749
 750        pp = (struct rxrpc_key_token **)&key->payload.data;
 751        while (*pp)
 752                pp = &(*pp)->next;
 753        *pp = token;
 754        if (token->kad->expiry < key->expiry)
 755                key->expiry = token->kad->expiry;
 756        token = NULL;
 757        ret = 0;
 758
 759error_free:
 760        kfree(token);
 761error:
 762        return ret;
 763}
 764
 765/*
 766 * instantiate a server secret key
 767 * data should be a pointer to the 8-byte secret key
 768 */
 769static int rxrpc_instantiate_s(struct key *key, const void *data,
 770                               size_t datalen)
 771{
 772        struct crypto_blkcipher *ci;
 773
 774        _enter("{%x},,%zu", key_serial(key), datalen);
 775
 776        if (datalen != 8)
 777                return -EINVAL;
 778
 779        memcpy(&key->type_data, data, 8);
 780
 781        ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
 782        if (IS_ERR(ci)) {
 783                _leave(" = %ld", PTR_ERR(ci));
 784                return PTR_ERR(ci);
 785        }
 786
 787        if (crypto_blkcipher_setkey(ci, data, 8) < 0)
 788                BUG();
 789
 790        key->payload.data = ci;
 791        _leave(" = 0");
 792        return 0;
 793}
 794
 795/*
 796 * dispose of the data dangling from the corpse of a rxrpc key
 797 */
 798static void rxrpc_destroy(struct key *key)
 799{
 800        struct rxrpc_key_token *token;
 801
 802        while ((token = key->payload.data)) {
 803                key->payload.data = token->next;
 804                switch (token->security_index) {
 805                case RXRPC_SECURITY_RXKAD:
 806                        kfree(token->kad);
 807                        break;
 808                case RXRPC_SECURITY_RXK5:
 809                        if (token->k5)
 810                                rxrpc_rxk5_free(token->k5);
 811                        break;
 812                default:
 813                        printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
 814                               token->security_index);
 815                        BUG();
 816                }
 817
 818                kfree(token);
 819        }
 820}
 821
 822/*
 823 * dispose of the data dangling from the corpse of a rxrpc key
 824 */
 825static void rxrpc_destroy_s(struct key *key)
 826{
 827        if (key->payload.data) {
 828                crypto_free_blkcipher(key->payload.data);
 829                key->payload.data = NULL;
 830        }
 831}
 832
 833/*
 834 * describe the rxrpc key
 835 */
 836static void rxrpc_describe(const struct key *key, struct seq_file *m)
 837{
 838        seq_puts(m, key->description);
 839}
 840
 841/*
 842 * grab the security key for a socket
 843 */
 844int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen)
 845{
 846        struct key *key;
 847        char *description;
 848
 849        _enter("");
 850
 851        if (optlen <= 0 || optlen > PAGE_SIZE - 1)
 852                return -EINVAL;
 853
 854        description = kmalloc(optlen + 1, GFP_KERNEL);
 855        if (!description)
 856                return -ENOMEM;
 857
 858        if (copy_from_user(description, optval, optlen)) {
 859                kfree(description);
 860                return -EFAULT;
 861        }
 862        description[optlen] = 0;
 863
 864        key = request_key(&key_type_rxrpc, description, NULL);
 865        if (IS_ERR(key)) {
 866                kfree(description);
 867                _leave(" = %ld", PTR_ERR(key));
 868                return PTR_ERR(key);
 869        }
 870
 871        rx->key = key;
 872        kfree(description);
 873        _leave(" = 0 [key %x]", key->serial);
 874        return 0;
 875}
 876
 877/*
 878 * grab the security keyring for a server socket
 879 */
 880int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval,
 881                         int optlen)
 882{
 883        struct key *key;
 884        char *description;
 885
 886        _enter("");
 887
 888        if (optlen <= 0 || optlen > PAGE_SIZE - 1)
 889                return -EINVAL;
 890
 891        description = kmalloc(optlen + 1, GFP_KERNEL);
 892        if (!description)
 893                return -ENOMEM;
 894
 895        if (copy_from_user(description, optval, optlen)) {
 896                kfree(description);
 897                return -EFAULT;
 898        }
 899        description[optlen] = 0;
 900
 901        key = request_key(&key_type_keyring, description, NULL);
 902        if (IS_ERR(key)) {
 903                kfree(description);
 904                _leave(" = %ld", PTR_ERR(key));
 905                return PTR_ERR(key);
 906        }
 907
 908        rx->securities = key;
 909        kfree(description);
 910        _leave(" = 0 [key %x]", key->serial);
 911        return 0;
 912}
 913
 914/*
 915 * generate a server data key
 916 */
 917int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
 918                              const void *session_key,
 919                              time_t expiry,
 920                              u32 kvno)
 921{
 922        const struct cred *cred = current_cred();
 923        struct key *key;
 924        int ret;
 925
 926        struct {
 927                u32 kver;
 928                struct rxrpc_key_data_v1 v1;
 929        } data;
 930
 931        _enter("");
 932
 933        key = key_alloc(&key_type_rxrpc, "x", 0, 0, cred, 0,
 934                        KEY_ALLOC_NOT_IN_QUOTA);
 935        if (IS_ERR(key)) {
 936                _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
 937                return -ENOMEM;
 938        }
 939
 940        _debug("key %d", key_serial(key));
 941
 942        data.kver = 1;
 943        data.v1.security_index = RXRPC_SECURITY_RXKAD;
 944        data.v1.ticket_length = 0;
 945        data.v1.expiry = expiry;
 946        data.v1.kvno = 0;
 947
 948        memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
 949
 950        ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
 951        if (ret < 0)
 952                goto error;
 953
 954        conn->key = key;
 955        _leave(" = 0 [%d]", key_serial(key));
 956        return 0;
 957
 958error:
 959        key_revoke(key);
 960        key_put(key);
 961        _leave(" = -ENOMEM [ins %d]", ret);
 962        return -ENOMEM;
 963}
 964EXPORT_SYMBOL(rxrpc_get_server_data_key);
 965
 966/**
 967 * rxrpc_get_null_key - Generate a null RxRPC key
 968 * @keyname: The name to give the key.
 969 *
 970 * Generate a null RxRPC key that can be used to indicate anonymous security is
 971 * required for a particular domain.
 972 */
 973struct key *rxrpc_get_null_key(const char *keyname)
 974{
 975        const struct cred *cred = current_cred();
 976        struct key *key;
 977        int ret;
 978
 979        key = key_alloc(&key_type_rxrpc, keyname, 0, 0, cred,
 980                        KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
 981        if (IS_ERR(key))
 982                return key;
 983
 984        ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
 985        if (ret < 0) {
 986                key_revoke(key);
 987                key_put(key);
 988                return ERR_PTR(ret);
 989        }
 990
 991        return key;
 992}
 993EXPORT_SYMBOL(rxrpc_get_null_key);
 994
 995/*
 996 * read the contents of an rxrpc key
 997 * - this returns the result in XDR form
 998 */
 999static long rxrpc_read(const struct key *key,
1000                       char __user *buffer, size_t buflen)
1001{
1002        const struct rxrpc_key_token *token;
1003        const struct krb5_principal *princ;
1004        size_t size;
1005        __be32 __user *xdr, *oldxdr;
1006        u32 cnlen, toksize, ntoks, tok, zero;
1007        u16 toksizes[AFSTOKEN_MAX];
1008        int loop;
1009
1010        _enter("");
1011
1012        /* we don't know what form we should return non-AFS keys in */
1013        if (memcmp(key->description, "afs@", 4) != 0)
1014                return -EOPNOTSUPP;
1015        cnlen = strlen(key->description + 4);
1016
1017#define RND(X) (((X) + 3) & ~3)
1018
1019        /* AFS keys we return in XDR form, so we need to work out the size of
1020         * the XDR */
1021        size = 2 * 4;   /* flags, cellname len */
1022        size += RND(cnlen);     /* cellname */
1023        size += 1 * 4;  /* token count */
1024
1025        ntoks = 0;
1026        for (token = key->payload.data; token; token = token->next) {
1027                toksize = 4;    /* sec index */
1028
1029                switch (token->security_index) {
1030                case RXRPC_SECURITY_RXKAD:
1031                        toksize += 8 * 4;       /* viceid, kvno, key*2, begin,
1032                                                 * end, primary, tktlen */
1033                        toksize += RND(token->kad->ticket_len);
1034                        break;
1035
1036                case RXRPC_SECURITY_RXK5:
1037                        princ = &token->k5->client;
1038                        toksize += 4 + princ->n_name_parts * 4;
1039                        for (loop = 0; loop < princ->n_name_parts; loop++)
1040                                toksize += RND(strlen(princ->name_parts[loop]));
1041                        toksize += 4 + RND(strlen(princ->realm));
1042
1043                        princ = &token->k5->server;
1044                        toksize += 4 + princ->n_name_parts * 4;
1045                        for (loop = 0; loop < princ->n_name_parts; loop++)
1046                                toksize += RND(strlen(princ->name_parts[loop]));
1047                        toksize += 4 + RND(strlen(princ->realm));
1048
1049                        toksize += 8 + RND(token->k5->session.data_len);
1050
1051                        toksize += 4 * 8 + 2 * 4;
1052
1053                        toksize += 4 + token->k5->n_addresses * 8;
1054                        for (loop = 0; loop < token->k5->n_addresses; loop++)
1055                                toksize += RND(token->k5->addresses[loop].data_len);
1056
1057                        toksize += 4 + RND(token->k5->ticket_len);
1058                        toksize += 4 + RND(token->k5->ticket2_len);
1059
1060                        toksize += 4 + token->k5->n_authdata * 8;
1061                        for (loop = 0; loop < token->k5->n_authdata; loop++)
1062                                toksize += RND(token->k5->authdata[loop].data_len);
1063                        break;
1064
1065                default: /* we have a ticket we can't encode */
1066                        BUG();
1067                        continue;
1068                }
1069
1070                _debug("token[%u]: toksize=%u", ntoks, toksize);
1071                ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
1072
1073                toksizes[ntoks++] = toksize;
1074                size += toksize + 4; /* each token has a length word */
1075        }
1076
1077#undef RND
1078
1079        if (!buffer || buflen < size)
1080                return size;
1081
1082        xdr = (__be32 __user *) buffer;
1083        zero = 0;
1084#define ENCODE(x)                               \
1085        do {                                    \
1086                __be32 y = htonl(x);            \
1087                if (put_user(y, xdr++) < 0)     \
1088                        goto fault;             \
1089        } while(0)
1090#define ENCODE_DATA(l, s)                                               \
1091        do {                                                            \
1092                u32 _l = (l);                                           \
1093                ENCODE(l);                                              \
1094                if (copy_to_user(xdr, (s), _l) != 0)                    \
1095                        goto fault;                                     \
1096                if (_l & 3 &&                                           \
1097                    copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \
1098                        goto fault;                                     \
1099                xdr += (_l + 3) >> 2;                                   \
1100        } while(0)
1101#define ENCODE64(x)                                     \
1102        do {                                            \
1103                __be64 y = cpu_to_be64(x);              \
1104                if (copy_to_user(xdr, &y, 8) != 0)      \
1105                        goto fault;                     \
1106                xdr += 8 >> 2;                          \
1107        } while(0)
1108#define ENCODE_STR(s)                           \
1109        do {                                    \
1110                const char *_s = (s);           \
1111                ENCODE_DATA(strlen(_s), _s);    \
1112        } while(0)
1113
1114        ENCODE(0);                                      /* flags */
1115        ENCODE_DATA(cnlen, key->description + 4);       /* cellname */
1116        ENCODE(ntoks);
1117
1118        tok = 0;
1119        for (token = key->payload.data; token; token = token->next) {
1120                toksize = toksizes[tok++];
1121                ENCODE(toksize);
1122                oldxdr = xdr;
1123                ENCODE(token->security_index);
1124
1125                switch (token->security_index) {
1126                case RXRPC_SECURITY_RXKAD:
1127                        ENCODE(token->kad->vice_id);
1128                        ENCODE(token->kad->kvno);
1129                        ENCODE_DATA(8, token->kad->session_key);
1130                        ENCODE(token->kad->start);
1131                        ENCODE(token->kad->expiry);
1132                        ENCODE(token->kad->primary_flag);
1133                        ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
1134                        break;
1135
1136                case RXRPC_SECURITY_RXK5:
1137                        princ = &token->k5->client;
1138                        ENCODE(princ->n_name_parts);
1139                        for (loop = 0; loop < princ->n_name_parts; loop++)
1140                                ENCODE_STR(princ->name_parts[loop]);
1141                        ENCODE_STR(princ->realm);
1142
1143                        princ = &token->k5->server;
1144                        ENCODE(princ->n_name_parts);
1145                        for (loop = 0; loop < princ->n_name_parts; loop++)
1146                                ENCODE_STR(princ->name_parts[loop]);
1147                        ENCODE_STR(princ->realm);
1148
1149                        ENCODE(token->k5->session.tag);
1150                        ENCODE_DATA(token->k5->session.data_len,
1151                                    token->k5->session.data);
1152
1153                        ENCODE64(token->k5->authtime);
1154                        ENCODE64(token->k5->starttime);
1155                        ENCODE64(token->k5->endtime);
1156                        ENCODE64(token->k5->renew_till);
1157                        ENCODE(token->k5->is_skey);
1158                        ENCODE(token->k5->flags);
1159
1160                        ENCODE(token->k5->n_addresses);
1161                        for (loop = 0; loop < token->k5->n_addresses; loop++) {
1162                                ENCODE(token->k5->addresses[loop].tag);
1163                                ENCODE_DATA(token->k5->addresses[loop].data_len,
1164                                            token->k5->addresses[loop].data);
1165                        }
1166
1167                        ENCODE_DATA(token->k5->ticket_len, token->k5->ticket);
1168                        ENCODE_DATA(token->k5->ticket2_len, token->k5->ticket2);
1169
1170                        ENCODE(token->k5->n_authdata);
1171                        for (loop = 0; loop < token->k5->n_authdata; loop++) {
1172                                ENCODE(token->k5->authdata[loop].tag);
1173                                ENCODE_DATA(token->k5->authdata[loop].data_len,
1174                                            token->k5->authdata[loop].data);
1175                        }
1176                        break;
1177
1178                default:
1179                        BUG();
1180                        break;
1181                }
1182
1183                ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
1184                          toksize);
1185        }
1186
1187#undef ENCODE_STR
1188#undef ENCODE_DATA
1189#undef ENCODE64
1190#undef ENCODE
1191
1192        ASSERTCMP(tok, ==, ntoks);
1193        ASSERTCMP((char __user *) xdr - buffer, ==, size);
1194        _leave(" = %zu", size);
1195        return size;
1196
1197fault:
1198        _leave(" = -EFAULT");
1199        return -EFAULT;
1200}
1201