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