linux/net/sunrpc/auth_gss/gss_krb5_mech.c
<<
>>
Prefs
   1/*
   2 *  linux/net/sunrpc/gss_krb5_mech.c
   3 *
   4 *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
   5 *  All rights reserved.
   6 *
   7 *  Andy Adamson <andros@umich.edu>
   8 *  J. Bruce Fields <bfields@umich.edu>
   9 *
  10 *  Redistribution and use in source and binary forms, with or without
  11 *  modification, are permitted provided that the following conditions
  12 *  are met:
  13 *
  14 *  1. Redistributions of source code must retain the above copyright
  15 *     notice, this list of conditions and the following disclaimer.
  16 *  2. Redistributions in binary form must reproduce the above copyright
  17 *     notice, this list of conditions and the following disclaimer in the
  18 *     documentation and/or other materials provided with the distribution.
  19 *  3. Neither the name of the University nor the names of its
  20 *     contributors may be used to endorse or promote products derived
  21 *     from this software without specific prior written permission.
  22 *
  23 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  30 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34 *
  35 */
  36
  37#include <linux/err.h>
  38#include <linux/module.h>
  39#include <linux/init.h>
  40#include <linux/types.h>
  41#include <linux/slab.h>
  42#include <linux/sunrpc/auth.h>
  43#include <linux/sunrpc/gss_krb5.h>
  44#include <linux/sunrpc/xdr.h>
  45#include <linux/crypto.h>
  46#include <linux/sunrpc/gss_krb5_enctypes.h>
  47
  48#ifdef RPC_DEBUG
  49# define RPCDBG_FACILITY        RPCDBG_AUTH
  50#endif
  51
  52static struct gss_api_mech gss_kerberos_mech;   /* forward declaration */
  53
  54static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
  55        /*
  56         * DES (All DES enctypes are mapped to the same gss functionality)
  57         */
  58        {
  59          .etype = ENCTYPE_DES_CBC_RAW,
  60          .ctype = CKSUMTYPE_RSA_MD5,
  61          .name = "des-cbc-crc",
  62          .encrypt_name = "cbc(des)",
  63          .cksum_name = "md5",
  64          .encrypt = krb5_encrypt,
  65          .decrypt = krb5_decrypt,
  66          .mk_key = NULL,
  67          .signalg = SGN_ALG_DES_MAC_MD5,
  68          .sealalg = SEAL_ALG_DES,
  69          .keybytes = 7,
  70          .keylength = 8,
  71          .blocksize = 8,
  72          .conflen = 8,
  73          .cksumlength = 8,
  74          .keyed_cksum = 0,
  75        },
  76        /*
  77         * RC4-HMAC
  78         */
  79        {
  80          .etype = ENCTYPE_ARCFOUR_HMAC,
  81          .ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR,
  82          .name = "rc4-hmac",
  83          .encrypt_name = "ecb(arc4)",
  84          .cksum_name = "hmac(md5)",
  85          .encrypt = krb5_encrypt,
  86          .decrypt = krb5_decrypt,
  87          .mk_key = NULL,
  88          .signalg = SGN_ALG_HMAC_MD5,
  89          .sealalg = SEAL_ALG_MICROSOFT_RC4,
  90          .keybytes = 16,
  91          .keylength = 16,
  92          .blocksize = 1,
  93          .conflen = 8,
  94          .cksumlength = 8,
  95          .keyed_cksum = 1,
  96        },
  97        /*
  98         * 3DES
  99         */
 100        {
 101          .etype = ENCTYPE_DES3_CBC_RAW,
 102          .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
 103          .name = "des3-hmac-sha1",
 104          .encrypt_name = "cbc(des3_ede)",
 105          .cksum_name = "hmac(sha1)",
 106          .encrypt = krb5_encrypt,
 107          .decrypt = krb5_decrypt,
 108          .mk_key = gss_krb5_des3_make_key,
 109          .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
 110          .sealalg = SEAL_ALG_DES3KD,
 111          .keybytes = 21,
 112          .keylength = 24,
 113          .blocksize = 8,
 114          .conflen = 8,
 115          .cksumlength = 20,
 116          .keyed_cksum = 1,
 117        },
 118        /*
 119         * AES128
 120         */
 121        {
 122          .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
 123          .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
 124          .name = "aes128-cts",
 125          .encrypt_name = "cts(cbc(aes))",
 126          .cksum_name = "hmac(sha1)",
 127          .encrypt = krb5_encrypt,
 128          .decrypt = krb5_decrypt,
 129          .mk_key = gss_krb5_aes_make_key,
 130          .encrypt_v2 = gss_krb5_aes_encrypt,
 131          .decrypt_v2 = gss_krb5_aes_decrypt,
 132          .signalg = -1,
 133          .sealalg = -1,
 134          .keybytes = 16,
 135          .keylength = 16,
 136          .blocksize = 16,
 137          .conflen = 16,
 138          .cksumlength = 12,
 139          .keyed_cksum = 1,
 140        },
 141        /*
 142         * AES256
 143         */
 144        {
 145          .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
 146          .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
 147          .name = "aes256-cts",
 148          .encrypt_name = "cts(cbc(aes))",
 149          .cksum_name = "hmac(sha1)",
 150          .encrypt = krb5_encrypt,
 151          .decrypt = krb5_decrypt,
 152          .mk_key = gss_krb5_aes_make_key,
 153          .encrypt_v2 = gss_krb5_aes_encrypt,
 154          .decrypt_v2 = gss_krb5_aes_decrypt,
 155          .signalg = -1,
 156          .sealalg = -1,
 157          .keybytes = 32,
 158          .keylength = 32,
 159          .blocksize = 16,
 160          .conflen = 16,
 161          .cksumlength = 12,
 162          .keyed_cksum = 1,
 163        },
 164};
 165
 166static const int num_supported_enctypes =
 167        ARRAY_SIZE(supported_gss_krb5_enctypes);
 168
 169static int
 170supported_gss_krb5_enctype(int etype)
 171{
 172        int i;
 173        for (i = 0; i < num_supported_enctypes; i++)
 174                if (supported_gss_krb5_enctypes[i].etype == etype)
 175                        return 1;
 176        return 0;
 177}
 178
 179static const struct gss_krb5_enctype *
 180get_gss_krb5_enctype(int etype)
 181{
 182        int i;
 183        for (i = 0; i < num_supported_enctypes; i++)
 184                if (supported_gss_krb5_enctypes[i].etype == etype)
 185                        return &supported_gss_krb5_enctypes[i];
 186        return NULL;
 187}
 188
 189static const void *
 190simple_get_bytes(const void *p, const void *end, void *res, int len)
 191{
 192        const void *q = (const void *)((const char *)p + len);
 193        if (unlikely(q > end || q < p))
 194                return ERR_PTR(-EFAULT);
 195        memcpy(res, p, len);
 196        return q;
 197}
 198
 199static const void *
 200simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
 201{
 202        const void *q;
 203        unsigned int len;
 204
 205        p = simple_get_bytes(p, end, &len, sizeof(len));
 206        if (IS_ERR(p))
 207                return p;
 208        q = (const void *)((const char *)p + len);
 209        if (unlikely(q > end || q < p))
 210                return ERR_PTR(-EFAULT);
 211        res->data = kmemdup(p, len, GFP_NOFS);
 212        if (unlikely(res->data == NULL))
 213                return ERR_PTR(-ENOMEM);
 214        res->len = len;
 215        return q;
 216}
 217
 218static inline const void *
 219get_key(const void *p, const void *end,
 220        struct krb5_ctx *ctx, struct crypto_blkcipher **res)
 221{
 222        struct xdr_netobj       key;
 223        int                     alg;
 224
 225        p = simple_get_bytes(p, end, &alg, sizeof(alg));
 226        if (IS_ERR(p))
 227                goto out_err;
 228
 229        switch (alg) {
 230        case ENCTYPE_DES_CBC_CRC:
 231        case ENCTYPE_DES_CBC_MD4:
 232        case ENCTYPE_DES_CBC_MD5:
 233                /* Map all these key types to ENCTYPE_DES_CBC_RAW */
 234                alg = ENCTYPE_DES_CBC_RAW;
 235                break;
 236        }
 237
 238        if (!supported_gss_krb5_enctype(alg)) {
 239                printk(KERN_WARNING "gss_kerberos_mech: unsupported "
 240                        "encryption key algorithm %d\n", alg);
 241                p = ERR_PTR(-EINVAL);
 242                goto out_err;
 243        }
 244        p = simple_get_netobj(p, end, &key);
 245        if (IS_ERR(p))
 246                goto out_err;
 247
 248        *res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
 249                                                        CRYPTO_ALG_ASYNC);
 250        if (IS_ERR(*res)) {
 251                printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
 252                        "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
 253                *res = NULL;
 254                goto out_err_free_key;
 255        }
 256        if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
 257                printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
 258                        "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
 259                goto out_err_free_tfm;
 260        }
 261
 262        kfree(key.data);
 263        return p;
 264
 265out_err_free_tfm:
 266        crypto_free_blkcipher(*res);
 267out_err_free_key:
 268        kfree(key.data);
 269        p = ERR_PTR(-EINVAL);
 270out_err:
 271        return p;
 272}
 273
 274static int
 275gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
 276{
 277        int tmp;
 278
 279        p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
 280        if (IS_ERR(p))
 281                goto out_err;
 282
 283        /* Old format supports only DES!  Any other enctype uses new format */
 284        ctx->enctype = ENCTYPE_DES_CBC_RAW;
 285
 286        ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
 287        if (ctx->gk5e == NULL) {
 288                p = ERR_PTR(-EINVAL);
 289                goto out_err;
 290        }
 291
 292        /* The downcall format was designed before we completely understood
 293         * the uses of the context fields; so it includes some stuff we
 294         * just give some minimal sanity-checking, and some we ignore
 295         * completely (like the next twenty bytes): */
 296        if (unlikely(p + 20 > end || p + 20 < p)) {
 297                p = ERR_PTR(-EFAULT);
 298                goto out_err;
 299        }
 300        p += 20;
 301        p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
 302        if (IS_ERR(p))
 303                goto out_err;
 304        if (tmp != SGN_ALG_DES_MAC_MD5) {
 305                p = ERR_PTR(-ENOSYS);
 306                goto out_err;
 307        }
 308        p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
 309        if (IS_ERR(p))
 310                goto out_err;
 311        if (tmp != SEAL_ALG_DES) {
 312                p = ERR_PTR(-ENOSYS);
 313                goto out_err;
 314        }
 315        p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
 316        if (IS_ERR(p))
 317                goto out_err;
 318        p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
 319        if (IS_ERR(p))
 320                goto out_err;
 321        p = simple_get_netobj(p, end, &ctx->mech_used);
 322        if (IS_ERR(p))
 323                goto out_err;
 324        p = get_key(p, end, ctx, &ctx->enc);
 325        if (IS_ERR(p))
 326                goto out_err_free_mech;
 327        p = get_key(p, end, ctx, &ctx->seq);
 328        if (IS_ERR(p))
 329                goto out_err_free_key1;
 330        if (p != end) {
 331                p = ERR_PTR(-EFAULT);
 332                goto out_err_free_key2;
 333        }
 334
 335        return 0;
 336
 337out_err_free_key2:
 338        crypto_free_blkcipher(ctx->seq);
 339out_err_free_key1:
 340        crypto_free_blkcipher(ctx->enc);
 341out_err_free_mech:
 342        kfree(ctx->mech_used.data);
 343out_err:
 344        return PTR_ERR(p);
 345}
 346
 347static struct crypto_blkcipher *
 348context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
 349{
 350        struct crypto_blkcipher *cp;
 351
 352        cp = crypto_alloc_blkcipher(cname, 0, CRYPTO_ALG_ASYNC);
 353        if (IS_ERR(cp)) {
 354                dprintk("gss_kerberos_mech: unable to initialize "
 355                        "crypto algorithm %s\n", cname);
 356                return NULL;
 357        }
 358        if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
 359                dprintk("gss_kerberos_mech: error setting key for "
 360                        "crypto algorithm %s\n", cname);
 361                crypto_free_blkcipher(cp);
 362                return NULL;
 363        }
 364        return cp;
 365}
 366
 367static inline void
 368set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
 369{
 370        cdata[0] = (usage>>24)&0xff;
 371        cdata[1] = (usage>>16)&0xff;
 372        cdata[2] = (usage>>8)&0xff;
 373        cdata[3] = usage&0xff;
 374        cdata[4] = seed;
 375}
 376
 377static int
 378context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)
 379{
 380        struct xdr_netobj c, keyin, keyout;
 381        u8 cdata[GSS_KRB5_K5CLENGTH];
 382        u32 err;
 383
 384        c.len = GSS_KRB5_K5CLENGTH;
 385        c.data = cdata;
 386
 387        keyin.data = ctx->Ksess;
 388        keyin.len = ctx->gk5e->keylength;
 389        keyout.len = ctx->gk5e->keylength;
 390
 391        /* seq uses the raw key */
 392        ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
 393                                           ctx->Ksess);
 394        if (ctx->seq == NULL)
 395                goto out_err;
 396
 397        ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
 398                                           ctx->Ksess);
 399        if (ctx->enc == NULL)
 400                goto out_free_seq;
 401
 402        /* derive cksum */
 403        set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
 404        keyout.data = ctx->cksum;
 405        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 406        if (err) {
 407                dprintk("%s: Error %d deriving cksum key\n",
 408                        __func__, err);
 409                goto out_free_enc;
 410        }
 411
 412        return 0;
 413
 414out_free_enc:
 415        crypto_free_blkcipher(ctx->enc);
 416out_free_seq:
 417        crypto_free_blkcipher(ctx->seq);
 418out_err:
 419        return -EINVAL;
 420}
 421
 422/*
 423 * Note that RC4 depends on deriving keys using the sequence
 424 * number or the checksum of a token.  Therefore, the final keys
 425 * cannot be calculated until the token is being constructed!
 426 */
 427static int
 428context_derive_keys_rc4(struct krb5_ctx *ctx)
 429{
 430        struct crypto_hash *hmac;
 431        char sigkeyconstant[] = "signaturekey";
 432        int slen = strlen(sigkeyconstant) + 1;  /* include null terminator */
 433        struct hash_desc desc;
 434        struct scatterlist sg[1];
 435        int err;
 436
 437        dprintk("RPC:       %s: entered\n", __func__);
 438        /*
 439         * derive cksum (aka Ksign) key
 440         */
 441        hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
 442        if (IS_ERR(hmac)) {
 443                dprintk("%s: error %ld allocating hash '%s'\n",
 444                        __func__, PTR_ERR(hmac), ctx->gk5e->cksum_name);
 445                err = PTR_ERR(hmac);
 446                goto out_err;
 447        }
 448
 449        err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength);
 450        if (err)
 451                goto out_err_free_hmac;
 452
 453        sg_init_table(sg, 1);
 454        sg_set_buf(sg, sigkeyconstant, slen);
 455
 456        desc.tfm = hmac;
 457        desc.flags = 0;
 458
 459        err = crypto_hash_init(&desc);
 460        if (err)
 461                goto out_err_free_hmac;
 462
 463        err = crypto_hash_digest(&desc, sg, slen, ctx->cksum);
 464        if (err)
 465                goto out_err_free_hmac;
 466        /*
 467         * allocate hash, and blkciphers for data and seqnum encryption
 468         */
 469        ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
 470                                          CRYPTO_ALG_ASYNC);
 471        if (IS_ERR(ctx->enc)) {
 472                err = PTR_ERR(ctx->enc);
 473                goto out_err_free_hmac;
 474        }
 475
 476        ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
 477                                          CRYPTO_ALG_ASYNC);
 478        if (IS_ERR(ctx->seq)) {
 479                crypto_free_blkcipher(ctx->enc);
 480                err = PTR_ERR(ctx->seq);
 481                goto out_err_free_hmac;
 482        }
 483
 484        dprintk("RPC:       %s: returning success\n", __func__);
 485
 486        err = 0;
 487
 488out_err_free_hmac:
 489        crypto_free_hash(hmac);
 490out_err:
 491        dprintk("RPC:       %s: returning %d\n", __func__, err);
 492        return err;
 493}
 494
 495static int
 496context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
 497{
 498        struct xdr_netobj c, keyin, keyout;
 499        u8 cdata[GSS_KRB5_K5CLENGTH];
 500        u32 err;
 501
 502        c.len = GSS_KRB5_K5CLENGTH;
 503        c.data = cdata;
 504
 505        keyin.data = ctx->Ksess;
 506        keyin.len = ctx->gk5e->keylength;
 507        keyout.len = ctx->gk5e->keylength;
 508
 509        /* initiator seal encryption */
 510        set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
 511        keyout.data = ctx->initiator_seal;
 512        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 513        if (err) {
 514                dprintk("%s: Error %d deriving initiator_seal key\n",
 515                        __func__, err);
 516                goto out_err;
 517        }
 518        ctx->initiator_enc = context_v2_alloc_cipher(ctx,
 519                                                     ctx->gk5e->encrypt_name,
 520                                                     ctx->initiator_seal);
 521        if (ctx->initiator_enc == NULL)
 522                goto out_err;
 523
 524        /* acceptor seal encryption */
 525        set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
 526        keyout.data = ctx->acceptor_seal;
 527        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 528        if (err) {
 529                dprintk("%s: Error %d deriving acceptor_seal key\n",
 530                        __func__, err);
 531                goto out_free_initiator_enc;
 532        }
 533        ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
 534                                                    ctx->gk5e->encrypt_name,
 535                                                    ctx->acceptor_seal);
 536        if (ctx->acceptor_enc == NULL)
 537                goto out_free_initiator_enc;
 538
 539        /* initiator sign checksum */
 540        set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
 541        keyout.data = ctx->initiator_sign;
 542        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 543        if (err) {
 544                dprintk("%s: Error %d deriving initiator_sign key\n",
 545                        __func__, err);
 546                goto out_free_acceptor_enc;
 547        }
 548
 549        /* acceptor sign checksum */
 550        set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
 551        keyout.data = ctx->acceptor_sign;
 552        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 553        if (err) {
 554                dprintk("%s: Error %d deriving acceptor_sign key\n",
 555                        __func__, err);
 556                goto out_free_acceptor_enc;
 557        }
 558
 559        /* initiator seal integrity */
 560        set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
 561        keyout.data = ctx->initiator_integ;
 562        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 563        if (err) {
 564                dprintk("%s: Error %d deriving initiator_integ key\n",
 565                        __func__, err);
 566                goto out_free_acceptor_enc;
 567        }
 568
 569        /* acceptor seal integrity */
 570        set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
 571        keyout.data = ctx->acceptor_integ;
 572        err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
 573        if (err) {
 574                dprintk("%s: Error %d deriving acceptor_integ key\n",
 575                        __func__, err);
 576                goto out_free_acceptor_enc;
 577        }
 578
 579        switch (ctx->enctype) {
 580        case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
 581        case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
 582                ctx->initiator_enc_aux =
 583                        context_v2_alloc_cipher(ctx, "cbc(aes)",
 584                                                ctx->initiator_seal);
 585                if (ctx->initiator_enc_aux == NULL)
 586                        goto out_free_acceptor_enc;
 587                ctx->acceptor_enc_aux =
 588                        context_v2_alloc_cipher(ctx, "cbc(aes)",
 589                                                ctx->acceptor_seal);
 590                if (ctx->acceptor_enc_aux == NULL) {
 591                        crypto_free_blkcipher(ctx->initiator_enc_aux);
 592                        goto out_free_acceptor_enc;
 593                }
 594        }
 595
 596        return 0;
 597
 598out_free_acceptor_enc:
 599        crypto_free_blkcipher(ctx->acceptor_enc);
 600out_free_initiator_enc:
 601        crypto_free_blkcipher(ctx->initiator_enc);
 602out_err:
 603        return -EINVAL;
 604}
 605
 606static int
 607gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
 608                gfp_t gfp_mask)
 609{
 610        int keylen;
 611
 612        p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
 613        if (IS_ERR(p))
 614                goto out_err;
 615        ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
 616
 617        p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
 618        if (IS_ERR(p))
 619                goto out_err;
 620        p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));
 621        if (IS_ERR(p))
 622                goto out_err;
 623        /* set seq_send for use by "older" enctypes */
 624        ctx->seq_send = ctx->seq_send64;
 625        if (ctx->seq_send64 != ctx->seq_send) {
 626                dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,
 627                        (unsigned long)ctx->seq_send64, ctx->seq_send);
 628                p = ERR_PTR(-EINVAL);
 629                goto out_err;
 630        }
 631        p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
 632        if (IS_ERR(p))
 633                goto out_err;
 634        /* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
 635        if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
 636                ctx->enctype = ENCTYPE_DES3_CBC_RAW;
 637        ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
 638        if (ctx->gk5e == NULL) {
 639                dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
 640                        ctx->enctype);
 641                p = ERR_PTR(-EINVAL);
 642                goto out_err;
 643        }
 644        keylen = ctx->gk5e->keylength;
 645
 646        p = simple_get_bytes(p, end, ctx->Ksess, keylen);
 647        if (IS_ERR(p))
 648                goto out_err;
 649
 650        if (p != end) {
 651                p = ERR_PTR(-EINVAL);
 652                goto out_err;
 653        }
 654
 655        ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
 656                                      gss_kerberos_mech.gm_oid.len, gfp_mask);
 657        if (unlikely(ctx->mech_used.data == NULL)) {
 658                p = ERR_PTR(-ENOMEM);
 659                goto out_err;
 660        }
 661        ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
 662
 663        switch (ctx->enctype) {
 664        case ENCTYPE_DES3_CBC_RAW:
 665                return context_derive_keys_des3(ctx, gfp_mask);
 666        case ENCTYPE_ARCFOUR_HMAC:
 667                return context_derive_keys_rc4(ctx);
 668        case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
 669        case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
 670                return context_derive_keys_new(ctx, gfp_mask);
 671        default:
 672                return -EINVAL;
 673        }
 674
 675out_err:
 676        return PTR_ERR(p);
 677}
 678
 679static int
 680gss_import_sec_context_kerberos(const void *p, size_t len,
 681                                struct gss_ctx *ctx_id,
 682                                gfp_t gfp_mask)
 683{
 684        const void *end = (const void *)((const char *)p + len);
 685        struct  krb5_ctx *ctx;
 686        int ret;
 687
 688        ctx = kzalloc(sizeof(*ctx), gfp_mask);
 689        if (ctx == NULL)
 690                return -ENOMEM;
 691
 692        if (len == 85)
 693                ret = gss_import_v1_context(p, end, ctx);
 694        else
 695                ret = gss_import_v2_context(p, end, ctx, gfp_mask);
 696
 697        if (ret == 0)
 698                ctx_id->internal_ctx_id = ctx;
 699        else
 700                kfree(ctx);
 701
 702        dprintk("RPC:       %s: returning %d\n", __func__, ret);
 703        return ret;
 704}
 705
 706static void
 707gss_delete_sec_context_kerberos(void *internal_ctx) {
 708        struct krb5_ctx *kctx = internal_ctx;
 709
 710        crypto_free_blkcipher(kctx->seq);
 711        crypto_free_blkcipher(kctx->enc);
 712        crypto_free_blkcipher(kctx->acceptor_enc);
 713        crypto_free_blkcipher(kctx->initiator_enc);
 714        crypto_free_blkcipher(kctx->acceptor_enc_aux);
 715        crypto_free_blkcipher(kctx->initiator_enc_aux);
 716        kfree(kctx->mech_used.data);
 717        kfree(kctx);
 718}
 719
 720static const struct gss_api_ops gss_kerberos_ops = {
 721        .gss_import_sec_context = gss_import_sec_context_kerberos,
 722        .gss_get_mic            = gss_get_mic_kerberos,
 723        .gss_verify_mic         = gss_verify_mic_kerberos,
 724        .gss_wrap               = gss_wrap_kerberos,
 725        .gss_unwrap             = gss_unwrap_kerberos,
 726        .gss_delete_sec_context = gss_delete_sec_context_kerberos,
 727};
 728
 729static struct pf_desc gss_kerberos_pfs[] = {
 730        [0] = {
 731                .pseudoflavor = RPC_AUTH_GSS_KRB5,
 732                .service = RPC_GSS_SVC_NONE,
 733                .name = "krb5",
 734        },
 735        [1] = {
 736                .pseudoflavor = RPC_AUTH_GSS_KRB5I,
 737                .service = RPC_GSS_SVC_INTEGRITY,
 738                .name = "krb5i",
 739        },
 740        [2] = {
 741                .pseudoflavor = RPC_AUTH_GSS_KRB5P,
 742                .service = RPC_GSS_SVC_PRIVACY,
 743                .name = "krb5p",
 744        },
 745};
 746
 747MODULE_ALIAS("rpc-auth-gss-krb5");
 748MODULE_ALIAS("rpc-auth-gss-krb5i");
 749MODULE_ALIAS("rpc-auth-gss-krb5p");
 750MODULE_ALIAS("rpc-auth-gss-390003");
 751MODULE_ALIAS("rpc-auth-gss-390004");
 752MODULE_ALIAS("rpc-auth-gss-390005");
 753
 754static struct gss_api_mech gss_kerberos_mech = {
 755        .gm_name        = "krb5",
 756        .gm_owner       = THIS_MODULE,
 757        .gm_oid         = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
 758        .gm_ops         = &gss_kerberos_ops,
 759        .gm_pf_num      = ARRAY_SIZE(gss_kerberos_pfs),
 760        .gm_pfs         = gss_kerberos_pfs,
 761        .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
 762};
 763
 764static int __init init_kerberos_module(void)
 765{
 766        int status;
 767
 768        status = gss_mech_register(&gss_kerberos_mech);
 769        if (status)
 770                printk("Failed to register kerberos gss mechanism!\n");
 771        return status;
 772}
 773
 774static void __exit cleanup_kerberos_module(void)
 775{
 776        gss_mech_unregister(&gss_kerberos_mech);
 777}
 778
 779MODULE_LICENSE("GPL");
 780module_init(init_kerberos_module);
 781module_exit(cleanup_kerberos_module);
 782