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