xref: /xnu-12377.1.9/bsd/nfs/gss/gss_krb5_mech.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
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/mbuf.h>
68 #include <sys/kpi_mbuf.h>
69 #include <sys/random.h>
70 #include <mach_assert.h>
71 #include <kern/assert.h>
72 #include <libkern/OSAtomic.h>
73 #include <IOKit/IOLib.h>
74 #include "gss_krb5_mech.h"
75 
76 LCK_GRP_DECLARE(gss_krb5_mech_grp, "gss_krb5_mech");
77 
78 typedef struct crypt_walker_ctx {
79 	size_t length;
80 	const struct ccmode_cbc *ccmode;
81 	cccbc_ctx *crypt_ctx;
82 	cccbc_iv *iv;
83 } *crypt_walker_ctx_t;
84 
85 typedef struct hmac_walker_ctx {
86 	const struct ccdigest_info *di;
87 	struct cchmac_ctx *hmac_ctx;
88 } *hmac_walker_ctx_t;
89 
90 typedef size_t (*ccpad_func)(const struct ccmode_cbc *, cccbc_ctx *, cccbc_iv *,
91     size_t nbytes, const void *, void *);
92 
93 static int krb5_n_fold(const void *instr, size_t len, void *foldstr, size_t size);
94 
95 size_t gss_mbuf_len(mbuf_t, size_t);
96 errno_t gss_prepend_mbuf(mbuf_t *, uint8_t *, size_t);
97 errno_t gss_append_mbuf(mbuf_t, uint8_t *, size_t);
98 errno_t gss_strip_mbuf(mbuf_t, int);
99 int mbuf_walk(mbuf_t, size_t, size_t, size_t, int (*)(void *, uint8_t *, size_t), void *);
100 
101 void do_crypt_init(crypt_walker_ctx_t, int, crypto_ctx_t, cccbc_ctx *);
102 int do_crypt(void *, uint8_t *, size_t);
103 void do_hmac_init(hmac_walker_ctx_t, crypto_ctx_t, void *);
104 int do_hmac(void *, uint8_t *, size_t);
105 void do_hmac_destroy(hmac_walker_ctx_t, crypto_ctx_t);
106 
107 void krb5_make_usage(uint32_t, uint8_t, uint8_t[KRB5_USAGE_LEN]);
108 void krb5_key_derivation(crypto_ctx_t, const void *, size_t, krb5_key_t *, size_t);
109 void cc_key_schedule_create(crypto_ctx_t);
110 void gss_crypto_ctx_free(crypto_ctx_t);
111 int gss_crypto_ctx_init(struct crypto_ctx *, lucid_context_t);
112 
113 errno_t krb5_crypt_mbuf(crypto_ctx_t, mbuf_t *, size_t, int, cccbc_ctx *);
114 int krb5_mic(crypto_ctx_t, gss_buffer_t, gss_buffer_t, gss_buffer_t, uint8_t *, int *, int, int);
115 int krb5_mic_mbuf(crypto_ctx_t, gss_buffer_t, mbuf_t, size_t, size_t, gss_buffer_t, uint8_t *, int *, int, int);
116 
117 uint32_t gss_krb5_cfx_get_mic(uint32_t *, gss_ctx_id_t, gss_qop_t, gss_buffer_t, gss_buffer_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", (mtod(mb, uint8_t *))[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 = mtod(*chain, uint8_t *);
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 = mtod(*chain, uint8_t *);
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 = mtod(mb, uint8_t *);
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 = mtod(nmb, uint8_t *);
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_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)1264 gss_krb5_cfx_get_mic_mbuf(uint32_t *minor,      /* minor_status */
1265     gss_ctx_id_t ctx,                           /* context_handle */
1266     gss_qop_t qop __unused,                       /* qop_req (ignored) */
1267     mbuf_t mbp,                         /* message mbuf */
1268     size_t offset,                              /* offest */
1269     size_t len,                         /* length */
1270     gss_buffer_t mic /* message_token */)
1271 {
1272 	gss_cfx_mic_token_desc token;
1273 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1274 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1275 	uint32_t rv;
1276 	uint64_t seq = htonll(lctx->send_seq);
1277 	gss_buffer_desc header;
1278 
1279 	if (minor == NULL) {
1280 		minor = &rv;
1281 	}
1282 	*minor = 0;
1283 
1284 	token = mic_cfx_token;
1285 	mic->length = sizeof(token) + cctx->digest_size;
1286 	mic->value = kalloc_data(mic->length, Z_WAITOK | Z_ZERO);
1287 	if (!lctx->initiate) {
1288 		token.Flags |= CFXSentByAcceptor;
1289 	}
1290 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1291 		token.Flags |= CFXAcceptorSubkey;
1292 	}
1293 
1294 	memcpy(&token.SND_SEQ, &seq, sizeof(lctx->send_seq));
1295 	lctx->send_seq++; //XXX should only update this below on success? Heimdal seems to do it this way
1296 
1297 	header.length = sizeof(token);
1298 	header.value = &token;
1299 
1300 	len = len ? len : gss_mbuf_len(mbp, offset);
1301 	*minor = krb5_mic_mbuf(cctx, NULL, mbp, offset, len, &header, (uint8_t *)mic->value + sizeof(token), NULL, 0, 0);
1302 
1303 	if (*minor) {
1304 		mic->length = 0;
1305 		kfree_data(mic->value, mic->length);
1306 	} else {
1307 		memcpy(mic->value, &token, sizeof(token));
1308 	}
1309 
1310 	return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
1311 }
1312 
1313 
1314 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)1315 gss_krb5_cfx_verify_mic_mbuf(uint32_t *minor,   /* minor_status */
1316     gss_ctx_id_t ctx,                           /* context_handle */
1317     mbuf_t mbp,                                         /* message_buffer */
1318     size_t offset,                                      /* offset */
1319     size_t len,                                         /* length */
1320     gss_buffer_t mic,                           /* message_token */
1321     gss_qop_t *qop /* qop_state */)
1322 {
1323 	gss_cfx_mic_token token = mic->value;
1324 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1325 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1326 	uint8_t *digest = (uint8_t *)mic->value + sizeof(gss_cfx_mic_token_desc);
1327 	int verified;
1328 	uint64_t seq;
1329 	uint32_t rv;
1330 	gss_buffer_desc header;
1331 
1332 	if (qop) {
1333 		*qop = GSS_C_QOP_DEFAULT;
1334 	}
1335 
1336 	if (minor == NULL) {
1337 		minor = &rv;
1338 	}
1339 
1340 	*minor = gss_krb5_cfx_verify_mic_token(ctx, token);
1341 	if (*minor) {
1342 		return GSS_S_FAILURE;
1343 	}
1344 
1345 	header.length = sizeof(gss_cfx_mic_token_desc);
1346 	header.value = mic->value;
1347 
1348 	*minor = krb5_mic_mbuf(cctx, NULL, mbp, offset, len, &header, digest, &verified, 0, 0);
1349 	if (*minor) {
1350 		return GSS_S_FAILURE;
1351 	}
1352 
1353 	//XXX  errors and such? Sequencing and replay? Not Supported RPCSEC_GSS
1354 	memcpy(&seq, token->SND_SEQ, sizeof(uint64_t));
1355 	seq = ntohll(seq);
1356 	lctx->recv_seq = seq;
1357 
1358 	return verified ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
1359 }
1360 
1361 errno_t
krb5_cfx_crypt_mbuf(crypto_ctx_t ctx,mbuf_t * mbp,size_t * len,int encrypt,int reverse)1362 krb5_cfx_crypt_mbuf(crypto_ctx_t ctx, mbuf_t *mbp, size_t *len, int encrypt, int reverse)
1363 {
1364 	const struct ccmode_cbc *ccmode = encrypt ? ctx->enc_mode : ctx->dec_mode;
1365 	uint8_t *confounder = NULL;
1366 	uint8_t *mpad = NULL;
1367 	uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1368 	size_t tlen, r = 0;
1369 	errno_t error;
1370 
1371 	confounder = kalloc_data(ccmode->block_size, Z_WAITOK | Z_ZERO);
1372 	if (confounder == NULL) {
1373 		error = ENOMEM;
1374 		goto out;
1375 	}
1376 	if (encrypt) {
1377 		assert(ccmode->block_size <= UINT_MAX);
1378 		read_random(confounder, (u_int)ccmode->block_size);
1379 		error = gss_prepend_mbuf(mbp, confounder, ccmode->block_size);
1380 		if (error) {
1381 			goto out;
1382 		}
1383 		tlen = *len + ccmode->block_size;
1384 		if (ctx->mpad > 1) {
1385 			r = ctx->mpad - (tlen % ctx->mpad);
1386 		}
1387 		/* We expect that r == 0 from krb5_cfx_wrap */
1388 		if (r != 0) {
1389 			mpad = kalloc_data(r, Z_WAITOK | Z_ZERO);
1390 			if (mpad == NULL) {
1391 				error = ENOMEM;
1392 				goto out;
1393 			}
1394 			error = gss_append_mbuf(*mbp, mpad, r);
1395 			if (error) {
1396 				goto out;
1397 			}
1398 		}
1399 		tlen += r;
1400 		error = krb5_mic_mbuf(ctx, NULL, *mbp, 0, tlen, NULL, digest, NULL, 1, 0);
1401 		if (error) {
1402 			goto out;
1403 		}
1404 		error = krb5_crypt_mbuf(ctx, mbp, tlen, 1, NULL);
1405 		if (error) {
1406 			goto out;
1407 		}
1408 		error = gss_append_mbuf(*mbp, digest, ctx->digest_size);
1409 		if (error) {
1410 			goto out;
1411 		}
1412 		*len = tlen + ctx->digest_size;
1413 		error = 0;
1414 		goto out;
1415 	} else {
1416 		int verf;
1417 		cccbc_ctx *ks = NULL;
1418 
1419 		if (*len < ctx->digest_size + sizeof(confounder)) {
1420 			error = EBADRPC;
1421 			goto out;
1422 		}
1423 		tlen = *len - ctx->digest_size;
1424 		/* get the digest */
1425 		error = mbuf_copydata(*mbp, tlen, ctx->digest_size, digest);
1426 		/* Remove the digest from the mbuffer */
1427 		error = gss_strip_mbuf(*mbp, -ctx->digest_size);
1428 		if (error) {
1429 			goto out;
1430 		}
1431 
1432 		if (reverse) {
1433 			/*
1434 			 * Derive a key schedule that the sender can unwrap with. This
1435 			 * is so that RPCSEC_GSS can restore encrypted arguments for
1436 			 * resending. We do that because the RPCSEC_GSS sequence number in
1437 			 * the rpc header is prepended to the body of the message before wrapping.
1438 			 */
1439 			krb5_key_t ekey;
1440 			uint8_t usage_string[KRB5_USAGE_LEN];
1441 			lucid_context_t lctx = ctx->gss_ctx;
1442 
1443 			krb5_make_usage(lctx->initiate ?
1444 			    KRB5_USAGE_INITIATOR_SEAL : KRB5_USAGE_ACCEPTOR_SEAL,
1445 			    0xAA, usage_string);
1446 			krb5_key_derivation(ctx, usage_string, KRB5_USAGE_LEN, &ekey, ctx->keylen);
1447 			ks = kalloc_data(ctx->dec_mode->size, Z_WAITOK | Z_ZERO);
1448 			cccbc_init(ctx->dec_mode, ks, ctx->keylen, ekey.key_val);
1449 			gss_krb5_key_free(&ekey, 1);
1450 		}
1451 		error = krb5_crypt_mbuf(ctx, mbp, tlen, 0, ks);
1452 		kfree_data(ks, ctx->dec_mode->size);
1453 		if (error) {
1454 			goto out;
1455 		}
1456 		error = krb5_mic_mbuf(ctx, NULL, *mbp, 0, tlen, NULL, digest, &verf, 1, reverse);
1457 		if (error) {
1458 			goto out;
1459 		}
1460 		if (!verf) {
1461 			error = EBADRPC;
1462 			goto out;
1463 		}
1464 		/* strip off the confounder */
1465 		assert(ccmode->block_size <= INT_MAX);
1466 		error = gss_strip_mbuf(*mbp, (int)ccmode->block_size);
1467 		if (error) {
1468 			goto out;
1469 		}
1470 		*len = tlen - ccmode->block_size;
1471 	}
1472 
1473 	error = 0;
1474 out:
1475 	kfree_data(mpad, r);
1476 	kfree_data(confounder, ccmode->block_size);
1477 	return error;
1478 }
1479 
1480 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)1481 gss_krb5_cfx_wrap_mbuf(uint32_t *minor,         /* minor_status */
1482     gss_ctx_id_t ctx,                           /* context_handle */
1483     int conf_flag,                              /* conf_req_flag */
1484     gss_qop_t qop __unused,                     /* qop_req */
1485     mbuf_t *mbp,                                /* input/output message_buffer */
1486     size_t len,                                 /* mbuf chain length */
1487     int *conf /* conf_state */)
1488 {
1489 	gss_cfx_wrap_token_desc token;
1490 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1491 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1492 	int error = 0;
1493 	uint32_t mv;
1494 	uint64_t seq = htonll(lctx->send_seq);
1495 
1496 	if (minor == NULL) {
1497 		minor = &mv;
1498 	}
1499 	if (conf) {
1500 		*conf = conf_flag;
1501 	}
1502 
1503 	*minor = 0;
1504 	token = wrap_cfx_token;
1505 	if (!lctx->initiate) {
1506 		token.Flags |= CFXSentByAcceptor;
1507 	}
1508 	if (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey) {
1509 		token.Flags |= CFXAcceptorSubkey;
1510 	}
1511 	memcpy(&token.SND_SEQ, &seq, sizeof(uint64_t));
1512 	lctx->send_seq++;
1513 	if (conf_flag) {
1514 		uint8_t *pad = NULL;
1515 		size_t plen = 0;
1516 
1517 		pad = kalloc_data(cctx->mpad, Z_WAITOK | Z_ZERO);
1518 		if (pad == NULL) {
1519 			*minor = ENOMEM;
1520 			return GSS_S_FAILURE;
1521 		}
1522 		token.Flags |= CFXSealed;
1523 		if (cctx->mpad > 1) {
1524 			size_t val = cctx->mpad - ((len + sizeof(gss_cfx_wrap_token_desc)) % cctx->mpad);
1525 			plen = sizeof(val) > sizeof(uint32_t) ? htonll(val) : htonl(val);
1526 			token.EC[0] = ((plen >> 8) & 0xff);
1527 			token.EC[1] = (plen & 0xff);
1528 		}
1529 		if (plen) {
1530 			error = gss_append_mbuf(*mbp, pad, plen);
1531 			len += plen;
1532 		}
1533 		if (error == 0) {
1534 			error = gss_append_mbuf(*mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1535 			len += sizeof(gss_cfx_wrap_token_desc);
1536 		}
1537 		if (error == 0) {
1538 			error = krb5_cfx_crypt_mbuf(cctx, mbp, &len, 1, 0);
1539 		}
1540 		if (error == 0) {
1541 			error = gss_prepend_mbuf(mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1542 		}
1543 		kfree_data(pad, cctx->mpad);
1544 	} else {
1545 		uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1546 		gss_buffer_desc header;
1547 
1548 		header.length = sizeof(token);
1549 		header.value = &token;
1550 
1551 		error = krb5_mic_mbuf(cctx, NULL, *mbp, 0, len, &header, digest, NULL, 1, 0);
1552 		if (error == 0) {
1553 			error = gss_append_mbuf(*mbp, digest, cctx->digest_size);
1554 			if (error == 0) {
1555 				uint32_t plen = htonl(cctx->digest_size);
1556 				memcpy(token.EC, &plen, 2);
1557 				error = gss_prepend_mbuf(mbp, (uint8_t *)&token, sizeof(gss_cfx_wrap_token_desc));
1558 			}
1559 		}
1560 	}
1561 	if (error) {
1562 		*minor = error;
1563 		return GSS_S_FAILURE;
1564 	}
1565 
1566 	return GSS_S_COMPLETE;
1567 }
1568 
1569 /*
1570  * Given a wrap token the has a rrc, move the trailer back to the end.
1571  */
1572 static void
gss_krb5_cfx_unwrap_rrc_mbuf(mbuf_t header,size_t rrc)1573 gss_krb5_cfx_unwrap_rrc_mbuf(mbuf_t header, size_t rrc)
1574 {
1575 	mbuf_t body, trailer;
1576 
1577 	gss_normalize_mbuf(header, sizeof(gss_cfx_wrap_token_desc), &rrc, &trailer, &body, 0);
1578 	gss_join_mbuf(header, body, trailer);
1579 }
1580 
1581 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)1582 gss_krb5_cfx_unwrap_mbuf(uint32_t * minor,      /* minor_status */
1583     gss_ctx_id_t ctx,                           /* context_handle */
1584     mbuf_t *mbp,                                /* input/output message_buffer */
1585     size_t len,                                 /* mbuf chain length */
1586     int *conf_flag,                             /* conf_state */
1587     gss_qop_t *qop /* qop state */)
1588 {
1589 	gss_cfx_wrap_token_desc token;
1590 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1591 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1592 	int error, conf;
1593 	uint32_t ec = 0, rrc = 0;
1594 	uint64_t seq;
1595 	int reverse = (*qop == GSS_C_QOP_REVERSE);
1596 	int initiate = lctx->initiate ? (reverse ? 0 : 1) : (reverse ? 1 : 0);
1597 
1598 	error = mbuf_copydata(*mbp, 0, sizeof(gss_cfx_wrap_token_desc), &token);
1599 	gss_strip_mbuf(*mbp, sizeof(gss_cfx_wrap_token_desc));
1600 	len -= sizeof(gss_cfx_wrap_token_desc);
1601 
1602 	/* Check for valid token */
1603 	if (token.TOK_ID[0] != wrap_cfx_token.TOK_ID[0] ||
1604 	    token.TOK_ID[1] != wrap_cfx_token.TOK_ID[1] ||
1605 	    token.Filler != wrap_cfx_token.Filler) {
1606 		printf("Token id does not match\n");
1607 		goto badrpc;
1608 	}
1609 	if ((initiate && !(token.Flags & CFXSentByAcceptor)) ||
1610 	    (lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey && !(token.Flags & CFXAcceptorSubkey))) {
1611 		printf("Bad flags %x\n", token.Flags);
1612 		goto badrpc;
1613 	}
1614 
1615 	/* XXX Sequence replay detection */
1616 	memcpy(&seq, token.SND_SEQ, sizeof(seq));
1617 	seq = ntohll(seq);
1618 	lctx->recv_seq = seq;
1619 
1620 	ec = (token.EC[0] << 8) | token.EC[1];
1621 	rrc = (token.RRC[0] << 8) | token.RRC[1];
1622 	*qop = GSS_C_QOP_DEFAULT;
1623 	conf = ((token.Flags & CFXSealed) == CFXSealed);
1624 	if (conf_flag) {
1625 		*conf_flag = conf;
1626 	}
1627 	if (conf) {
1628 		gss_cfx_wrap_token_desc etoken;
1629 
1630 		if (rrc) { /* Handle Right rotation count */
1631 			gss_krb5_cfx_unwrap_rrc_mbuf(*mbp, rrc);
1632 		}
1633 		error = krb5_cfx_crypt_mbuf(cctx, mbp, &len, 0, reverse);
1634 		if (error) {
1635 			printf("krb5_cfx_crypt_mbuf %d\n", error);
1636 			*minor = error;
1637 			return GSS_S_FAILURE;
1638 		}
1639 		if (len >= sizeof(gss_cfx_wrap_token_desc)) {
1640 			len -= sizeof(gss_cfx_wrap_token_desc);
1641 		} else {
1642 			goto badrpc;
1643 		}
1644 		mbuf_copydata(*mbp, len, sizeof(gss_cfx_wrap_token_desc), &etoken);
1645 		/* Verify etoken with the token wich should be the same, except the rc field is always zero */
1646 		token.RRC[0] = token.RRC[1] = 0;
1647 		if (memcmp(&token, &etoken, sizeof(gss_cfx_wrap_token_desc)) != 0) {
1648 			printf("Encrypted token mismach\n");
1649 			goto badrpc;
1650 		}
1651 		/* strip the encrypted token and any pad bytes */
1652 		gss_strip_mbuf(*mbp, -(sizeof(gss_cfx_wrap_token_desc) + ec));
1653 		len -= (sizeof(gss_cfx_wrap_token_desc) + ec);
1654 	} else {
1655 		uint8_t digest[CRYPTO_MAX_DIGSET_SIZE];
1656 		int verf;
1657 		gss_buffer_desc header;
1658 
1659 		if (ec != cctx->digest_size || len >= cctx->digest_size) {
1660 			goto badrpc;
1661 		}
1662 		len -= cctx->digest_size;
1663 		mbuf_copydata(*mbp, len, cctx->digest_size, digest);
1664 		gss_strip_mbuf(*mbp, -cctx->digest_size);
1665 		/* When calculating the mic header fields ec and rcc must be zero */
1666 		token.EC[0] = token.EC[1] = token.RRC[0] = token.RRC[1] = 0;
1667 		header.value = &token;
1668 		header.length = sizeof(gss_cfx_wrap_token_desc);
1669 		error = krb5_mic_mbuf(cctx, NULL, *mbp, 0, len, &header, digest, &verf, 1, reverse);
1670 		if (error) {
1671 			goto badrpc;
1672 		}
1673 	}
1674 	return GSS_S_COMPLETE;
1675 
1676 badrpc:
1677 	*minor = EBADRPC;
1678 	return GSS_S_FAILURE;
1679 }
1680 
1681 /*
1682  * RFC 1964 3DES support
1683  */
1684 
1685 typedef struct gss_1964_mic_token_desc_struct {
1686 	uint8_t TOK_ID[2];      /* 01 01 */
1687 	uint8_t Sign_Alg[2];
1688 	uint8_t Filler[4];      /* ff ff ff ff */
1689 } gss_1964_mic_token_desc, *gss_1964_mic_token;
1690 
1691 typedef struct gss_1964_wrap_token_desc_struct {
1692 	uint8_t TOK_ID[2];      /* 02 01 */
1693 	uint8_t Sign_Alg[2];
1694 	uint8_t Seal_Alg[2];
1695 	uint8_t Filler[2];      /* ff ff */
1696 } gss_1964_wrap_token_desc, *gss_1964_wrap_token;
1697 
1698 typedef struct gss_1964_delete_token_desc_struct {
1699 	uint8_t TOK_ID[2];      /* 01 02 */
1700 	uint8_t Sign_Alg[2];
1701 	uint8_t Filler[4];      /* ff ff ff ff */
1702 } gss_1964_delete_token_desc, *gss_1964_delete_token;
1703 
1704 typedef struct gss_1964_header_desc_struct {
1705 	uint8_t App0;           /* 0x60 Application 0 constructed */
1706 	uint8_t AppLen[];       /* Variable Der length */
1707 } gss_1964_header_desc, *gss_1964_header;
1708 
1709 typedef union {
1710 	gss_1964_mic_token_desc         mic_tok;
1711 	gss_1964_wrap_token_desc        wrap_tok;
1712 	gss_1964_delete_token_desc      del_tok;
1713 } gss_1964_tok_type __attribute__((transparent_union));
1714 
1715 typedef struct gss_1964_token_body_struct {
1716 	uint8_t OIDType;        /* 0x06 */
1717 	uint8_t OIDLen;         /* 0x09 */
1718 	uint8_t kerb_mech[9];   /* Der Encode kerberos mech 1.2.840.113554.1.2.2
1719 	                         *  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 */
1720 	gss_1964_tok_type body;
1721 	uint8_t SND_SEQ[8];
1722 	uint8_t Hash[];         /* Mic */
1723 } gss_1964_token_body_desc, *gss_1964_token_body;
1724 
1725 
1726 gss_1964_header_desc tok_1964_header = {
1727 	.App0 = 0x60
1728 };
1729 
1730 gss_1964_mic_token_desc mic_1964_token = {
1731 	.TOK_ID = "\x01\x01",
1732 	.Filler = "\xff\xff\xff\xff"
1733 };
1734 
1735 gss_1964_wrap_token_desc wrap_1964_token = {
1736 	.TOK_ID = "\x02\x01",
1737 	.Filler = "\xff\xff"
1738 };
1739 
1740 gss_1964_delete_token_desc del_1964_token = {
1741 	.TOK_ID = "\x01\x01",
1742 	.Filler = "\xff\xff\xff\xff"
1743 };
1744 
1745 gss_1964_token_body_desc body_1964_token = {
1746 	.OIDType = 0x06,
1747 	.OIDLen = 0x09,
1748 	.kerb_mech = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02",
1749 };
1750 
1751 #define GSS_KRB5_3DES_MAXTOKSZ (sizeof(gss_1964_header_desc) + 5 /* max der length supported */ + sizeof(gss_1964_token_body_desc))
1752 
1753 uint32_t gss_krb5_3des_get_mic(uint32_t *, gss_ctx_id_t, gss_qop_t, gss_buffer_t, gss_buffer_t);
1754 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);
1755 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 *);
1756 uint32_t gss_krb5_3des_wrap_mbuf(uint32_t *, gss_ctx_id_t, int, gss_qop_t, mbuf_t *, size_t, int *);
1757 uint32_t gss_krb5_3des_unwrap_mbuf(uint32_t *, gss_ctx_id_t, mbuf_t *, size_t, int *, gss_qop_t *);
1758 
1759 /*
1760  * Decode an ASN.1 DER length field
1761  */
1762 static ssize_t
gss_krb5_der_length_get(uint8_t ** pp)1763 gss_krb5_der_length_get(uint8_t **pp)
1764 {
1765 	uint8_t *p = *pp;
1766 	uint32_t flen, len = 0;
1767 
1768 	flen = *p & 0x7f;
1769 
1770 	if (*p++ & 0x80) {
1771 		if (flen > sizeof(uint32_t)) {
1772 			return -1;
1773 		}
1774 		while (flen--) {
1775 			len = (len << 8) + *p++;
1776 		}
1777 	} else {
1778 		len = flen;
1779 	}
1780 	*pp = p;
1781 	return len;
1782 }
1783 
1784 /*
1785  * Determine size of ASN.1 DER length
1786  */
1787 static int
gss_krb5_der_length_size(size_t len)1788 gss_krb5_der_length_size(size_t len)
1789 {
1790 	return
1791 	        len < (1 <<  7) ? 1 :
1792 	        len < (1 <<  8) ? 2 :
1793 	        len < (1 << 16) ? 3 :
1794 	        len < (1 << 24) ? 4 : 5;
1795 }
1796 
1797 /*
1798  * Encode an ASN.1 DER length field
1799  */
1800 static void
gss_krb5_der_length_put(uint8_t ** pp,size_t len)1801 gss_krb5_der_length_put(uint8_t **pp, size_t len)
1802 {
1803 	int sz = gss_krb5_der_length_size(len);
1804 	uint8_t *p = *pp;
1805 
1806 	if (sz == 1) {
1807 		*p++ = (uint8_t) len;
1808 	} else {
1809 		*p++ = (uint8_t) ((sz - 1) | 0x80);
1810 		sz -= 1;
1811 		while (sz--) {
1812 			*p++ = (uint8_t) ((len >> (sz * 8)) & 0xff);
1813 		}
1814 	}
1815 
1816 	*pp = p;
1817 }
1818 
1819 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)1820 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)
1821 {
1822 	gss_1964_header token;
1823 	gss_1964_token_body tokbody;
1824 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1825 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1826 	uint32_t seq = (uint32_t) (lctx->send_seq++ & 0xffff);
1827 	size_t toklen = sizeof(gss_1964_token_body_desc)  + cctx->digest_size;
1828 	size_t alloclen = toklen + sizeof(gss_1964_header_desc) + gss_krb5_der_length_size(toklen + datalen);
1829 	uint8_t *tokptr;
1830 
1831 	token = kalloc_data(alloclen, Z_WAITOK | Z_ZERO);
1832 	*token = tok_1964_header;
1833 	tokptr = token->AppLen;
1834 	gss_krb5_der_length_put(&tokptr, toklen + datalen);
1835 	tokbody = (gss_1964_token_body)tokptr;
1836 	*tokbody = body_1964_token;  /* Initalize the token body */
1837 	tokbody->body = body;  /* and now set the body to the token type passed in */
1838 	seq = htonl(seq);
1839 	for (int i = 0; i < 4; i++) {
1840 		tokbody->SND_SEQ[i] = (uint8_t)((seq >> (i * 8)) & 0xff);
1841 	}
1842 	for (int i = 4; i < 8; i++) {
1843 		tokbody->SND_SEQ[i] = lctx->initiate ? 0x00 : 0xff;
1844 	}
1845 
1846 	size_t blocksize = cctx->enc_mode->block_size;
1847 	cccbc_iv_decl(blocksize, iv);
1848 	cccbc_ctx_decl(cctx->enc_mode->size, enc_ctx);
1849 	cccbc_set_iv(cctx->enc_mode, iv, hash->value);
1850 	cccbc_init(cctx->enc_mode, enc_ctx, cctx->keylen, cctx->key);
1851 	cccbc_update(cctx->enc_mode, enc_ctx, iv, 1, tokbody->SND_SEQ, tokbody->SND_SEQ);
1852 
1853 	assert(hash->length == cctx->digest_size);
1854 	memcpy(tokbody->Hash, hash->value, hash->length);
1855 	des3_token->length = alloclen;
1856 	des3_token->value = token;
1857 }
1858 
1859 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)1860 gss_krb5_3des_token_get(gss_ctx_id_t ctx, gss_buffer_t intok,
1861     gss_1964_tok_type body, gss_buffer_t hash, size_t *offset, size_t *len, int reverse)
1862 {
1863 	gss_1964_header token = intok->value;
1864 	gss_1964_token_body tokbody;
1865 	lucid_context_t lctx = &ctx->gss_lucid_ctx;
1866 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1867 	ssize_t length;
1868 	size_t toklen;
1869 	uint8_t *tokptr;
1870 	uint32_t seq;
1871 	int initiate;
1872 
1873 	if (token->App0 != tok_1964_header.App0) {
1874 		printf("%s: bad framing\n", __func__);
1875 		printgbuf(__func__, intok);
1876 		return EBADRPC;
1877 	}
1878 	tokptr = token->AppLen;
1879 	length = gss_krb5_der_length_get(&tokptr);
1880 	if (length < 0) {
1881 		printf("%s: invalid length\n", __func__);
1882 		printgbuf(__func__, intok);
1883 		return EBADRPC;
1884 	}
1885 	toklen = sizeof(gss_1964_header_desc) + gss_krb5_der_length_size(length)
1886 	    + sizeof(gss_1964_token_body_desc);
1887 
1888 	if (intok->length < toklen + cctx->digest_size) {
1889 		printf("%s: token to short", __func__);
1890 		printf("toklen = %d, length = %d\n", (int)toklen, (int)length);
1891 		printgbuf(__func__, intok);
1892 		return EBADRPC;
1893 	}
1894 
1895 	if (offset) {
1896 		*offset = toklen + cctx->digest_size;
1897 	}
1898 
1899 	if (len) {
1900 		*len = length - sizeof(gss_1964_token_body_desc) - cctx->digest_size;
1901 	}
1902 
1903 	tokbody = (gss_1964_token_body)tokptr;
1904 	if (tokbody->OIDType != body_1964_token.OIDType ||
1905 	    tokbody->OIDLen != body_1964_token.OIDLen ||
1906 	    memcmp(tokbody->kerb_mech, body_1964_token.kerb_mech, tokbody->OIDLen) != 0) {
1907 		printf("%s: Invalid mechanism\n", __func__);
1908 		printgbuf(__func__, intok);
1909 		return EBADRPC;
1910 	}
1911 	if (memcmp(&tokbody->body, &body, sizeof(gss_1964_tok_type)) != 0) {
1912 		printf("%s: Invalid body\n", __func__);
1913 		printgbuf(__func__, intok);
1914 		return EBADRPC;
1915 	}
1916 	size_t blocksize = cctx->enc_mode->block_size;
1917 	uint8_t *block = tokbody->SND_SEQ;
1918 
1919 	assert(blocksize == sizeof(tokbody->SND_SEQ));
1920 	cccbc_iv_decl(blocksize, iv);
1921 	cccbc_ctx_decl(cctx->dec_mode->size, dec_ctx);
1922 	cccbc_set_iv(cctx->dec_mode, iv, tokbody->Hash);
1923 	cccbc_init(cctx->dec_mode, dec_ctx, cctx->keylen, cctx->key);
1924 	cccbc_update(cctx->dec_mode, dec_ctx, iv, 1, block, block);
1925 
1926 	initiate = lctx->initiate ? (reverse ? 0 : 1) : (reverse ? 1 : 0);
1927 	for (int i = 4; i < 8; i++) {
1928 		if (tokbody->SND_SEQ[i] != (initiate ? 0xff : 0x00)) {
1929 			printf("%s: Invalid des mac\n", __func__);
1930 			printgbuf(__func__, intok);
1931 			return EAUTH;
1932 		}
1933 	}
1934 
1935 	memcpy(&seq, tokbody->SND_SEQ, sizeof(uint32_t));
1936 
1937 	lctx->recv_seq = ntohl(seq);
1938 
1939 	assert(hash->length >= cctx->digest_size);
1940 	memcpy(hash->value, tokbody->Hash, cctx->digest_size);
1941 
1942 	return 0;
1943 }
1944 
1945 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)1946 gss_krb5_3des_get_mic(uint32_t *minor,          /* minor status */
1947     gss_ctx_id_t ctx,                           /* krb5 context id */
1948     gss_qop_t qop __unused,                     /* qop_req (ignored) */
1949     gss_buffer_t mbp,                           /* message buffer in */
1950     gss_buffer_t mic)                           /* mic token out */
1951 {
1952 	gss_1964_mic_token_desc tokbody = mic_1964_token;
1953 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1954 	gss_buffer_desc hash;
1955 	gss_buffer_desc header;
1956 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
1957 
1958 	hash.length = cctx->digest_size;
1959 	hash.value = hashval;
1960 	tokbody.Sign_Alg[0] = 0x04; /* lctx->keydata.lucid_protocol_u.data_1964.sign_alg */
1961 	tokbody.Sign_Alg[1] = 0x00;
1962 	header.length = sizeof(gss_1964_mic_token_desc);
1963 	header.value = &tokbody;
1964 
1965 	/* Hash the data */
1966 	*minor = krb5_mic(cctx, &header, mbp, NULL, hashval, NULL, 0, 0);
1967 	if (*minor) {
1968 		return GSS_S_FAILURE;
1969 	}
1970 
1971 	/* Make the token */
1972 	gss_krb5_3des_token_put(ctx, tokbody, &hash, 0, mic);
1973 
1974 	return GSS_S_COMPLETE;
1975 }
1976 
1977 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)1978 gss_krb5_3des_get_mic_mbuf(uint32_t *minor,
1979     gss_ctx_id_t ctx,
1980     gss_qop_t qop __unused,
1981     mbuf_t mbp,
1982     size_t offset,
1983     size_t len,
1984     gss_buffer_t mic)
1985 {
1986 	gss_1964_mic_token_desc tokbody = mic_1964_token;
1987 	crypto_ctx_t cctx = &ctx->gss_cryptor;
1988 	gss_buffer_desc header;
1989 	gss_buffer_desc hash;
1990 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
1991 
1992 	hash.length = cctx->digest_size;
1993 	hash.value = hashval;
1994 	tokbody.Sign_Alg[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_4121.sign_alg */
1995 	tokbody.Sign_Alg[1] = 0x00;
1996 	header.length = sizeof(gss_1964_mic_token_desc);
1997 	header.value = &tokbody;
1998 
1999 	/* Hash the data */
2000 	*minor = krb5_mic_mbuf(cctx, &header, mbp, offset, len, NULL, hashval, NULL, 0, 0);
2001 	if (*minor) {
2002 		return GSS_S_FAILURE;
2003 	}
2004 
2005 	/* Make the token */
2006 	gss_krb5_3des_token_put(ctx, tokbody, &hash, 0, mic);
2007 
2008 	return GSS_S_COMPLETE;
2009 }
2010 
2011 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)2012 gss_krb5_3des_verify_mic_mbuf(uint32_t *minor,
2013     gss_ctx_id_t ctx,
2014     mbuf_t mbp,
2015     size_t offset,
2016     size_t len,
2017     gss_buffer_t mic,
2018     gss_qop_t *qop)
2019 {
2020 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2021 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2022 	gss_buffer_desc header;
2023 	gss_buffer_desc hash;
2024 	gss_1964_mic_token_desc mtok = mic_1964_token;
2025 	int verf;
2026 
2027 	mtok.Sign_Alg[0] = 0x04; /* lctx->key_data.lucic_protocol_u.data1964.sign_alg */
2028 	mtok.Sign_Alg[1] = 0x00;
2029 	hash.length = cctx->digest_size;
2030 	hash.value = hashval;
2031 	header.length = sizeof(gss_1964_mic_token_desc);
2032 	header.value = &mtok;
2033 
2034 	if (qop) {
2035 		*qop = GSS_C_QOP_DEFAULT;
2036 	}
2037 
2038 	*minor = gss_krb5_3des_token_get(ctx, mic, mtok, &hash, NULL, NULL, 0);
2039 	if (*minor) {
2040 		return GSS_S_FAILURE;
2041 	}
2042 
2043 	*minor = krb5_mic_mbuf(cctx, &header, mbp, offset, len, NULL, hashval, &verf, 0, 0);
2044 	if (*minor) {
2045 		return GSS_S_FAILURE;
2046 	}
2047 
2048 	return verf ? GSS_S_COMPLETE : GSS_S_BAD_SIG;
2049 }
2050 
2051 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)2052 gss_krb5_3des_wrap_mbuf(uint32_t *minor,
2053     gss_ctx_id_t ctx,
2054     int conf_flag,
2055     gss_qop_t qop __unused,
2056     mbuf_t *mbp,
2057     size_t len,
2058     int *conf_state)
2059 {
2060 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2061 	const struct ccmode_cbc *ccmode = cctx->enc_mode;
2062 	uint8_t padlen;
2063 	uint8_t pad[8];
2064 	uint8_t *confounder = NULL;
2065 	gss_1964_wrap_token_desc tokbody = wrap_1964_token;
2066 	gss_buffer_desc header;
2067 	gss_buffer_desc mic;
2068 	gss_buffer_desc hash;
2069 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2070 
2071 	confounder = kalloc_data(ccmode->block_size, Z_WAITOK | Z_ZERO);
2072 	if (confounder == NULL) {
2073 		*minor = ENOMEM;
2074 		goto out;
2075 	}
2076 	if (conf_state) {
2077 		*conf_state = conf_flag;
2078 	}
2079 
2080 	hash.length = cctx->digest_size;
2081 	hash.value = hashval;
2082 	tokbody.Sign_Alg[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_1964.sign_alg */
2083 	tokbody.Sign_Alg[1] = 0x00;
2084 	/* conf_flag ? lctx->key_data.lucid_protocol_u.data_1964.seal_alg : 0xffff */
2085 	tokbody.Seal_Alg[0] = conf_flag ? 0x02 : 0xff;
2086 	tokbody.Seal_Alg[1] = conf_flag ? 0x00 : 0xff;
2087 	header.length = sizeof(gss_1964_wrap_token_desc);
2088 	header.value = &tokbody;
2089 
2090 	/* Prepend confounder */
2091 	assert(ccmode->block_size <= UINT_MAX);
2092 	read_random(confounder, (u_int)ccmode->block_size);
2093 	*minor = gss_prepend_mbuf(mbp, confounder, ccmode->block_size);
2094 	if (*minor) {
2095 		goto out;
2096 	}
2097 
2098 	/* Append trailer of up to 8 bytes and set pad length in each trailer byte */
2099 	padlen = 8 - len % 8;
2100 	for (int i = 0; i < padlen; i++) {
2101 		pad[i] = padlen;
2102 	}
2103 	*minor = gss_append_mbuf(*mbp, pad, padlen);
2104 	if (*minor) {
2105 		goto out;
2106 	}
2107 
2108 	len += ccmode->block_size + padlen;
2109 
2110 	/* Hash the data */
2111 	*minor = krb5_mic_mbuf(cctx, &header, *mbp, 0, len, NULL, hashval, NULL, 0, 0);
2112 	if (*minor) {
2113 		goto out;
2114 	}
2115 
2116 	/* Make the token */
2117 	gss_krb5_3des_token_put(ctx, tokbody, &hash, len, &mic);
2118 
2119 	if (conf_flag) {
2120 		*minor = krb5_crypt_mbuf(cctx, mbp, len, 1, 0);
2121 		if (*minor) {
2122 			goto out;
2123 		}
2124 	}
2125 
2126 	*minor = gss_prepend_mbuf(mbp, mic.value, mic.length);
2127 
2128 out:
2129 	kfree_data(confounder, ccmode->block_size);
2130 	return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
2131 }
2132 
2133 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)2134 gss_krb5_3des_unwrap_mbuf(uint32_t *minor,
2135     gss_ctx_id_t ctx,
2136     mbuf_t *mbp,
2137     size_t len,
2138     int *conf_state,
2139     gss_qop_t *qop)
2140 {
2141 	crypto_ctx_t cctx = &ctx->gss_cryptor;
2142 	const struct ccmode_cbc *ccmode = cctx->dec_mode;
2143 	size_t length = 0, offset = 0;
2144 	gss_buffer_desc hash;
2145 	uint8_t hashval[CRYPTO_MAX_DIGSET_SIZE];
2146 	gss_buffer_desc itoken;
2147 	uint8_t tbuffer[GSS_KRB5_3DES_MAXTOKSZ + CRYPTO_MAX_DIGSET_SIZE];
2148 	itoken.length = GSS_KRB5_3DES_MAXTOKSZ + cctx->digest_size;
2149 	itoken.value = tbuffer;
2150 	gss_1964_wrap_token_desc wrap = wrap_1964_token;
2151 	gss_buffer_desc header;
2152 	uint8_t padlen;
2153 	mbuf_t smb, tmb;
2154 	int cflag, verified, reverse = 0;
2155 
2156 	if (len < GSS_KRB5_3DES_MAXTOKSZ) {
2157 		*minor = EBADRPC;
2158 		return GSS_S_FAILURE;
2159 	}
2160 
2161 	if (*qop == GSS_C_QOP_REVERSE) {
2162 		reverse = 1;
2163 	}
2164 	*qop = GSS_C_QOP_DEFAULT;
2165 
2166 	*minor = mbuf_copydata(*mbp, 0, itoken.length, itoken.value);
2167 	if (*minor) {
2168 		return GSS_S_FAILURE;
2169 	}
2170 
2171 	hash.length = cctx->digest_size;
2172 	hash.value = hashval;
2173 	wrap.Sign_Alg[0] = 0x04;
2174 	wrap.Sign_Alg[1] = 0x00;
2175 	wrap.Seal_Alg[0] = 0x02;
2176 	wrap.Seal_Alg[1] = 0x00;
2177 
2178 	for (cflag = 1; cflag >= 0; cflag--) {
2179 		*minor = gss_krb5_3des_token_get(ctx, &itoken, wrap, &hash, &offset, &length, reverse);
2180 		if (*minor == 0) {
2181 			break;
2182 		}
2183 		wrap.Seal_Alg[0] = 0xff;
2184 		wrap.Seal_Alg[1] = 0xff;
2185 	}
2186 	if (*minor) {
2187 		return GSS_S_FAILURE;
2188 	}
2189 
2190 	if (conf_state) {
2191 		*conf_state = cflag;
2192 	}
2193 
2194 	/*
2195 	 * Seperate off the header
2196 	 */
2197 	*minor = gss_normalize_mbuf(*mbp, offset, &length, &smb, &tmb, 0);
2198 	if (*minor) {
2199 		return GSS_S_FAILURE;
2200 	}
2201 
2202 	assert(tmb == NULL);
2203 
2204 	/* Decrypt the chain if needed */
2205 	if (cflag) {
2206 		*minor = krb5_crypt_mbuf(cctx, &smb, length, 0, NULL);
2207 		if (*minor) {
2208 			return GSS_S_FAILURE;
2209 		}
2210 	}
2211 
2212 	/* Verify the mic */
2213 	header.length = sizeof(gss_1964_wrap_token_desc);
2214 	header.value = &wrap;
2215 
2216 	*minor = krb5_mic_mbuf(cctx, &header, smb, 0, length, NULL, hashval, &verified, 0, 0);
2217 	if (*minor) {
2218 		return GSS_S_FAILURE;
2219 	}
2220 	if (!verified) {
2221 		return GSS_S_BAD_SIG;
2222 	}
2223 
2224 	/* Get the pad bytes */
2225 	*minor = mbuf_copydata(smb, length - 1, 1, &padlen);
2226 	if (*minor) {
2227 		return GSS_S_FAILURE;
2228 	}
2229 
2230 	/* Strip the confounder and trailing pad bytes */
2231 	gss_strip_mbuf(smb, -padlen);
2232 	assert(ccmode->block_size <= INT_MAX);
2233 	gss_strip_mbuf(smb, (int)ccmode->block_size);
2234 
2235 	if (*mbp != smb) {
2236 		mbuf_freem(*mbp);
2237 		*mbp = smb;
2238 	}
2239 
2240 	return GSS_S_COMPLETE;
2241 }
2242 
2243 static const char *
etype_name(etypes etype)2244 etype_name(etypes etype)
2245 {
2246 	switch (etype) {
2247 	case DES3_CBC_SHA1_KD:
2248 		return "des3-cbc-sha1";
2249 	case AES128_CTS_HMAC_SHA1_96:
2250 		return "aes128-cts-hmac-sha1-96";
2251 	case AES256_CTS_HMAC_SHA1_96:
2252 		return "aes-cts-hmac-sha1-96";
2253 	default:
2254 		return "unknown enctype";
2255 	}
2256 }
2257 
2258 static int
supported_etype(uint32_t proto,etypes etype)2259 supported_etype(uint32_t proto, etypes etype)
2260 {
2261 	const char *proto_name;
2262 
2263 	switch (proto) {
2264 	case 0:
2265 		/* RFC 1964 */
2266 		proto_name = "RFC 1964 krb5 gss mech";
2267 		switch (etype) {
2268 		case DES3_CBC_SHA1_KD:
2269 			return 1;
2270 		default:
2271 			break;
2272 		}
2273 		break;
2274 	case 1:
2275 		/* RFC 4121 */
2276 		proto_name = "RFC 4121 krb5 gss mech";
2277 		switch (etype) {
2278 		case AES256_CTS_HMAC_SHA1_96:
2279 		case AES128_CTS_HMAC_SHA1_96:
2280 			return 1;
2281 		default:
2282 			break;
2283 		}
2284 		break;
2285 	default:
2286 		proto_name = "Unknown krb5 gss mech";
2287 		break;
2288 	}
2289 	printf("%s: Non supported encryption %s (%d) type for protocol %s (%d)\n",
2290 	    __func__, etype_name(etype), etype, proto_name, proto);
2291 	return 0;
2292 }
2293 
2294 /*
2295  * Kerberos gss mech entry points
2296  */
2297 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)2298 gss_krb5_get_mic(uint32_t *minor,       /* minor_status */
2299     gss_ctx_id_t ctx,                   /* context_handle */
2300     gss_qop_t qop,                      /* qop_req */
2301     gss_buffer_t mbp,                   /* message buffer */
2302     gss_buffer_t mic /* message_token */)
2303 {
2304 	uint32_t minor_stat = 0;
2305 
2306 	if (minor == NULL) {
2307 		minor = &minor_stat;
2308 	}
2309 	*minor = 0;
2310 
2311 	/* Validate context */
2312 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2313 		return GSS_S_NO_CONTEXT;
2314 	}
2315 
2316 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2317 		*minor = ENOTSUP;
2318 		return GSS_S_FAILURE;
2319 	}
2320 
2321 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2322 	case 0:
2323 		/* RFC 1964 DES3 case */
2324 		return gss_krb5_3des_get_mic(minor, ctx, qop, mbp, mic);
2325 	case 1:
2326 		/* RFC 4121 CFX case */
2327 		return gss_krb5_cfx_get_mic(minor, ctx, qop, mbp, mic);
2328 	}
2329 
2330 	return GSS_S_COMPLETE;
2331 }
2332 
2333 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)2334 gss_krb5_get_mic_mbuf(uint32_t *minor,  /* minor_status */
2335     gss_ctx_id_t ctx,                   /* context_handle */
2336     gss_qop_t qop,                      /* qop_req */
2337     mbuf_t mbp,                         /* message mbuf */
2338     size_t offset,                      /* offest */
2339     size_t len,                         /* length */
2340     gss_buffer_t mic /* message_token */)
2341 {
2342 	uint32_t minor_stat = 0;
2343 
2344 	if (minor == NULL) {
2345 		minor = &minor_stat;
2346 	}
2347 	*minor = 0;
2348 
2349 	if (len == 0) {
2350 		len = ~(size_t)0;
2351 	}
2352 
2353 	/* Validate context */
2354 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2355 		return GSS_S_NO_CONTEXT;
2356 	}
2357 
2358 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2359 		*minor = ENOTSUP;
2360 		return GSS_S_FAILURE;
2361 	}
2362 
2363 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2364 	case 0:
2365 		/* RFC 1964 DES3 case */
2366 		return gss_krb5_3des_get_mic_mbuf(minor, ctx, qop, mbp, offset, len, mic);
2367 	case 1:
2368 		/* RFC 4121 CFX case */
2369 		return gss_krb5_cfx_get_mic_mbuf(minor, ctx, qop, mbp, offset, len, mic);
2370 	}
2371 
2372 	return GSS_S_COMPLETE;
2373 }
2374 
2375 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)2376 gss_krb5_verify_mic_mbuf(uint32_t *minor,               /* minor_status */
2377     gss_ctx_id_t ctx,                                   /* context_handle */
2378     mbuf_t mbp,                                         /* message_buffer */
2379     size_t offset,                              /* offset */
2380     size_t len,                                         /* length */
2381     gss_buffer_t mic,                                   /* message_token */
2382     gss_qop_t *qop /* qop_state */)
2383 {
2384 	uint32_t minor_stat = 0;
2385 	gss_qop_t qop_val = GSS_C_QOP_DEFAULT;
2386 
2387 	if (minor == NULL) {
2388 		minor = &minor_stat;
2389 	}
2390 	if (qop == NULL) {
2391 		qop = &qop_val;
2392 	}
2393 
2394 	*minor = 0;
2395 
2396 	if (len == 0) {
2397 		len = ~(size_t)0;
2398 	}
2399 
2400 	/* Validate context */
2401 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2402 		return GSS_S_NO_CONTEXT;
2403 	}
2404 
2405 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2406 		*minor = ENOTSUP;
2407 		return GSS_S_FAILURE;
2408 	}
2409 
2410 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2411 	case 0:
2412 		/* RFC 1964 DES3 case */
2413 		return gss_krb5_3des_verify_mic_mbuf(minor, ctx, mbp, offset, len, mic, qop);
2414 	case 1:
2415 		/* RFC 4121 CFX case */
2416 		return gss_krb5_cfx_verify_mic_mbuf(minor, ctx, mbp, offset, len, mic, qop);
2417 	}
2418 
2419 	return GSS_S_COMPLETE;
2420 }
2421 
2422 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)2423 gss_krb5_wrap_mbuf(uint32_t *minor,     /* minor_status */
2424     gss_ctx_id_t ctx,                   /* context_handle */
2425     int conf_flag,                      /* conf_req_flag */
2426     gss_qop_t qop,                      /* qop_req */
2427     mbuf_t *mbp,                        /* input/output message_buffer */
2428     size_t offset,                      /* offset */
2429     size_t len,                         /* length */
2430     int *conf_state /* conf state */)
2431 {
2432 	uint32_t major = GSS_S_FAILURE, minor_stat = 0;
2433 	mbuf_t smb, tmb;
2434 	int conf_val = 0;
2435 
2436 	if (minor == NULL) {
2437 		minor = &minor_stat;
2438 	}
2439 	if (conf_state == NULL) {
2440 		conf_state = &conf_val;
2441 	}
2442 
2443 	*minor = 0;
2444 
2445 	/* Validate context */
2446 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2447 		return GSS_S_NO_CONTEXT;
2448 	}
2449 
2450 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2451 		*minor = ENOTSUP;
2452 		return GSS_S_FAILURE;
2453 	}
2454 
2455 	gss_normalize_mbuf(*mbp, offset, &len, &smb, &tmb, 0);
2456 
2457 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2458 	case 0:
2459 		/* RFC 1964 DES3 case */
2460 		major = gss_krb5_3des_wrap_mbuf(minor, ctx, conf_flag, qop, &smb, len, conf_state);
2461 		break;
2462 	case 1:
2463 		/* RFC 4121 CFX case */
2464 		major = gss_krb5_cfx_wrap_mbuf(minor, ctx, conf_flag, qop, &smb, len, conf_state);
2465 		break;
2466 	}
2467 
2468 	if (offset) {
2469 		gss_join_mbuf(*mbp, smb, tmb);
2470 	} else {
2471 		*mbp = smb;
2472 		gss_join_mbuf(smb, tmb, NULL);
2473 	}
2474 
2475 	return major;
2476 }
2477 
2478 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)2479 gss_krb5_unwrap_mbuf(uint32_t * minor,          /* minor_status */
2480     gss_ctx_id_t ctx,                           /* context_handle */
2481     mbuf_t *mbp,                                /* input/output message_buffer */
2482     size_t offset,                              /* offset */
2483     size_t len,                                 /* length */
2484     int *conf_flag,                             /* conf_state */
2485     gss_qop_t *qop /* qop state */)
2486 {
2487 	uint32_t major = GSS_S_FAILURE, minor_stat = 0;
2488 	gss_qop_t qop_val = GSS_C_QOP_DEFAULT;
2489 	int conf_val = 0;
2490 	mbuf_t smb, tmb;
2491 
2492 	if (minor == NULL) {
2493 		minor = &minor_stat;
2494 	}
2495 	if (qop == NULL) {
2496 		qop = &qop_val;
2497 	}
2498 	if (conf_flag == NULL) {
2499 		conf_flag = &conf_val;
2500 	}
2501 
2502 	/* Validate context */
2503 	if (ctx == NULL || ((lucid_context_version_t)ctx)->version != 1) {
2504 		return GSS_S_NO_CONTEXT;
2505 	}
2506 
2507 	if (!supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_cryptor.etype)) {
2508 		*minor = ENOTSUP;
2509 		return GSS_S_FAILURE;
2510 	}
2511 
2512 	gss_normalize_mbuf(*mbp, offset, &len, &smb, &tmb, 0);
2513 
2514 	switch (ctx->gss_lucid_ctx.key_data.proto) {
2515 	case 0:
2516 		/* RFC 1964 DES3 case */
2517 		major = gss_krb5_3des_unwrap_mbuf(minor, ctx, &smb, len, conf_flag, qop);
2518 		break;
2519 	case 1:
2520 		/* RFC 4121 CFX case */
2521 		major = gss_krb5_cfx_unwrap_mbuf(minor, ctx, &smb, len, conf_flag, qop);
2522 		break;
2523 	}
2524 
2525 	if (offset) {
2526 		gss_join_mbuf(*mbp, smb, tmb);
2527 	} else {
2528 		*mbp = smb;
2529 		gss_join_mbuf(smb, tmb, NULL);
2530 	}
2531 
2532 	return major;
2533 }
2534 
2535 #include <nfs/xdr_subs.h>
2536 
2537 static int
xdr_lucid_context(void * data,uint32_t length,lucid_context_t lctx)2538 xdr_lucid_context(void *data, uint32_t length, lucid_context_t lctx)
2539 {
2540 	struct xdrbuf xb;
2541 	int error = 0;
2542 	uint32_t keylen = 0;
2543 
2544 	xb_init_buffer(&xb, data, length);
2545 	xb_get_32(error, &xb, lctx->vers);
2546 	if (!error && lctx->vers != 1) {
2547 		error = EINVAL;
2548 		printf("%s: invalid version %d\n", __func__, (int)lctx->vers);
2549 		goto out;
2550 	}
2551 	xb_get_32(error, &xb, lctx->initiate);
2552 	if (error) {
2553 		printf("%s: Could not decode initiate\n", __func__);
2554 		goto out;
2555 	}
2556 	xb_get_32(error, &xb, lctx->endtime);
2557 	if (error) {
2558 		printf("%s: Could not decode endtime\n", __func__);
2559 		goto out;
2560 	}
2561 	xb_get_64(error, &xb, lctx->send_seq);
2562 	if (error) {
2563 		printf("%s: Could not decode send_seq\n", __func__);
2564 		goto out;
2565 	}
2566 	xb_get_64(error, &xb, lctx->recv_seq);
2567 	if (error) {
2568 		printf("%s: Could not decode recv_seq\n", __func__);
2569 		goto out;
2570 	}
2571 	xb_get_32(error, &xb, lctx->key_data.proto);
2572 	if (error) {
2573 		printf("%s: Could not decode mech protocol\n", __func__);
2574 		goto out;
2575 	}
2576 	switch (lctx->key_data.proto) {
2577 	case 0:
2578 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_1964.sign_alg);
2579 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_1964.seal_alg);
2580 		if (error) {
2581 			printf("%s: Could not decode rfc1964 sign and seal\n", __func__);
2582 		}
2583 		break;
2584 	case 1:
2585 		xb_get_32(error, &xb, lctx->key_data.lucid_protocol_u.data_4121.acceptor_subkey);
2586 		if (error) {
2587 			printf("%s: Could not decode rfc4121 acceptor_subkey", __func__);
2588 		}
2589 		break;
2590 	default:
2591 		printf("%s: Invalid mech protocol %d\n", __func__, (int)lctx->key_data.proto);
2592 		error = EINVAL;
2593 	}
2594 	if (error) {
2595 		goto out;
2596 	}
2597 	xb_get_32(error, &xb, lctx->ctx_key.etype);
2598 	if (error) {
2599 		printf("%s: Could not decode key enctype\n", __func__);
2600 		goto out;
2601 	}
2602 	switch (lctx->ctx_key.etype) {
2603 	case DES3_CBC_SHA1_KD:
2604 		keylen = 24;
2605 		break;
2606 	case AES128_CTS_HMAC_SHA1_96:
2607 		keylen = 16;
2608 		break;
2609 	case AES256_CTS_HMAC_SHA1_96:
2610 		keylen = 32;
2611 		break;
2612 	default:
2613 		error = ENOTSUP;
2614 		goto out;
2615 	}
2616 	xb_get_32(error, &xb, lctx->ctx_key.key.key_len);
2617 	if (error) {
2618 		printf("%s: could not decode key length\n", __func__);
2619 		goto out;
2620 	}
2621 	if (lctx->ctx_key.key.key_len != keylen) {
2622 		error = EINVAL;
2623 		printf("%s: etype = %d keylen = %d expected keylen = %d\n", __func__,
2624 		    lctx->ctx_key.etype, lctx->ctx_key.key.key_len, keylen);
2625 		goto out;
2626 	}
2627 
2628 	lctx->ctx_key.key.key_val = xb_malloc(keylen);
2629 	if (lctx->ctx_key.key.key_val == NULL) {
2630 		printf("%s: could not get memory for key\n", __func__);
2631 		error = ENOMEM;
2632 		goto out;
2633 	}
2634 	error = xb_get_bytes(&xb, (char *)lctx->ctx_key.key.key_val, keylen, 1);
2635 	if (error) {
2636 		printf("%s: could get key value\n", __func__);
2637 		xb_free_size(lctx->ctx_key.key.key_val, keylen);
2638 	}
2639 out:
2640 	return error;
2641 }
2642 
2643 gss_ctx_id_t
gss_krb5_make_context(void * data,uint32_t datalen)2644 gss_krb5_make_context(void *data, uint32_t datalen)
2645 {
2646 	gss_ctx_id_t ctx;
2647 
2648 	if (!corecrypto_available()) {
2649 		return NULL;
2650 	}
2651 
2652 	gss_krb5_mech_init();
2653 	ctx = kalloc_type(struct gss_ctx_id_desc, Z_WAITOK | Z_ZERO);
2654 	if (xdr_lucid_context(data, datalen, &ctx->gss_lucid_ctx) ||
2655 	    !supported_etype(ctx->gss_lucid_ctx.key_data.proto, ctx->gss_lucid_ctx.ctx_key.etype)) {
2656 		kfree_type(struct gss_ctx_id_desc, ctx);
2657 		return NULL;
2658 	}
2659 
2660 	/* Set up crypto context */
2661 	gss_crypto_ctx_init(&ctx->gss_cryptor, &ctx->gss_lucid_ctx);
2662 	return ctx;
2663 }
2664 
2665 void
gss_krb5_destroy_context(gss_ctx_id_t ctx)2666 gss_krb5_destroy_context(gss_ctx_id_t ctx)
2667 {
2668 	if (ctx == NULL) {
2669 		return;
2670 	}
2671 	gss_crypto_ctx_free(&ctx->gss_cryptor);
2672 	xb_free(ctx->gss_lucid_ctx.ctx_key.key.key_val);
2673 	cc_clear(sizeof(lucid_context_t), &ctx->gss_lucid_ctx);
2674 	kfree_type(struct gss_ctx_id_desc, ctx);
2675 }
2676