xref: /xnu-8019.80.24/bsd/nfs/gss/gss_krb5_mech.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea) !
1 /*
2  * Copyright (c) 2015 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * Copyright (c) 1999 Kungliga Tekniska Högskolan
31  * (Royal Institute of Technology, Stockholm, Sweden).
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions
36  * are met:
37  *
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  *
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  *
45  * 3. Neither the name of KTH nor the names of its contributors may be
46  *    used to endorse or promote products derived from this software without
47  *    specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
50  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
53  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
56  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
57  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
58  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60  */
61 
62 #include <stdint.h>
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/malloc.h>
67 #include <sys/kpi_mbuf.h>
68 #include <sys/random.h>
69 #include <mach_assert.h>
70 #include <kern/assert.h>
71 #include <libkern/OSAtomic.h>
72 #include "gss_krb5_mech.h"
73 
74 LCK_GRP_DECLARE(gss_krb5_mech_grp, "gss_krb5_mech");
75 
76 typedef struct crypt_walker_ctx {
77 	size_t length;
78 	const struct ccmode_cbc *ccmode;
79 	cccbc_ctx *crypt_ctx;
80 	cccbc_iv *iv;
81 } *crypt_walker_ctx_t;
82 
83 typedef struct hmac_walker_ctx {
84 	const struct ccdigest_info *di;
85 	struct cchmac_ctx *hmac_ctx;
86 } *hmac_walker_ctx_t;
87 
88 typedef size_t (*ccpad_func)(const struct ccmode_cbc *, cccbc_ctx *, cccbc_iv *,
89     size_t nbytes, const void *, void *);
90 
91 static int krb5_n_fold(const void *instr, size_t len, void *foldstr, size_t size);
92 
93 size_t gss_mbuf_len(mbuf_t, size_t);
94 errno_t gss_prepend_mbuf(mbuf_t *, uint8_t *, size_t);
95 errno_t gss_append_mbuf(mbuf_t, uint8_t *, size_t);
96 errno_t gss_strip_mbuf(mbuf_t, int);
97 int mbuf_walk(mbuf_t, size_t, size_t, size_t, int (*)(void *, uint8_t *, size_t), void *);
98 
99 void do_crypt_init(crypt_walker_ctx_t, int, crypto_ctx_t, cccbc_ctx *);
100 int do_crypt(void *, uint8_t *, size_t);
101 void do_hmac_init(hmac_walker_ctx_t, crypto_ctx_t, void *);
102 int do_hmac(void *, uint8_t *, size_t);
103 void do_hmac_destroy(hmac_walker_ctx_t, crypto_ctx_t);
104 
105 void krb5_make_usage(uint32_t, uint8_t, uint8_t[KRB5_USAGE_LEN]);
106 void krb5_key_derivation(crypto_ctx_t, const void *, size_t, krb5_key_t *, size_t);
107 void cc_key_schedule_create(crypto_ctx_t);
108 void gss_crypto_ctx_free(crypto_ctx_t);
109 int gss_crypto_ctx_init(struct crypto_ctx *, lucid_context_t);
110 
111 errno_t krb5_crypt_mbuf(crypto_ctx_t, mbuf_t *, size_t, int, cccbc_ctx *);
112 int krb5_mic(crypto_ctx_t, gss_buffer_t, gss_buffer_t, gss_buffer_t, uint8_t *, int *, int, int);
113 int krb5_mic_mbuf(crypto_ctx_t, gss_buffer_t, mbuf_t, size_t, size_t, gss_buffer_t, uint8_t *, int *, int, int);
114 
115 uint32_t gss_krb5_cfx_get_mic(uint32_t *, gss_ctx_id_t, gss_qop_t, gss_buffer_t, gss_buffer_t);
116 uint32_t gss_krb5_cfx_verify_mic(uint32_t *, gss_ctx_id_t, gss_buffer_t, gss_buffer_t, gss_qop_t *);
117 uint32_t gss_krb5_cfx_get_mic_mbuf(uint32_t *, gss_ctx_id_t, gss_qop_t, mbuf_t, size_t, size_t, gss_buffer_t);
118 uint32_t gss_krb5_cfx_verify_mic_mbuf(uint32_t *, gss_ctx_id_t, mbuf_t, size_t, size_t, gss_buffer_t, gss_qop_t *);
119 errno_t krb5_cfx_crypt_mbuf(crypto_ctx_t, mbuf_t *, size_t *, int, int);
120 uint32_t gss_krb5_cfx_wrap_mbuf(uint32_t *, gss_ctx_id_t, int, gss_qop_t, mbuf_t *, size_t, int *);
121 uint32_t gss_krb5_cfx_unwrap_mbuf(uint32_t *, gss_ctx_id_t, mbuf_t *, size_t, int *, gss_qop_t *);
122 
123 int gss_krb5_mech_is_initialized(void);
124 void gss_krb5_mech_init(void);
125 
126 /* Debugging routines */
127 void
printmbuf(const char * str,mbuf_t mb,uint32_t offset,uint32_t len)128 printmbuf(const char *str, mbuf_t mb, uint32_t offset, uint32_t len)
129 {
130 	size_t i;
131 	int cout = 1;
132 
133 	len = len ? len : ~0;
134 	printf("%s mbuf = %p offset = %d len = %d:\n", str ? str : "mbuf", mb, offset, len);
135 	for (; mb && len; mb = mbuf_next(mb)) {
136 		if (offset >= mbuf_len(mb)) {
137 			offset -= mbuf_len(mb);
138 			continue;
139 		}
140 		for (i = offset; len && i < mbuf_len(mb); i++) {
141 			const char *s = (cout % 8) ? " " : (cout % 16) ? "    " : "\n";
142 			printf("%02x%s", ((uint8_t *)mbuf_data(mb))[i], s);
143 			len--;
144 			cout++;
145 		}
146 		offset = 0;
147 	}
148 	if ((cout - 1) % 16) {
149 		printf("\n");
150 	}
151 	printf("Count chars %d\n", cout - 1);
152 }
153 
154 void
printgbuf(const char * str,gss_buffer_t buf)155 printgbuf(const char *str, gss_buffer_t buf)
156 {
157 	size_t i;
158 	size_t len = buf->length > 128 ? 128 : buf->length;
159 
160 	printf("%s:   len = %d value = %p\n", str ? str : "buffer", (int)buf->length, buf->value);
161 	for (i = 0; i < len; i++) {
162 		const char *s = ((i + 1) % 8) ? " " : ((i + 1) % 16) ? "    " : "\n";
163 		printf("%02x%s", ((uint8_t *)buf->value)[i], s);
164 	}
165 	if (i % 16) {
166 		printf("\n");
167 	}
168 }
169 
170 /*
171  * Initialize the data structures for the gss kerberos mech.
172  */
173 #define GSS_KRB5_NOT_INITIALIZED        0
174 #define GSS_KRB5_INITIALIZING   1
175 #define GSS_KRB5_INITIALIZED    2
176 static volatile uint32_t gss_krb5_mech_initted = GSS_KRB5_NOT_INITIALIZED;
177 
178 int
gss_krb5_mech_is_initialized(void)179 gss_krb5_mech_is_initialized(void)
180 {
181 	return gss_krb5_mech_initted == GSS_KRB5_NOT_INITIALIZED;
182 }
183 
184 static void
gss_krb5_key_set(krb5_key_t * krb_key,void * key,size_t len)185 gss_krb5_key_set(krb5_key_t *krb_key, void *key, size_t len)
186 {
187 	krb_key->key_val = key;
188 	krb_key->key_len = len;
189 }
190 
191 static void
gss_krb5_key_free(krb5_key_t * krb_key,int free)192 gss_krb5_key_free(krb5_key_t *krb_key, int free)
193 {
194 	if (free) {
195 		cc_clear(krb_key->key_len, krb_key->key_val);
196 		kfree_data(krb_key->key_val, krb_key->key_len);
197 	}
198 	memset(krb_key, 0, sizeof(krb5_key_t));
199 }
200 
201 static void
gss_krb5_key_ctx_free(krb5_key_t * krb_key,void * ctx_key)202 gss_krb5_key_ctx_free(krb5_key_t *krb_key, void *ctx_key)
203 {
204 	gss_krb5_key_free(krb_key, krb_key->key_val && ctx_key != krb_key->key_val);
205 }
206 
207 void
gss_krb5_mech_init(void)208 gss_krb5_mech_init(void)
209 {
210 	extern void IOSleep(int);
211 
212 	/* Once initted always initted */
213 	if (gss_krb5_mech_initted == GSS_KRB5_INITIALIZED) {
214 		return;
215 	}
216 
217 	/* make sure we init only once */
218 	if (!OSCompareAndSwap(GSS_KRB5_NOT_INITIALIZED, GSS_KRB5_INITIALIZING, &gss_krb5_mech_initted)) {
219 		/* wait until initialization is complete */
220 		while (!gss_krb5_mech_is_initialized()) {
221 			IOSleep(10);
222 		}
223 		return;
224 	}
225 	gss_krb5_mech_initted = GSS_KRB5_INITIALIZED;
226 }
227 
228 uint32_t
gss_release_buffer(uint32_t * minor,gss_buffer_t buf)229 gss_release_buffer(uint32_t *minor, gss_buffer_t buf)
230 {
231 	if (minor) {
232 		*minor = 0;
233 	}
234 	if (buf->value) {
235 		kfree_data(buf->value, buf->length);
236 	}
237 	buf->value = NULL;
238 	buf->length = 0;
239 	return GSS_S_COMPLETE;
240 }
241 
242 /*
243  * GSS mbuf routines
244  */
245 
246 size_t
gss_mbuf_len(mbuf_t mb,size_t offset)247 gss_mbuf_len(mbuf_t mb, size_t offset)
248 {
249 	size_t len;
250 
251 	for (len = 0; mb; mb = mbuf_next(mb)) {
252 		len += mbuf_len(mb);
253 	}
254 	return (offset > len) ? 0 : len - offset;
255 }
256 
257 /*
258  * Split an mbuf in a chain into two mbufs such that the original mbuf
259  * points to the original mbuf and the new mbuf points to the rest of the
260  * chain. The first mbuf length is the first len bytes and the second
261  * mbuf contains the remaining bytes. if len is zero or equals
262  * mbuf_len(mb) the don't create a new mbuf. We are already at an mbuf
263  * boundary. Return the mbuf that starts at the offset.
264  */
265 static errno_t
split_one_mbuf(mbuf_t mb,size_t offset,mbuf_t * nmb,int join)266 split_one_mbuf(mbuf_t mb, size_t offset, mbuf_t *nmb, int join)
267 {
268 	errno_t error;
269 
270 	*nmb = mb;
271 	/* We don't have an mbuf or we're alread on an mbuf boundary */
272 	if (mb == NULL || offset == 0) {
273 		return 0;
274 	}
275 
276 	/* If the mbuf length is offset then the next mbuf is the one we want */
277 	if (mbuf_len(mb) == offset) {
278 		*nmb = mbuf_next(mb);
279 		if (!join) {
280 			mbuf_setnext(mb, NULL);
281 		}
282 		return 0;
283 	}
284 
285 	if (offset > mbuf_len(mb)) {
286 		return EINVAL;
287 	}
288 
289 	error = mbuf_split(mb, offset, MBUF_WAITOK, nmb);
290 	if (error) {
291 		return error;
292 	}
293 
294 	if (mbuf_flags(*nmb) & MBUF_PKTHDR) {
295 		/* We don't want to copy the pkthdr. mbuf_split does that. */
296 		error = mbuf_setflags_mask(*nmb, ~MBUF_PKTHDR, MBUF_PKTHDR);
297 	}
298 
299 	if (join) {
300 		/* Join the chain again */
301 		mbuf_setnext(mb, *nmb);
302 	}
303 
304 	return 0;
305 }
306 
307 /*
308  * Given an mbuf with an offset and length return the chain such that
309  * offset and offset + *subchain_length are on mbuf boundaries.  If
310  * *mbuf_length is less that the length of the chain after offset
311  * return that length in *mbuf_length. The mbuf sub chain starting at
312  * offset is returned in *subchain. If an error occurs return the
313  * corresponding errno. Note if there are less than offset bytes then
314  * subchain will be set to NULL and *subchain_length will be set to
315  * zero. If *subchain_length is 0; then set it to the length of the
316  * chain starting at offset. Join parameter is used to indicate whether
317  * the mbuf chain will be joined again as on chain, just rearranged so
318  * that offset and subchain_length are on mbuf boundaries.
319  */
320 
321 errno_t
gss_normalize_mbuf(mbuf_t chain,size_t offset,size_t * subchain_length,mbuf_t * subchain,mbuf_t * tail,int join)322 gss_normalize_mbuf(mbuf_t chain, size_t offset, size_t *subchain_length, mbuf_t *subchain, mbuf_t *tail, int join)
323 {
324 	size_t length = *subchain_length ? *subchain_length : ~0;
325 	size_t len;
326 	mbuf_t mb, nmb;
327 	errno_t error;
328 
329 	if (tail == NULL) {
330 		tail = &nmb;
331 	}
332 	*tail = NULL;
333 	*subchain = NULL;
334 
335 	for (len = offset, mb = chain; mb && len > mbuf_len(mb); mb = mbuf_next(mb)) {
336 		len -= mbuf_len(mb);
337 	}
338 
339 	/* if we don't have offset bytes just return */
340 	if (mb == NULL) {
341 		return 0;
342 	}
343 
344 	error = split_one_mbuf(mb, len, subchain, join);
345 	if (error) {
346 		return error;
347 	}
348 
349 	assert(subchain != NULL && *subchain != NULL);
350 	assert(offset == 0 ? mb == *subchain : 1);
351 
352 	len = gss_mbuf_len(*subchain, 0);
353 	length =  (length > len) ? len : length;
354 	*subchain_length = length;
355 
356 	for (len = length, mb = *subchain; mb && len > mbuf_len(mb); mb = mbuf_next(mb)) {
357 		len -= mbuf_len(mb);
358 	}
359 
360 	error = split_one_mbuf(mb, len, tail, join);
361 
362 	return error;
363 }
364 
365 mbuf_t
gss_join_mbuf(mbuf_t head,mbuf_t body,mbuf_t tail)366 gss_join_mbuf(mbuf_t head, mbuf_t body, mbuf_t tail)
367 {
368 	mbuf_t mb;
369 
370 	for (mb = head; mb && mbuf_next(mb); mb = mbuf_next(mb)) {
371 		;
372 	}
373 	if (mb) {
374 		mbuf_setnext(mb, body);
375 	}
376 	for (mb = body; mb && mbuf_next(mb); mb = mbuf_next(mb)) {
377 		;
378 	}
379 	if (mb) {
380 		mbuf_setnext(mb, tail);
381 	}
382 	mb = head ? head : (body ? body : tail);
383 	return mb;
384 }
385 
386 /*
387  * Prepend size bytes to the mbuf chain.
388  */
389 errno_t
gss_prepend_mbuf(mbuf_t * chain,uint8_t * bytes,size_t size)390 gss_prepend_mbuf(mbuf_t *chain, uint8_t *bytes, size_t size)
391 {
392 	uint8_t *data = mbuf_data(*chain);
393 	size_t leading = mbuf_leadingspace(*chain);
394 	size_t trailing = mbuf_trailingspace(*chain);
395 	size_t mlen = mbuf_len(*chain);
396 	errno_t error;
397 
398 	if (size > leading && size <= leading + trailing) {
399 		data = memmove(data + size - leading, data, mlen);
400 		mbuf_setdata(*chain, data, mlen);
401 	}
402 
403 	error = mbuf_prepend(chain, size, MBUF_WAITOK);
404 	if (error) {
405 		return error;
406 	}
407 	data = mbuf_data(*chain);
408 	memcpy(data, bytes, size);
409 
410 	return 0;
411 }
412 
413 errno_t
gss_append_mbuf(mbuf_t chain,uint8_t * bytes,size_t size)414 gss_append_mbuf(mbuf_t chain, uint8_t *bytes, size_t size)
415 {
416 	size_t len = 0;
417 	mbuf_t mb;
418 
419 	if (chain == NULL) {
420 		return EINVAL;
421 	}
422 
423 	for (mb = chain; mb; mb = mbuf_next(mb)) {
424 		len += mbuf_len(mb);
425 	}
426 
427 	return mbuf_copyback(chain, len, size, bytes, MBUF_WAITOK);
428 }
429 
430 errno_t
gss_strip_mbuf(mbuf_t chain,int size)431 gss_strip_mbuf(mbuf_t chain, int size)
432 {
433 	if (chain == NULL) {
434 		return EINVAL;
435 	}
436 
437 	mbuf_adj(chain, size);
438 
439 	return 0;
440 }
441 
442 
443 /*
444  * Kerberos mech generic crypto support for mbufs
445  */
446 
447 /*
448  * Walk the mbuf after the given offset calling the passed in crypto function
449  * for len bytes. Note the length, len should be a multiple of the  blocksize and
450  * there should be at least len bytes available after the offset in the mbuf chain.
451  * padding should be done before calling this routine.
452  */
453 int
mbuf_walk(mbuf_t mbp,size_t offset,size_t len,size_t blocksize,int (* crypto_fn)(void *,uint8_t * data,size_t length),void * ctx)454 mbuf_walk(mbuf_t mbp, size_t offset, size_t len, size_t blocksize, int (*crypto_fn)(void *, uint8_t *data, size_t length), void *ctx)
455 {
456 	mbuf_t mb;
457 	size_t mlen, residue;
458 	uint8_t *ptr;
459 	int error = 0;
460 
461 	/* Move to the start of the chain */
462 	for (mb = mbp; mb && len > 0; mb = mbuf_next(mb)) {
463 		ptr = mbuf_data(mb);
464 		mlen = mbuf_len(mb);
465 		if (offset >= mlen) {
466 			/* Offset not yet reached */
467 			offset -= mlen;
468 			continue;
469 		}
470 		/* Found starting point in chain */
471 		ptr += offset;
472 		mlen -= offset;
473 		offset = 0;
474 
475 		/*
476 		 * Handle the data in this mbuf. If the length to
477 		 * walk is less than the data in the mbuf, set
478 		 * the mbuf length left to be the length left
479 		 */
480 		mlen = mlen < len ? mlen : len;
481 		/* Figure out how much is a multple of blocksize */
482 		residue = mlen % blocksize;
483 		/* And addjust the mleft length to be the largest multiple of blocksized */
484 		mlen -= residue;
485 		/* run our hash/encrypt/decrpyt function */
486 		if (mlen > 0) {
487 			error = crypto_fn(ctx, ptr, mlen);
488 			if (error) {
489 				break;
490 			}
491 			ptr += mlen;
492 			len -= mlen;
493 		}
494 		/*
495 		 * If we have a residue then to get a full block for our crypto
496 		 * function, we need to copy the residue into our block size
497 		 * block and use the next mbuf to get the rest of the data for
498 		 * the block.  N.B. We generally assume that from the offset
499 		 * passed in, that the total length, len, is a multple of
500 		 * blocksize and that there are at least len bytes in the chain
501 		 * from the offset.  We also assume there is at least (blocksize
502 		 * - residue) size data in any next mbuf for residue > 0. If not
503 		 * we attemp to pullup bytes from down the chain.
504 		 */
505 		if (residue) {
506 			mbuf_t nmb = mbuf_next(mb);
507 			uint8_t *nptr = NULL, *block = NULL;
508 
509 			block = kalloc_data(blocksize, Z_WAITOK | Z_ZERO);
510 			if (block == NULL) {
511 				return ENOMEM;
512 			}
513 			assert(nmb);
514 			len -= residue;
515 			offset = blocksize - residue;
516 			if (len < offset) {
517 				offset = len;
518 				/*
519 				 * We don't have enough bytes so zero the block
520 				 * so that any trailing bytes will be zero.
521 				 */
522 				cc_clear(blocksize, block);
523 			}
524 			memcpy(block, ptr, residue);
525 			if (len && nmb) {
526 				mlen = mbuf_len(nmb);
527 				if (mlen < offset) {
528 					error = mbuf_pullup(&nmb, offset - mlen);
529 					if (error) {
530 						mbuf_setnext(mb, NULL);
531 						kfree_data(block, blocksize);
532 						return error;
533 					}
534 				}
535 				nptr = mbuf_data(nmb);
536 				memcpy(block + residue, nptr, offset);
537 			}
538 			len -= offset;
539 			error = crypto_fn(ctx, block, blocksize);
540 			if (error) {
541 				kfree_data(block, blocksize);
542 				break;
543 			}
544 			memcpy(ptr, block, residue);
545 			if (nptr) {
546 				memcpy(nptr, block + residue, offset);
547 			}
548 			kfree_data(block, blocksize);
549 		}
550 	}
551 
552 	return error;
553 }
554 
555 void
do_crypt_init(crypt_walker_ctx_t wctx,int encrypt,crypto_ctx_t cctx,cccbc_ctx * ks)556 do_crypt_init(crypt_walker_ctx_t wctx, int encrypt, crypto_ctx_t cctx, cccbc_ctx *ks)
557 {
558 	memset(wctx, 0, sizeof(*wctx));
559 	wctx->length = 0;
560 	wctx->ccmode = encrypt ? cctx->enc_mode : cctx->dec_mode;
561 	wctx->crypt_ctx = ks;
562 	wctx->iv = kalloc_data(wctx->ccmode->block_size, Z_WAITOK | Z_ZERO);
563 	cccbc_set_iv(wctx->ccmode, wctx->iv, NULL);
564 }
565 
566 int
do_crypt(void * walker,uint8_t * data,size_t len)567 do_crypt(void *walker, uint8_t *data, size_t len)
568 {
569 	struct crypt_walker_ctx *wctx = (crypt_walker_ctx_t)walker;
570 	size_t nblocks;
571 
572 	nblocks = len / wctx->ccmode->block_size;
573 	assert(len % wctx->ccmode->block_size == 0);
574 	cccbc_update(wctx->ccmode, wctx->crypt_ctx, wctx->iv, nblocks, data, data);
575 	wctx->length += len;
576 
577 	return 0;
578 }
579 
580 void
do_hmac_init(hmac_walker_ctx_t wctx,crypto_ctx_t cctx,void * key)581 do_hmac_init(hmac_walker_ctx_t wctx, crypto_ctx_t cctx, void *key)
582 {
583 	size_t alloc_size = cchmac_di_size(cctx->di);
584 
585 	wctx->di = cctx->di;
586 	wctx->hmac_ctx = kalloc_data(alloc_size, Z_WAITOK | Z_ZERO);
587 	cchmac_init(cctx->di, wctx->hmac_ctx, cctx->keylen, key);
588 }
589 
590 int
do_hmac(void * walker,uint8_t * data,size_t len)591 do_hmac(void *walker, uint8_t *data, size_t len)
592 {
593 	hmac_walker_ctx_t wctx = (hmac_walker_ctx_t)walker;
594 
595 	cchmac_update(wctx->di, wctx->hmac_ctx, len, data);
596 
597 	return 0;
598 }
599 
600 void
do_hmac_destroy(hmac_walker_ctx_t wctx,crypto_ctx_t cctx)601 do_hmac_destroy(hmac_walker_ctx_t wctx, crypto_ctx_t cctx)
602 {
603 	size_t alloc_size = cchmac_di_size(cctx->di);
604 	kfree_data(wctx->hmac_ctx, alloc_size);
605 }
606 
607 int
krb5_mic(crypto_ctx_t ctx,gss_buffer_t header,gss_buffer_t bp,gss_buffer_t trailer,uint8_t * mic,int * verify,int ikey,int reverse)608 krb5_mic(crypto_ctx_t ctx, gss_buffer_t header, gss_buffer_t bp, gss_buffer_t trailer, uint8_t *mic, int *verify, int ikey, int reverse)
609 {
610 	uint8_t *digest = NULL;
611 	cchmac_di_decl(ctx->di, hmac_ctx);
612 	int kdx = (verify == NULL) ? (reverse ? GSS_RCV : GSS_SND) : (reverse ? GSS_SND : GSS_RCV);
613 	void *key2use;
614 
615 	digest = kalloc_data(ctx->di->output_size, Z_WAITOK | Z_ZERO);
616 	if (digest == NULL) {
617 		return ENOMEM;
618 	}
619 	if (ikey) {
620 		if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
621 			lck_mtx_lock(&ctx->lock);
622 			if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
623 				cc_key_schedule_create(ctx);
624 			}
625 			ctx->flags |= CRYPTO_KS_ALLOCED;
626 			lck_mtx_unlock(&ctx->lock);
627 		}
628 		key2use = ctx->ks.ikeys[kdx].key_val;
629 	} else {
630 		key2use = ctx->ckeys[kdx].key_val;
631 	}
632 
633 	cchmac_init(ctx->di, hmac_ctx, ctx->keylen, key2use);
634 
635 	if (header) {
636 		cchmac_update(ctx->di, hmac_ctx, header->length, header->value);
637 	}
638 
639 	cchmac_update(ctx->di, hmac_ctx, bp->length, bp->value);
640 
641 	if (trailer) {
642 		cchmac_update(ctx->di, hmac_ctx, trailer->length, trailer->value);
643 	}
644 
645 	cchmac_final(ctx->di, hmac_ctx, digest);
646 
647 	if (verify) {
648 		*verify = (memcmp(mic, digest, ctx->digest_size) == 0);
649 	} else {
650 		memcpy(mic, digest, ctx->digest_size);
651 	}
652 
653 	kfree_data(digest, ctx->di->output_size);
654 	return 0;
655 }
656 
657 int
krb5_mic_mbuf(crypto_ctx_t ctx,gss_buffer_t header,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t trailer,uint8_t * mic,int * verify,int ikey,int reverse)658 krb5_mic_mbuf(crypto_ctx_t ctx, gss_buffer_t header,
659     mbuf_t mbp, size_t offset, size_t len, gss_buffer_t trailer, uint8_t *mic, int *verify, int ikey, int reverse)
660 {
661 	struct hmac_walker_ctx wctx;
662 	uint8_t *digest = NULL;
663 	int error;
664 	int kdx = (verify == NULL) ? (reverse ? GSS_RCV : GSS_SND) : (reverse ? GSS_SND : GSS_RCV);
665 	void *key2use;
666 
667 	digest = kalloc_data(ctx->di->output_size, Z_WAITOK | Z_ZERO);
668 	if (digest == NULL) {
669 		return ENOMEM;
670 	}
671 	if (ikey) {
672 		if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
673 			lck_mtx_lock(&ctx->lock);
674 			if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
675 				cc_key_schedule_create(ctx);
676 			}
677 			ctx->flags |= CRYPTO_KS_ALLOCED;
678 			lck_mtx_unlock(&ctx->lock);
679 		}
680 		key2use = ctx->ks.ikeys[kdx].key_val;
681 	} else {
682 		key2use = ctx->ckeys[kdx].key_val;
683 	}
684 
685 	do_hmac_init(&wctx, ctx, key2use);
686 
687 	if (header) {
688 		cchmac_update(ctx->di, wctx.hmac_ctx, header->length, header->value);
689 	}
690 
691 	error = mbuf_walk(mbp, offset, len, 1, do_hmac, &wctx);
692 
693 	if (error) {
694 		kfree_data(digest, ctx->di->output_size);
695 		return error;
696 	}
697 	if (trailer) {
698 		cchmac_update(ctx->di, wctx.hmac_ctx, trailer->length, trailer->value);
699 	}
700 
701 	cchmac_final(ctx->di, wctx.hmac_ctx, digest);
702 	do_hmac_destroy(&wctx, ctx);
703 
704 	if (verify) {
705 		*verify = (memcmp(mic, digest, ctx->digest_size) == 0);
706 		if (!*verify) {
707 			kfree_data(digest, ctx->di->output_size);
708 			return EBADRPC;
709 		}
710 	} else {
711 		memcpy(mic, digest, ctx->digest_size);
712 	}
713 
714 	kfree_data(digest, ctx->di->output_size);
715 	return 0;
716 }
717 
718 errno_t
719 /* __attribute__((optnone)) */
krb5_crypt_mbuf(crypto_ctx_t ctx,mbuf_t * mbp,size_t len,int encrypt,cccbc_ctx * ks)720 krb5_crypt_mbuf(crypto_ctx_t ctx, mbuf_t *mbp, size_t len, int encrypt, cccbc_ctx *ks)
721 {
722 	struct crypt_walker_ctx wctx;
723 	const struct ccmode_cbc *ccmode = encrypt ? ctx->enc_mode : ctx->dec_mode;
724 	size_t plen = len;
725 	size_t cts_len = 0;
726 	mbuf_t mb, lmb = NULL;
727 	int error;
728 
729 	if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
730 		lck_mtx_lock(&ctx->lock);
731 		if (!(ctx->flags & CRYPTO_KS_ALLOCED)) {
732 			cc_key_schedule_create(ctx);
733 		}
734 		ctx->flags |= CRYPTO_KS_ALLOCED;
735 		lck_mtx_unlock(&ctx->lock);
736 	}
737 	if (!ks) {
738 		ks = encrypt ? ctx->ks.enc : ctx->ks.dec;
739 	}
740 
741 	if ((ctx->flags & CRYPTO_CTS_ENABLE) && ctx->mpad == 1) {
742 		uint8_t *block = NULL;
743 
744 		block = kalloc_data(ccmode->block_size, Z_WAITOK | Z_ZERO);
745 		if (block == NULL) {
746 			return ENOMEM;
747 		}
748 		/* if the length is less than or equal to a blocksize. We just encrypt the block */
749 		if (len <= ccmode->block_size) {
750 			if (len < ccmode->block_size) {
751 				gss_append_mbuf(*mbp, block, ccmode->block_size);
752 			}
753 			plen = ccmode->block_size;
754 		} else {
755 			/* determine where the last two blocks are */
756 			size_t r = len % ccmode->block_size;
757 
758 			cts_len  = r ? r + ccmode->block_size : 2 * ccmode->block_size;
759 			plen = len - cts_len;
760 			/* If plen is 0 we only have two blocks to crypt with ccpad below */
761 			if (plen == 0) {
762 				lmb = *mbp;
763 			} else {
764 				gss_normalize_mbuf(*mbp, 0, &plen, &mb, &lmb, 0);
765 				assert(*mbp == mb);
766 				assert(plen == len - cts_len);
767 				assert(gss_mbuf_len(mb, 0) == plen);
768 				assert(gss_mbuf_len(lmb, 0) == cts_len);
769 			}
770 		}
771 		kfree_data(block, ccmode->block_size);
772 	} else if (len % ctx->mpad) {
773 		uint8_t *pad_block = NULL;
774 		size_t padlen = ctx->mpad - (len % ctx->mpad);
775 
776 		pad_block = kalloc_data(ctx->mpad, Z_WAITOK | Z_ZERO);
777 		if (pad_block == NULL) {
778 			return ENOMEM;
779 		}
780 		error = gss_append_mbuf(*mbp, pad_block, padlen);
781 		if (error) {
782 			kfree_data(pad_block, ctx->mpad);
783 			return error;
784 		}
785 		plen = len + padlen;
786 		kfree_data(pad_block, ctx->mpad);
787 	}
788 	do_crypt_init(&wctx, encrypt, ctx, ks);
789 	if (plen) {
790 		error = mbuf_walk(*mbp, 0, plen, ccmode->block_size, do_crypt, &wctx);
791 		if (error) {
792 			return error;
793 		}
794 	}
795 
796 	if ((ctx->flags & CRYPTO_CTS_ENABLE) && cts_len) {
797 		uint8_t *cts_pad = NULL;
798 		ccpad_func do_ccpad = encrypt ? ccpad_cts3_encrypt : ccpad_cts3_decrypt;
799 
800 		cts_pad = kalloc_data(2 * ccmode->block_size, Z_WAITOK | Z_ZERO);
801 		if (cts_pad == NULL) {
802 			return ENOMEM;
803 		}
804 		assert(cts_len <= 2 * ccmode->block_size && cts_len > ccmode->block_size);
805 		mbuf_copydata(lmb, 0, cts_len, cts_pad);
806 		mbuf_freem(lmb);
807 		do_ccpad(ccmode, wctx.crypt_ctx, wctx.iv, cts_len, cts_pad, cts_pad);
808 		gss_append_mbuf(*mbp, cts_pad, cts_len);
809 		kfree_data(cts_pad, 2 * ccmode->block_size);
810 	}
811 	kfree_data(wctx.iv, wctx.ccmode->block_size);
812 
813 	return 0;
814 }
815 
816 /*
817  * Key derivation routines
818  */
819 
820 static int
rr13(unsigned char * buf,size_t len)821 rr13(unsigned char *buf, size_t len)
822 {
823 	size_t bytes = (len + 7) / 8;
824 	unsigned char *tmp = NULL;
825 	size_t i;
826 
827 	if (len == 0) {
828 		return 0;
829 	}
830 
831 	tmp = kalloc_data(bytes, Z_WAITOK | Z_ZERO);
832 
833 	{
834 		const int bits = 13 % len;
835 		const int lbit = len % 8;
836 
837 		memcpy(tmp, buf, bytes);
838 		if (lbit) {
839 			/* pad final byte with inital bits */
840 			tmp[bytes - 1] &= 0xff << (8 - lbit);
841 			for (i = lbit; i < 8; i += len) {
842 				tmp[bytes - 1] |= buf[0] >> i;
843 			}
844 		}
845 		for (i = 0; i < bytes; i++) {
846 			ssize_t bb;
847 			ssize_t b1, s1, b2, s2;
848 
849 			/* calculate first bit position of this byte */
850 			bb = 8 * i - bits;
851 			while (bb < 0) {
852 				bb += len;
853 			}
854 			/* byte offset and shift count */
855 			b1 = bb / 8;
856 			s1 = bb % 8;
857 			if ((size_t)bb + 8 > bytes * 8) {
858 				/* watch for wraparound */
859 				s2 = (len + 8 - s1) % 8;
860 			} else {
861 				s2 = 8 - s1;
862 			}
863 			b2 = (b1 + 1) % bytes;
864 			buf[i] = 0xff & ((tmp[b1] << s1) | (tmp[b2] >> s2));
865 		}
866 	}
867 	kfree_data(tmp, bytes);
868 	return 0;
869 }
870 
871 
872 /* Add `b' to `a', both being one's complement numbers. */
873 static void
add1(unsigned char * a,unsigned char * b,size_t len)874 add1(unsigned char *a, unsigned char *b, size_t len)
875 {
876 	ssize_t i;
877 	int carry = 0;
878 
879 	for (i = len - 1; i >= 0; i--) {
880 		int x = a[i] + b[i] + carry;
881 		carry = x > 0xff;
882 		a[i] = x & 0xff;
883 	}
884 	for (i = len - 1; carry && i >= 0; i--) {
885 		int x = a[i] + carry;
886 		carry = x > 0xff;
887 		a[i] = x & 0xff;
888 	}
889 }
890 
891 
892 static int
krb5_n_fold(const void * instr,size_t len,void * foldstr,size_t size)893 krb5_n_fold(const void *instr, size_t len, void *foldstr, size_t size)
894 {
895 	/* if len < size we need at most N * len bytes, ie < 2 * size;
896 	 *  if len > size we need at most 2 * len */
897 	int ret = 0;
898 	size_t maxlen = 2 * lmax(size, len);
899 	size_t l = 0;
900 	unsigned char *tmp = NULL;
901 	unsigned char *buf = NULL;
902 
903 	tmp = kalloc_data(maxlen, Z_WAITOK | Z_ZERO);
904 	buf = kalloc_data(len, Z_WAITOK | Z_ZERO);
905 
906 	memcpy(buf, instr, len);
907 	memset(foldstr, 0, size);
908 	do {
909 		memcpy(tmp + l, buf, len);
910 		l += len;
911 		ret = rr13(buf, len * 8);
912 		if (ret) {
913 			goto out;
914 		}
915 		while (l >= size) {
916 			add1(foldstr, tmp, size);
917 			l -= size;
918 			if (l == 0) {
919 				break;
920 			}
921 			memmove(tmp, tmp + size, l);
922 		}
923 	} while (l != 0);
924 out:
925 
926 	kfree_data(tmp, maxlen);
927 	kfree_data(buf, len);
928 	return ret;
929 }
930 
931 void
krb5_make_usage(uint32_t usage_no,uint8_t suffix,uint8_t usage_string[KRB5_USAGE_LEN])932 krb5_make_usage(uint32_t usage_no, uint8_t suffix, uint8_t usage_string[KRB5_USAGE_LEN])
933 {
934 	uint32_t i;
935 
936 	for (i = 0; i < 4; i++) {
937 		usage_string[i] = ((usage_no >> 8 * (3 - i)) & 0xff);
938 	}
939 	usage_string[i] = suffix;
940 }
941 
942 void
krb5_key_derivation(crypto_ctx_t ctx,const void * cons,size_t conslen,krb5_key_t * dkey,size_t dklen)943 krb5_key_derivation(crypto_ctx_t ctx, const void *cons, size_t conslen, krb5_key_t *dkey, size_t dklen)
944 {
945 	size_t blocksize = ctx->enc_mode->block_size;
946 	cccbc_iv_decl(blocksize, iv);
947 	cccbc_ctx_decl(ctx->enc_mode->size, enc_ctx);
948 	size_t ksize = 8 * dklen;
949 	size_t nblocks = (ksize + 8 * blocksize - 1) / (8 * blocksize);
950 	uint8_t *dkptr;
951 	uint8_t *block = NULL;
952 
953 	block = kalloc_data(blocksize, Z_WAITOK | Z_ZERO);
954 	gss_krb5_key_set(dkey, kalloc_data(nblocks * blocksize, Z_WAITOK | Z_ZERO), nblocks * blocksize);
955 	dkptr = dkey->key_val;
956 
957 	krb5_n_fold(cons, conslen, block, blocksize);
958 	cccbc_init(ctx->enc_mode, enc_ctx, ctx->keylen, ctx->key);
959 	for (size_t i = 0; i < nblocks; i++) {
960 		cccbc_set_iv(ctx->enc_mode, iv, NULL);
961 		cccbc_update(ctx->enc_mode, enc_ctx, iv, 1, block, block);
962 		memcpy(dkptr, block, blocksize);
963 		dkptr += blocksize;
964 	}
965 	kfree_data(block, blocksize);
966 }
967 
968 static void
des_make_key(const uint8_t rawkey[7],uint8_t deskey[8])969 des_make_key(const uint8_t rawkey[7], uint8_t deskey[8])
970 {
971 	uint8_t val = 0;
972 
973 	memcpy(deskey, rawkey, 7);
974 	for (int i = 0; i < 7; i++) {
975 		val |= ((deskey[i] & 1) << (i + 1));
976 	}
977 	deskey[7] = val;
978 	ccdes_key_set_odd_parity(deskey, 8);
979 }
980 
981 static void
krb5_3des_key_derivation(crypto_ctx_t ctx,const void * cons,size_t conslen,krb5_key_t * des3key)982 krb5_3des_key_derivation(crypto_ctx_t ctx, const void *cons, size_t conslen, krb5_key_t *des3key)
983 {
984 	const struct ccmode_cbc *cbcmode = ctx->enc_mode;
985 	krb5_key_t rawkey;
986 	size_t rawkey_len;
987 	uint8_t *kptr, *rptr;
988 
989 	gss_krb5_key_set(des3key, kalloc_data(3 * cbcmode->block_size, Z_WAITOK | Z_ZERO), 3 * cbcmode->block_size);
990 	rawkey_len = 3 * (cbcmode->block_size - 1);
991 	krb5_key_derivation(ctx, cons, conslen, &rawkey, rawkey_len);
992 	kptr = des3key->key_val;
993 	rptr = rawkey.key_val;
994 
995 	for (int i = 0; i < 3; i++) {
996 		des_make_key(rptr, kptr);
997 		rptr += cbcmode->block_size - 1;
998 		kptr += cbcmode->block_size;
999 	}
1000 
1001 	gss_krb5_key_free(&rawkey, 1);
1002 }
1003 
1004 /*
1005  * Create a key schecule
1006  *
1007  */
1008 void
cc_key_schedule_create(crypto_ctx_t ctx)1009 cc_key_schedule_create(crypto_ctx_t ctx)
1010 {
1011 	uint8_t usage_string[KRB5_USAGE_LEN];
1012 	lucid_context_t lctx = ctx->gss_ctx;
1013 	krb5_key_t ekey;
1014 
1015 	switch (lctx->key_data.proto) {
1016 	case 0: {
1017 		if (ctx->ks.enc == NULL) {
1018 			ctx->ks.enc = kalloc_data(ctx->enc_mode->size, Z_WAITOK | Z_ZERO);
1019 			cccbc_init(ctx->enc_mode, ctx->ks.enc, ctx->keylen, ctx->key);
1020 		}
1021 		if (ctx->ks.dec == NULL) {
1022 			ctx->ks.dec = kalloc_data(ctx->dec_mode->size, Z_WAITOK | Z_ZERO);
1023 			cccbc_init(ctx->dec_mode, ctx->ks.dec, ctx->keylen, ctx->key);
1024 		}
1025 	}
1026 		OS_FALLTHROUGH;
1027 	case 1: {
1028 		if (ctx->ks.enc == NULL) {
1029 			krb5_make_usage(lctx->initiate ?
1030 			    KRB5_USAGE_INITIATOR_SEAL : KRB5_USAGE_ACCEPTOR_SEAL,
1031 			    0xAA, usage_string);
1032 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ekey, ctx->keylen);
1033 			ctx->ks.enc = kalloc_data(ctx->enc_mode->size, Z_WAITOK | Z_ZERO);
1034 			cccbc_init(ctx->enc_mode, ctx->ks.enc, ctx->keylen, ekey.key_val);
1035 			gss_krb5_key_free(&ekey, 1);
1036 		}
1037 		if (ctx->ks.dec == NULL) {
1038 			krb5_make_usage(lctx->initiate ?
1039 			    KRB5_USAGE_ACCEPTOR_SEAL : KRB5_USAGE_INITIATOR_SEAL,
1040 			    0xAA, usage_string);
1041 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ekey, ctx->keylen);
1042 			ctx->ks.dec = kalloc_data(ctx->dec_mode->size, Z_WAITOK | Z_ZERO);
1043 			cccbc_init(ctx->dec_mode, ctx->ks.dec, ctx->keylen, ekey.key_val);
1044 			gss_krb5_key_free(&ekey, 1);
1045 		}
1046 		if (ctx->ks.ikeys[GSS_SND].key_val == NULL) {
1047 			krb5_make_usage(lctx->initiate ?
1048 			    KRB5_USAGE_INITIATOR_SEAL : KRB5_USAGE_ACCEPTOR_SEAL,
1049 			    0x55, usage_string);
1050 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ks.ikeys[GSS_SND], ctx->keylen);
1051 		}
1052 		if (ctx->ks.ikeys[GSS_RCV].key_val == NULL) {
1053 			krb5_make_usage(lctx->initiate ?
1054 			    KRB5_USAGE_ACCEPTOR_SEAL : KRB5_USAGE_INITIATOR_SEAL,
1055 			    0x55, usage_string);
1056 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ks.ikeys[GSS_RCV], ctx->keylen);
1057 		}
1058 	}
1059 	}
1060 }
1061 
1062 void
gss_crypto_ctx_free(crypto_ctx_t ctx)1063 gss_crypto_ctx_free(crypto_ctx_t ctx)
1064 {
1065 	lck_mtx_destroy(&ctx->lock, &gss_krb5_mech_grp);
1066 
1067 	gss_krb5_key_ctx_free(&ctx->ks.ikeys[GSS_SND], ctx->key);
1068 	gss_krb5_key_ctx_free(&ctx->ks.ikeys[GSS_RCV], ctx->key);
1069 	if (ctx->ks.enc) {
1070 		cccbc_ctx_clear(ctx->enc_mode->size, ctx->ks.enc);
1071 		kfree_data(ctx->ks.enc, ctx->enc_mode->size);
1072 	}
1073 	if (ctx->ks.dec) {
1074 		cccbc_ctx_clear(ctx->dec_mode->size, ctx->ks.dec);
1075 		kfree_data(ctx->ks.dec, ctx->dec_mode->size);
1076 	}
1077 	gss_krb5_key_ctx_free(&ctx->ckeys[GSS_SND], ctx->key);
1078 	gss_krb5_key_ctx_free(&ctx->ckeys[GSS_RCV], ctx->key);
1079 	ctx->key = NULL;
1080 	ctx->keylen = 0;
1081 }
1082 
1083 int
gss_crypto_ctx_init(struct crypto_ctx * ctx,lucid_context_t lucid)1084 gss_crypto_ctx_init(struct crypto_ctx *ctx, lucid_context_t lucid)
1085 {
1086 	ctx->gss_ctx = lucid;
1087 	void *key;
1088 	uint8_t usage_string[KRB5_USAGE_LEN];
1089 
1090 	ctx->keylen = ctx->gss_ctx->ctx_key.key.key_len;
1091 	key = ctx->gss_ctx->ctx_key.key.key_val;
1092 	ctx->etype = ctx->gss_ctx->ctx_key.etype;
1093 	ctx->key = key;
1094 
1095 	switch (ctx->etype) {
1096 	case AES128_CTS_HMAC_SHA1_96:
1097 	case AES256_CTS_HMAC_SHA1_96:
1098 		ctx->enc_mode = ccaes_cbc_encrypt_mode();
1099 		assert(ctx->enc_mode);
1100 		ctx->dec_mode = ccaes_cbc_decrypt_mode();
1101 		assert(ctx->dec_mode);
1102 		ctx->ks.enc = NULL;
1103 		ctx->ks.dec = NULL;
1104 		ctx->di = ccsha1_di();
1105 		assert(ctx->di);
1106 		ctx->flags = CRYPTO_CTS_ENABLE;
1107 		ctx->mpad = 1;
1108 		ctx->digest_size = 12; /* 96 bits */
1109 		krb5_make_usage(ctx->gss_ctx->initiate ?
1110 		    KRB5_USAGE_INITIATOR_SIGN : KRB5_USAGE_ACCEPTOR_SIGN,
1111 		    0x99, usage_string);
1112 		krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ckeys[GSS_SND], ctx->keylen);
1113 		krb5_make_usage(ctx->gss_ctx->initiate ?
1114 		    KRB5_USAGE_ACCEPTOR_SIGN : KRB5_USAGE_INITIATOR_SIGN,
1115 		    0x99, usage_string);
1116 		krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ckeys[GSS_RCV], ctx->keylen);
1117 		break;
1118 	case DES3_CBC_SHA1_KD:
1119 		ctx->enc_mode = ccdes3_cbc_encrypt_mode();
1120 		assert(ctx->enc_mode);
1121 		ctx->dec_mode = ccdes3_cbc_decrypt_mode();
1122 		assert(ctx->dec_mode);
1123 		gss_krb5_key_set(&ctx->ks.ikeys[GSS_SND], ctx->key, ctx->keylen);
1124 		gss_krb5_key_set(&ctx->ks.ikeys[GSS_RCV], ctx->key, ctx->keylen);
1125 		ctx->di = ccsha1_di();
1126 		assert(ctx->di);
1127 		ctx->flags = 0;
1128 		ctx->mpad = ctx->enc_mode->block_size;
1129 		ctx->digest_size = 20; /* 160 bits */
1130 		krb5_make_usage(KRB5_USAGE_ACCEPTOR_SIGN, 0x99, usage_string);
1131 		krb5_3des_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ckeys[GSS_SND]);
1132 		krb5_3des_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ctx->ckeys[GSS_RCV]);
1133 		break;
1134 	default:
1135 		return ENOTSUP;
1136 	}
1137 
1138 	lck_mtx_init(&ctx->lock, &gss_krb5_mech_grp, LCK_ATTR_NULL);
1139 
1140 	return 0;
1141 }
1142 
1143 /*
1144  * CFX gss support routines
1145  */
1146 /* From Heimdal cfx.h file RFC 4121 Cryptoo framework extensions */
1147 typedef struct gss_cfx_mic_token_desc_struct {
1148 	uint8_t TOK_ID[2];      /* 04 04 */
1149 	uint8_t Flags;
1150 	uint8_t Filler[5];
1151 	uint8_t SND_SEQ[8];
1152 } gss_cfx_mic_token_desc, *gss_cfx_mic_token;
1153 
1154 typedef struct gss_cfx_wrap_token_desc_struct {
1155 	uint8_t TOK_ID[2];      /* 05 04 */
1156 	uint8_t Flags;
1157 	uint8_t Filler;
1158 	uint8_t EC[2];
1159 	uint8_t RRC[2];
1160 	uint8_t SND_SEQ[8];
1161 } gss_cfx_wrap_token_desc, *gss_cfx_wrap_token;
1162 
1163 /* End of cfx.h file */
1164 
1165 #define CFXSentByAcceptor       (1 << 0)
1166 #define CFXSealed               (1 << 1)
1167 #define CFXAcceptorSubkey       (1 << 2)
1168 
1169 const gss_cfx_mic_token_desc mic_cfx_token = {
1170 	.TOK_ID = "\x04\x04",
1171 	.Flags = 0,
1172 	.Filler = "\xff\xff\xff\xff\xff",
1173 	.SND_SEQ = "\x00\x00\x00\x00\x00\x00\x00\x00"
1174 };
1175 
1176 const gss_cfx_wrap_token_desc wrap_cfx_token = {
1177 	.TOK_ID = "\x05\04",
1178 	.Flags = 0,
1179 	.Filler = '\xff',
1180 	.EC = "\x00\x00",
1181 	.RRC = "\x00\x00",
1182 	.SND_SEQ = "\x00\x00\x00\x00\x00\x00\x00\x00"
1183 };
1184 
1185 static int
gss_krb5_cfx_verify_mic_token(gss_ctx_id_t ctx,gss_cfx_mic_token token)1186 gss_krb5_cfx_verify_mic_token(gss_ctx_id_t ctx, gss_cfx_mic_token token)
1187 {
1188 	int i;
1189 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1190 	uint8_t flags = 0;
1191 
1192 	if (token->TOK_ID[0] != mic_cfx_token.TOK_ID[0] || token->TOK_ID[1] != mic_cfx_token.TOK_ID[1]) {
1193 		printf("Bad mic TOK_ID %x %x\n", token->TOK_ID[0], token->TOK_ID[1]);
1194 		return EBADRPC;
1195 	}
1196 	if (lctx->initiate) {
1197 		flags |= CFXSentByAcceptor;
1198 	}
1199 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1200 		flags |= CFXAcceptorSubkey;
1201 	}
1202 	if (token->Flags != flags) {
1203 		printf("Bad flags received %x exptect %x\n", token->Flags, flags);
1204 		return EBADRPC;
1205 	}
1206 	for (i = 0; i < 5; i++) {
1207 		if (token->Filler[i] != mic_cfx_token.Filler[i]) {
1208 			break;
1209 		}
1210 	}
1211 
1212 	if (i != 5) {
1213 		printf("Bad mic filler %x @ %d\n", token->Filler[i], i);
1214 		return EBADRPC;
1215 	}
1216 
1217 	return 0;
1218 }
1219 
1220 uint32_t
gss_krb5_cfx_get_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop __unused,gss_buffer_t mbp,gss_buffer_t mic)1221 gss_krb5_cfx_get_mic(uint32_t *minor,           /* minor_status */
1222     gss_ctx_id_t ctx,                           /* context_handle */
1223     gss_qop_t qop __unused,                     /* qop_req (ignored) */
1224     gss_buffer_t mbp,                           /* message mbuf */
1225     gss_buffer_t mic /* message_token */)
1226 {
1227 	gss_cfx_mic_token_desc token;
1228 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1229 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1230 	gss_buffer_desc header;
1231 	uint32_t rv;
1232 	uint64_t seq = htonll(lctx->send_seq);
1233 
1234 	if (minor == NULL) {
1235 		minor = &rv;
1236 	}
1237 	*minor = 0;
1238 	token = mic_cfx_token;
1239 	mic->length = sizeof(token) + cctx->digest_size;
1240 	mic->value = kalloc_data(mic->length, Z_WAITOK | Z_ZERO);
1241 	if (!lctx->initiate) {
1242 		token.Flags |= CFXSentByAcceptor;
1243 	}
1244 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1245 		token.Flags |= CFXAcceptorSubkey;
1246 	}
1247 	memcpy(&token.SND_SEQ, &seq, sizeof(lctx->send_seq));
1248 	lctx->send_seq++; //XXX should only update this below on success? Heimdal seems to do it this way
1249 	header.value = &token;
1250 	header.length = sizeof(gss_cfx_mic_token_desc);
1251 
1252 	*minor = krb5_mic(cctx, NULL, mbp, &header, (uint8_t *)mic->value + sizeof(token), NULL, 0, 0);
1253 
1254 	if (*minor) {
1255 		mic->length = 0;
1256 		kfree_data(mic->value, mic->length);
1257 	} else {
1258 		memcpy(mic->value, &token, sizeof(token));
1259 	}
1260 
1261 	return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
1262 }
1263 
1264 uint32_t
gss_krb5_cfx_verify_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_buffer_t mbp,gss_buffer_t mic,gss_qop_t * qop)1265 gss_krb5_cfx_verify_mic(uint32_t *minor,        /* minor_status */
1266     gss_ctx_id_t ctx,                           /* context_handle */
1267     gss_buffer_t mbp,                           /* message_buffer */
1268     gss_buffer_t mic,                           /* message_token */
1269     gss_qop_t *qop /* qop_state */)
1270 {
1271 	gss_cfx_mic_token token = mic->value;
1272 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1273 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1274 	uint8_t *digest = (uint8_t *)mic->value + sizeof(gss_cfx_mic_token_desc);
1275 	int verified = 0;
1276 	uint64_t seq;
1277 	uint32_t rv;
1278 	gss_buffer_desc header;
1279 
1280 	if (qop) {
1281 		*qop = GSS_C_QOP_DEFAULT;
1282 	}
1283 	if (minor == NULL) {
1284 		minor = &rv;
1285 	}
1286 
1287 	if (mic->length != sizeof(gss_cfx_mic_token_desc) + cctx->digest_size) {
1288 		printf("mic token wrong length\n");
1289 		*minor = EBADRPC;
1290 		goto out;
1291 	}
1292 	*minor = gss_krb5_cfx_verify_mic_token(ctx, token);
1293 	if (*minor) {
1294 		return GSS_S_FAILURE;
1295 	}
1296 	header.value = token;
1297 	header.length = sizeof(gss_cfx_mic_token_desc);
1298 	*minor = krb5_mic(cctx, NULL, mbp, &header, digest, &verified, 0, 0);
1299 
1300 	if (verified) {
1301 		//XXX  errors and such? Sequencing and replay? Not supported in RPCSEC_GSS
1302 		memcpy(&seq, token->SND_SEQ, sizeof(uint64_t));
1303 		seq = ntohll(seq);
1304 		lctx->recv_seq = seq;
1305 	}
1306 
1307 out:
1308 	return verified ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
1309 }
1310 
1311 uint32_t
gss_krb5_cfx_get_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop __unused,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic)1312 gss_krb5_cfx_get_mic_mbuf(uint32_t *minor,      /* minor_status */
1313     gss_ctx_id_t ctx,                           /* context_handle */
1314     gss_qop_t qop __unused,                       /* qop_req (ignored) */
1315     mbuf_t mbp,                         /* message mbuf */
1316     size_t offset,                              /* offest */
1317     size_t len,                         /* length */
1318     gss_buffer_t mic /* message_token */)
1319 {
1320 	gss_cfx_mic_token_desc token;
1321 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1322 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1323 	uint32_t rv;
1324 	uint64_t seq = htonll(lctx->send_seq);
1325 	gss_buffer_desc header;
1326 
1327 	if (minor == NULL) {
1328 		minor = &rv;
1329 	}
1330 	*minor = 0;
1331 
1332 	token = mic_cfx_token;
1333 	mic->length = sizeof(token) + cctx->digest_size;
1334 	mic->value = kalloc_data(mic->length, Z_WAITOK | Z_ZERO);
1335 	if (!lctx->initiate) {
1336 		token.Flags |= CFXSentByAcceptor;
1337 	}
1338 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1339 		token.Flags |= CFXAcceptorSubkey;
1340 	}
1341 
1342 	memcpy(&token.SND_SEQ, &seq, sizeof(lctx->send_seq));
1343 	lctx->send_seq++; //XXX should only update this below on success? Heimdal seems to do it this way
1344 
1345 	header.length = sizeof(token);
1346 	header.value = &token;
1347 
1348 	len = len ? len : gss_mbuf_len(mbp, offset);
1349 	*minor = krb5_mic_mbuf(cctx, NULL, mbp, offset, len, &header, (uint8_t *)mic->value + sizeof(token), NULL, 0, 0);
1350 
1351 	if (*minor) {
1352 		mic->length = 0;
1353 		kfree_data(mic->value, mic->length);
1354 	} else {
1355 		memcpy(mic->value, &token, sizeof(token));
1356 	}
1357 
1358 	return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
1359 }
1360 
1361 
1362 uint32_t
gss_krb5_cfx_verify_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic,gss_qop_t * qop)1363 gss_krb5_cfx_verify_mic_mbuf(uint32_t *minor,   /* minor_status */
1364     gss_ctx_id_t ctx,                           /* context_handle */
1365     mbuf_t mbp,                                         /* message_buffer */
1366     size_t offset,                                      /* offset */
1367     size_t len,                                         /* length */
1368     gss_buffer_t mic,                           /* message_token */
1369     gss_qop_t *qop /* qop_state */)
1370 {
1371 	gss_cfx_mic_token token = mic->value;
1372 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1373 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1374 	uint8_t *digest = (uint8_t *)mic->value + sizeof(gss_cfx_mic_token_desc);
1375 	int verified;
1376 	uint64_t seq;
1377 	uint32_t rv;
1378 	gss_buffer_desc header;
1379 
1380 	if (qop) {
1381 		*qop = GSS_C_QOP_DEFAULT;
1382 	}
1383 
1384 	if (minor == NULL) {
1385 		minor = &rv;
1386 	}
1387 
1388 	*minor = gss_krb5_cfx_verify_mic_token(ctx, token);
1389 	if (*minor) {
1390 		return GSS_S_FAILURE;
1391 	}
1392 
1393 	header.length = sizeof(gss_cfx_mic_token_desc);
1394 	header.value = mic->value;
1395 
1396 	*minor = krb5_mic_mbuf(cctx, NULL, mbp, offset, len, &header, digest, &verified, 0, 0);
1397 	if (*minor) {
1398 		return GSS_S_FAILURE;
1399 	}
1400 
1401 	//XXX  errors and such? Sequencing and replay? Not Supported RPCSEC_GSS
1402 	memcpy(&seq, token->SND_SEQ, sizeof(uint64_t));
1403 	seq = ntohll(seq);
1404 	lctx->recv_seq = seq;
1405 
1406 	return verified ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
1407 }
1408 
1409 errno_t
krb5_cfx_crypt_mbuf(crypto_ctx_t ctx,mbuf_t * mbp,size_t * len,int encrypt,int reverse)1410 krb5_cfx_crypt_mbuf(crypto_ctx_t ctx, mbuf_t *mbp, size_t *len, int encrypt, int reverse)
1411 {
1412 	const struct ccmode_cbc *ccmode = encrypt ? ctx->enc_mode : ctx->dec_mode;
1413 	uint8_t *confounder = NULL;
1414 	uint8_t *mpad = NULL;
1415 	uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1416 	size_t tlen, r = 0;
1417 	errno_t error;
1418 
1419 	confounder = kalloc_data(ccmode->block_size, Z_WAITOK | Z_ZERO);
1420 	if (confounder == NULL) {
1421 		error = ENOMEM;
1422 		goto out;
1423 	}
1424 	if (encrypt) {
1425 		assert(ccmode->block_size <= UINT_MAX);
1426 		read_random(confounder, (u_int)ccmode->block_size);
1427 		error = gss_prepend_mbuf(mbp, confounder, ccmode->block_size);
1428 		if (error) {
1429 			goto out;
1430 		}
1431 		tlen = *len + ccmode->block_size;
1432 		if (ctx->mpad > 1) {
1433 			r = ctx->mpad - (tlen % ctx->mpad);
1434 		}
1435 		/* We expect that r == 0 from krb5_cfx_wrap */
1436 		if (r != 0) {
1437 			mpad = kalloc_data(r, Z_WAITOK | Z_ZERO);
1438 			if (mpad == NULL) {
1439 				error = ENOMEM;
1440 				goto out;
1441 			}
1442 			error = gss_append_mbuf(*mbp, mpad, r);
1443 			if (error) {
1444 				goto out;
1445 			}
1446 		}
1447 		tlen += r;
1448 		error = krb5_mic_mbuf(ctx, NULL, *mbp, 0, tlen, NULL, digest, NULL, 1, 0);
1449 		if (error) {
1450 			goto out;
1451 		}
1452 		error = krb5_crypt_mbuf(ctx, mbp, tlen, 1, NULL);
1453 		if (error) {
1454 			goto out;
1455 		}
1456 		error = gss_append_mbuf(*mbp, digest, ctx->digest_size);
1457 		if (error) {
1458 			goto out;
1459 		}
1460 		*len = tlen + ctx->digest_size;
1461 		error = 0;
1462 		goto out;
1463 	} else {
1464 		int verf;
1465 		cccbc_ctx *ks = NULL;
1466 
1467 		if (*len < ctx->digest_size + sizeof(confounder)) {
1468 			error = EBADRPC;
1469 			goto out;
1470 		}
1471 		tlen = *len - ctx->digest_size;
1472 		/* get the digest */
1473 		error = mbuf_copydata(*mbp, tlen, ctx->digest_size, digest);
1474 		/* Remove the digest from the mbuffer */
1475 		error = gss_strip_mbuf(*mbp, -ctx->digest_size);
1476 		if (error) {
1477 			goto out;
1478 		}
1479 
1480 		if (reverse) {
1481 			/*
1482 			 * Derive a key schedule that the sender can unwrap with. This
1483 			 * is so that RPCSEC_GSS can restore encrypted arguments for
1484 			 * resending. We do that because the RPCSEC_GSS sequence number in
1485 			 * the rpc header is prepended to the body of the message before wrapping.
1486 			 */
1487 			krb5_key_t ekey;
1488 			uint8_t usage_string[KRB5_USAGE_LEN];
1489 			lucid_context_t lctx = ctx->gss_ctx;
1490 
1491 			krb5_make_usage(lctx->initiate ?
1492 			    KRB5_USAGE_INITIATOR_SEAL : KRB5_USAGE_ACCEPTOR_SEAL,
1493 			    0xAA, usage_string);
1494 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ekey, ctx->keylen);
1495 			ks = kalloc_data(ctx->dec_mode->size, Z_WAITOK | Z_ZERO);
1496 			cccbc_init(ctx->dec_mode, ks, ctx->keylen, ekey.key_val);
1497 			gss_krb5_key_free(&ekey, 1);
1498 		}
1499 		error = krb5_crypt_mbuf(ctx, mbp, tlen, 0, ks);
1500 		kfree_data(ks, ctx->dec_mode->size);
1501 		if (error) {
1502 			goto out;
1503 		}
1504 		error = krb5_mic_mbuf(ctx, NULL, *mbp, 0, tlen, NULL, digest, &verf, 1, reverse);
1505 		if (error) {
1506 			goto out;
1507 		}
1508 		if (!verf) {
1509 			error = EBADRPC;
1510 			goto out;
1511 		}
1512 		/* strip off the confounder */
1513 		assert(ccmode->block_size <= INT_MAX);
1514 		error = gss_strip_mbuf(*mbp, (int)ccmode->block_size);
1515 		if (error) {
1516 			goto out;
1517 		}
1518 		*len = tlen - ccmode->block_size;
1519 	}
1520 
1521 	error = 0;
1522 out:
1523 	kfree_data(mpad, r);
1524 	kfree_data(confounder, ccmode->block_size);
1525 	return error;
1526 }
1527 
1528 uint32_t
gss_krb5_cfx_wrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,int conf_flag,gss_qop_t qop __unused,mbuf_t * mbp,size_t len,int * conf)1529 gss_krb5_cfx_wrap_mbuf(uint32_t *minor,         /* minor_status */
1530     gss_ctx_id_t ctx,                           /* context_handle */
1531     int conf_flag,                              /* conf_req_flag */
1532     gss_qop_t qop __unused,                     /* qop_req */
1533     mbuf_t *mbp,                                /* input/output message_buffer */
1534     size_t len,                                 /* mbuf chain length */
1535     int *conf /* conf_state */)
1536 {
1537 	gss_cfx_wrap_token_desc token;
1538 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1539 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1540 	int error = 0;
1541 	uint32_t mv;
1542 	uint64_t seq = htonll(lctx->send_seq);
1543 
1544 	if (minor == NULL) {
1545 		minor = &mv;
1546 	}
1547 	if (conf) {
1548 		*conf = conf_flag;
1549 	}
1550 
1551 	*minor = 0;
1552 	token = wrap_cfx_token;
1553 	if (!lctx->initiate) {
1554 		token.Flags |= CFXSentByAcceptor;
1555 	}
1556 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1557 		token.Flags |= CFXAcceptorSubkey;
1558 	}
1559 	memcpy(&token.SND_SEQ, &seq, sizeof(uint64_t));
1560 	lctx->send_seq++;
1561 	if (conf_flag) {
1562 		uint8_t *pad = NULL;
1563 		size_t plen = 0;
1564 
1565 		pad = kalloc_data(cctx->mpad, Z_WAITOK | Z_ZERO);
1566 		if (pad == NULL) {
1567 			*minor = ENOMEM;
1568 			return GSS_S_FAILURE;
1569 		}
1570 		token.Flags |= CFXSealed;
1571 		if (cctx->mpad > 1) {
1572 			size_t val = cctx->mpad - ((len + sizeof(gss_cfx_wrap_token_desc)) % cctx->mpad);
1573 			plen = sizeof(val) > sizeof(uint32_t) ? htonll(val) : htonl(val);
1574 			token.EC[0] = ((plen >> 8) & 0xff);
1575 			token.EC[1] = (plen & 0xff);
1576 		}
1577 		if (plen) {
1578 			error = gss_append_mbuf(*mbp, pad, plen);
1579 			len += plen;
1580 		}
1581 		if (error == 0) {
1582 			error = gss_append_mbuf(*mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1583 			len += sizeof(gss_cfx_wrap_token_desc);
1584 		}
1585 		if (error == 0) {
1586 			error = krb5_cfx_crypt_mbuf(cctx, mbp, &len, 1, 0);
1587 		}
1588 		if (error == 0) {
1589 			error = gss_prepend_mbuf(mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1590 		}
1591 		kfree_data(pad, cctx->mpad);
1592 	} else {
1593 		uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1594 		gss_buffer_desc header;
1595 
1596 		header.length = sizeof(token);
1597 		header.value = &token;
1598 
1599 		error = krb5_mic_mbuf(cctx, NULL, *mbp, 0, len, &header, digest, NULL, 1, 0);
1600 		if (error == 0) {
1601 			error = gss_append_mbuf(*mbp, digest, cctx->digest_size);
1602 			if (error == 0) {
1603 				uint32_t plen = htonl(cctx->digest_size);
1604 				memcpy(token.EC, &plen, 2);
1605 				error = gss_prepend_mbuf(mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1606 			}
1607 		}
1608 	}
1609 	if (error) {
1610 		*minor = error;
1611 		return GSS_S_FAILURE;
1612 	}
1613 
1614 	return GSS_S_COMPLETE;
1615 }
1616 
1617 /*
1618  * Given a wrap token the has a rrc, move the trailer back to the end.
1619  */
1620 static void
gss_krb5_cfx_unwrap_rrc_mbuf(mbuf_t header,size_t rrc)1621 gss_krb5_cfx_unwrap_rrc_mbuf(mbuf_t header, size_t rrc)
1622 {
1623 	mbuf_t body, trailer;
1624 
1625 	gss_normalize_mbuf(header, sizeof(gss_cfx_wrap_token_desc), &rrc, &trailer, &body, 0);
1626 	gss_join_mbuf(header, body, trailer);
1627 }
1628 
1629 uint32_t
gss_krb5_cfx_unwrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t * mbp,size_t len,int * conf_flag,gss_qop_t * qop)1630 gss_krb5_cfx_unwrap_mbuf(uint32_t * minor,      /* minor_status */
1631     gss_ctx_id_t ctx,                           /* context_handle */
1632     mbuf_t *mbp,                                /* input/output message_buffer */
1633     size_t len,                                 /* mbuf chain length */
1634     int *conf_flag,                             /* conf_state */
1635     gss_qop_t *qop /* qop state */)
1636 {
1637 	gss_cfx_wrap_token_desc token;
1638 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1639 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1640 	int error, conf;
1641 	uint32_t ec = 0, rrc = 0;
1642 	uint64_t seq;
1643 	int reverse = (*qop == GSS_C_QOP_REVERSE);
1644 	int initiate = lctx->initiate ? (reverse ? 0 : 1) : (reverse ? 1 : 0);
1645 
1646 	error = mbuf_copydata(*mbp, 0, sizeof(gss_cfx_wrap_token_desc), &token);
1647 	gss_strip_mbuf(*mbp, sizeof(gss_cfx_wrap_token_desc));
1648 	len -= sizeof(gss_cfx_wrap_token_desc);
1649 
1650 	/* Check for valid token */
1651 	if (token.TOK_ID[0] != wrap_cfx_token.TOK_ID[0] ||
1652 	    token.TOK_ID[1] != wrap_cfx_token.TOK_ID[1] ||
1653 	    token.Filler != wrap_cfx_token.Filler) {
1654 		printf("Token id does not match\n");
1655 		goto badrpc;
1656 	}
1657 	if ((initiate && !(token.Flags & CFXSentByAcceptor)) ||
1658 	    (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey && !(token.Flags & CFXAcceptorSubkey))) {
1659 		printf("Bad flags %x\n", token.Flags);
1660 		goto badrpc;
1661 	}
1662 
1663 	/* XXX Sequence replay detection */
1664 	memcpy(&seq, token.SND_SEQ, sizeof(seq));
1665 	seq = ntohll(seq);
1666 	lctx->recv_seq = seq;
1667 
1668 	ec = (token.EC[0] << 8) | token.EC[1];
1669 	rrc = (token.RRC[0] << 8) | token.RRC[1];
1670 	*qop = GSS_C_QOP_DEFAULT;
1671 	conf = ((token.Flags & CFXSealed) == CFXSealed);
1672 	if (conf_flag) {
1673 		*conf_flag = conf;
1674 	}
1675 	if (conf) {
1676 		gss_cfx_wrap_token_desc etoken;
1677 
1678 		if (rrc) { /* Handle Right rotation count */
1679 			gss_krb5_cfx_unwrap_rrc_mbuf(*mbp, rrc);
1680 		}
1681 		error = krb5_cfx_crypt_mbuf(cctx, mbp, &len, 0, reverse);
1682 		if (error) {
1683 			printf("krb5_cfx_crypt_mbuf %d\n", error);
1684 			*minor = error;
1685 			return GSS_S_FAILURE;
1686 		}
1687 		if (len >= sizeof(gss_cfx_wrap_token_desc)) {
1688 			len -= sizeof(gss_cfx_wrap_token_desc);
1689 		} else {
1690 			goto badrpc;
1691 		}
1692 		mbuf_copydata(*mbp, len, sizeof(gss_cfx_wrap_token_desc), &etoken);
1693 		/* Verify etoken with the token wich should be the same, except the rc field is always zero */
1694 		token.RRC[0] = token.RRC[1] = 0;
1695 		if (memcmp(&token, &etoken, sizeof(gss_cfx_wrap_token_desc)) != 0) {
1696 			printf("Encrypted token mismach\n");
1697 			goto badrpc;
1698 		}
1699 		/* strip the encrypted token and any pad bytes */
1700 		gss_strip_mbuf(*mbp, -(sizeof(gss_cfx_wrap_token_desc) + ec));
1701 		len -= (sizeof(gss_cfx_wrap_token_desc) + ec);
1702 	} else {
1703 		uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1704 		int verf;
1705 		gss_buffer_desc header;
1706 
1707 		if (ec != cctx->digest_size || len >= cctx->digest_size) {
1708 			goto badrpc;
1709 		}
1710 		len -= cctx->digest_size;
1711 		mbuf_copydata(*mbp, len, cctx->digest_size, digest);
1712 		gss_strip_mbuf(*mbp, -cctx->digest_size);
1713 		/* When calculating the mic header fields ec and rcc must be zero */
1714 		token.EC[0] = token.EC[1] = token.RRC[0] = token.RRC[1] = 0;
1715 		header.value = &token;
1716 		header.length = sizeof(gss_cfx_wrap_token_desc);
1717 		error = krb5_mic_mbuf(cctx, NULL, *mbp, 0, len, &header, digest, &verf, 1, reverse);
1718 		if (error) {
1719 			goto badrpc;
1720 		}
1721 	}
1722 	return GSS_S_COMPLETE;
1723 
1724 badrpc:
1725 	*minor = EBADRPC;
1726 	return GSS_S_FAILURE;
1727 }
1728 
1729 /*
1730  * RFC 1964 3DES support
1731  */
1732 
1733 typedef struct gss_1964_mic_token_desc_struct {
1734 	uint8_t TOK_ID[2];      /* 01 01 */
1735 	uint8_t Sign_Alg[2];
1736 	uint8_t Filler[4];      /* ff ff ff ff */
1737 } gss_1964_mic_token_desc, *gss_1964_mic_token;
1738 
1739 typedef struct gss_1964_wrap_token_desc_struct {
1740 	uint8_t TOK_ID[2];      /* 02 01 */
1741 	uint8_t Sign_Alg[2];
1742 	uint8_t Seal_Alg[2];
1743 	uint8_t Filler[2];      /* ff ff */
1744 } gss_1964_wrap_token_desc, *gss_1964_wrap_token;
1745 
1746 typedef struct gss_1964_delete_token_desc_struct {
1747 	uint8_t TOK_ID[2];      /* 01 02 */
1748 	uint8_t Sign_Alg[2];
1749 	uint8_t Filler[4];      /* ff ff ff ff */
1750 } gss_1964_delete_token_desc, *gss_1964_delete_token;
1751 
1752 typedef struct gss_1964_header_desc_struct {
1753 	uint8_t App0;           /* 0x60 Application 0 constructed */
1754 	uint8_t AppLen[];       /* Variable Der length */
1755 } gss_1964_header_desc, *gss_1964_header;
1756 
1757 typedef union {
1758 	gss_1964_mic_token_desc         mic_tok;
1759 	gss_1964_wrap_token_desc        wrap_tok;
1760 	gss_1964_delete_token_desc      del_tok;
1761 } gss_1964_tok_type __attribute__((transparent_union));
1762 
1763 typedef struct gss_1964_token_body_struct {
1764 	uint8_t OIDType;        /* 0x06 */
1765 	uint8_t OIDLen;         /* 0x09 */
1766 	uint8_t kerb_mech[9];   /* Der Encode kerberos mech 1.2.840.113554.1.2.2
1767 	                         *  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 */
1768 	gss_1964_tok_type body;
1769 	uint8_t SND_SEQ[8];
1770 	uint8_t Hash[];         /* Mic */
1771 } gss_1964_token_body_desc, *gss_1964_token_body;
1772 
1773 
1774 gss_1964_header_desc tok_1964_header = {
1775 	.App0 = 0x60
1776 };
1777 
1778 gss_1964_mic_token_desc mic_1964_token = {
1779 	.TOK_ID = "\x01\x01",
1780 	.Filler = "\xff\xff\xff\xff"
1781 };
1782 
1783 gss_1964_wrap_token_desc wrap_1964_token = {
1784 	.TOK_ID = "\x02\x01",
1785 	.Filler = "\xff\xff"
1786 };
1787 
1788 gss_1964_delete_token_desc del_1964_token = {
1789 	.TOK_ID = "\x01\x01",
1790 	.Filler = "\xff\xff\xff\xff"
1791 };
1792 
1793 gss_1964_token_body_desc body_1964_token = {
1794 	.OIDType = 0x06,
1795 	.OIDLen = 0x09,
1796 	.kerb_mech = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02",
1797 };
1798 
1799 #define GSS_KRB5_3DES_MAXTOKSZ (sizeof(gss_1964_header_desc) + 5 /* max der length supported */ + sizeof(gss_1964_token_body_desc))
1800 
1801 uint32_t gss_krb5_3des_get_mic(uint32_t *, gss_ctx_id_t, gss_qop_t, gss_buffer_t, gss_buffer_t);
1802 uint32_t gss_krb5_3des_verify_mic(uint32_t *, gss_ctx_id_t, gss_buffer_t, gss_buffer_t, gss_qop_t *);
1803 uint32_t gss_krb5_3des_get_mic_mbuf(uint32_t *, gss_ctx_id_t, gss_qop_t, mbuf_t, size_t, size_t, gss_buffer_t);
1804 uint32_t gss_krb5_3des_verify_mic_mbuf(uint32_t *, gss_ctx_id_t, mbuf_t, size_t, size_t, gss_buffer_t, gss_qop_t *);
1805 uint32_t gss_krb5_3des_wrap_mbuf(uint32_t *, gss_ctx_id_t, int, gss_qop_t, mbuf_t *, size_t, int *);
1806 uint32_t gss_krb5_3des_unwrap_mbuf(uint32_t *, gss_ctx_id_t, mbuf_t *, size_t, int *, gss_qop_t *);
1807 
1808 /*
1809  * Decode an ASN.1 DER length field
1810  */
1811 static ssize_t
gss_krb5_der_length_get(uint8_t ** pp)1812 gss_krb5_der_length_get(uint8_t **pp)
1813 {
1814 	uint8_t *p = *pp;
1815 	uint32_t flen, len = 0;
1816 
1817 	flen = *p & 0x7f;
1818 
1819 	if (*p++ & 0x80) {
1820 		if (flen > sizeof(uint32_t)) {
1821 			return -1;
1822 		}
1823 		while (flen--) {
1824 			len = (len << 8) + *p++;
1825 		}
1826 	} else {
1827 		len = flen;
1828 	}
1829 	*pp = p;
1830 	return len;
1831 }
1832 
1833 /*
1834  * Determine size of ASN.1 DER length
1835  */
1836 static int
gss_krb5_der_length_size(size_t len)1837 gss_krb5_der_length_size(size_t len)
1838 {
1839 	return
1840 	        len < (1 <<  7) ? 1 :
1841 	        len < (1 <<  8) ? 2 :
1842 	        len < (1 << 16) ? 3 :
1843 	        len < (1 << 24) ? 4 : 5;
1844 }
1845 
1846 /*
1847  * Encode an ASN.1 DER length field
1848  */
1849 static void
gss_krb5_der_length_put(uint8_t ** pp,size_t len)1850 gss_krb5_der_length_put(uint8_t **pp, size_t len)
1851 {
1852 	int sz = gss_krb5_der_length_size(len);
1853 	uint8_t *p = *pp;
1854 
1855 	if (sz == 1) {
1856 		*p++ = (uint8_t) len;
1857 	} else {
1858 		*p++ = (uint8_t) ((sz - 1) | 0x80);
1859 		sz -= 1;
1860 		while (sz--) {
1861 			*p++ = (uint8_t) ((len >> (sz * 8)) & 0xff);
1862 		}
1863 	}
1864 
1865 	*pp = p;
1866 }
1867 
1868 static void
gss_krb5_3des_token_put(gss_ctx_id_t ctx,gss_1964_tok_type body,gss_buffer_t hash,size_t datalen,gss_buffer_t des3_token)1869 gss_krb5_3des_token_put(gss_ctx_id_t ctx, gss_1964_tok_type body, gss_buffer_t hash, size_t datalen, gss_buffer_t des3_token)
1870 {
1871 	gss_1964_header token;
1872 	gss_1964_token_body tokbody;
1873 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1874 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1875 	uint32_t seq = (uint32_t) (lctx->send_seq++ & 0xffff);
1876 	size_t toklen = sizeof(gss_1964_token_body_desc)  + cctx->digest_size;
1877 	size_t alloclen = toklen + sizeof(gss_1964_header_desc) + gss_krb5_der_length_size(toklen + datalen);
1878 	uint8_t *tokptr;
1879 
1880 	token = kalloc_data(alloclen, Z_WAITOK | Z_ZERO);
1881 	*token = tok_1964_header;
1882 	tokptr = token->AppLen;
1883 	gss_krb5_der_length_put(&tokptr, toklen + datalen);
1884 	tokbody = (gss_1964_token_body)tokptr;
1885 	*tokbody = body_1964_token;  /* Initalize the token body */
1886 	tokbody->body = body;  /* and now set the body to the token type passed in */
1887 	seq = htonl(seq);
1888 	for (int i = 0; i < 4; i++) {
1889 		tokbody->SND_SEQ[i] = (uint8_t)((seq >> (i * 8)) & 0xff);
1890 	}
1891 	for (int i = 4; i < 8; i++) {
1892 		tokbody->SND_SEQ[i] = lctx->initiate ? 0x00 : 0xff;
1893 	}
1894 
1895 	size_t blocksize = cctx->enc_mode->block_size;
1896 	cccbc_iv_decl(blocksize, iv);
1897 	cccbc_ctx_decl(cctx->enc_mode->size, enc_ctx);
1898 	cccbc_set_iv(cctx->enc_mode, iv, hash->value);
1899 	cccbc_init(cctx->enc_mode, enc_ctx, cctx->keylen, cctx->key);
1900 	cccbc_update(cctx->enc_mode, enc_ctx, iv, 1, tokbody->SND_SEQ, tokbody->SND_SEQ);
1901 
1902 	assert(hash->length == cctx->digest_size);
1903 	memcpy(tokbody->Hash, hash->value, hash->length);
1904 	des3_token->length = alloclen;
1905 	des3_token->value = token;
1906 }
1907 
1908 static int
gss_krb5_3des_token_get(gss_ctx_id_t ctx,gss_buffer_t intok,gss_1964_tok_type body,gss_buffer_t hash,size_t * offset,size_t * len,int reverse)1909 gss_krb5_3des_token_get(gss_ctx_id_t ctx, gss_buffer_t intok,
1910     gss_1964_tok_type body, gss_buffer_t hash, size_t *offset, size_t *len, int reverse)
1911 {
1912 	gss_1964_header token = intok->value;
1913 	gss_1964_token_body tokbody;
1914 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1915 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1916 	ssize_t length;
1917 	size_t toklen;
1918 	uint8_t *tokptr;
1919 	uint32_t seq;
1920 	int initiate;
1921 
1922 	if (token->App0 != tok_1964_header.App0) {
1923 		printf("%s: bad framing\n", __func__);
1924 		printgbuf(__func__, intok);
1925 		return EBADRPC;
1926 	}
1927 	tokptr = token->AppLen;
1928 	length = gss_krb5_der_length_get(&tokptr);
1929 	if (length < 0) {
1930 		printf("%s: invalid length\n", __func__);
1931 		printgbuf(__func__, intok);
1932 		return EBADRPC;
1933 	}
1934 	toklen = sizeof(gss_1964_header_desc) + gss_krb5_der_length_size(length)
1935 	    + sizeof(gss_1964_token_body_desc);
1936 
1937 	if (intok->length < toklen + cctx->digest_size) {
1938 		printf("%s: token to short", __func__);
1939 		printf("toklen = %d, length = %d\n", (int)toklen, (int)length);
1940 		printgbuf(__func__, intok);
1941 		return EBADRPC;
1942 	}
1943 
1944 	if (offset) {
1945 		*offset = toklen + cctx->digest_size;
1946 	}
1947 
1948 	if (len) {
1949 		*len = length - sizeof(gss_1964_token_body_desc) - cctx->digest_size;
1950 	}
1951 
1952 	tokbody = (gss_1964_token_body)tokptr;
1953 	if (tokbody->OIDType != body_1964_token.OIDType ||
1954 	    tokbody->OIDLen != body_1964_token.OIDLen ||
1955 	    memcmp(tokbody->kerb_mech, body_1964_token.kerb_mech, tokbody->OIDLen) != 0) {
1956 		printf("%s: Invalid mechanism\n", __func__);
1957 		printgbuf(__func__, intok);
1958 		return EBADRPC;
1959 	}
1960 	if (memcmp(&tokbody->body, &body, sizeof(gss_1964_tok_type)) != 0) {
1961 		printf("%s: Invalid body\n", __func__);
1962 		printgbuf(__func__, intok);
1963 		return EBADRPC;
1964 	}
1965 	size_t blocksize = cctx->enc_mode->block_size;
1966 	uint8_t *block = tokbody->SND_SEQ;
1967 
1968 	assert(blocksize == sizeof(tokbody->SND_SEQ));
1969 	cccbc_iv_decl(blocksize, iv);
1970 	cccbc_ctx_decl(cctx->dec_mode->size, dec_ctx);
1971 	cccbc_set_iv(cctx->dec_mode, iv, tokbody->Hash);
1972 	cccbc_init(cctx->dec_mode, dec_ctx, cctx->keylen, cctx->key);
1973 	cccbc_update(cctx->dec_mode, dec_ctx, iv, 1, block, block);
1974 
1975 	initiate = lctx->initiate ? (reverse ? 0 : 1) : (reverse ? 1 : 0);
1976 	for (int i = 4; i < 8; i++) {
1977 		if (tokbody->SND_SEQ[i] != (initiate ? 0xff : 0x00)) {
1978 			printf("%s: Invalid des mac\n", __func__);
1979 			printgbuf(__func__, intok);
1980 			return EAUTH;
1981 		}
1982 	}
1983 
1984 	memcpy(&seq, tokbody->SND_SEQ, sizeof(uint32_t));
1985 
1986 	lctx->recv_seq = ntohl(seq);
1987 
1988 	assert(hash->length >= cctx->digest_size);
1989 	memcpy(hash->value, tokbody->Hash, cctx->digest_size);
1990 
1991 	return 0;
1992 }
1993 
1994 uint32_t
gss_krb5_3des_get_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop __unused,gss_buffer_t mbp,gss_buffer_t mic)1995 gss_krb5_3des_get_mic(uint32_t *minor,          /* minor status */
1996     gss_ctx_id_t ctx,                           /* krb5 context id */
1997     gss_qop_t qop __unused,                     /* qop_req (ignored) */
1998     gss_buffer_t mbp,                           /* message buffer in */
1999     gss_buffer_t mic)                           /* mic token out */
2000 {
2001 	gss_1964_mic_token_desc tokbody = mic_1964_token;
2002 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2003 	gss_buffer_desc hash;
2004 	gss_buffer_desc header;
2005 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2006 
2007 	hash.length = cctx->digest_size;
2008 	hash.value = hashval;
2009 	tokbody.Sign_Alg[0] = 0x04; /* lctx->keydata.lucid_protocol_u.data_1964.sign_alg */
2010 	tokbody.Sign_Alg[1] = 0x00;
2011 	header.length = sizeof(gss_1964_mic_token_desc);
2012 	header.value = &tokbody;
2013 
2014 	/* Hash the data */
2015 	*minor = krb5_mic(cctx, &header, mbp, NULL, hashval, NULL, 0, 0);
2016 	if (*minor) {
2017 		return GSS_S_FAILURE;
2018 	}
2019 
2020 	/* Make the token */
2021 	gss_krb5_3des_token_put(ctx, tokbody, &hash, 0, mic);
2022 
2023 	return GSS_S_COMPLETE;
2024 }
2025 
2026 uint32_t
gss_krb5_3des_verify_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_buffer_t mbp,gss_buffer_t mic,gss_qop_t * qop)2027 gss_krb5_3des_verify_mic(uint32_t *minor,
2028     gss_ctx_id_t ctx,
2029     gss_buffer_t mbp,
2030     gss_buffer_t mic,
2031     gss_qop_t *qop)
2032 {
2033 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2034 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2035 	gss_buffer_desc hash;
2036 	gss_1964_mic_token_desc mtok = mic_1964_token;
2037 	gss_buffer_desc header;
2038 	int verf;
2039 
2040 	mtok.Sign_Alg[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_1964.sign_alg */
2041 	mtok.Sign_Alg[1] = 0x00;
2042 	hash.length = cctx->digest_size;
2043 	hash.value = hashval;
2044 	header.length = sizeof(gss_1964_mic_token_desc);
2045 	header.value = &mtok;
2046 
2047 	if (qop) {
2048 		*qop = GSS_C_QOP_DEFAULT;
2049 	}
2050 
2051 	*minor = gss_krb5_3des_token_get(ctx, mic, mtok, &hash, NULL, NULL, 0);
2052 	if (*minor) {
2053 		return GSS_S_FAILURE;
2054 	}
2055 
2056 	*minor = krb5_mic(cctx, &header, mbp, NULL, hashval, &verf, 0, 0);
2057 	if (*minor) {
2058 		return GSS_S_FAILURE;
2059 	}
2060 
2061 	return verf ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
2062 }
2063 
2064 uint32_t
gss_krb5_3des_get_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop __unused,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic)2065 gss_krb5_3des_get_mic_mbuf(uint32_t *minor,
2066     gss_ctx_id_t ctx,
2067     gss_qop_t qop __unused,
2068     mbuf_t mbp,
2069     size_t offset,
2070     size_t len,
2071     gss_buffer_t mic)
2072 {
2073 	gss_1964_mic_token_desc tokbody = mic_1964_token;
2074 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2075 	gss_buffer_desc header;
2076 	gss_buffer_desc hash;
2077 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2078 
2079 	hash.length = cctx->digest_size;
2080 	hash.value = hashval;
2081 	tokbody.Sign_Alg[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_4121.sign_alg */
2082 	tokbody.Sign_Alg[1] = 0x00;
2083 	header.length = sizeof(gss_1964_mic_token_desc);
2084 	header.value = &tokbody;
2085 
2086 	/* Hash the data */
2087 	*minor = krb5_mic_mbuf(cctx, &header, mbp, offset, len, NULL, hashval, NULL, 0, 0);
2088 	if (*minor) {
2089 		return GSS_S_FAILURE;
2090 	}
2091 
2092 	/* Make the token */
2093 	gss_krb5_3des_token_put(ctx, tokbody, &hash, 0, mic);
2094 
2095 	return GSS_S_COMPLETE;
2096 }
2097 
2098 uint32_t
gss_krb5_3des_verify_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic,gss_qop_t * qop)2099 gss_krb5_3des_verify_mic_mbuf(uint32_t *minor,
2100     gss_ctx_id_t ctx,
2101     mbuf_t mbp,
2102     size_t offset,
2103     size_t len,
2104     gss_buffer_t mic,
2105     gss_qop_t *qop)
2106 {
2107 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2108 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2109 	gss_buffer_desc header;
2110 	gss_buffer_desc hash;
2111 	gss_1964_mic_token_desc mtok = mic_1964_token;
2112 	int verf;
2113 
2114 	mtok.Sign_Alg[0] = 0x04; /* lctx->key_data.lucic_protocol_u.data1964.sign_alg */
2115 	mtok.Sign_Alg[1] = 0x00;
2116 	hash.length = cctx->digest_size;
2117 	hash.value = hashval;
2118 	header.length = sizeof(gss_1964_mic_token_desc);
2119 	header.value = &mtok;
2120 
2121 	if (qop) {
2122 		*qop = GSS_C_QOP_DEFAULT;
2123 	}
2124 
2125 	*minor = gss_krb5_3des_token_get(ctx, mic, mtok, &hash, NULL, NULL, 0);
2126 	if (*minor) {
2127 		return GSS_S_FAILURE;
2128 	}
2129 
2130 	*minor = krb5_mic_mbuf(cctx, &header, mbp, offset, len, NULL, hashval, &verf, 0, 0);
2131 	if (*minor) {
2132 		return GSS_S_FAILURE;
2133 	}
2134 
2135 	return verf ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
2136 }
2137 
2138 uint32_t
gss_krb5_3des_wrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,int conf_flag,gss_qop_t qop __unused,mbuf_t * mbp,size_t len,int * conf_state)2139 gss_krb5_3des_wrap_mbuf(uint32_t *minor,
2140     gss_ctx_id_t ctx,
2141     int conf_flag,
2142     gss_qop_t qop __unused,
2143     mbuf_t *mbp,
2144     size_t len,
2145     int *conf_state)
2146 {
2147 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2148 	const struct ccmode_cbc *ccmode = cctx->enc_mode;
2149 	uint8_t padlen;
2150 	uint8_t pad[8];
2151 	uint8_t *confounder = NULL;
2152 	gss_1964_wrap_token_desc tokbody = wrap_1964_token;
2153 	gss_buffer_desc header;
2154 	gss_buffer_desc mic;
2155 	gss_buffer_desc hash;
2156 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2157 
2158 	confounder = kalloc_data(ccmode->block_size, Z_WAITOK | Z_ZERO);
2159 	if (confounder == NULL) {
2160 		*minor = ENOMEM;
2161 		goto out;
2162 	}
2163 	if (conf_state) {
2164 		*conf_state = conf_flag;
2165 	}
2166 
2167 	hash.length = cctx->digest_size;
2168 	hash.value = hashval;
2169 	tokbody.Sign_Alg[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_1964.sign_alg */
2170 	tokbody.Sign_Alg[1] = 0x00;
2171 	/* conf_flag ? lctx->key_data.lucid_protocol_u.data_1964.seal_alg : 0xffff */
2172 	tokbody.Seal_Alg[0] = conf_flag ? 0x02 : 0xff;
2173 	tokbody.Seal_Alg[1] = conf_flag ? 0x00 : 0xff;
2174 	header.length = sizeof(gss_1964_wrap_token_desc);
2175 	header.value = &tokbody;
2176 
2177 	/* Prepend confounder */
2178 	assert(ccmode->block_size <= UINT_MAX);
2179 	read_random(confounder, (u_int)ccmode->block_size);
2180 	*minor = gss_prepend_mbuf(mbp, confounder, ccmode->block_size);
2181 	if (*minor) {
2182 		goto out;
2183 	}
2184 
2185 	/* Append trailer of up to 8 bytes and set pad length in each trailer byte */
2186 	padlen = 8 - len % 8;
2187 	for (int i = 0; i < padlen; i++) {
2188 		pad[i] = padlen;
2189 	}
2190 	*minor = gss_append_mbuf(*mbp, pad, padlen);
2191 	if (*minor) {
2192 		goto out;
2193 	}
2194 
2195 	len += ccmode->block_size + padlen;
2196 
2197 	/* Hash the data */
2198 	*minor = krb5_mic_mbuf(cctx, &header, *mbp, 0, len, NULL, hashval, NULL, 0, 0);
2199 	if (*minor) {
2200 		goto out;
2201 	}
2202 
2203 	/* Make the token */
2204 	gss_krb5_3des_token_put(ctx, tokbody, &hash, len, &mic);
2205 
2206 	if (conf_flag) {
2207 		*minor = krb5_crypt_mbuf(cctx, mbp, len, 1, 0);
2208 		if (*minor) {
2209 			goto out;
2210 		}
2211 	}
2212 
2213 	*minor = gss_prepend_mbuf(mbp, mic.value, mic.length);
2214 
2215 out:
2216 	kfree_data(confounder, ccmode->block_size);
2217 	return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
2218 }
2219 
2220 uint32_t
gss_krb5_3des_unwrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t * mbp,size_t len,int * conf_state,gss_qop_t * qop)2221 gss_krb5_3des_unwrap_mbuf(uint32_t *minor,
2222     gss_ctx_id_t ctx,
2223     mbuf_t *mbp,
2224     size_t len,
2225     int *conf_state,
2226     gss_qop_t *qop)
2227 {
2228 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2229 	const struct ccmode_cbc *ccmode = cctx->dec_mode;
2230 	size_t length = 0, offset = 0;
2231 	gss_buffer_desc hash;
2232 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2233 	gss_buffer_desc itoken;
2234 	uint8_t tbuffer[GSS_KRB5_3DES_MAXTOKSZ + CRYPTO_MAX_DIGSET_SIZE];
2235 	itoken.length = GSS_KRB5_3DES_MAXTOKSZ + cctx->digest_size;
2236 	itoken.value = tbuffer;
2237 	gss_1964_wrap_token_desc wrap = wrap_1964_token;
2238 	gss_buffer_desc header;
2239 	uint8_t padlen;
2240 	mbuf_t smb, tmb;
2241 	int cflag, verified, reverse = 0;
2242 
2243 	if (len < GSS_KRB5_3DES_MAXTOKSZ) {
2244 		*minor = EBADRPC;
2245 		return GSS_S_FAILURE;
2246 	}
2247 
2248 	if (*qop == GSS_C_QOP_REVERSE) {
2249 		reverse = 1;
2250 	}
2251 	*qop = GSS_C_QOP_DEFAULT;
2252 
2253 	*minor = mbuf_copydata(*mbp, 0, itoken.length, itoken.value);
2254 	if (*minor) {
2255 		return GSS_S_FAILURE;
2256 	}
2257 
2258 	hash.length = cctx->digest_size;
2259 	hash.value = hashval;
2260 	wrap.Sign_Alg[0] = 0x04;
2261 	wrap.Sign_Alg[1] = 0x00;
2262 	wrap.Seal_Alg[0] = 0x02;
2263 	wrap.Seal_Alg[1] = 0x00;
2264 
2265 	for (cflag = 1; cflag >= 0; cflag--) {
2266 		*minor = gss_krb5_3des_token_get(ctx, &itoken, wrap, &hash, &offset, &length, reverse);
2267 		if (*minor == 0) {
2268 			break;
2269 		}
2270 		wrap.Seal_Alg[0] = 0xff;
2271 		wrap.Seal_Alg[1] = 0xff;
2272 	}
2273 	if (*minor) {
2274 		return GSS_S_FAILURE;
2275 	}
2276 
2277 	if (conf_state) {
2278 		*conf_state = cflag;
2279 	}
2280 
2281 	/*
2282 	 * Seperate off the header
2283 	 */
2284 	*minor = gss_normalize_mbuf(*mbp, offset, &length, &smb, &tmb, 0);
2285 	if (*minor) {
2286 		return GSS_S_FAILURE;
2287 	}
2288 
2289 	assert(tmb == NULL);
2290 
2291 	/* Decrypt the chain if needed */
2292 	if (cflag) {
2293 		*minor = krb5_crypt_mbuf(cctx, &smb, length, 0, NULL);
2294 		if (*minor) {
2295 			return GSS_S_FAILURE;
2296 		}
2297 	}
2298 
2299 	/* Verify the mic */
2300 	header.length = sizeof(gss_1964_wrap_token_desc);
2301 	header.value = &wrap;
2302 
2303 	*minor = krb5_mic_mbuf(cctx, &header, smb, 0, length, NULL, hashval, &verified, 0, 0);
2304 	if (*minor) {
2305 		return GSS_S_FAILURE;
2306 	}
2307 	if (!verified) {
2308 		return GSS_S_BAD_SIG;
2309 	}
2310 
2311 	/* Get the pad bytes */
2312 	*minor = mbuf_copydata(smb, length - 1, 1, &padlen);
2313 	if (*minor) {
2314 		return GSS_S_FAILURE;
2315 	}
2316 
2317 	/* Strip the confounder and trailing pad bytes */
2318 	gss_strip_mbuf(smb, -padlen);
2319 	assert(ccmode->block_size <= INT_MAX);
2320 	gss_strip_mbuf(smb, (int)ccmode->block_size);
2321 
2322 	if (*mbp != smb) {
2323 		mbuf_freem(*mbp);
2324 		*mbp = smb;
2325 	}
2326 
2327 	return GSS_S_COMPLETE;
2328 }
2329 
2330 static const char *
etype_name(etypes etype)2331 etype_name(etypes etype)
2332 {
2333 	switch (etype) {
2334 	case DES3_CBC_SHA1_KD:
2335 		return "des3-cbc-sha1";
2336 	case AES128_CTS_HMAC_SHA1_96:
2337 		return "aes128-cts-hmac-sha1-96";
2338 	case AES256_CTS_HMAC_SHA1_96:
2339 		return "aes-cts-hmac-sha1-96";
2340 	default:
2341 		return "unknown enctype";
2342 	}
2343 }
2344 
2345 static int
supported_etype(uint32_t proto,etypes etype)2346 supported_etype(uint32_t proto, etypes etype)
2347 {
2348 	const char *proto_name;
2349 
2350 	switch (proto) {
2351 	case 0:
2352 		/* RFC 1964 */
2353 		proto_name = "RFC 1964 krb5 gss mech";
2354 		switch (etype) {
2355 		case DES3_CBC_SHA1_KD:
2356 			return 1;
2357 		default:
2358 			break;
2359 		}
2360 		break;
2361 	case 1:
2362 		/* RFC 4121 */
2363 		proto_name = "RFC 4121 krb5 gss mech";
2364 		switch (etype) {
2365 		case AES256_CTS_HMAC_SHA1_96:
2366 		case AES128_CTS_HMAC_SHA1_96:
2367 			return 1;
2368 		default:
2369 			break;
2370 		}
2371 		break;
2372 	default:
2373 		proto_name = "Unknown krb5 gss mech";
2374 		break;
2375 	}
2376 	printf("%s: Non supported encryption %s (%d) type for protocol %s (%d)\n",
2377 	    __func__, etype_name(etype), etype, proto_name, proto);
2378 	return 0;
2379 }
2380 
2381 /*
2382  * Kerberos gss mech entry points
2383  */
2384 uint32_t
gss_krb5_get_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop,gss_buffer_t mbp,gss_buffer_t mic)2385 gss_krb5_get_mic(uint32_t *minor,       /* minor_status */
2386     gss_ctx_id_t ctx,                   /* context_handle */
2387     gss_qop_t qop,                      /* qop_req */
2388     gss_buffer_t mbp,                   /* message buffer */
2389     gss_buffer_t mic /* message_token */)
2390 {
2391 	uint32_t minor_stat = 0;
2392 
2393 	if (minor == NULL) {
2394 		minor = &minor_stat;
2395 	}
2396 	*minor = 0;
2397 
2398 	/* Validate context */
2399 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2400 		return GSS_S_NO_CONTEXT;
2401 	}
2402 
2403 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2404 		*minor = ENOTSUP;
2405 		return GSS_S_FAILURE;
2406 	}
2407 
2408 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2409 	case 0:
2410 		/* RFC 1964 DES3 case */
2411 		return gss_krb5_3des_get_mic(minor, ctx, qop, mbp, mic);
2412 	case 1:
2413 		/* RFC 4121 CFX case */
2414 		return gss_krb5_cfx_get_mic(minor, ctx, qop, mbp, mic);
2415 	}
2416 
2417 	return GSS_S_COMPLETE;
2418 }
2419 
2420 uint32_t
gss_krb5_verify_mic(uint32_t * minor,gss_ctx_id_t ctx,gss_buffer_t mbp,gss_buffer_t mic,gss_qop_t * qop)2421 gss_krb5_verify_mic(uint32_t *minor,            /* minor_status */
2422     gss_ctx_id_t ctx,                           /* context_handle */
2423     gss_buffer_t mbp,                           /* message_buffer */
2424     gss_buffer_t mic,                           /* message_token */
2425     gss_qop_t *qop /* qop_state */)
2426 {
2427 	uint32_t minor_stat = 0;
2428 	gss_qop_t qop_val = GSS_C_QOP_DEFAULT;
2429 
2430 	if (minor == NULL) {
2431 		minor = &minor_stat;
2432 	}
2433 	if (qop == NULL) {
2434 		qop = &qop_val;
2435 	}
2436 
2437 	*minor = 0;
2438 
2439 	/* Validate context */
2440 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2441 		return GSS_S_NO_CONTEXT;
2442 	}
2443 
2444 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2445 		*minor = ENOTSUP;
2446 		return GSS_S_FAILURE;
2447 	}
2448 
2449 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2450 	case 0:
2451 		/* RFC 1964 DES3 case */
2452 		return gss_krb5_3des_verify_mic(minor, ctx, mbp, mic, qop);
2453 	case 1:
2454 		/* RFC 4121 CFX case */
2455 		return gss_krb5_cfx_verify_mic(minor, ctx, mbp, mic, qop);
2456 	}
2457 	return GSS_S_COMPLETE;
2458 }
2459 
2460 uint32_t
gss_krb5_get_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,gss_qop_t qop,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic)2461 gss_krb5_get_mic_mbuf(uint32_t *minor,  /* minor_status */
2462     gss_ctx_id_t ctx,                   /* context_handle */
2463     gss_qop_t qop,                      /* qop_req */
2464     mbuf_t mbp,                         /* message mbuf */
2465     size_t offset,                      /* offest */
2466     size_t len,                         /* length */
2467     gss_buffer_t mic /* message_token */)
2468 {
2469 	uint32_t minor_stat = 0;
2470 
2471 	if (minor == NULL) {
2472 		minor = &minor_stat;
2473 	}
2474 	*minor = 0;
2475 
2476 	if (len == 0) {
2477 		len = ~(size_t)0;
2478 	}
2479 
2480 	/* Validate context */
2481 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2482 		return GSS_S_NO_CONTEXT;
2483 	}
2484 
2485 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2486 		*minor = ENOTSUP;
2487 		return GSS_S_FAILURE;
2488 	}
2489 
2490 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2491 	case 0:
2492 		/* RFC 1964 DES3 case */
2493 		return gss_krb5_3des_get_mic_mbuf(minor, ctx, qop, mbp, offset, len, mic);
2494 	case 1:
2495 		/* RFC 4121 CFX case */
2496 		return gss_krb5_cfx_get_mic_mbuf(minor, ctx, qop, mbp, offset, len, mic);
2497 	}
2498 
2499 	return GSS_S_COMPLETE;
2500 }
2501 
2502 uint32_t
gss_krb5_verify_mic_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t mbp,size_t offset,size_t len,gss_buffer_t mic,gss_qop_t * qop)2503 gss_krb5_verify_mic_mbuf(uint32_t *minor,               /* minor_status */
2504     gss_ctx_id_t ctx,                                   /* context_handle */
2505     mbuf_t mbp,                                         /* message_buffer */
2506     size_t offset,                              /* offset */
2507     size_t len,                                         /* length */
2508     gss_buffer_t mic,                                   /* message_token */
2509     gss_qop_t *qop /* qop_state */)
2510 {
2511 	uint32_t minor_stat = 0;
2512 	gss_qop_t qop_val = GSS_C_QOP_DEFAULT;
2513 
2514 	if (minor == NULL) {
2515 		minor = &minor_stat;
2516 	}
2517 	if (qop == NULL) {
2518 		qop = &qop_val;
2519 	}
2520 
2521 	*minor = 0;
2522 
2523 	if (len == 0) {
2524 		len = ~(size_t)0;
2525 	}
2526 
2527 	/* Validate context */
2528 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2529 		return GSS_S_NO_CONTEXT;
2530 	}
2531 
2532 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2533 		*minor = ENOTSUP;
2534 		return GSS_S_FAILURE;
2535 	}
2536 
2537 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2538 	case 0:
2539 		/* RFC 1964 DES3 case */
2540 		return gss_krb5_3des_verify_mic_mbuf(minor, ctx, mbp, offset, len, mic, qop);
2541 	case 1:
2542 		/* RFC 4121 CFX case */
2543 		return gss_krb5_cfx_verify_mic_mbuf(minor, ctx, mbp, offset, len, mic, qop);
2544 	}
2545 
2546 	return GSS_S_COMPLETE;
2547 }
2548 
2549 uint32_t
gss_krb5_wrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,int conf_flag,gss_qop_t qop,mbuf_t * mbp,size_t offset,size_t len,int * conf_state)2550 gss_krb5_wrap_mbuf(uint32_t *minor,     /* minor_status */
2551     gss_ctx_id_t ctx,                   /* context_handle */
2552     int conf_flag,                      /* conf_req_flag */
2553     gss_qop_t qop,                      /* qop_req */
2554     mbuf_t *mbp,                        /* input/output message_buffer */
2555     size_t offset,                      /* offset */
2556     size_t len,                         /* length */
2557     int *conf_state /* conf state */)
2558 {
2559 	uint32_t major = GSS_S_FAILURE, minor_stat = 0;
2560 	mbuf_t smb, tmb;
2561 	int conf_val = 0;
2562 
2563 	if (minor == NULL) {
2564 		minor = &minor_stat;
2565 	}
2566 	if (conf_state == NULL) {
2567 		conf_state = &conf_val;
2568 	}
2569 
2570 	*minor = 0;
2571 
2572 	/* Validate context */
2573 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2574 		return GSS_S_NO_CONTEXT;
2575 	}
2576 
2577 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2578 		*minor = ENOTSUP;
2579 		return GSS_S_FAILURE;
2580 	}
2581 
2582 	gss_normalize_mbuf(*mbp, offset, &len, &smb, &tmb, 0);
2583 
2584 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2585 	case 0:
2586 		/* RFC 1964 DES3 case */
2587 		major = gss_krb5_3des_wrap_mbuf(minor, ctx, conf_flag, qop, &smb, len, conf_state);
2588 		break;
2589 	case 1:
2590 		/* RFC 4121 CFX case */
2591 		major = gss_krb5_cfx_wrap_mbuf(minor, ctx, conf_flag, qop, &smb, len, conf_state);
2592 		break;
2593 	}
2594 
2595 	if (offset) {
2596 		gss_join_mbuf(*mbp, smb, tmb);
2597 	} else {
2598 		*mbp = smb;
2599 		gss_join_mbuf(smb, tmb, NULL);
2600 	}
2601 
2602 	return major;
2603 }
2604 
2605 uint32_t
gss_krb5_unwrap_mbuf(uint32_t * minor,gss_ctx_id_t ctx,mbuf_t * mbp,size_t offset,size_t len,int * conf_flag,gss_qop_t * qop)2606 gss_krb5_unwrap_mbuf(uint32_t * minor,          /* minor_status */
2607     gss_ctx_id_t ctx,                           /* context_handle */
2608     mbuf_t *mbp,                                /* input/output message_buffer */
2609     size_t offset,                              /* offset */
2610     size_t len,                                 /* length */
2611     int *conf_flag,                             /* conf_state */
2612     gss_qop_t *qop /* qop state */)
2613 {
2614 	uint32_t major = GSS_S_FAILURE, minor_stat = 0;
2615 	gss_qop_t qop_val = GSS_C_QOP_DEFAULT;
2616 	int conf_val = 0;
2617 	mbuf_t smb, tmb;
2618 
2619 	if (minor == NULL) {
2620 		minor = &minor_stat;
2621 	}
2622 	if (qop == NULL) {
2623 		qop = &qop_val;
2624 	}
2625 	if (conf_flag == NULL) {
2626 		conf_flag = &conf_val;
2627 	}
2628 
2629 	/* Validate context */
2630 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2631 		return GSS_S_NO_CONTEXT;
2632 	}
2633 
2634 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2635 		*minor = ENOTSUP;
2636 		return GSS_S_FAILURE;
2637 	}
2638 
2639 	gss_normalize_mbuf(*mbp, offset, &len, &smb, &tmb, 0);
2640 
2641 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2642 	case 0:
2643 		/* RFC 1964 DES3 case */
2644 		major = gss_krb5_3des_unwrap_mbuf(minor, ctx, &smb, len, conf_flag, qop);
2645 		break;
2646 	case 1:
2647 		/* RFC 4121 CFX case */
2648 		major = gss_krb5_cfx_unwrap_mbuf(minor, ctx, &smb, len, conf_flag, qop);
2649 		break;
2650 	}
2651 
2652 	if (offset) {
2653 		gss_join_mbuf(*mbp, smb, tmb);
2654 	} else {
2655 		*mbp = smb;
2656 		gss_join_mbuf(smb, tmb, NULL);
2657 	}
2658 
2659 	return major;
2660 }
2661 
2662 #include <nfs/xdr_subs.h>
2663 
2664 static int
xdr_lucid_context(void * data,uint32_t length,lucid_context_t lctx)2665 xdr_lucid_context(void *data, uint32_t length, lucid_context_t lctx)
2666 {
2667 	struct xdrbuf xb;
2668 	int error = 0;
2669 	uint32_t keylen = 0;
2670 
2671 	xb_init_buffer(&xb, data, length);
2672 	xb_get_32(error, &xb, lctx->vers);
2673 	if (!error && lctx->vers != 1) {
2674 		error = EINVAL;
2675 		printf("%s: invalid version %d\n", __func__, (int)lctx->vers);
2676 		goto out;
2677 	}
2678 	xb_get_32(error, &xb, lctx->initiate);
2679 	if (error) {
2680 		printf("%s: Could not decode initiate\n", __func__);
2681 		goto out;
2682 	}
2683 	xb_get_32(error, &xb, lctx->endtime);
2684 	if (error) {
2685 		printf("%s: Could not decode endtime\n", __func__);
2686 		goto out;
2687 	}
2688 	xb_get_64(error, &xb, lctx->send_seq);
2689 	if (error) {
2690 		printf("%s: Could not decode send_seq\n", __func__);
2691 		goto out;
2692 	}
2693 	xb_get_64(error, &xb, lctx->recv_seq);
2694 	if (error) {
2695 		printf("%s: Could not decode recv_seq\n", __func__);
2696 		goto out;
2697 	}
2698 	xb_get_32(error, &xb, lctx->key_data.proto);
2699 	if (error) {
2700 		printf("%s: Could not decode mech protocol\n", __func__);
2701 		goto out;
2702 	}
2703 	switch (lctx->key_data.proto) {
2704 	case 0:
2705 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_1964.sign_alg);
2706 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_1964.seal_alg);
2707 		if (error) {
2708 			printf("%s: Could not decode rfc1964 sign and seal\n", __func__);
2709 		}
2710 		break;
2711 	case 1:
2712 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey);
2713 		if (error) {
2714 			printf("%s: Could not decode rfc4121 acceptor_subkey", __func__);
2715 		}
2716 		break;
2717 	default:
2718 		printf("%s: Invalid mech protocol %d\n", __func__, (int)lctx->key_data.proto);
2719 		error = EINVAL;
2720 	}
2721 	if (error) {
2722 		goto out;
2723 	}
2724 	xb_get_32(error, &xb, lctx->ctx_key.etype);
2725 	if (error) {
2726 		printf("%s: Could not decode key enctype\n", __func__);
2727 		goto out;
2728 	}
2729 	switch (lctx->ctx_key.etype) {
2730 	case DES3_CBC_SHA1_KD:
2731 		keylen = 24;
2732 		break;
2733 	case AES128_CTS_HMAC_SHA1_96:
2734 		keylen = 16;
2735 		break;
2736 	case AES256_CTS_HMAC_SHA1_96:
2737 		keylen = 32;
2738 		break;
2739 	default:
2740 		error = ENOTSUP;
2741 		goto out;
2742 	}
2743 	xb_get_32(error, &xb, lctx->ctx_key.key.key_len);
2744 	if (error) {
2745 		printf("%s: could not decode key length\n", __func__);
2746 		goto out;
2747 	}
2748 	if (lctx->ctx_key.key.key_len != keylen) {
2749 		error = EINVAL;
2750 		printf("%s: etype = %d keylen = %d expected keylen = %d\n", __func__,
2751 		    lctx->ctx_key.etype, lctx->ctx_key.key.key_len, keylen);
2752 		goto out;
2753 	}
2754 
2755 	lctx->ctx_key.key.key_val = xb_malloc(keylen);
2756 	if (lctx->ctx_key.key.key_val == NULL) {
2757 		printf("%s: could not get memory for key\n", __func__);
2758 		error = ENOMEM;
2759 		goto out;
2760 	}
2761 	error = xb_get_bytes(&xb, (char *)lctx->ctx_key.key.key_val, keylen, 1);
2762 	if (error) {
2763 		printf("%s: could get key value\n", __func__);
2764 		xb_free(lctx->ctx_key.key.key_val);
2765 	}
2766 out:
2767 	return error;
2768 }
2769 
2770 gss_ctx_id_t
gss_krb5_make_context(void * data,uint32_t datalen)2771 gss_krb5_make_context(void *data, uint32_t datalen)
2772 {
2773 	gss_ctx_id_t ctx;
2774 
2775 	if (!corecrypto_available()) {
2776 		return NULL;
2777 	}
2778 
2779 	gss_krb5_mech_init();
2780 	ctx = kalloc_type(struct gss_ctx_id_desc, Z_WAITOK | Z_ZERO);
2781 	if (xdr_lucid_context(data, datalen, &ctx->gss_lucid_ctx) ||
2782 	    !supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_lucid_ctx.ctx_key.etype)) {
2783 		kfree_type(struct gss_ctx_id_desc, ctx);
2784 		FREE(data, M_TEMP);
2785 		return NULL;
2786 	}
2787 
2788 	/* Set up crypto context */
2789 	gss_crypto_ctx_init(&ctx->gss_cryptor, &ctx->gss_lucid_ctx);
2790 	FREE(data, M_TEMP);
2791 
2792 	return ctx;
2793 }
2794 
2795 void
gss_krb5_destroy_context(gss_ctx_id_t ctx)2796 gss_krb5_destroy_context(gss_ctx_id_t ctx)
2797 {
2798 	if (ctx == NULL) {
2799 		return;
2800 	}
2801 	gss_crypto_ctx_free(&ctx->gss_cryptor);
2802 	FREE(ctx->gss_lucid_ctx.ctx_key.key.key_val, M_TEMP);
2803 	cc_clear(sizeof(lucid_context_t), &ctx->gss_lucid_ctx);
2804 	kfree_type(struct gss_ctx_id_desc, ctx);
2805 }
2806