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