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