Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gss_krb5_mech.c
Go to the documentation of this file.
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 <[email protected]>
8  * J. Bruce Fields <[email protected]>
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>
47 
48 #ifdef RPC_DEBUG
49 # define RPCDBG_FACILITY RPCDBG_AUTH
50 #endif
51 
52 static struct gss_api_mech gss_kerberos_mech; /* forward declaration */
53 
54 static 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,
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  {
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  {
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 
166 static const int num_supported_enctypes =
167  ARRAY_SIZE(supported_gss_krb5_enctypes);
168 
169 static int
170 supported_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 
179 static const struct gss_krb5_enctype *
180 get_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 
189 static const void *
190 simple_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 
199 static const void *
200 simple_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 
218 static inline const void *
219 get_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,
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 
265 out_err_free_tfm:
266  crypto_free_blkcipher(*res);
267 out_err_free_key:
268  kfree(key.data);
269  p = ERR_PTR(-EINVAL);
270 out_err:
271  return p;
272 }
273 
274 static int
275 gss_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 */
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 
337 out_err_free_key2:
338  crypto_free_blkcipher(ctx->seq);
339 out_err_free_key1:
340  crypto_free_blkcipher(ctx->enc);
341 out_err_free_mech:
342  kfree(ctx->mech_used.data);
343 out_err:
344  return PTR_ERR(p);
345 }
346 
347 static struct crypto_blkcipher *
348 context_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 
367 static inline void
368 set_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 
377 static int
378 context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)
379 {
380  struct xdr_netobj c, keyin, keyout;
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 
414 out_free_enc:
415  crypto_free_blkcipher(ctx->enc);
416 out_free_seq:
417  crypto_free_blkcipher(ctx->seq);
418 out_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  */
427 static int
428 context_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,
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,
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 
488 out_err_free_hmac:
489  crypto_free_hash(hmac);
490 out_err:
491  dprintk("RPC: %s: returning %d\n", __func__, err);
492  return err;
493 }
494 
495 static int
496 context_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 */
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 */
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 */
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 */
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 */
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 */
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) {
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 
598 out_free_acceptor_enc:
599  crypto_free_blkcipher(ctx->acceptor_enc);
600 out_free_initiator_enc:
601  crypto_free_blkcipher(ctx->initiator_enc);
602 out_err:
603  return -EINVAL;
604 }
605 
606 static int
607 gss_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)
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) {
665  return context_derive_keys_des3(ctx, gfp_mask);
667  return context_derive_keys_rc4(ctx);
670  return context_derive_keys_new(ctx, gfp_mask);
671  default:
672  return -EINVAL;
673  }
674 
675 out_err:
676  return PTR_ERR(p);
677 }
678 
679 static int
680 gss_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 
706 static void
707 gss_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 
720 static 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 
729 static 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 
747 MODULE_ALIAS("rpc-auth-gss-krb5");
748 MODULE_ALIAS("rpc-auth-gss-krb5i");
749 MODULE_ALIAS("rpc-auth-gss-krb5p");
750 MODULE_ALIAS("rpc-auth-gss-390003");
751 MODULE_ALIAS("rpc-auth-gss-390004");
752 MODULE_ALIAS("rpc-auth-gss-390005");
753 
754 static 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 
764 static 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 
774 static void __exit cleanup_kerberos_module(void)
775 {
776  gss_mech_unregister(&gss_kerberos_mech);
777 }
778 
779 MODULE_LICENSE("GPL");
780 module_init(init_kerberos_module);
781 module_exit(cleanup_kerberos_module);