root/net/sunrpc/auth_gss/gss_krb5_mech.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. supported_gss_krb5_enctype
  2. get_gss_krb5_enctype
  3. simple_get_bytes
  4. simple_get_netobj
  5. get_key
  6. gss_import_v1_context
  7. context_v2_alloc_cipher
  8. set_cdata
  9. context_derive_keys_des3
  10. context_derive_keys_rc4
  11. context_derive_keys_new
  12. gss_import_v2_context
  13. gss_import_sec_context_kerberos
  14. gss_delete_sec_context_kerberos
  15. init_kerberos_module
  16. cleanup_kerberos_module

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

/* [<][>][^][v][top][bottom][index][help] */