2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 1999 Kungliga Tekniska Högskolan
31 * (Royal Institute of Technology, Stockholm, Sweden).
32 * All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
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"
74 lck_grp_t
*gss_krb5_mech_grp
;
76 typedef struct crypt_walker_ctx
{
78 const struct ccmode_cbc
*ccmode
;
81 } *crypt_walker_ctx_t
;
83 typedef struct hmac_walker_ctx
{
84 const struct ccdigest_info
*di
;
85 struct cchmac_ctx
*hmac_ctx
;
88 typedef size_t (*ccpad_func
)(const struct ccmode_cbc
*, cccbc_ctx
*, cccbc_iv
*,
89 size_t nbytes
, const void *, void *);
91 static int krb5_n_fold(const void *instr
, size_t len
, void *foldstr
, size_t size
);
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 *);
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);
104 void krb5_make_usage(uint32_t, uint8_t, uint8_t[KRB5_USAGE_LEN
]);
105 void krb5_key_derivation(crypto_ctx_t
, const void *, size_t, void **, size_t);
106 void cc_key_schedule_create(crypto_ctx_t
);
107 void gss_crypto_ctx_free(crypto_ctx_t
);
108 int gss_crypto_ctx_init(struct crypto_ctx
*, lucid_context_t
);
110 errno_t
krb5_crypt_mbuf(crypto_ctx_t
, mbuf_t
*, size_t, int, cccbc_ctx
*);
111 int krb5_mic(crypto_ctx_t
, gss_buffer_t
, gss_buffer_t
, gss_buffer_t
, uint8_t *, int *, int, int);
112 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 uint32_t gss_krb5_cfx_get_mic(uint32_t *, gss_ctx_id_t
, gss_qop_t
, gss_buffer_t
, gss_buffer_t
);
115 uint32_t gss_krb5_cfx_verify_mic(uint32_t *, gss_ctx_id_t
, gss_buffer_t
, gss_buffer_t
, gss_qop_t
*);
116 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
);
117 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
*);
118 errno_t
krb5_cfx_crypt_mbuf(crypto_ctx_t
, mbuf_t
*, size_t *, int, int);
119 uint32_t gss_krb5_cfx_wrap_mbuf(uint32_t *, gss_ctx_id_t
, int, gss_qop_t
, mbuf_t
*, size_t, int *);
120 uint32_t gss_krb5_cfx_unwrap_mbuf(uint32_t *, gss_ctx_id_t
, mbuf_t
*, size_t, int *, gss_qop_t
*);
122 int gss_krb5_mech_is_initialized(void);
123 void gss_krb5_mech_init(void);
125 /* Debugging routines */
127 printmbuf(const char *str
, mbuf_t mb
, uint32_t offset
, uint32_t len
)
132 len
= len
? len
: ~0;
133 printf("%s mbuf = %p offset = %d len = %d:\n", str
? str
: "mbuf", mb
, offset
, len
);
134 for (; mb
&& len
; mb
= mbuf_next(mb
)) {
135 if (offset
>= mbuf_len(mb
)) {
136 offset
-= mbuf_len(mb
);
139 for (i
= offset
; len
&& i
< mbuf_len(mb
); i
++) {
140 const char *s
= (cout
% 8) ? " " : (cout
% 16) ? " " : "\n";
141 printf("%02x%s", ((uint8_t *)mbuf_data(mb
))[i
], s
);
147 if ((cout
- 1) % 16) {
150 printf("Count chars %d\n", cout
- 1);
154 printgbuf(const char *str
, gss_buffer_t buf
)
157 size_t len
= buf
->length
> 128 ? 128 : buf
->length
;
159 printf("%s: len = %d value = %p\n", str
? str
: "buffer", (int)buf
->length
, buf
->value
);
160 for (i
= 0; i
< len
; i
++) {
161 const char *s
= ((i
+ 1) % 8) ? " " : ((i
+ 1) % 16) ? " " : "\n";
162 printf("%02x%s", ((uint8_t *)buf
->value
)[i
], s
);
170 * Initialize the data structures for the gss kerberos mech.
172 #define GSS_KRB5_NOT_INITIALIZED 0
173 #define GSS_KRB5_INITIALIZING 1
174 #define GSS_KRB5_INITIALIZED 2
175 static volatile uint32_t gss_krb5_mech_initted
= GSS_KRB5_NOT_INITIALIZED
;
178 gss_krb5_mech_is_initialized(void)
180 return gss_krb5_mech_initted
== GSS_KRB5_NOT_INITIALIZED
;
184 gss_krb5_mech_init(void)
186 extern void IOSleep(int);
188 /* Once initted always initted */
189 if (gss_krb5_mech_initted
== GSS_KRB5_INITIALIZED
) {
193 /* make sure we init only once */
194 if (!OSCompareAndSwap(GSS_KRB5_NOT_INITIALIZED
, GSS_KRB5_INITIALIZING
, &gss_krb5_mech_initted
)) {
195 /* wait until initialization is complete */
196 while (!gss_krb5_mech_is_initialized()) {
201 gss_krb5_mech_grp
= lck_grp_alloc_init("gss_krb5_mech", LCK_GRP_ATTR_NULL
);
202 gss_krb5_mech_initted
= GSS_KRB5_INITIALIZED
;
206 gss_release_buffer(uint32_t *minor
, gss_buffer_t buf
)
212 FREE(buf
->value
, M_TEMP
);
216 return GSS_S_COMPLETE
;
224 gss_mbuf_len(mbuf_t mb
, size_t offset
)
228 for (len
= 0; mb
; mb
= mbuf_next(mb
)) {
231 return (offset
> len
) ? 0 : len
- offset
;
235 * Split an mbuf in a chain into two mbufs such that the original mbuf
236 * points to the original mbuf and the new mbuf points to the rest of the
237 * chain. The first mbuf length is the first len bytes and the second
238 * mbuf contains the remaining bytes. if len is zero or equals
239 * mbuf_len(mb) the don't create a new mbuf. We are already at an mbuf
240 * boundary. Return the mbuf that starts at the offset.
243 split_one_mbuf(mbuf_t mb
, size_t offset
, mbuf_t
*nmb
, int join
)
248 /* We don't have an mbuf or we're alread on an mbuf boundary */
249 if (mb
== NULL
|| offset
== 0) {
253 /* If the mbuf length is offset then the next mbuf is the one we want */
254 if (mbuf_len(mb
) == offset
) {
255 *nmb
= mbuf_next(mb
);
257 mbuf_setnext(mb
, NULL
);
262 if (offset
> mbuf_len(mb
)) {
266 error
= mbuf_split(mb
, offset
, MBUF_WAITOK
, nmb
);
271 if (mbuf_flags(*nmb
) & MBUF_PKTHDR
) {
272 /* We don't want to copy the pkthdr. mbuf_split does that. */
273 error
= mbuf_setflags_mask(*nmb
, ~MBUF_PKTHDR
, MBUF_PKTHDR
);
277 /* Join the chain again */
278 mbuf_setnext(mb
, *nmb
);
285 * Given an mbuf with an offset and length return the chain such that
286 * offset and offset + *subchain_length are on mbuf boundaries. If
287 * *mbuf_length is less that the length of the chain after offset
288 * return that length in *mbuf_length. The mbuf sub chain starting at
289 * offset is returned in *subchain. If an error occurs return the
290 * corresponding errno. Note if there are less than offset bytes then
291 * subchain will be set to NULL and *subchain_length will be set to
292 * zero. If *subchain_length is 0; then set it to the length of the
293 * chain starting at offset. Join parameter is used to indicate whether
294 * the mbuf chain will be joined again as on chain, just rearranged so
295 * that offset and subchain_length are on mbuf boundaries.
299 gss_normalize_mbuf(mbuf_t chain
, size_t offset
, size_t *subchain_length
, mbuf_t
*subchain
, mbuf_t
*tail
, int join
)
301 size_t length
= *subchain_length
? *subchain_length
: ~0;
312 for (len
= offset
, mb
= chain
; mb
&& len
> mbuf_len(mb
); mb
= mbuf_next(mb
)) {
316 /* if we don't have offset bytes just return */
321 error
= split_one_mbuf(mb
, len
, subchain
, join
);
326 assert(subchain
!= NULL
&& *subchain
!= NULL
);
327 assert(offset
== 0 ? mb
== *subchain
: 1);
329 len
= gss_mbuf_len(*subchain
, 0);
330 length
= (length
> len
) ? len
: length
;
331 *subchain_length
= length
;
333 for (len
= length
, mb
= *subchain
; mb
&& len
> mbuf_len(mb
); mb
= mbuf_next(mb
)) {
337 error
= split_one_mbuf(mb
, len
, tail
, join
);
343 gss_join_mbuf(mbuf_t head
, mbuf_t body
, mbuf_t tail
)
347 for (mb
= head
; mb
&& mbuf_next(mb
); mb
= mbuf_next(mb
)) {
351 mbuf_setnext(mb
, body
);
353 for (mb
= body
; mb
&& mbuf_next(mb
); mb
= mbuf_next(mb
)) {
357 mbuf_setnext(mb
, tail
);
359 mb
= head
? head
: (body
? body
: tail
);
364 * Prepend size bytes to the mbuf chain.
367 gss_prepend_mbuf(mbuf_t
*chain
, uint8_t *bytes
, size_t size
)
369 uint8_t *data
= mbuf_data(*chain
);
370 size_t leading
= mbuf_leadingspace(*chain
);
371 size_t trailing
= mbuf_trailingspace(*chain
);
372 size_t mlen
= mbuf_len(*chain
);
375 if (size
> leading
&& size
<= leading
+ trailing
) {
376 data
= memmove(data
+ size
- leading
, data
, mlen
);
377 mbuf_setdata(*chain
, data
, mlen
);
380 error
= mbuf_prepend(chain
, size
, MBUF_WAITOK
);
384 data
= mbuf_data(*chain
);
385 memcpy(data
, bytes
, size
);
391 gss_append_mbuf(mbuf_t chain
, uint8_t *bytes
, size_t size
)
400 for (mb
= chain
; mb
; mb
= mbuf_next(mb
)) {
404 return mbuf_copyback(chain
, len
, size
, bytes
, MBUF_WAITOK
);
408 gss_strip_mbuf(mbuf_t chain
, int size
)
414 mbuf_adj(chain
, size
);
421 * Kerberos mech generic crypto support for mbufs
425 * Walk the mbuf after the given offset calling the passed in crypto function
426 * for len bytes. Note the length, len should be a multiple of the blocksize and
427 * there should be at least len bytes available after the offset in the mbuf chain.
428 * padding should be done before calling this routine.
431 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
)
434 size_t mlen
, residue
;
438 /* Move to the start of the chain */
439 for (mb
= mbp
; mb
&& len
> 0; mb
= mbuf_next(mb
)) {
442 if (offset
>= mlen
) {
443 /* Offset not yet reached */
447 /* Found starting point in chain */
453 * Handle the data in this mbuf. If the length to
454 * walk is less than the data in the mbuf, set
455 * the mbuf length left to be the length left
457 mlen
= mlen
< len
? mlen
: len
;
458 /* Figure out how much is a multple of blocksize */
459 residue
= mlen
% blocksize
;
460 /* And addjust the mleft length to be the largest multiple of blocksized */
462 /* run our hash/encrypt/decrpyt function */
464 error
= crypto_fn(ctx
, ptr
, mlen
);
472 * If we have a residue then to get a full block for our crypto
473 * function, we need to copy the residue into our block size
474 * block and use the next mbuf to get the rest of the data for
475 * the block. N.B. We generally assume that from the offset
476 * passed in, that the total length, len, is a multple of
477 * blocksize and that there are at least len bytes in the chain
478 * from the offset. We also assume there is at least (blocksize
479 * - residue) size data in any next mbuf for residue > 0. If not
480 * we attemp to pullup bytes from down the chain.
483 mbuf_t nmb
= mbuf_next(mb
);
484 uint8_t *nptr
= NULL
, block
[blocksize
];
488 offset
= blocksize
- residue
;
492 * We don't have enough bytes so zero the block
493 * so that any trailing bytes will be zero.
495 cc_clear(sizeof(block
), block
);
497 memcpy(block
, ptr
, residue
);
499 mlen
= mbuf_len(nmb
);
501 error
= mbuf_pullup(&nmb
, offset
- mlen
);
503 mbuf_setnext(mb
, NULL
);
507 nptr
= mbuf_data(nmb
);
508 memcpy(block
+ residue
, nptr
, offset
);
511 error
= crypto_fn(ctx
, block
, sizeof(block
));
515 memcpy(ptr
, block
, residue
);
517 memcpy(nptr
, block
+ residue
, offset
);
526 do_crypt_init(crypt_walker_ctx_t wctx
, int encrypt
, crypto_ctx_t cctx
, cccbc_ctx
*ks
)
528 memset(wctx
, 0, sizeof(*wctx
));
530 wctx
->ccmode
= encrypt
? cctx
->enc_mode
: cctx
->dec_mode
;
531 wctx
->crypt_ctx
= ks
;
532 MALLOC(wctx
->iv
, cccbc_iv
*, wctx
->ccmode
->block_size
, M_TEMP
, M_WAITOK
| M_ZERO
);
533 cccbc_set_iv(wctx
->ccmode
, wctx
->iv
, NULL
);
537 do_crypt(void *walker
, uint8_t *data
, size_t len
)
539 struct crypt_walker_ctx
*wctx
= (crypt_walker_ctx_t
)walker
;
542 nblocks
= len
/ wctx
->ccmode
->block_size
;
543 assert(len
% wctx
->ccmode
->block_size
== 0);
544 cccbc_update(wctx
->ccmode
, wctx
->crypt_ctx
, wctx
->iv
, nblocks
, data
, data
);
551 do_hmac_init(hmac_walker_ctx_t wctx
, crypto_ctx_t cctx
, void *key
)
553 size_t alloc_size
= cchmac_di_size(cctx
->di
);
556 MALLOC(wctx
->hmac_ctx
, struct cchmac_ctx
*, alloc_size
, M_TEMP
, M_WAITOK
| M_ZERO
);
557 cchmac_init(cctx
->di
, wctx
->hmac_ctx
, cctx
->keylen
, key
);
561 do_hmac(void *walker
, uint8_t *data
, size_t len
)
563 hmac_walker_ctx_t wctx
= (hmac_walker_ctx_t
)walker
;
565 cchmac_update(wctx
->di
, wctx
->hmac_ctx
, len
, data
);
572 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
)
574 uint8_t digest
[ctx
->di
->output_size
];
575 cchmac_di_decl(ctx
->di
, hmac_ctx
);
576 int kdx
= (verify
== NULL
) ? (reverse
? GSS_RCV
: GSS_SND
) : (reverse
? GSS_SND
: GSS_RCV
);
580 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
581 lck_mtx_lock(ctx
->lock
);
582 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
583 cc_key_schedule_create(ctx
);
585 ctx
->flags
|= CRYPTO_KS_ALLOCED
;
586 lck_mtx_unlock(ctx
->lock
);
588 key2use
= ctx
->ks
.ikey
[kdx
];
590 key2use
= ctx
->ckey
[kdx
];
593 cchmac_init(ctx
->di
, hmac_ctx
, ctx
->keylen
, key2use
);
596 cchmac_update(ctx
->di
, hmac_ctx
, header
->length
, header
->value
);
599 cchmac_update(ctx
->di
, hmac_ctx
, bp
->length
, bp
->value
);
602 cchmac_update(ctx
->di
, hmac_ctx
, trailer
->length
, trailer
->value
);
605 cchmac_final(ctx
->di
, hmac_ctx
, digest
);
608 *verify
= (memcmp(mic
, digest
, ctx
->digest_size
) == 0);
610 memcpy(mic
, digest
, ctx
->digest_size
);
617 krb5_mic_mbuf(crypto_ctx_t ctx
, gss_buffer_t header
,
618 mbuf_t mbp
, size_t offset
, size_t len
, gss_buffer_t trailer
, uint8_t *mic
, int *verify
, int ikey
, int reverse
)
620 struct hmac_walker_ctx wctx
;
621 uint8_t digest
[ctx
->di
->output_size
];
623 int kdx
= (verify
== NULL
) ? (reverse
? GSS_RCV
: GSS_SND
) : (reverse
? GSS_SND
: GSS_RCV
);
627 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
628 lck_mtx_lock(ctx
->lock
);
629 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
630 cc_key_schedule_create(ctx
);
632 ctx
->flags
|= CRYPTO_KS_ALLOCED
;
633 lck_mtx_unlock(ctx
->lock
);
635 key2use
= ctx
->ks
.ikey
[kdx
];
637 key2use
= ctx
->ckey
[kdx
];
640 do_hmac_init(&wctx
, ctx
, key2use
);
643 cchmac_update(ctx
->di
, wctx
.hmac_ctx
, header
->length
, header
->value
);
646 error
= mbuf_walk(mbp
, offset
, len
, 1, do_hmac
, &wctx
);
652 cchmac_update(ctx
->di
, wctx
.hmac_ctx
, trailer
->length
, trailer
->value
);
655 cchmac_final(ctx
->di
, wctx
.hmac_ctx
, digest
);
656 FREE(wctx
.hmac_ctx
, M_TEMP
);
659 *verify
= (memcmp(mic
, digest
, ctx
->digest_size
) == 0);
664 memcpy(mic
, digest
, ctx
->digest_size
);
671 /* __attribute__((optnone)) */
672 krb5_crypt_mbuf(crypto_ctx_t ctx
, mbuf_t
*mbp
, size_t len
, int encrypt
, cccbc_ctx
*ks
)
674 struct crypt_walker_ctx wctx
;
675 const struct ccmode_cbc
*ccmode
= encrypt
? ctx
->enc_mode
: ctx
->dec_mode
;
678 mbuf_t mb
, lmb
= NULL
;
681 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
682 lck_mtx_lock(ctx
->lock
);
683 if (!(ctx
->flags
& CRYPTO_KS_ALLOCED
)) {
684 cc_key_schedule_create(ctx
);
686 ctx
->flags
|= CRYPTO_KS_ALLOCED
;
687 lck_mtx_unlock(ctx
->lock
);
690 ks
= encrypt
? ctx
->ks
.enc
: ctx
->ks
.dec
;
693 if ((ctx
->flags
& CRYPTO_CTS_ENABLE
) && ctx
->mpad
== 1) {
694 uint8_t block
[ccmode
->block_size
];
695 /* if the length is less than or equal to a blocksize. We just encrypt the block */
696 if (len
<= ccmode
->block_size
) {
697 if (len
< ccmode
->block_size
) {
698 memset(block
, 0, sizeof(block
));
699 gss_append_mbuf(*mbp
, block
, ccmode
->block_size
);
701 plen
= ccmode
->block_size
;
703 /* determine where the last two blocks are */
704 size_t r
= len
% ccmode
->block_size
;
706 cts_len
= r
? r
+ ccmode
->block_size
: 2 * ccmode
->block_size
;
707 plen
= len
- cts_len
;
708 /* If plen is 0 we only have two blocks to crypt with ccpad below */
712 gss_normalize_mbuf(*mbp
, 0, &plen
, &mb
, &lmb
, 0);
714 assert(plen
== len
- cts_len
);
715 assert(gss_mbuf_len(mb
, 0) == plen
);
716 assert(gss_mbuf_len(lmb
, 0) == cts_len
);
719 } else if (len
% ctx
->mpad
) {
720 uint8_t pad_block
[ctx
->mpad
];
721 size_t padlen
= ctx
->mpad
- (len
% ctx
->mpad
);
723 memset(pad_block
, 0, padlen
);
724 error
= gss_append_mbuf(*mbp
, pad_block
, padlen
);
730 do_crypt_init(&wctx
, encrypt
, ctx
, ks
);
732 error
= mbuf_walk(*mbp
, 0, plen
, ccmode
->block_size
, do_crypt
, &wctx
);
738 if ((ctx
->flags
& CRYPTO_CTS_ENABLE
) && cts_len
) {
739 uint8_t cts_pad
[2 * ccmode
->block_size
];
740 ccpad_func do_ccpad
= encrypt
? ccpad_cts3_encrypt
: ccpad_cts3_decrypt
;
742 assert(cts_len
<= 2 * ccmode
->block_size
&& cts_len
> ccmode
->block_size
);
743 memset(cts_pad
, 0, sizeof(cts_pad
));
744 mbuf_copydata(lmb
, 0, cts_len
, cts_pad
);
746 do_ccpad(ccmode
, wctx
.crypt_ctx
, wctx
.iv
, cts_len
, cts_pad
, cts_pad
);
747 gss_append_mbuf(*mbp
, cts_pad
, cts_len
);
749 FREE(wctx
.iv
, M_TEMP
);
755 * Key derivation routines
759 rr13(unsigned char *buf
, size_t len
)
761 size_t bytes
= (len
+ 7) / 8;
762 unsigned char tmp
[bytes
];
770 const int bits
= 13 % len
;
771 const int lbit
= len
% 8;
773 memcpy(tmp
, buf
, bytes
);
775 /* pad final byte with inital bits */
776 tmp
[bytes
- 1] &= 0xff << (8 - lbit
);
777 for (i
= lbit
; i
< 8; i
+= len
) {
778 tmp
[bytes
- 1] |= buf
[0] >> i
;
781 for (i
= 0; i
< bytes
; i
++) {
783 ssize_t b1
, s1
, b2
, s2
;
785 /* calculate first bit position of this byte */
790 /* byte offset and shift count */
793 if ((size_t)bb
+ 8 > bytes
* 8) {
794 /* watch for wraparound */
795 s2
= (len
+ 8 - s1
) % 8;
799 b2
= (b1
+ 1) % bytes
;
800 buf
[i
] = 0xff & ((tmp
[b1
] << s1
) | (tmp
[b2
] >> s2
));
807 /* Add `b' to `a', both being one's complement numbers. */
809 add1(unsigned char *a
, unsigned char *b
, size_t len
)
814 for (i
= len
- 1; i
>= 0; i
--) {
815 int x
= a
[i
] + b
[i
] + carry
;
819 for (i
= len
- 1; carry
&& i
>= 0; i
--) {
820 int x
= a
[i
] + carry
;
828 krb5_n_fold(const void *instr
, size_t len
, void *foldstr
, size_t size
)
830 /* if len < size we need at most N * len bytes, ie < 2 * size;
831 * if len > size we need at most 2 * len */
833 size_t maxlen
= 2 * lmax(size
, len
);
835 unsigned char tmp
[maxlen
];
836 unsigned char buf
[len
];
838 memcpy(buf
, instr
, len
);
839 memset(foldstr
, 0, size
);
841 memcpy(tmp
+ l
, buf
, len
);
843 ret
= rr13(buf
, len
* 8);
848 add1(foldstr
, tmp
, size
);
853 memmove(tmp
, tmp
+ size
, l
);
862 krb5_make_usage(uint32_t usage_no
, uint8_t suffix
, uint8_t usage_string
[KRB5_USAGE_LEN
])
866 for (i
= 0; i
< 4; i
++) {
867 usage_string
[i
] = ((usage_no
>> 8 * (3 - i
)) & 0xff);
869 usage_string
[i
] = suffix
;
873 krb5_key_derivation(crypto_ctx_t ctx
, const void *cons
, size_t conslen
, void **dkey
, size_t dklen
)
875 size_t blocksize
= ctx
->enc_mode
->block_size
;
876 cccbc_iv_decl(blocksize
, iv
);
877 cccbc_ctx_decl(ctx
->enc_mode
->size
, enc_ctx
);
878 size_t ksize
= 8 * dklen
;
879 size_t nblocks
= (ksize
+ 8 * blocksize
- 1) / (8 * blocksize
);
881 uint8_t block
[blocksize
];
883 MALLOC(*dkey
, void *, nblocks
* blocksize
, M_TEMP
, M_WAITOK
| M_ZERO
);
886 krb5_n_fold(cons
, conslen
, block
, blocksize
);
887 cccbc_init(ctx
->enc_mode
, enc_ctx
, ctx
->keylen
, ctx
->key
);
888 for (size_t i
= 0; i
< nblocks
; i
++) {
889 cccbc_set_iv(ctx
->enc_mode
, iv
, NULL
);
890 cccbc_update(ctx
->enc_mode
, enc_ctx
, iv
, 1, block
, block
);
891 memcpy(dkptr
, block
, blocksize
);
897 des_make_key(const uint8_t rawkey
[7], uint8_t deskey
[8])
901 memcpy(deskey
, rawkey
, 7);
902 for (int i
= 0; i
< 7; i
++) {
903 val
|= ((deskey
[i
] & 1) << (i
+ 1));
906 ccdes_key_set_odd_parity(deskey
, 8);
910 krb5_3des_key_derivation(crypto_ctx_t ctx
, const void *cons
, size_t conslen
, void **des3key
)
912 const struct ccmode_cbc
*cbcmode
= ctx
->enc_mode
;
914 uint8_t *kptr
, *rptr
;
916 MALLOC(*des3key
, void *, 3 * cbcmode
->block_size
, M_TEMP
, M_WAITOK
| M_ZERO
);
917 krb5_key_derivation(ctx
, cons
, conslen
, &rawkey
, 3 * (cbcmode
->block_size
- 1));
918 kptr
= (uint8_t *)*des3key
;
919 rptr
= (uint8_t *)rawkey
;
921 for (int i
= 0; i
< 3; i
++) {
922 des_make_key(rptr
, kptr
);
923 rptr
+= cbcmode
->block_size
- 1;
924 kptr
+= cbcmode
->block_size
;
927 cc_clear(3 * (cbcmode
->block_size
- 1), rawkey
);
928 FREE(rawkey
, M_TEMP
);
932 * Create a key schecule
936 cc_key_schedule_create(crypto_ctx_t ctx
)
938 uint8_t usage_string
[KRB5_USAGE_LEN
];
939 lucid_context_t lctx
= ctx
->gss_ctx
;
942 switch (lctx
->key_data
.proto
) {
944 if (ctx
->ks
.enc
== NULL
) {
945 MALLOC(ctx
->ks
.enc
, cccbc_ctx
*, ctx
->enc_mode
->size
, M_TEMP
, M_WAITOK
| M_ZERO
);
946 cccbc_init(ctx
->enc_mode
, ctx
->ks
.enc
, ctx
->keylen
, ctx
->key
);
948 if (ctx
->ks
.dec
== NULL
) {
949 MALLOC(ctx
->ks
.dec
, cccbc_ctx
*, ctx
->dec_mode
->size
, M_TEMP
, M_WAITOK
| M_ZERO
);
950 cccbc_init(ctx
->dec_mode
, ctx
->ks
.dec
, ctx
->keylen
, ctx
->key
);
955 if (ctx
->ks
.enc
== NULL
) {
956 krb5_make_usage(lctx
->initiate
?
957 KRB5_USAGE_INITIATOR_SEAL
: KRB5_USAGE_ACCEPTOR_SEAL
,
959 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ekey
, ctx
->keylen
);
960 MALLOC(ctx
->ks
.enc
, cccbc_ctx
*, ctx
->enc_mode
->size
, M_TEMP
, M_WAITOK
| M_ZERO
);
961 cccbc_init(ctx
->enc_mode
, ctx
->ks
.enc
, ctx
->keylen
, ekey
);
964 if (ctx
->ks
.dec
== NULL
) {
965 krb5_make_usage(lctx
->initiate
?
966 KRB5_USAGE_ACCEPTOR_SEAL
: KRB5_USAGE_INITIATOR_SEAL
,
968 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ekey
, ctx
->keylen
);
969 MALLOC(ctx
->ks
.dec
, cccbc_ctx
*, ctx
->dec_mode
->size
, M_TEMP
, M_WAITOK
| M_ZERO
);
970 cccbc_init(ctx
->dec_mode
, ctx
->ks
.dec
, ctx
->keylen
, ekey
);
973 if (ctx
->ks
.ikey
[GSS_SND
] == NULL
) {
974 krb5_make_usage(lctx
->initiate
?
975 KRB5_USAGE_INITIATOR_SEAL
: KRB5_USAGE_ACCEPTOR_SEAL
,
977 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ks
.ikey
[GSS_SND
], ctx
->keylen
);
979 if (ctx
->ks
.ikey
[GSS_RCV
] == NULL
) {
980 krb5_make_usage(lctx
->initiate
?
981 KRB5_USAGE_ACCEPTOR_SEAL
: KRB5_USAGE_INITIATOR_SEAL
,
983 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ks
.ikey
[GSS_RCV
], ctx
->keylen
);
990 gss_crypto_ctx_free(crypto_ctx_t ctx
)
992 ctx
->ks
.ikey
[GSS_SND
] = NULL
;
993 if (ctx
->ks
.ikey
[GSS_RCV
] && ctx
->key
!= ctx
->ks
.ikey
[GSS_RCV
]) {
994 cc_clear(ctx
->keylen
, ctx
->ks
.ikey
[GSS_RCV
]);
995 FREE(ctx
->ks
.ikey
[GSS_RCV
], M_TEMP
);
997 ctx
->ks
.ikey
[GSS_RCV
] = NULL
;
999 cccbc_ctx_clear(ctx
->enc_mode
->size
, ctx
->ks
.enc
);
1000 FREE(ctx
->ks
.enc
, M_TEMP
);
1004 cccbc_ctx_clear(ctx
->dec_mode
->size
, ctx
->ks
.dec
);
1005 FREE(ctx
->ks
.dec
, M_TEMP
);
1008 if (ctx
->ckey
[GSS_SND
] && ctx
->ckey
[GSS_SND
] != ctx
->key
) {
1009 cc_clear(ctx
->keylen
, ctx
->ckey
[GSS_SND
]);
1010 FREE(ctx
->ckey
[GSS_SND
], M_TEMP
);
1012 ctx
->ckey
[GSS_SND
] = NULL
;
1013 if (ctx
->ckey
[GSS_RCV
] && ctx
->ckey
[GSS_RCV
] != ctx
->key
) {
1014 cc_clear(ctx
->keylen
, ctx
->ckey
[GSS_RCV
]);
1015 FREE(ctx
->ckey
[GSS_RCV
], M_TEMP
);
1017 ctx
->ckey
[GSS_RCV
] = NULL
;
1023 gss_crypto_ctx_init(struct crypto_ctx
*ctx
, lucid_context_t lucid
)
1025 ctx
->gss_ctx
= lucid
;
1027 uint8_t usage_string
[KRB5_USAGE_LEN
];
1029 ctx
->keylen
= ctx
->gss_ctx
->ctx_key
.key
.key_len
;
1030 key
= ctx
->gss_ctx
->ctx_key
.key
.key_val
;
1031 ctx
->etype
= ctx
->gss_ctx
->ctx_key
.etype
;
1034 switch (ctx
->etype
) {
1035 case AES128_CTS_HMAC_SHA1_96
:
1036 case AES256_CTS_HMAC_SHA1_96
:
1037 ctx
->enc_mode
= ccaes_cbc_encrypt_mode();
1038 assert(ctx
->enc_mode
);
1039 ctx
->dec_mode
= ccaes_cbc_decrypt_mode();
1040 assert(ctx
->dec_mode
);
1043 ctx
->di
= ccsha1_di();
1045 ctx
->flags
= CRYPTO_CTS_ENABLE
;
1047 ctx
->digest_size
= 12; /* 96 bits */
1048 krb5_make_usage(ctx
->gss_ctx
->initiate
?
1049 KRB5_USAGE_INITIATOR_SIGN
: KRB5_USAGE_ACCEPTOR_SIGN
,
1050 0x99, usage_string
);
1051 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ckey
[GSS_SND
], ctx
->keylen
);
1052 krb5_make_usage(ctx
->gss_ctx
->initiate
?
1053 KRB5_USAGE_ACCEPTOR_SIGN
: KRB5_USAGE_INITIATOR_SIGN
,
1054 0x99, usage_string
);
1055 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ckey
[GSS_RCV
], ctx
->keylen
);
1057 case DES3_CBC_SHA1_KD
:
1058 ctx
->enc_mode
= ccdes3_cbc_encrypt_mode();
1059 assert(ctx
->enc_mode
);
1060 ctx
->dec_mode
= ccdes3_cbc_decrypt_mode();
1061 assert(ctx
->dec_mode
);
1062 ctx
->ks
.ikey
[GSS_SND
] = ctx
->key
;
1063 ctx
->ks
.ikey
[GSS_RCV
] = ctx
->key
;
1064 ctx
->di
= ccsha1_di();
1067 ctx
->mpad
= ctx
->enc_mode
->block_size
;
1068 ctx
->digest_size
= 20; /* 160 bits */
1069 krb5_make_usage(KRB5_USAGE_ACCEPTOR_SIGN
, 0x99, usage_string
);
1070 krb5_3des_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ckey
[GSS_SND
]);
1071 krb5_3des_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ctx
->ckey
[GSS_RCV
]);
1077 ctx
->lock
= lck_mtx_alloc_init(gss_krb5_mech_grp
, LCK_ATTR_NULL
);
1083 * CFX gss support routines
1085 /* From Heimdal cfx.h file RFC 4121 Cryptoo framework extensions */
1086 typedef struct gss_cfx_mic_token_desc_struct
{
1087 uint8_t TOK_ID
[2]; /* 04 04 */
1091 } gss_cfx_mic_token_desc
, *gss_cfx_mic_token
;
1093 typedef struct gss_cfx_wrap_token_desc_struct
{
1094 uint8_t TOK_ID
[2]; /* 05 04 */
1100 } gss_cfx_wrap_token_desc
, *gss_cfx_wrap_token
;
1102 /* End of cfx.h file */
1104 #define CFXSentByAcceptor (1 << 0)
1105 #define CFXSealed (1 << 1)
1106 #define CFXAcceptorSubkey (1 << 2)
1108 const gss_cfx_mic_token_desc mic_cfx_token
= {
1109 .TOK_ID
= "\x04\x04",
1111 .Filler
= "\xff\xff\xff\xff\xff",
1112 .SND_SEQ
= "\x00\x00\x00\x00\x00\x00\x00\x00"
1115 const gss_cfx_wrap_token_desc wrap_cfx_token
= {
1116 .TOK_ID
= "\x05\04",
1121 .SND_SEQ
= "\x00\x00\x00\x00\x00\x00\x00\x00"
1125 gss_krb5_cfx_verify_mic_token(gss_ctx_id_t ctx
, gss_cfx_mic_token token
)
1128 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1131 if (token
->TOK_ID
[0] != mic_cfx_token
.TOK_ID
[0] || token
->TOK_ID
[1] != mic_cfx_token
.TOK_ID
[1]) {
1132 printf("Bad mic TOK_ID %x %x\n", token
->TOK_ID
[0], token
->TOK_ID
[1]);
1135 if (lctx
->initiate
) {
1136 flags
|= CFXSentByAcceptor
;
1138 if (lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
) {
1139 flags
|= CFXAcceptorSubkey
;
1141 if (token
->Flags
!= flags
) {
1142 printf("Bad flags received %x exptect %x\n", token
->Flags
, flags
);
1145 for (i
= 0; i
< 5; i
++) {
1146 if (token
->Filler
[i
] != mic_cfx_token
.Filler
[i
]) {
1152 printf("Bad mic filler %x @ %d\n", token
->Filler
[i
], i
);
1160 gss_krb5_cfx_get_mic(uint32_t *minor
, /* minor_status */
1161 gss_ctx_id_t ctx
, /* context_handle */
1162 gss_qop_t qop __unused
, /* qop_req (ignored) */
1163 gss_buffer_t mbp
, /* message mbuf */
1164 gss_buffer_t mic
/* message_token */)
1166 gss_cfx_mic_token_desc token
;
1167 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1168 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1169 gss_buffer_desc header
;
1171 uint64_t seq
= htonll(lctx
->send_seq
);
1173 if (minor
== NULL
) {
1177 token
= mic_cfx_token
;
1178 mic
->length
= sizeof(token
) + cctx
->digest_size
;
1179 MALLOC(mic
->value
, void *, mic
->length
, M_TEMP
, M_WAITOK
| M_ZERO
);
1180 if (!lctx
->initiate
) {
1181 token
.Flags
|= CFXSentByAcceptor
;
1183 if (lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
) {
1184 token
.Flags
|= CFXAcceptorSubkey
;
1186 memcpy(&token
.SND_SEQ
, &seq
, sizeof(lctx
->send_seq
));
1187 lctx
->send_seq
++; //XXX should only update this below on success? Heimdal seems to do it this way
1188 header
.value
= &token
;
1189 header
.length
= sizeof(gss_cfx_mic_token_desc
);
1191 *minor
= krb5_mic(cctx
, NULL
, mbp
, &header
, (uint8_t *)mic
->value
+ sizeof(token
), NULL
, 0, 0);
1195 FREE(mic
->value
, M_TEMP
);
1198 memcpy(mic
->value
, &token
, sizeof(token
));
1201 return *minor
? GSS_S_FAILURE
: GSS_S_COMPLETE
;
1205 gss_krb5_cfx_verify_mic(uint32_t *minor
, /* minor_status */
1206 gss_ctx_id_t ctx
, /* context_handle */
1207 gss_buffer_t mbp
, /* message_buffer */
1208 gss_buffer_t mic
, /* message_token */
1209 gss_qop_t
*qop
/* qop_state */)
1211 gss_cfx_mic_token token
= mic
->value
;
1212 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1213 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1214 uint8_t *digest
= (uint8_t *)mic
->value
+ sizeof(gss_cfx_mic_token_desc
);
1218 gss_buffer_desc header
;
1221 *qop
= GSS_C_QOP_DEFAULT
;
1223 if (minor
== NULL
) {
1227 if (mic
->length
!= sizeof(gss_cfx_mic_token_desc
) + cctx
->digest_size
) {
1228 printf("mic token wrong length\n");
1232 *minor
= gss_krb5_cfx_verify_mic_token(ctx
, token
);
1234 return GSS_S_FAILURE
;
1236 header
.value
= token
;
1237 header
.length
= sizeof(gss_cfx_mic_token_desc
);
1238 *minor
= krb5_mic(cctx
, NULL
, mbp
, &header
, digest
, &verified
, 0, 0);
1241 //XXX errors and such? Sequencing and replay? Not supported in RPCSEC_GSS
1242 memcpy(&seq
, token
->SND_SEQ
, sizeof(uint64_t));
1244 lctx
->recv_seq
= seq
;
1248 return verified
? GSS_S_COMPLETE
: GSS_S_BAD_SIG
;
1252 gss_krb5_cfx_get_mic_mbuf(uint32_t *minor
, /* minor_status */
1253 gss_ctx_id_t ctx
, /* context_handle */
1254 gss_qop_t qop __unused
, /* qop_req (ignored) */
1255 mbuf_t mbp
, /* message mbuf */
1256 size_t offset
, /* offest */
1257 size_t len
, /* length */
1258 gss_buffer_t mic
/* message_token */)
1260 gss_cfx_mic_token_desc token
;
1261 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1262 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1264 uint64_t seq
= htonll(lctx
->send_seq
);
1265 gss_buffer_desc header
;
1267 if (minor
== NULL
) {
1272 token
= mic_cfx_token
;
1273 mic
->length
= sizeof(token
) + cctx
->digest_size
;
1274 MALLOC(mic
->value
, void *, mic
->length
, M_TEMP
, M_WAITOK
| M_ZERO
);
1275 if (!lctx
->initiate
) {
1276 token
.Flags
|= CFXSentByAcceptor
;
1278 if (lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
) {
1279 token
.Flags
|= CFXAcceptorSubkey
;
1282 memcpy(&token
.SND_SEQ
, &seq
, sizeof(lctx
->send_seq
));
1283 lctx
->send_seq
++; //XXX should only update this below on success? Heimdal seems to do it this way
1285 header
.length
= sizeof(token
);
1286 header
.value
= &token
;
1288 len
= len
? len
: gss_mbuf_len(mbp
, offset
);
1289 *minor
= krb5_mic_mbuf(cctx
, NULL
, mbp
, offset
, len
, &header
, (uint8_t *)mic
->value
+ sizeof(token
), NULL
, 0, 0);
1293 FREE(mic
->value
, M_TEMP
);
1296 memcpy(mic
->value
, &token
, sizeof(token
));
1299 return *minor
? GSS_S_FAILURE
: GSS_S_COMPLETE
;
1304 gss_krb5_cfx_verify_mic_mbuf(uint32_t *minor
, /* minor_status */
1305 gss_ctx_id_t ctx
, /* context_handle */
1306 mbuf_t mbp
, /* message_buffer */
1307 size_t offset
, /* offset */
1308 size_t len
, /* length */
1309 gss_buffer_t mic
, /* message_token */
1310 gss_qop_t
*qop
/* qop_state */)
1312 gss_cfx_mic_token token
= mic
->value
;
1313 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1314 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1315 uint8_t *digest
= (uint8_t *)mic
->value
+ sizeof(gss_cfx_mic_token_desc
);
1319 gss_buffer_desc header
;
1322 *qop
= GSS_C_QOP_DEFAULT
;
1325 if (minor
== NULL
) {
1329 *minor
= gss_krb5_cfx_verify_mic_token(ctx
, token
);
1331 return GSS_S_FAILURE
;
1334 header
.length
= sizeof(gss_cfx_mic_token_desc
);
1335 header
.value
= mic
->value
;
1337 *minor
= krb5_mic_mbuf(cctx
, NULL
, mbp
, offset
, len
, &header
, digest
, &verified
, 0, 0);
1339 return GSS_S_FAILURE
;
1342 //XXX errors and such? Sequencing and replay? Not Supported RPCSEC_GSS
1343 memcpy(&seq
, token
->SND_SEQ
, sizeof(uint64_t));
1345 lctx
->recv_seq
= seq
;
1347 return verified
? GSS_S_COMPLETE
: GSS_S_BAD_SIG
;
1351 krb5_cfx_crypt_mbuf(crypto_ctx_t ctx
, mbuf_t
*mbp
, size_t *len
, int encrypt
, int reverse
)
1353 const struct ccmode_cbc
*ccmode
= encrypt
? ctx
->enc_mode
: ctx
->dec_mode
;
1354 uint8_t confounder
[ccmode
->block_size
];
1355 uint8_t digest
[ctx
->digest_size
];
1360 assert(ccmode
->block_size
<= UINT_MAX
);
1361 read_random(confounder
, (u_int
)ccmode
->block_size
);
1362 error
= gss_prepend_mbuf(mbp
, confounder
, ccmode
->block_size
);
1366 tlen
= *len
+ ccmode
->block_size
;
1367 if (ctx
->mpad
> 1) {
1368 r
= ctx
->mpad
- (tlen
% ctx
->mpad
);
1370 /* We expect that r == 0 from krb5_cfx_wrap */
1374 error
= gss_append_mbuf(*mbp
, mpad
, r
);
1380 error
= krb5_mic_mbuf(ctx
, NULL
, *mbp
, 0, tlen
, NULL
, digest
, NULL
, 1, 0);
1384 error
= krb5_crypt_mbuf(ctx
, mbp
, tlen
, 1, NULL
);
1388 error
= gss_append_mbuf(*mbp
, digest
, ctx
->digest_size
);
1392 *len
= tlen
+ ctx
->digest_size
;
1396 cccbc_ctx
*ks
= NULL
;
1398 if (*len
< ctx
->digest_size
+ sizeof(confounder
)) {
1401 tlen
= *len
- ctx
->digest_size
;
1402 /* get the digest */
1403 error
= mbuf_copydata(*mbp
, tlen
, ctx
->digest_size
, digest
);
1404 /* Remove the digest from the mbuffer */
1405 error
= gss_strip_mbuf(*mbp
, -ctx
->digest_size
);
1412 * Derive a key schedule that the sender can unwrap with. This
1413 * is so that RPCSEC_GSS can restore encrypted arguments for
1414 * resending. We do that because the RPCSEC_GSS sequence number in
1415 * the rpc header is prepended to the body of the message before wrapping.
1418 uint8_t usage_string
[KRB5_USAGE_LEN
];
1419 lucid_context_t lctx
= ctx
->gss_ctx
;
1421 krb5_make_usage(lctx
->initiate
?
1422 KRB5_USAGE_INITIATOR_SEAL
: KRB5_USAGE_ACCEPTOR_SEAL
,
1423 0xAA, usage_string
);
1424 krb5_key_derivation(ctx
, usage_string
, KRB5_USAGE_LEN
, &ekey
, ctx
->keylen
);
1425 MALLOC(ks
, cccbc_ctx
*, ctx
->dec_mode
->size
, M_TEMP
, M_WAITOK
| M_ZERO
);
1426 cccbc_init(ctx
->dec_mode
, ks
, ctx
->keylen
, ekey
);
1429 error
= krb5_crypt_mbuf(ctx
, mbp
, tlen
, 0, ks
);
1434 error
= krb5_mic_mbuf(ctx
, NULL
, *mbp
, 0, tlen
, NULL
, digest
, &verf
, 1, reverse
);
1441 /* strip off the confounder */
1442 assert(ccmode
->block_size
<= INT_MAX
);
1443 error
= gss_strip_mbuf(*mbp
, (int)ccmode
->block_size
);
1447 *len
= tlen
- ccmode
->block_size
;
1453 gss_krb5_cfx_wrap_mbuf(uint32_t *minor
, /* minor_status */
1454 gss_ctx_id_t ctx
, /* context_handle */
1455 int conf_flag
, /* conf_req_flag */
1456 gss_qop_t qop __unused
, /* qop_req */
1457 mbuf_t
*mbp
, /* input/output message_buffer */
1458 size_t len
, /* mbuf chain length */
1459 int *conf
/* conf_state */)
1461 gss_cfx_wrap_token_desc token
;
1462 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1463 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1466 uint64_t seq
= htonll(lctx
->send_seq
);
1468 if (minor
== NULL
) {
1476 token
= wrap_cfx_token
;
1477 if (!lctx
->initiate
) {
1478 token
.Flags
|= CFXSentByAcceptor
;
1480 if (lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
) {
1481 token
.Flags
|= CFXAcceptorSubkey
;
1483 memcpy(&token
.SND_SEQ
, &seq
, sizeof(uint64_t));
1486 uint8_t pad
[cctx
->mpad
];
1489 token
.Flags
|= CFXSealed
;
1490 memset(pad
, 0, cctx
->mpad
);
1491 if (cctx
->mpad
> 1) {
1492 size_t val
= cctx
->mpad
- ((len
+ sizeof(gss_cfx_wrap_token_desc
)) % cctx
->mpad
);
1493 plen
= sizeof(val
) > sizeof(uint32_t) ? htonll(val
) : htonl(val
);
1494 token
.EC
[0] = ((plen
>> 8) & 0xff);
1495 token
.EC
[1] = (plen
& 0xff);
1498 error
= gss_append_mbuf(*mbp
, pad
, plen
);
1502 error
= gss_append_mbuf(*mbp
, (uint8_t *)&token
, sizeof(gss_cfx_wrap_token_desc
));
1503 len
+= sizeof(gss_cfx_wrap_token_desc
);
1506 error
= krb5_cfx_crypt_mbuf(cctx
, mbp
, &len
, 1, 0);
1509 error
= gss_prepend_mbuf(mbp
, (uint8_t *)&token
, sizeof(gss_cfx_wrap_token_desc
));
1512 uint8_t digest
[cctx
->digest_size
];
1513 gss_buffer_desc header
;
1515 header
.length
= sizeof(token
);
1516 header
.value
= &token
;
1518 error
= krb5_mic_mbuf(cctx
, NULL
, *mbp
, 0, len
, &header
, digest
, NULL
, 1, 0);
1520 error
= gss_append_mbuf(*mbp
, digest
, cctx
->digest_size
);
1522 uint32_t plen
= htonl(cctx
->digest_size
);
1523 memcpy(token
.EC
, &plen
, 2);
1524 error
= gss_prepend_mbuf(mbp
, (uint8_t *)&token
, sizeof(gss_cfx_wrap_token_desc
));
1530 return GSS_S_FAILURE
;
1533 return GSS_S_COMPLETE
;
1537 * Given a wrap token the has a rrc, move the trailer back to the end.
1540 gss_krb5_cfx_unwrap_rrc_mbuf(mbuf_t header
, size_t rrc
)
1542 mbuf_t body
, trailer
;
1544 gss_normalize_mbuf(header
, sizeof(gss_cfx_wrap_token_desc
), &rrc
, &trailer
, &body
, 0);
1545 gss_join_mbuf(header
, body
, trailer
);
1549 gss_krb5_cfx_unwrap_mbuf(uint32_t * minor
, /* minor_status */
1550 gss_ctx_id_t ctx
, /* context_handle */
1551 mbuf_t
*mbp
, /* input/output message_buffer */
1552 size_t len
, /* mbuf chain length */
1553 int *conf_flag
, /* conf_state */
1554 gss_qop_t
*qop
/* qop state */)
1556 gss_cfx_wrap_token_desc token
;
1557 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1558 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1560 uint32_t ec
= 0, rrc
= 0;
1562 int reverse
= (*qop
== GSS_C_QOP_REVERSE
);
1563 int initiate
= lctx
->initiate
? (reverse
? 0 : 1) : (reverse
? 1 : 0);
1565 error
= mbuf_copydata(*mbp
, 0, sizeof(gss_cfx_wrap_token_desc
), &token
);
1566 gss_strip_mbuf(*mbp
, sizeof(gss_cfx_wrap_token_desc
));
1567 len
-= sizeof(gss_cfx_wrap_token_desc
);
1569 /* Check for valid token */
1570 if (token
.TOK_ID
[0] != wrap_cfx_token
.TOK_ID
[0] ||
1571 token
.TOK_ID
[1] != wrap_cfx_token
.TOK_ID
[1] ||
1572 token
.Filler
!= wrap_cfx_token
.Filler
) {
1573 printf("Token id does not match\n");
1576 if ((initiate
&& !(token
.Flags
& CFXSentByAcceptor
)) ||
1577 (lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
&& !(token
.Flags
& CFXAcceptorSubkey
))) {
1578 printf("Bad flags %x\n", token
.Flags
);
1582 /* XXX Sequence replay detection */
1583 memcpy(&seq
, token
.SND_SEQ
, sizeof(seq
));
1585 lctx
->recv_seq
= seq
;
1587 ec
= (token
.EC
[0] << 8) | token
.EC
[1];
1588 rrc
= (token
.RRC
[0] << 8) | token
.RRC
[1];
1589 *qop
= GSS_C_QOP_DEFAULT
;
1590 conf
= ((token
.Flags
& CFXSealed
) == CFXSealed
);
1595 gss_cfx_wrap_token_desc etoken
;
1597 if (rrc
) { /* Handle Right rotation count */
1598 gss_krb5_cfx_unwrap_rrc_mbuf(*mbp
, rrc
);
1600 error
= krb5_cfx_crypt_mbuf(cctx
, mbp
, &len
, 0, reverse
);
1602 printf("krb5_cfx_crypt_mbuf %d\n", error
);
1604 return GSS_S_FAILURE
;
1606 if (len
>= sizeof(gss_cfx_wrap_token_desc
)) {
1607 len
-= sizeof(gss_cfx_wrap_token_desc
);
1611 mbuf_copydata(*mbp
, len
, sizeof(gss_cfx_wrap_token_desc
), &etoken
);
1612 /* Verify etoken with the token wich should be the same, except the rc field is always zero */
1613 token
.RRC
[0] = token
.RRC
[1] = 0;
1614 if (memcmp(&token
, &etoken
, sizeof(gss_cfx_wrap_token_desc
)) != 0) {
1615 printf("Encrypted token mismach\n");
1618 /* strip the encrypted token and any pad bytes */
1619 gss_strip_mbuf(*mbp
, -(sizeof(gss_cfx_wrap_token_desc
) + ec
));
1620 len
-= (sizeof(gss_cfx_wrap_token_desc
) + ec
);
1622 uint8_t digest
[cctx
->digest_size
];
1624 gss_buffer_desc header
;
1626 if (ec
!= cctx
->digest_size
|| len
>= cctx
->digest_size
) {
1629 len
-= cctx
->digest_size
;
1630 mbuf_copydata(*mbp
, len
, cctx
->digest_size
, digest
);
1631 gss_strip_mbuf(*mbp
, -cctx
->digest_size
);
1632 /* When calculating the mic header fields ec and rcc must be zero */
1633 token
.EC
[0] = token
.EC
[1] = token
.RRC
[0] = token
.RRC
[1] = 0;
1634 header
.value
= &token
;
1635 header
.length
= sizeof(gss_cfx_wrap_token_desc
);
1636 error
= krb5_mic_mbuf(cctx
, NULL
, *mbp
, 0, len
, &header
, digest
, &verf
, 1, reverse
);
1641 return GSS_S_COMPLETE
;
1645 return GSS_S_FAILURE
;
1649 * RFC 1964 3DES support
1652 typedef struct gss_1964_mic_token_desc_struct
{
1653 uint8_t TOK_ID
[2]; /* 01 01 */
1654 uint8_t Sign_Alg
[2];
1655 uint8_t Filler
[4]; /* ff ff ff ff */
1656 } gss_1964_mic_token_desc
, *gss_1964_mic_token
;
1658 typedef struct gss_1964_wrap_token_desc_struct
{
1659 uint8_t TOK_ID
[2]; /* 02 01 */
1660 uint8_t Sign_Alg
[2];
1661 uint8_t Seal_Alg
[2];
1662 uint8_t Filler
[2]; /* ff ff */
1663 } gss_1964_wrap_token_desc
, *gss_1964_wrap_token
;
1665 typedef struct gss_1964_delete_token_desc_struct
{
1666 uint8_t TOK_ID
[2]; /* 01 02 */
1667 uint8_t Sign_Alg
[2];
1668 uint8_t Filler
[4]; /* ff ff ff ff */
1669 } gss_1964_delete_token_desc
, *gss_1964_delete_token
;
1671 typedef struct gss_1964_header_desc_struct
{
1672 uint8_t App0
; /* 0x60 Application 0 constructed */
1673 uint8_t AppLen
[]; /* Variable Der length */
1674 } gss_1964_header_desc
, *gss_1964_header
;
1677 gss_1964_mic_token_desc mic_tok
;
1678 gss_1964_wrap_token_desc wrap_tok
;
1679 gss_1964_delete_token_desc del_tok
;
1680 } gss_1964_tok_type
__attribute__((transparent_union
));
1682 typedef struct gss_1964_token_body_struct
{
1683 uint8_t OIDType
; /* 0x06 */
1684 uint8_t OIDLen
; /* 0x09 */
1685 uint8_t kerb_mech
[9]; /* Der Encode kerberos mech 1.2.840.113554.1.2.2
1686 * 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 */
1687 gss_1964_tok_type body
;
1689 uint8_t Hash
[]; /* Mic */
1690 } gss_1964_token_body_desc
, *gss_1964_token_body
;
1693 gss_1964_header_desc tok_1964_header
= {
1697 gss_1964_mic_token_desc mic_1964_token
= {
1698 .TOK_ID
= "\x01\x01",
1699 .Filler
= "\xff\xff\xff\xff"
1702 gss_1964_wrap_token_desc wrap_1964_token
= {
1703 .TOK_ID
= "\x02\x01",
1704 .Filler
= "\xff\xff"
1707 gss_1964_delete_token_desc del_1964_token
= {
1708 .TOK_ID
= "\x01\x01",
1709 .Filler
= "\xff\xff\xff\xff"
1712 gss_1964_token_body_desc body_1964_token
= {
1715 .kerb_mech
= "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02",
1718 #define GSS_KRB5_3DES_MAXTOKSZ (sizeof(gss_1964_header_desc) + 5 /* max der length supported */ + sizeof(gss_1964_token_body_desc))
1720 uint32_t gss_krb5_3des_get_mic(uint32_t *, gss_ctx_id_t
, gss_qop_t
, gss_buffer_t
, gss_buffer_t
);
1721 uint32_t gss_krb5_3des_verify_mic(uint32_t *, gss_ctx_id_t
, gss_buffer_t
, gss_buffer_t
, gss_qop_t
*);
1722 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
);
1723 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
*);
1724 uint32_t gss_krb5_3des_wrap_mbuf(uint32_t *, gss_ctx_id_t
, int, gss_qop_t
, mbuf_t
*, size_t, int *);
1725 uint32_t gss_krb5_3des_unwrap_mbuf(uint32_t *, gss_ctx_id_t
, mbuf_t
*, size_t, int *, gss_qop_t
*);
1728 * Decode an ASN.1 DER length field
1731 gss_krb5_der_length_get(uint8_t **pp
)
1734 uint32_t flen
, len
= 0;
1739 if (flen
> sizeof(uint32_t)) {
1743 len
= (len
<< 8) + *p
++;
1753 * Determine size of ASN.1 DER length
1756 gss_krb5_der_length_size(size_t len
)
1759 len
< (1 << 7) ? 1 :
1760 len
< (1 << 8) ? 2 :
1761 len
< (1 << 16) ? 3 :
1762 len
< (1 << 24) ? 4 : 5;
1766 * Encode an ASN.1 DER length field
1769 gss_krb5_der_length_put(uint8_t **pp
, size_t len
)
1771 int sz
= gss_krb5_der_length_size(len
);
1775 *p
++ = (uint8_t) len
;
1777 *p
++ = (uint8_t) ((sz
- 1) | 0x80);
1780 *p
++ = (uint8_t) ((len
>> (sz
* 8)) & 0xff);
1788 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
)
1790 gss_1964_header token
;
1791 gss_1964_token_body tokbody
;
1792 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1793 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1794 uint32_t seq
= (uint32_t) (lctx
->send_seq
++ & 0xffff);
1795 size_t toklen
= sizeof(gss_1964_token_body_desc
) + cctx
->digest_size
;
1796 size_t alloclen
= toklen
+ sizeof(gss_1964_header_desc
) + gss_krb5_der_length_size(toklen
+ datalen
);
1799 MALLOC(token
, gss_1964_header
, alloclen
, M_TEMP
, M_WAITOK
| M_ZERO
);
1800 *token
= tok_1964_header
;
1801 tokptr
= token
->AppLen
;
1802 gss_krb5_der_length_put(&tokptr
, toklen
+ datalen
);
1803 tokbody
= (gss_1964_token_body
)tokptr
;
1804 *tokbody
= body_1964_token
; /* Initalize the token body */
1805 tokbody
->body
= body
; /* and now set the body to the token type passed in */
1807 for (int i
= 0; i
< 4; i
++) {
1808 tokbody
->SND_SEQ
[i
] = (uint8_t)((seq
>> (i
* 8)) & 0xff);
1810 for (int i
= 4; i
< 8; i
++) {
1811 tokbody
->SND_SEQ
[i
] = lctx
->initiate
? 0x00 : 0xff;
1814 size_t blocksize
= cctx
->enc_mode
->block_size
;
1815 cccbc_iv_decl(blocksize
, iv
);
1816 cccbc_ctx_decl(cctx
->enc_mode
->size
, enc_ctx
);
1817 cccbc_set_iv(cctx
->enc_mode
, iv
, hash
->value
);
1818 cccbc_init(cctx
->enc_mode
, enc_ctx
, cctx
->keylen
, cctx
->key
);
1819 cccbc_update(cctx
->enc_mode
, enc_ctx
, iv
, 1, tokbody
->SND_SEQ
, tokbody
->SND_SEQ
);
1821 assert(hash
->length
== cctx
->digest_size
);
1822 memcpy(tokbody
->Hash
, hash
->value
, hash
->length
);
1823 des3_token
->length
= alloclen
;
1824 des3_token
->value
= token
;
1828 gss_krb5_3des_token_get(gss_ctx_id_t ctx
, gss_buffer_t intok
,
1829 gss_1964_tok_type body
, gss_buffer_t hash
, size_t *offset
, size_t *len
, int reverse
)
1831 gss_1964_header token
= intok
->value
;
1832 gss_1964_token_body tokbody
;
1833 lucid_context_t lctx
= &ctx
->gss_lucid_ctx
;
1834 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1841 if (token
->App0
!= tok_1964_header
.App0
) {
1842 printf("%s: bad framing\n", __func__
);
1843 printgbuf(__func__
, intok
);
1846 tokptr
= token
->AppLen
;
1847 length
= gss_krb5_der_length_get(&tokptr
);
1849 printf("%s: invalid length\n", __func__
);
1850 printgbuf(__func__
, intok
);
1853 toklen
= sizeof(gss_1964_header_desc
) + gss_krb5_der_length_size(length
)
1854 + sizeof(gss_1964_token_body_desc
);
1856 if (intok
->length
< toklen
+ cctx
->digest_size
) {
1857 printf("%s: token to short", __func__
);
1858 printf("toklen = %d, length = %d\n", (int)toklen
, (int)length
);
1859 printgbuf(__func__
, intok
);
1864 *offset
= toklen
+ cctx
->digest_size
;
1868 *len
= length
- sizeof(gss_1964_token_body_desc
) - cctx
->digest_size
;
1871 tokbody
= (gss_1964_token_body
)tokptr
;
1872 if (tokbody
->OIDType
!= body_1964_token
.OIDType
||
1873 tokbody
->OIDLen
!= body_1964_token
.OIDLen
||
1874 memcmp(tokbody
->kerb_mech
, body_1964_token
.kerb_mech
, tokbody
->OIDLen
) != 0) {
1875 printf("%s: Invalid mechanism\n", __func__
);
1876 printgbuf(__func__
, intok
);
1879 if (memcmp(&tokbody
->body
, &body
, sizeof(gss_1964_tok_type
)) != 0) {
1880 printf("%s: Invalid body\n", __func__
);
1881 printgbuf(__func__
, intok
);
1884 size_t blocksize
= cctx
->enc_mode
->block_size
;
1885 uint8_t *block
= tokbody
->SND_SEQ
;
1887 assert(blocksize
== sizeof(tokbody
->SND_SEQ
));
1888 cccbc_iv_decl(blocksize
, iv
);
1889 cccbc_ctx_decl(cctx
->dec_mode
->size
, dec_ctx
);
1890 cccbc_set_iv(cctx
->dec_mode
, iv
, tokbody
->Hash
);
1891 cccbc_init(cctx
->dec_mode
, dec_ctx
, cctx
->keylen
, cctx
->key
);
1892 cccbc_update(cctx
->dec_mode
, dec_ctx
, iv
, 1, block
, block
);
1894 initiate
= lctx
->initiate
? (reverse
? 0 : 1) : (reverse
? 1 : 0);
1895 for (int i
= 4; i
< 8; i
++) {
1896 if (tokbody
->SND_SEQ
[i
] != (initiate
? 0xff : 0x00)) {
1897 printf("%s: Invalid des mac\n", __func__
);
1898 printgbuf(__func__
, intok
);
1903 memcpy(&seq
, tokbody
->SND_SEQ
, sizeof(uint32_t));
1905 lctx
->recv_seq
= ntohl(seq
);
1907 assert(hash
->length
>= cctx
->digest_size
);
1908 memcpy(hash
->value
, tokbody
->Hash
, cctx
->digest_size
);
1914 gss_krb5_3des_get_mic(uint32_t *minor
, /* minor status */
1915 gss_ctx_id_t ctx
, /* krb5 context id */
1916 gss_qop_t qop __unused
, /* qop_req (ignored) */
1917 gss_buffer_t mbp
, /* message buffer in */
1918 gss_buffer_t mic
) /* mic token out */
1920 gss_1964_mic_token_desc tokbody
= mic_1964_token
;
1921 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1922 gss_buffer_desc hash
;
1923 gss_buffer_desc header
;
1924 uint8_t hashval
[cctx
->digest_size
];
1926 hash
.length
= cctx
->digest_size
;
1927 hash
.value
= hashval
;
1928 tokbody
.Sign_Alg
[0] = 0x04; /* lctx->keydata.lucid_protocol_u.data_1964.sign_alg */
1929 tokbody
.Sign_Alg
[1] = 0x00;
1930 header
.length
= sizeof(gss_1964_mic_token_desc
);
1931 header
.value
= &tokbody
;
1934 *minor
= krb5_mic(cctx
, &header
, mbp
, NULL
, hashval
, NULL
, 0, 0);
1936 return GSS_S_FAILURE
;
1939 /* Make the token */
1940 gss_krb5_3des_token_put(ctx
, tokbody
, &hash
, 0, mic
);
1942 return GSS_S_COMPLETE
;
1946 gss_krb5_3des_verify_mic(uint32_t *minor
,
1952 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1953 uint8_t hashval
[cctx
->digest_size
];
1954 gss_buffer_desc hash
;
1955 gss_1964_mic_token_desc mtok
= mic_1964_token
;
1956 gss_buffer_desc header
;
1959 mtok
.Sign_Alg
[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_1964.sign_alg */
1960 mtok
.Sign_Alg
[1] = 0x00;
1961 hash
.length
= cctx
->digest_size
;
1962 hash
.value
= hashval
;
1963 header
.length
= sizeof(gss_1964_mic_token_desc
);
1964 header
.value
= &mtok
;
1967 *qop
= GSS_C_QOP_DEFAULT
;
1970 *minor
= gss_krb5_3des_token_get(ctx
, mic
, mtok
, &hash
, NULL
, NULL
, 0);
1972 return GSS_S_FAILURE
;
1975 *minor
= krb5_mic(cctx
, &header
, mbp
, NULL
, hashval
, &verf
, 0, 0);
1977 return GSS_S_FAILURE
;
1980 return verf
? GSS_S_COMPLETE
: GSS_S_BAD_SIG
;
1984 gss_krb5_3des_get_mic_mbuf(uint32_t *minor
,
1986 gss_qop_t qop __unused
,
1992 gss_1964_mic_token_desc tokbody
= mic_1964_token
;
1993 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
1994 gss_buffer_desc header
;
1995 gss_buffer_desc hash
;
1996 uint8_t hashval
[cctx
->digest_size
];
1998 hash
.length
= cctx
->digest_size
;
1999 hash
.value
= hashval
;
2000 tokbody
.Sign_Alg
[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_4121.sign_alg */
2001 tokbody
.Sign_Alg
[1] = 0x00;
2002 header
.length
= sizeof(gss_1964_mic_token_desc
);
2003 header
.value
= &tokbody
;
2006 *minor
= krb5_mic_mbuf(cctx
, &header
, mbp
, offset
, len
, NULL
, hashval
, NULL
, 0, 0);
2008 return GSS_S_FAILURE
;
2011 /* Make the token */
2012 gss_krb5_3des_token_put(ctx
, tokbody
, &hash
, 0, mic
);
2014 return GSS_S_COMPLETE
;
2018 gss_krb5_3des_verify_mic_mbuf(uint32_t *minor
,
2026 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
2027 uint8_t hashval
[cctx
->digest_size
];
2028 gss_buffer_desc header
;
2029 gss_buffer_desc hash
;
2030 gss_1964_mic_token_desc mtok
= mic_1964_token
;
2033 mtok
.Sign_Alg
[0] = 0x04; /* lctx->key_data.lucic_protocol_u.data1964.sign_alg */
2034 mtok
.Sign_Alg
[1] = 0x00;
2035 hash
.length
= cctx
->digest_size
;
2036 hash
.value
= hashval
;
2037 header
.length
= sizeof(gss_1964_mic_token_desc
);
2038 header
.value
= &mtok
;
2041 *qop
= GSS_C_QOP_DEFAULT
;
2044 *minor
= gss_krb5_3des_token_get(ctx
, mic
, mtok
, &hash
, NULL
, NULL
, 0);
2046 return GSS_S_FAILURE
;
2049 *minor
= krb5_mic_mbuf(cctx
, &header
, mbp
, offset
, len
, NULL
, hashval
, &verf
, 0, 0);
2051 return GSS_S_FAILURE
;
2054 return verf
? GSS_S_COMPLETE
: GSS_S_BAD_SIG
;
2058 gss_krb5_3des_wrap_mbuf(uint32_t *minor
,
2061 gss_qop_t qop __unused
,
2066 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
2067 const struct ccmode_cbc
*ccmode
= cctx
->enc_mode
;
2070 uint8_t confounder
[ccmode
->block_size
];
2071 gss_1964_wrap_token_desc tokbody
= wrap_1964_token
;
2072 gss_buffer_desc header
;
2073 gss_buffer_desc mic
;
2074 gss_buffer_desc hash
;
2075 uint8_t hashval
[cctx
->digest_size
];
2078 *conf_state
= conf_flag
;
2081 hash
.length
= cctx
->digest_size
;
2082 hash
.value
= hashval
;
2083 tokbody
.Sign_Alg
[0] = 0x04; /* lctx->key_data.lucid_protocol_u.data_1964.sign_alg */
2084 tokbody
.Sign_Alg
[1] = 0x00;
2085 /* conf_flag ? lctx->key_data.lucid_protocol_u.data_1964.seal_alg : 0xffff */
2086 tokbody
.Seal_Alg
[0] = conf_flag
? 0x02 : 0xff;
2087 tokbody
.Seal_Alg
[1] = conf_flag
? 0x00 : 0xff;
2088 header
.length
= sizeof(gss_1964_wrap_token_desc
);
2089 header
.value
= &tokbody
;
2091 /* Prepend confounder */
2092 assert(ccmode
->block_size
<= UINT_MAX
);
2093 read_random(confounder
, (u_int
)ccmode
->block_size
);
2094 *minor
= gss_prepend_mbuf(mbp
, confounder
, ccmode
->block_size
);
2096 return GSS_S_FAILURE
;
2099 /* Append trailer of up to 8 bytes and set pad length in each trailer byte */
2100 padlen
= 8 - len
% 8;
2101 for (int i
= 0; i
< padlen
; i
++) {
2104 *minor
= gss_append_mbuf(*mbp
, pad
, padlen
);
2106 return GSS_S_FAILURE
;
2109 len
+= ccmode
->block_size
+ padlen
;
2112 *minor
= krb5_mic_mbuf(cctx
, &header
, *mbp
, 0, len
, NULL
, hashval
, NULL
, 0, 0);
2114 return GSS_S_FAILURE
;
2117 /* Make the token */
2118 gss_krb5_3des_token_put(ctx
, tokbody
, &hash
, len
, &mic
);
2121 *minor
= krb5_crypt_mbuf(cctx
, mbp
, len
, 1, 0);
2123 return GSS_S_FAILURE
;
2127 *minor
= gss_prepend_mbuf(mbp
, mic
.value
, mic
.length
);
2129 return *minor
? GSS_S_FAILURE
: GSS_S_COMPLETE
;
2133 gss_krb5_3des_unwrap_mbuf(uint32_t *minor
,
2140 crypto_ctx_t cctx
= &ctx
->gss_cryptor
;
2141 const struct ccmode_cbc
*ccmode
= cctx
->dec_mode
;
2142 size_t length
= 0, offset
= 0;
2143 gss_buffer_desc hash
;
2144 uint8_t hashval
[cctx
->digest_size
];
2145 gss_buffer_desc itoken
;
2146 uint8_t tbuffer
[GSS_KRB5_3DES_MAXTOKSZ
+ cctx
->digest_size
];
2147 itoken
.length
= GSS_KRB5_3DES_MAXTOKSZ
+ cctx
->digest_size
;
2148 itoken
.value
= tbuffer
;
2149 gss_1964_wrap_token_desc wrap
= wrap_1964_token
;
2150 gss_buffer_desc header
;
2153 int cflag
, verified
, reverse
= 0;
2155 if (len
< GSS_KRB5_3DES_MAXTOKSZ
) {
2157 return GSS_S_FAILURE
;
2160 if (*qop
== GSS_C_QOP_REVERSE
) {
2163 *qop
= GSS_C_QOP_DEFAULT
;
2165 *minor
= mbuf_copydata(*mbp
, 0, itoken
.length
, itoken
.value
);
2167 return GSS_S_FAILURE
;
2170 hash
.length
= cctx
->digest_size
;
2171 hash
.value
= hashval
;
2172 wrap
.Sign_Alg
[0] = 0x04;
2173 wrap
.Sign_Alg
[1] = 0x00;
2174 wrap
.Seal_Alg
[0] = 0x02;
2175 wrap
.Seal_Alg
[1] = 0x00;
2177 for (cflag
= 1; cflag
>= 0; cflag
--) {
2178 *minor
= gss_krb5_3des_token_get(ctx
, &itoken
, wrap
, &hash
, &offset
, &length
, reverse
);
2182 wrap
.Seal_Alg
[0] = 0xff;
2183 wrap
.Seal_Alg
[1] = 0xff;
2186 return GSS_S_FAILURE
;
2190 *conf_state
= cflag
;
2194 * Seperate off the header
2196 *minor
= gss_normalize_mbuf(*mbp
, offset
, &length
, &smb
, &tmb
, 0);
2198 return GSS_S_FAILURE
;
2201 assert(tmb
== NULL
);
2203 /* Decrypt the chain if needed */
2205 *minor
= krb5_crypt_mbuf(cctx
, &smb
, length
, 0, NULL
);
2207 return GSS_S_FAILURE
;
2211 /* Verify the mic */
2212 header
.length
= sizeof(gss_1964_wrap_token_desc
);
2213 header
.value
= &wrap
;
2215 *minor
= krb5_mic_mbuf(cctx
, &header
, smb
, 0, length
, NULL
, hashval
, &verified
, 0, 0);
2217 return GSS_S_FAILURE
;
2220 return GSS_S_BAD_SIG
;
2223 /* Get the pad bytes */
2224 *minor
= mbuf_copydata(smb
, length
- 1, 1, &padlen
);
2226 return GSS_S_FAILURE
;
2229 /* Strip the confounder and trailing pad bytes */
2230 gss_strip_mbuf(smb
, -padlen
);
2231 assert(ccmode
->block_size
<= INT_MAX
);
2232 gss_strip_mbuf(smb
, (int)ccmode
->block_size
);
2239 return GSS_S_COMPLETE
;
2243 etype_name(etypes etype
)
2246 case DES3_CBC_SHA1_KD
:
2247 return "des3-cbc-sha1";
2248 case AES128_CTS_HMAC_SHA1_96
:
2249 return "aes128-cts-hmac-sha1-96";
2250 case AES256_CTS_HMAC_SHA1_96
:
2251 return "aes-cts-hmac-sha1-96";
2253 return "unknown enctype";
2258 supported_etype(uint32_t proto
, etypes etype
)
2260 const char *proto_name
;
2265 proto_name
= "RFC 1964 krb5 gss mech";
2267 case DES3_CBC_SHA1_KD
:
2275 proto_name
= "RFC 4121 krb5 gss mech";
2277 case AES256_CTS_HMAC_SHA1_96
:
2278 case AES128_CTS_HMAC_SHA1_96
:
2285 proto_name
= "Unknown krb5 gss mech";
2288 printf("%s: Non supported encryption %s (%d) type for protocol %s (%d)\n",
2289 __func__
, etype_name(etype
), etype
, proto_name
, proto
);
2294 * Kerberos gss mech entry points
2297 gss_krb5_get_mic(uint32_t *minor
, /* minor_status */
2298 gss_ctx_id_t ctx
, /* context_handle */
2299 gss_qop_t qop
, /* qop_req */
2300 gss_buffer_t mbp
, /* message buffer */
2301 gss_buffer_t mic
/* message_token */)
2303 uint32_t minor_stat
= 0;
2305 if (minor
== NULL
) {
2306 minor
= &minor_stat
;
2310 /* Validate context */
2311 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2312 return GSS_S_NO_CONTEXT
;
2315 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2317 return GSS_S_FAILURE
;
2320 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2322 /* RFC 1964 DES3 case */
2323 return gss_krb5_3des_get_mic(minor
, ctx
, qop
, mbp
, mic
);
2325 /* RFC 4121 CFX case */
2326 return gss_krb5_cfx_get_mic(minor
, ctx
, qop
, mbp
, mic
);
2329 return GSS_S_COMPLETE
;
2333 gss_krb5_verify_mic(uint32_t *minor
, /* minor_status */
2334 gss_ctx_id_t ctx
, /* context_handle */
2335 gss_buffer_t mbp
, /* message_buffer */
2336 gss_buffer_t mic
, /* message_token */
2337 gss_qop_t
*qop
/* qop_state */)
2339 uint32_t minor_stat
= 0;
2340 gss_qop_t qop_val
= GSS_C_QOP_DEFAULT
;
2342 if (minor
== NULL
) {
2343 minor
= &minor_stat
;
2351 /* Validate context */
2352 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2353 return GSS_S_NO_CONTEXT
;
2356 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2358 return GSS_S_FAILURE
;
2361 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2363 /* RFC 1964 DES3 case */
2364 return gss_krb5_3des_verify_mic(minor
, ctx
, mbp
, mic
, qop
);
2366 /* RFC 4121 CFX case */
2367 return gss_krb5_cfx_verify_mic(minor
, ctx
, mbp
, mic
, qop
);
2369 return GSS_S_COMPLETE
;
2373 gss_krb5_get_mic_mbuf(uint32_t *minor
, /* minor_status */
2374 gss_ctx_id_t ctx
, /* context_handle */
2375 gss_qop_t qop
, /* qop_req */
2376 mbuf_t mbp
, /* message mbuf */
2377 size_t offset
, /* offest */
2378 size_t len
, /* length */
2379 gss_buffer_t mic
/* message_token */)
2381 uint32_t minor_stat
= 0;
2383 if (minor
== NULL
) {
2384 minor
= &minor_stat
;
2392 /* Validate context */
2393 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2394 return GSS_S_NO_CONTEXT
;
2397 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2399 return GSS_S_FAILURE
;
2402 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2404 /* RFC 1964 DES3 case */
2405 return gss_krb5_3des_get_mic_mbuf(minor
, ctx
, qop
, mbp
, offset
, len
, mic
);
2407 /* RFC 4121 CFX case */
2408 return gss_krb5_cfx_get_mic_mbuf(minor
, ctx
, qop
, mbp
, offset
, len
, mic
);
2411 return GSS_S_COMPLETE
;
2415 gss_krb5_verify_mic_mbuf(uint32_t *minor
, /* minor_status */
2416 gss_ctx_id_t ctx
, /* context_handle */
2417 mbuf_t mbp
, /* message_buffer */
2418 size_t offset
, /* offset */
2419 size_t len
, /* length */
2420 gss_buffer_t mic
, /* message_token */
2421 gss_qop_t
*qop
/* qop_state */)
2423 uint32_t minor_stat
= 0;
2424 gss_qop_t qop_val
= GSS_C_QOP_DEFAULT
;
2426 if (minor
== NULL
) {
2427 minor
= &minor_stat
;
2439 /* Validate context */
2440 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2441 return GSS_S_NO_CONTEXT
;
2444 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2446 return GSS_S_FAILURE
;
2449 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2451 /* RFC 1964 DES3 case */
2452 return gss_krb5_3des_verify_mic_mbuf(minor
, ctx
, mbp
, offset
, len
, mic
, qop
);
2454 /* RFC 4121 CFX case */
2455 return gss_krb5_cfx_verify_mic_mbuf(minor
, ctx
, mbp
, offset
, len
, mic
, qop
);
2458 return GSS_S_COMPLETE
;
2462 gss_krb5_wrap_mbuf(uint32_t *minor
, /* minor_status */
2463 gss_ctx_id_t ctx
, /* context_handle */
2464 int conf_flag
, /* conf_req_flag */
2465 gss_qop_t qop
, /* qop_req */
2466 mbuf_t
*mbp
, /* input/output message_buffer */
2467 size_t offset
, /* offset */
2468 size_t len
, /* length */
2469 int *conf_state
/* conf state */)
2471 uint32_t major
= GSS_S_FAILURE
, minor_stat
= 0;
2475 if (minor
== NULL
) {
2476 minor
= &minor_stat
;
2478 if (conf_state
== NULL
) {
2479 conf_state
= &conf_val
;
2484 /* Validate context */
2485 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2486 return GSS_S_NO_CONTEXT
;
2489 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2491 return GSS_S_FAILURE
;
2494 gss_normalize_mbuf(*mbp
, offset
, &len
, &smb
, &tmb
, 0);
2496 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2498 /* RFC 1964 DES3 case */
2499 major
= gss_krb5_3des_wrap_mbuf(minor
, ctx
, conf_flag
, qop
, &smb
, len
, conf_state
);
2502 /* RFC 4121 CFX case */
2503 major
= gss_krb5_cfx_wrap_mbuf(minor
, ctx
, conf_flag
, qop
, &smb
, len
, conf_state
);
2508 gss_join_mbuf(*mbp
, smb
, tmb
);
2511 gss_join_mbuf(smb
, tmb
, NULL
);
2518 gss_krb5_unwrap_mbuf(uint32_t * minor
, /* minor_status */
2519 gss_ctx_id_t ctx
, /* context_handle */
2520 mbuf_t
*mbp
, /* input/output message_buffer */
2521 size_t offset
, /* offset */
2522 size_t len
, /* length */
2523 int *conf_flag
, /* conf_state */
2524 gss_qop_t
*qop
/* qop state */)
2526 uint32_t major
= GSS_S_FAILURE
, minor_stat
= 0;
2527 gss_qop_t qop_val
= GSS_C_QOP_DEFAULT
;
2531 if (minor
== NULL
) {
2532 minor
= &minor_stat
;
2537 if (conf_flag
== NULL
) {
2538 conf_flag
= &conf_val
;
2541 /* Validate context */
2542 if (ctx
== NULL
|| ((lucid_context_version_t
)ctx
)->version
!= 1) {
2543 return GSS_S_NO_CONTEXT
;
2546 if (!supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_cryptor
.etype
)) {
2548 return GSS_S_FAILURE
;
2551 gss_normalize_mbuf(*mbp
, offset
, &len
, &smb
, &tmb
, 0);
2553 switch (ctx
->gss_lucid_ctx
.key_data
.proto
) {
2555 /* RFC 1964 DES3 case */
2556 major
= gss_krb5_3des_unwrap_mbuf(minor
, ctx
, &smb
, len
, conf_flag
, qop
);
2559 /* RFC 4121 CFX case */
2560 major
= gss_krb5_cfx_unwrap_mbuf(minor
, ctx
, &smb
, len
, conf_flag
, qop
);
2565 gss_join_mbuf(*mbp
, smb
, tmb
);
2568 gss_join_mbuf(smb
, tmb
, NULL
);
2574 #include <nfs/xdr_subs.h>
2577 xdr_lucid_context(void *data
, uint32_t length
, lucid_context_t lctx
)
2581 uint32_t keylen
= 0;
2583 xb_init_buffer(&xb
, data
, length
);
2584 xb_get_32(error
, &xb
, lctx
->vers
);
2585 if (!error
&& lctx
->vers
!= 1) {
2587 printf("%s: invalid version %d\n", __func__
, (int)lctx
->vers
);
2590 xb_get_32(error
, &xb
, lctx
->initiate
);
2592 printf("%s: Could not decode initiate\n", __func__
);
2595 xb_get_32(error
, &xb
, lctx
->endtime
);
2597 printf("%s: Could not decode endtime\n", __func__
);
2600 xb_get_64(error
, &xb
, lctx
->send_seq
);
2602 printf("%s: Could not decode send_seq\n", __func__
);
2605 xb_get_64(error
, &xb
, lctx
->recv_seq
);
2607 printf("%s: Could not decode recv_seq\n", __func__
);
2610 xb_get_32(error
, &xb
, lctx
->key_data
.proto
);
2612 printf("%s: Could not decode mech protocol\n", __func__
);
2615 switch (lctx
->key_data
.proto
) {
2617 xb_get_32(error
, &xb
, lctx
->key_data
.lucid_protocol_u
.data_1964
.sign_alg
);
2618 xb_get_32(error
, &xb
, lctx
->key_data
.lucid_protocol_u
.data_1964
.seal_alg
);
2620 printf("%s: Could not decode rfc1964 sign and seal\n", __func__
);
2624 xb_get_32(error
, &xb
, lctx
->key_data
.lucid_protocol_u
.data_4121
.acceptor_subkey
);
2626 printf("%s: Could not decode rfc4121 acceptor_subkey", __func__
);
2630 printf("%s: Invalid mech protocol %d\n", __func__
, (int)lctx
->key_data
.proto
);
2636 xb_get_32(error
, &xb
, lctx
->ctx_key
.etype
);
2638 printf("%s: Could not decode key enctype\n", __func__
);
2641 switch (lctx
->ctx_key
.etype
) {
2642 case DES3_CBC_SHA1_KD
:
2645 case AES128_CTS_HMAC_SHA1_96
:
2648 case AES256_CTS_HMAC_SHA1_96
:
2655 xb_get_32(error
, &xb
, lctx
->ctx_key
.key
.key_len
);
2657 printf("%s: could not decode key length\n", __func__
);
2660 if (lctx
->ctx_key
.key
.key_len
!= keylen
) {
2662 printf("%s: etype = %d keylen = %d expected keylen = %d\n", __func__
,
2663 lctx
->ctx_key
.etype
, lctx
->ctx_key
.key
.key_len
, keylen
);
2667 lctx
->ctx_key
.key
.key_val
= xb_malloc(keylen
);
2668 if (lctx
->ctx_key
.key
.key_val
== NULL
) {
2669 printf("%s: could not get memory for key\n", __func__
);
2673 error
= xb_get_bytes(&xb
, (char *)lctx
->ctx_key
.key
.key_val
, keylen
, 1);
2675 printf("%s: could get key value\n", __func__
);
2676 xb_free(lctx
->ctx_key
.key
.key_val
);
2683 gss_krb5_make_context(void *data
, uint32_t datalen
)
2687 if (!corecrypto_available()) {
2691 gss_krb5_mech_init();
2692 MALLOC(ctx
, gss_ctx_id_t
, sizeof(struct gss_ctx_id_desc
), M_TEMP
, M_WAITOK
| M_ZERO
);
2693 if (xdr_lucid_context(data
, datalen
, &ctx
->gss_lucid_ctx
) ||
2694 !supported_etype(ctx
->gss_lucid_ctx
.key_data
.proto
, ctx
->gss_lucid_ctx
.ctx_key
.etype
)) {
2700 /* Set up crypto context */
2701 gss_crypto_ctx_init(&ctx
->gss_cryptor
, &ctx
->gss_lucid_ctx
);
2708 gss_krb5_destroy_context(gss_ctx_id_t ctx
)
2713 gss_crypto_ctx_free(&ctx
->gss_cryptor
);
2714 FREE(ctx
->gss_lucid_ctx
.ctx_key
.key
.key_val
, M_TEMP
);
2715 cc_clear(sizeof(lucid_context_t
), &ctx
->gss_lucid_ctx
);