From: Luke Howard Date: Wed, 8 Sep 2010 10:23:35 +0000 (+0200) Subject: More work on krb5 crypto merge X-Git-Tag: vm/20110310~395 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=commitdiff_plain;h=9fbf196192538e4712b5596790db276b74b7e35a More work on krb5 crypto merge --- diff --git a/Makefile.am b/Makefile.am index 3a86451..1938056 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ libmech_eap_la_SOURCES = \ util_cred.c \ util_crypt.c \ util_name.c \ + util_ordering.c \ verify_mic.c \ wrap.c \ wrap_iov.c \ diff --git a/TODO b/TODO new file mode 100644 index 0000000..7d185ab --- /dev/null +++ b/TODO @@ -0,0 +1,4 @@ +- SAML +- encoders +- OID encoders +- stream diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 128b0fe..b6e4b04 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -53,6 +53,7 @@ /* Kerberos includes */ #include +#include "util.h" struct gss_name_struct { OM_uint32 flags; @@ -135,88 +136,17 @@ struct gss_ctx_id_struct { #define TOK_FLAG_WRAP_CONFIDENTIAL 0x02 #define TOK_FLAG_ACCEPTOR_SUBKEY 0x04 +#define KEY_USAGE_ACCEPTOR_SEAL 512 +#define KEY_USAGE_ACCEPTOR_SIGN 513 +#define KEY_USAGE_INITIATOR_SEAL 514 +#define KEY_USAGE_INITIATOR_SIGN 515 + enum gss_eap_token_type { TOK_TYPE_MIC = 0x0404, TOK_TYPE_WRAP = 0x0504, TOK_TYPE_DELETE = 0x0405 }; -/* Helper APIs */ -OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); -OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); - -OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName); -OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName); - -OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred); -OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred); - -/* Kerberos token services */ -#define KRB_USAGE_ACCEPTOR_SEAL 22 -#define KRB_USAGE_ACCEPTOR_SIGN 23 -#define KRB_USAGE_INITIATOR_SEAL 24 -#define KRB_USAGE_INITIATOR_SIGN 25 - -#if 0 -#define KRB_KEYTYPE(key) ((key)->keytype) -#else -#define KRB_KEYTYPE(key) ((key)->enctype) -#endif - -/* util_crypt.c */ -int -gssEapEncrypt(krb5_context context, int dce_style, size_t ec, - size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, - gss_iov_buffer_desc *iov, int iov_count); - -int -gssEapDecrypt(krb5_context context, int dce_style, size_t ec, - size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, - gss_iov_buffer_desc *iov, int iov_count); - -krb5_cryptotype -gssEapTranslateCryptoFlag(OM_uint32 type); - -gss_iov_buffer_t -gssEapLocateIov(gss_iov_buffer_desc *iov, - int iov_count, - OM_uint32 type); - -void -gssEapIovMessageLength(gss_iov_buffer_desc *iov, - int iov_count, - size_t *data_length, - size_t *assoc_data_length); - -void -gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count); - -int -gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count); - -int -gssEapAllocIov(gss_iov_buffer_t iov, size_t size); - -/* util_cksum.c */ -int -gssEapSign(krb5_context context, - krb5_cksumtype type, - size_t rrc, - krb5_keyblock *key, - krb5_keyusage sign_usage, - gss_iov_buffer_desc *iov, - int iov_count); - -int -gssEapVerify(krb5_context context, - krb5_cksumtype type, - size_t rrc, - krb5_keyblock *key, - krb5_keyusage sign_usage, - gss_iov_buffer_desc *iov, - int iov_count, - int *valid); - /* wrap_iov.c */ OM_uint32 gssEapWrapOrGetMIC(OM_uint32 *minor, @@ -236,17 +166,5 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, int iov_count, enum gss_eap_token_type toktype); -/* Helper macros */ -#define GSSEAP_CALLOC(count, size) (calloc((count), (size))) -#define GSSEAP_FREE(ptr) (free((ptr))) -#define GSSEAP_MALLOC(size) (malloc((size))) -#define GSSEAP_REALLOC(ptr, size) (realloc((ptr), (size))) - -#define GSSEAP_NOT_IMPLEMENTED do { \ - assert(0 && "not implemented"); \ - *minor = ENOSYS; \ - return GSS_S_FAILURE; \ - } while (0) #endif /* _GSSAPIP_EAP_H_ */ - diff --git a/unwrap_iov.c b/unwrap_iov.c index 3cec4f0..45c4b25 100644 --- a/unwrap_iov.c +++ b/unwrap_iov.c @@ -30,8 +30,6 @@ * SUCH DAMAGE. */ /* - * lib/gssapi/krb5/k5sealv3iov.c - * * Copyright 2008 by the Massachusetts Institute of Technology. * All Rights Reserved. * @@ -53,20 +51,23 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * - * */ #include "gssapiP_eap.h" +/* + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except + * for DCE in which case it can just provide TOKEN | DATA (must + * guarantee that DATA is padded) + */ OM_uint32 -gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, - gss_ctx_id_t ctx, - int *conf_state, - gss_qop_t *qop_state, - gss_iov_buffer_desc *iov, - int iov_count, - enum gss_eap_token_type toktype) +unwrapToken(OM_uint32 *minor, + gss_ctx_id_t ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + enum gss_eap_token_type toktype) { OM_uint32 code; gss_iov_buffer_t header; @@ -78,18 +79,15 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, size_t rrc, ec; size_t data_length, assoc_data_length; uint64_t seqnum; - krb5_boolean valid; + int valid = 0; krb5_cksumtype cksumtype; int conf_flag = 0; - *minor_status = 0; + *minor = 0; if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; - if (!CTX_IS_ESTABLISHED(ctx)) - return GSS_S_NO_CONTEXT; - header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); assert(header != NULL); @@ -102,18 +100,18 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, acceptor_flag = CTX_IS_INITIATOR(ctx) ? TOK_FLAG_SENDER_IS_ACCEPTOR : 0; key_usage = (toktype == TOK_TYPE_WRAP ? (!CTX_IS_INITIATOR(ctx) - ? KRB_USAGE_INITIATOR_SEAL - : KRB_USAGE_ACCEPTOR_SEAL) + ? KEY_USAGE_INITIATOR_SEAL + : KEY_USAGE_ACCEPTOR_SEAL) : (!CTX_IS_INITIATOR(ctx) - ? KRB_USAGE_INITIATOR_SIGN - : KRB_USAGE_ACCEPTOR_SIGN)); + ? KEY_USAGE_INITIATOR_SIGN + : KEY_USAGE_ACCEPTOR_SIGN)); gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length); ptr = (unsigned char *)header->buffer.value; if (header->buffer.length < 16) { - *minor_status = 0; + *minor = 0; return GSS_S_DEFECTIVE_TOKEN; } @@ -128,14 +126,14 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, if (toktype == TOK_TYPE_WRAP) { unsigned int k5_trailerlen; - if (load_16_be(ptr) != TOK_TYPE_WRAP) + if (load_uint16_be(ptr) != TOK_TYPE_WRAP) goto defective; conf_flag = ((ptr[2] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0); if (ptr[3] != 0xFF) goto defective; - ec = load_16_be(ptr + 4); - rrc = load_16_be(ptr + 6); - seqnum = load_64_be(ptr + 8); + ec = load_uint16_be(ptr + 4); + rrc = load_uint16_be(ptr + 6); + seqnum = load_uint64_be(ptr + 8); code = krb5_c_crypto_length(ctx->kerberosCtx, KRB_KEYTYPE(ctx->encryptionKey), @@ -143,7 +141,7 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_trailerlen); if (code != 0) { - *minor_status = code; + *minor = code; return GSS_S_FAILURE; } @@ -174,7 +172,7 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, ec, rrc, ctx->encryptionKey, key_usage, 0, iov, iov_count); if (code != 0) { - *minor_status = code; + *minor = code; return GSS_S_BAD_SIG; } @@ -184,11 +182,11 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, else althdr = (unsigned char *)trailer->buffer.value + ec; - if (load_16_be(althdr) != TOK_TYPE_WRAP + if (load_uint16_be(althdr) != TOK_TYPE_WRAP || althdr[2] != ptr[2] || althdr[3] != ptr[3] || memcmp(althdr + 8, ptr + 8, 8) != 0) { - *minor_status = 0; + *minor = 0; return GSS_S_BAD_SIG; } } else { @@ -197,45 +195,45 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, goto defective; /* Zero EC, RRC before computing checksum */ - store_16_be(0, ptr + 4); - store_16_be(0, ptr + 6); + store_uint16_be(0, ptr + 4); + store_uint16_be(0, ptr + 6); code = gssEapVerify(ctx->kerberosCtx, cksumtype, rrc, ctx->encryptionKey, key_usage, iov, iov_count, &valid); if (code != 0 || valid == FALSE) { - *minor_status = code; + *minor = code; return GSS_S_BAD_SIG; } } - code = g_order_check(&ctx->seqState, seqnum); + code = sequenceCheck(&ctx->seqState, seqnum); } else if (toktype == TOK_TYPE_MIC) { - if (load_16_be(ptr) != TOK_TYPE_MIC) + if (load_uint16_be(ptr) != TOK_TYPE_MIC) goto defective; verify_mic_1: if (ptr[3] != 0xFF) goto defective; - seqnum = load_64_be(ptr + 8); + seqnum = load_uint64_be(ptr + 8); code = gssEapVerify(ctx->kerberosCtx, cksumtype, 0, ctx->encryptionKey, key_usage, iov, iov_count, &valid); if (code != 0 || valid == FALSE) { - *minor_status = code; + *minor = code; return GSS_S_BAD_SIG; } - code = g_order_check(&ctx->seqState, seqnum); + code = sequenceCheck(&ctx->seqState, seqnum); } else if (toktype == TOK_TYPE_DELETE) { - if (load_16_be(ptr) != TOK_TYPE_DELETE) + if (load_uint16_be(ptr) != TOK_TYPE_DELETE) goto defective; goto verify_mic_1; } else { goto defective; } - *minor_status = 0; + *minor = 0; if (conf_state != NULL) *conf_state = conf_flag; @@ -243,11 +241,242 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status, return code; defective: - *minor_status = 0; + *minor = 0; return GSS_S_DEFECTIVE_TOKEN; } +int +rotateLeft(void *ptr, size_t bufsiz, size_t rc) +{ + void *tbuf; + + if (bufsiz == 0) + return 0; + rc = rc % bufsiz; + if (rc == 0) + return 0; + + tbuf = GSSEAP_MALLOC(rc); + if (tbuf == NULL) + return ENOMEM; + + memcpy(tbuf, ptr, rc); + memmove(ptr, (char *)ptr + rc, bufsiz - rc); + memcpy((char *)ptr + bufsiz - rc, tbuf, rc); + GSSEAP_FREE(tbuf); + + return 0; +} + +/* + * Split a STREAM | SIGN_DATA | DATA into + * HEADER | SIGN_DATA | DATA | PADDING | TRAILER + */ +static OM_uint32 +unwrapStream(OM_uint32 *minor, + gss_ctx_id_t ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + enum gss_eap_token_type toktype) +{ + unsigned char *ptr; + OM_uint32 code = 0, major = GSS_S_FAILURE; + krb5_context context = ctx->kerberosCtx; + int conf_req_flag, toktype2; + int i = 0, j; + gss_iov_buffer_desc *tiov = NULL; + gss_iov_buffer_t stream, data = NULL; + gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer; + + assert(toktype == TOK_TYPE_WRAP); + + if (toktype != TOK_TYPE_WRAP || (ctx->gssFlags & GSS_C_DCE_STYLE)) { + code = EINVAL; + goto cleanup; + } + + stream = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM); + assert(stream != NULL); + + if (stream->buffer.length < 16) { + major = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + ptr = (unsigned char *)stream->buffer.value; + toktype2 = load_uint16_be(ptr); + ptr += 2; + + tiov = (gss_iov_buffer_desc *)GSSEAP_CALLOC((size_t)iov_count + 2, + sizeof(gss_iov_buffer_desc)); + if (tiov == NULL) { + code = ENOMEM; + goto cleanup; + } + + /* HEADER */ + theader = &tiov[i++]; + theader->type = GSS_IOV_BUFFER_TYPE_HEADER; + theader->buffer.value = stream->buffer.value; + theader->buffer.length = 16; + + /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */ + for (j = 0; j < iov_count; j++) { + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type); + + if (type == GSS_IOV_BUFFER_TYPE_DATA) { + if (data != NULL) { + /* only a single DATA buffer can appear */ + code = EINVAL; + goto cleanup; + } + + data = &iov[j]; + tdata = &tiov[i]; + } + if (type == GSS_IOV_BUFFER_TYPE_DATA || + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + tiov[i++] = iov[j]; + } + + if (data == NULL) { + /* a single DATA buffer must be present */ + code = EINVAL; + goto cleanup; + } + + /* PADDING | TRAILER */ + tpadding = &tiov[i++]; + tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING; + tpadding->buffer.length = 0; + tpadding->buffer.value = NULL; + + ttrailer = &tiov[i++]; + ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER; + + { + size_t ec, rrc; + unsigned int k5_headerlen = 0; + unsigned int k5_trailerlen = 0; + + conf_req_flag = ((ptr[0] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0); + ec = conf_req_flag ? load_uint16_be(ptr + 2) : 0; + rrc = load_uint16_be(ptr + 4); + + if (rrc != 0) { + code = rotateLeft((unsigned char *)stream->buffer.value + 16, + stream->buffer.length - 16, rrc); + if (code != 0) + goto cleanup; + store_uint16_be(0, ptr + 4); /* set RRC to zero */ + } + + if (conf_req_flag) { + code = krb5_c_crypto_length(context, ctx->encryptionType, + KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + goto cleanup; + theader->buffer.length += k5_headerlen; /* length validated later */ + } + + /* no PADDING for CFX, EC is used instead */ + code = krb5_c_crypto_length(context, ctx->encryptionType, + conf_req_flag + ? KRB5_CRYPTO_TYPE_TRAILER + : KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) + goto cleanup; + + ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + + k5_trailerlen; + ttrailer->buffer.value = (unsigned char *)stream->buffer.value + + stream->buffer.length - ttrailer->buffer.length; + } + + /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/ + /* Old: GSS-Header | Conf | Data | Pad | */ + /* CFX: GSS-Header | Kerb-Header | Data | | EC | E(Header) | Kerb-Trailer */ + /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/ + + /* validate lengths */ + if (stream->buffer.length < theader->buffer.length + + tpadding->buffer.length + + ttrailer->buffer.length) { + code = KRB5_BAD_MSIZE; + major = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + /* setup data */ + tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length - + tpadding->buffer.length - theader->buffer.length; + + assert(data != NULL); + + if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = gssEapAllocIov(tdata, tdata->buffer.length); + if (code != 0) + goto cleanup; + + memcpy(tdata->buffer.value, + (unsigned char *)stream->buffer.value + theader->buffer.length, + tdata->buffer.length); + } else { + tdata->buffer.value = (unsigned char *)stream->buffer.value + + theader->buffer.length; + } + + assert(i <= iov_count + 2); + + major = unwrapToken(&code, ctx, conf_state, qop_state, + tiov, i, toktype); + if (major == GSS_S_COMPLETE) { + *data = *tdata; + } else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + OM_uint32 tmp; + + gss_release_buffer(&tmp, &tdata->buffer); + tdata->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + +cleanup: + if (tiov != NULL) + GSSEAP_FREE(tiov); + + *minor = code; + + return major; +} + +OM_uint32 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + enum gss_eap_token_type toktype) +{ + OM_uint32 major; + + if (!CTX_IS_ESTABLISHED(ctx)) + return GSS_S_NO_CONTEXT; + + if (gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) { + major = unwrapStream(minor, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } else { + major = unwrapToken(minor, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } + + return major; +} + OM_uint32 gss_unwrap_iov(OM_uint32 *minor, gss_ctx_id_t ctx, @@ -256,8 +485,6 @@ gss_unwrap_iov(OM_uint32 *minor, gss_iov_buffer_desc *iov, int iov_count) { - return gssEapUnwrapOrVerifyMIC(minor, ctx, - iov, iov_count, conf_state, - qop_state, TOK_TYPE_WRAP); - + return gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state, + iov, iov_count, TOK_TYPE_WRAP); } diff --git a/util.h b/util.h new file mode 100644 index 0000000..f062888 --- /dev/null +++ b/util.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions Copyright 2003-2010 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ 1 + +/* Helper APIs */ +OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); +OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); + +OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName); +OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName); + +OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred); +OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred); + +/* Kerberos token services */ +#define KRB_KEYTYPE(key) ((key)->enctype) + +/* util_crypt.c */ +int +gssEapEncrypt(krb5_context context, int dce_style, size_t ec, + size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, + gss_iov_buffer_desc *iov, int iov_count); + +int +gssEapDecrypt(krb5_context context, int dce_style, size_t ec, + size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, + gss_iov_buffer_desc *iov, int iov_count); + +krb5_cryptotype +gssEapMapCryptoFlag(OM_uint32 type); + +gss_iov_buffer_t +gssEapLocateIov(gss_iov_buffer_desc *iov, + int iov_count, + OM_uint32 type); + +void +gssEapIovMessageLength(gss_iov_buffer_desc *iov, + int iov_count, + size_t *data_length, + size_t *assoc_data_length); + +void +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count); + +int +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count); + +int +gssEapAllocIov(gss_iov_buffer_t iov, size_t size); + +/* util_cksum.c */ +int +gssEapSign(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count); + +int +gssEapVerify(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_keyblock *key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int *valid); + +/* util_ordering.c */ +int +sequenceInternalize(void **vqueue, unsigned char **buf, size_t *lenremain); + +int +sequenceExternalize(void *vqueue, unsigned char **buf, size_t *lenremain); + +int +sequenceSize(void *vqueue, size_t *sizep); + +void +sequenceFree(void **vqueue); + +int +sequenceCheck(void **vqueue, uint64_t seqnum); + +int +sequenceInit(void **vqueue, uint64_t seqnum, + int do_replay, int do_sequence, int wide_nums); + +/* Helper macros */ +#define GSSEAP_CALLOC(count, size) (calloc((count), (size))) +#define GSSEAP_FREE(ptr) (free((ptr))) +#define GSSEAP_MALLOC(size) (malloc((size))) +#define GSSEAP_REALLOC(ptr, size) (realloc((ptr), (size))) + +#define GSSEAP_NOT_IMPLEMENTED do { \ + assert(0 && "not implemented"); \ + *minor = ENOSYS; \ + return GSS_S_FAILURE; \ + } while (0) + +/* Helper functions */ +static inline void +store_uint16_be(uint16_t val, void *vp) +{ + unsigned char *p = (unsigned char *)vp; + + p[0] = (val >> 8) & 0xff; + p[1] = (val ) & 0xff; +} + +static inline uint16_t +load_uint16_be(const void *cvp) +{ + const unsigned char *p = (const unsigned char *)cvp; + + return (p[1] | (p[0] << 8)); +} + +static inline void +store_uint32_be(uint32_t val, void *vp) +{ + unsigned char *p = (unsigned char *)vp; + + p[0] = (val >> 24) & 0xff; + p[1] = (val >> 16) & 0xff; + p[2] = (val >> 8) & 0xff; + p[3] = (val ) & 0xff; +} + +static inline uint32_t +load_uint32_be(const void *cvp) +{ + const unsigned char *p = (const unsigned char *)cvp; + + return (p[3] | (p[2] << 8) + | ((uint32_t) p[1] << 16) + | ((uint32_t) p[0] << 24)); +} + +static inline void +store_uint64_be(uint64_t val, void *vp) +{ + unsigned char *p = (unsigned char *)vp; + + p[0] = (unsigned char)((val >> 56) & 0xff); + p[1] = (unsigned char)((val >> 48) & 0xff); + p[2] = (unsigned char)((val >> 40) & 0xff); + p[3] = (unsigned char)((val >> 32) & 0xff); + p[4] = (unsigned char)((val >> 24) & 0xff); + p[5] = (unsigned char)((val >> 16) & 0xff); + p[6] = (unsigned char)((val >> 8) & 0xff); + p[7] = (unsigned char)((val ) & 0xff); +} + +static inline uint64_t +load_uint64_be(const void *cvp) +{ + const unsigned char *p = (const unsigned char *)cvp; + + return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4); +} + +#endif /* _UTIL_H_ */ diff --git a/util_cksum.c b/util_cksum.c index 4852127..d2b0bd8 100644 --- a/util_cksum.c +++ b/util_cksum.c @@ -75,7 +75,8 @@ gssEapChecksum(krb5_context context, if (verify) *valid = FALSE; - code = krb5_c_crypto_length(context, KRB_KEYTYPE(key), KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen); + code = krb5_c_crypto_length(context, KRB_KEYTYPE(key), + KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen); if (code != 0) return code; @@ -102,7 +103,7 @@ gssEapChecksum(krb5_context context, /* Data */ for (j = 0; j < iov_count; j++) { - kiov[i].flags = gssEapTranslateCryptoFlag(iov[j].type); + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type); kiov[i].data.length = iov[j].buffer.length; kiov[i].data.data = (char *)iov[j].buffer.value; i++; diff --git a/util_context.c b/util_context.c index 7121d7f..b0a9e52 100644 --- a/util_context.c +++ b/util_context.c @@ -98,6 +98,8 @@ gssEapReleaseContext(OM_uint32 *minor, gssEapReleaseName(&tmpMinor, &ctx->initiatorName); gssEapReleaseName(&tmpMinor, &ctx->acceptorName); + sequenceFree(ctx->seqState); + memset(ctx, 0, sizeof(*ctx)); GSSEAP_FREE(ctx); *pCtx = GSS_C_NO_CONTEXT; diff --git a/util_crypt.c b/util_crypt.c index 48f5a5e..e4d5d0d 100644 --- a/util_crypt.c +++ b/util_crypt.c @@ -85,10 +85,10 @@ * RRC is rotate count. */ static krb5_error_code -translateIov(krb5_context context, int dce_style, size_t ec, size_t rrc, - krb5_enctype enctype, gss_iov_buffer_desc *iov, - int iov_count, krb5_crypto_iov **pkiov, - size_t *pkiov_count) +mapIov(krb5_context context, int dce_style, size_t ec, size_t rrc, + krb5_enctype enctype, gss_iov_buffer_desc *iov, + int iov_count, krb5_crypto_iov **pkiov, + size_t *pkiov_count) { gss_iov_buffer_t header; gss_iov_buffer_t trailer; @@ -156,7 +156,7 @@ translateIov(krb5_context context, int dce_style, size_t ec, size_t rrc, i++; for (j = 0; j < iov_count; j++) { - kiov[i].flags = gssEapTranslateCryptoFlag(iov[j].type); + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type); if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY) continue; @@ -219,9 +219,9 @@ gssEapEncrypt(krb5_context context, int dce_style, size_t ec, pivd = NULL; } - code = translateIov(context, dce_style, ec, rrc, - KRB_KEYTYPE(key), iov, iov_count, - &kiov, &kiov_count); + code = mapIov(context, dce_style, ec, rrc, + KRB_KEYTYPE(key), iov, iov_count, + &kiov, &kiov_count); if (code == 0) { code = krb5_c_encrypt_iov(context, key, usage, pivd, kiov, kiov_count); GSSEAP_FREE(kiov); @@ -259,9 +259,9 @@ gssEapDecrypt(krb5_context context, int dce_style, size_t ec, pivd = NULL; } - code = translateIov(context, dce_style, ec, rrc, - KRB_KEYTYPE(key), iov, iov_count, - &kiov, &kiov_count); + code = mapIov(context, dce_style, ec, rrc, + KRB_KEYTYPE(key), iov, iov_count, + &kiov, &kiov_count); if (code == 0) { code = krb5_c_decrypt_iov(context, key, usage, pivd, kiov, kiov_count); GSSEAP_FREE(kiov); @@ -274,7 +274,7 @@ gssEapDecrypt(krb5_context context, int dce_style, size_t ec, } krb5_cryptotype -gssEapTranslateCryptoFlag(OM_uint32 type) +gssEapMapCryptoFlag(OM_uint32 type) { krb5_cryptotype ktype; diff --git a/wrap_iov.c b/wrap_iov.c index 7bf7f94..0b172f8 100644 --- a/wrap_iov.c +++ b/wrap_iov.c @@ -76,18 +76,17 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, unsigned int gss_headerlen, gss_trailerlen; size_t data_length, assoc_data_length; - if (!CTX_IS_ESTABLISHED(ctx)) { + if (!CTX_IS_ESTABLISHED(ctx)) return GSS_S_NO_CONTEXT; - } acceptor_flag = CTX_IS_INITIATOR(ctx) ? 0 : TOK_FLAG_SENDER_IS_ACCEPTOR; key_usage = ((toktype == TOK_TYPE_WRAP) ? (CTX_IS_INITIATOR(ctx) - ? KRB_USAGE_INITIATOR_SEAL - : KRB_USAGE_ACCEPTOR_SEAL) + ? KEY_USAGE_INITIATOR_SEAL + : KEY_USAGE_ACCEPTOR_SEAL) : (CTX_IS_INITIATOR(ctx) - ? KRB_USAGE_INITIATOR_SIGN - : KRB_USAGE_ACCEPTOR_SIGN)); + ? KEY_USAGE_INITIATOR_SIGN + : KEY_USAGE_ACCEPTOR_SIGN)); gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length); @@ -163,7 +162,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, } /* TOK_ID */ - store_16_be((uint16_t)toktype, outbuf); + store_uint16_be((uint16_t)toktype, outbuf); /* flags */ outbuf[2] = (acceptor_flag | (conf_req_flag ? TOK_FLAG_WRAP_CONFIDENTIAL : 0) @@ -171,12 +170,15 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, /* filler */ outbuf[3] = 0xFF; /* EC */ - store_16_be(ec, outbuf + 4); + store_uint16_be(ec, outbuf + 4); /* RRC */ - store_16_be(0, outbuf + 6); + store_uint16_be(0, outbuf + 6); store_64_be(ctx->sendSeq, outbuf + 8); - /* EC | copy of header to be encrypted, located in (possibly rotated) trailer */ + /* + * EC | copy of header to be encrypted, located in + * (possibly rotated) trailer + */ if (trailer == NULL) tbuf = (unsigned char *)header->buffer.value + 16; /* Header */ else @@ -193,7 +195,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, goto cleanup; /* RRC */ - store_16_be(rrc, outbuf + 6); + store_uint16_be(rrc, outbuf + 6); ctx->sendSeq++; } else if (toktype == TOK_TYPE_WRAP && !conf_req_flag) { @@ -234,7 +236,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, } /* TOK_ID */ - store_16_be((uint16_t)toktype, outbuf); + store_uint16_be((uint16_t)toktype, outbuf); /* flags */ outbuf[2] = (acceptor_flag | (0 ? TOK_FLAG_ACCEPTOR_SUBKEY : 0)); @@ -245,13 +247,13 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, * checksum length later. */ /* EC */ - store_16_be(0, outbuf + 4); + store_uint16_be(0, outbuf + 4); /* RRC */ - store_16_be(0, outbuf + 6); + store_uint16_be(0, outbuf + 6); } else { /* MIC and DEL store 0xFF in EC and RRC */ - store_16_be(0xFFFF, outbuf + 4); - store_16_be(0xFFFF, outbuf + 6); + store_uint16_be(0xFFFF, outbuf + 4); + store_uint16_be(0xFFFF, outbuf + 6); } store_64_be(ctx->sendSeq, outbuf + 8); @@ -265,9 +267,9 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, if (toktype == TOK_TYPE_WRAP) { /* Fix up EC field */ - store_16_be(gss_trailerlen, outbuf + 4); + store_uint16_be(gss_trailerlen, outbuf + 4); /* Fix up RRC field */ - store_16_be(rrc, outbuf + 6); + store_uint16_be(rrc, outbuf + 6); } } else if (toktype == TOK_TYPE_MIC) { trailer = NULL;