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