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