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