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