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