From b34c3f0b3501f316b4f1e907bc13f63917777bc4 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Wed, 8 Sep 2010 12:54:38 +0200 Subject: [PATCH] Implement get/verify_mic --- mech_eap/get_mic.c | 24 ++++++++++-- mech_eap/gssapiP_eap.h | 2 +- mech_eap/pseudo_random.c | 6 +-- mech_eap/unwrap_iov.c | 56 ++++++++++++++-------------- mech_eap/util_context.c | 4 +- mech_eap/verify_mic.c | 14 ++++++- mech_eap/wrap_iov.c | 96 ++++++++++++++++++++++++------------------------ 7 files changed, 113 insertions(+), 89 deletions(-) diff --git a/mech_eap/get_mic.c b/mech_eap/get_mic.c index 5b391b6..c91d63b 100644 --- a/mech_eap/get_mic.c +++ b/mech_eap/get_mic.c @@ -34,10 +34,28 @@ OM_uint32 gss_get_mic(OM_uint32 *minor, - gss_ctx_id_t context_handle, - gss_qop_t qop_req, + gss_ctx_id_t ctx, + gss_qop_t qop_req __attribute__((__unused__)), gss_buffer_t message_buffer, gss_buffer_t message_token) { - GSSEAP_NOT_IMPLEMENTED; + OM_uint32 major; + gss_iov_buffer_desc iov[2]; + + message_token->value = NULL; + message_token->length = 0; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer = *message_buffer; + + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[1].buffer.value = NULL; + iov[1].buffer.length = 0; + + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, FALSE, iov, 2, TOK_TYPE_MIC); + if (major == GSS_S_COMPLETE) { + *message_token = iov[1].buffer; + } + + return major; } diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h index b6e4b04..787b170 100644 --- a/mech_eap/gssapiP_eap.h +++ b/mech_eap/gssapiP_eap.h @@ -118,7 +118,7 @@ struct gss_ctx_id_struct { gss_OID mechanismUsed; krb5_enctype encryptionType; krb5_cksumtype checksumType; - krb5_keyblock *encryptionKey; + krb5_keyblock *rfc3961Key; gss_name_t initiatorName; gss_name_t acceptorName; time_t expiryTime; diff --git a/mech_eap/pseudo_random.c b/mech_eap/pseudo_random.c index 105a0d1..723a27b 100644 --- a/mech_eap/pseudo_random.c +++ b/mech_eap/pseudo_random.c @@ -30,8 +30,6 @@ * SUCH DAMAGE. */ /* - * lib/gssapi/krb5/prf.c - * * Copyright 2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * @@ -53,8 +51,6 @@ * 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" @@ -129,7 +125,7 @@ gss_pseudo_random(OM_uint32 *minor, while (desired_output_len > 0) { store_uint32_be(i, ns.data); - code = krb5_c_prf(ctx->kerberosCtx, ctx->encryptionKey, &ns, &t); + code = krb5_c_prf(ctx->kerberosCtx, ctx->rfc3961Key, &ns, &t); if (code != 0) goto cleanup; diff --git a/mech_eap/unwrap_iov.c b/mech_eap/unwrap_iov.c index 45c4b25..05ac8d9 100644 --- a/mech_eap/unwrap_iov.c +++ b/mech_eap/unwrap_iov.c @@ -73,11 +73,11 @@ unwrapToken(OM_uint32 *minor, gss_iov_buffer_t header; gss_iov_buffer_t padding; gss_iov_buffer_t trailer; - unsigned char acceptor_flag; + unsigned char acceptorFlag; unsigned char *ptr = NULL; - int key_usage; + int keyUsage; size_t rrc, ec; - size_t data_length, assoc_data_length; + size_t dataLen, assocDataLen; uint64_t seqnum; int valid = 0; krb5_cksumtype cksumtype; @@ -97,16 +97,16 @@ unwrapToken(OM_uint32 *minor, trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); - acceptor_flag = CTX_IS_INITIATOR(ctx) ? TOK_FLAG_SENDER_IS_ACCEPTOR : 0; - key_usage = (toktype == TOK_TYPE_WRAP - ? (!CTX_IS_INITIATOR(ctx) - ? KEY_USAGE_INITIATOR_SEAL - : KEY_USAGE_ACCEPTOR_SEAL) - : (!CTX_IS_INITIATOR(ctx) - ? KEY_USAGE_INITIATOR_SIGN - : KEY_USAGE_ACCEPTOR_SIGN)); + acceptorFlag = CTX_IS_INITIATOR(ctx) ? TOK_FLAG_SENDER_IS_ACCEPTOR : 0; + keyUsage = (toktype == TOK_TYPE_WRAP + ? (!CTX_IS_INITIATOR(ctx) + ? KEY_USAGE_INITIATOR_SEAL + : KEY_USAGE_ACCEPTOR_SEAL) + : (!CTX_IS_INITIATOR(ctx) + ? KEY_USAGE_INITIATOR_SIGN + : KEY_USAGE_ACCEPTOR_SIGN)); - gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length); + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen); ptr = (unsigned char *)header->buffer.value; @@ -115,7 +115,7 @@ unwrapToken(OM_uint32 *minor, return GSS_S_DEFECTIVE_TOKEN; } - if ((ptr[2] & TOK_FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { + if ((ptr[2] & TOK_FLAG_SENDER_IS_ACCEPTOR) != acceptorFlag) { return GSS_S_BAD_SIG; } @@ -124,7 +124,7 @@ unwrapToken(OM_uint32 *minor, } if (toktype == TOK_TYPE_WRAP) { - unsigned int k5_trailerlen; + unsigned int krbTrailerLen; if (load_uint16_be(ptr) != TOK_TYPE_WRAP) goto defective; @@ -136,10 +136,10 @@ unwrapToken(OM_uint32 *minor, seqnum = load_uint64_be(ptr + 8); code = krb5_c_crypto_length(ctx->kerberosCtx, - KRB_KEYTYPE(ctx->encryptionKey), + ctx->encryptionType, conf_flag ? KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, - &k5_trailerlen); + &krbTrailerLen); if (code != 0) { *minor = code; return GSS_S_FAILURE; @@ -147,7 +147,7 @@ unwrapToken(OM_uint32 *minor, /* Deal with RRC */ if (trailer == NULL) { - size_t desired_rrc = k5_trailerlen; + size_t desired_rrc = krbTrailerLen; if (conf_flag) { desired_rrc += 16; /* E(Header) */ @@ -169,8 +169,8 @@ unwrapToken(OM_uint32 *minor, /* Decrypt */ code = gssEapDecrypt(ctx->kerberosCtx, ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0), - ec, rrc, ctx->encryptionKey, - key_usage, 0, iov, iov_count); + ec, rrc, ctx->rfc3961Key, + keyUsage, 0, iov, iov_count); if (code != 0) { *minor = code; return GSS_S_BAD_SIG; @@ -191,7 +191,7 @@ unwrapToken(OM_uint32 *minor, } } else { /* Verify checksum: note EC is checksum size here, not padding */ - if (ec != k5_trailerlen) + if (ec != krbTrailerLen) goto defective; /* Zero EC, RRC before computing checksum */ @@ -199,7 +199,7 @@ unwrapToken(OM_uint32 *minor, store_uint16_be(0, ptr + 6); code = gssEapVerify(ctx->kerberosCtx, cksumtype, rrc, - ctx->encryptionKey, key_usage, + ctx->rfc3961Key, keyUsage, iov, iov_count, &valid); if (code != 0 || valid == FALSE) { *minor = code; @@ -218,7 +218,7 @@ unwrapToken(OM_uint32 *minor, seqnum = load_uint64_be(ptr + 8); code = gssEapVerify(ctx->kerberosCtx, cksumtype, 0, - ctx->encryptionKey, key_usage, + ctx->rfc3961Key, keyUsage, iov, iov_count, &valid); if (code != 0 || valid == FALSE) { *minor = code; @@ -359,8 +359,8 @@ unwrapStream(OM_uint32 *minor, { size_t ec, rrc; - unsigned int k5_headerlen = 0; - unsigned int k5_trailerlen = 0; + unsigned int krbHeaderLen = 0; + unsigned int krbTrailerLen = 0; conf_req_flag = ((ptr[0] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0); ec = conf_req_flag ? load_uint16_be(ptr + 2) : 0; @@ -376,10 +376,10 @@ unwrapStream(OM_uint32 *minor, if (conf_req_flag) { code = krb5_c_crypto_length(context, ctx->encryptionType, - KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen); if (code != 0) goto cleanup; - theader->buffer.length += k5_headerlen; /* length validated later */ + theader->buffer.length += krbHeaderLen; /* length validated later */ } /* no PADDING for CFX, EC is used instead */ @@ -387,12 +387,12 @@ unwrapStream(OM_uint32 *minor, conf_req_flag ? KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, - &k5_trailerlen); + &krbTrailerLen); if (code != 0) goto cleanup; ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + - k5_trailerlen; + krbTrailerLen; ttrailer->buffer.value = (unsigned char *)stream->buffer.value + stream->buffer.length - ttrailer->buffer.length; } diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c index b0a9e52..a29bd7e 100644 --- a/mech_eap/util_context.c +++ b/mech_eap/util_context.c @@ -87,8 +87,8 @@ gssEapReleaseContext(OM_uint32 *minor, releaseAcceptorContext(&ctx->acceptorCtx); } - if (ctx->encryptionKey != NULL) { - krb5_free_keyblock(ctx->kerberosCtx, ctx->encryptionKey); + if (ctx->rfc3961Key != NULL) { + krb5_free_keyblock(ctx->kerberosCtx, ctx->rfc3961Key); } if (ctx->kerberosCtx != NULL) { diff --git a/mech_eap/verify_mic.c b/mech_eap/verify_mic.c index f642d17..ee19b01 100644 --- a/mech_eap/verify_mic.c +++ b/mech_eap/verify_mic.c @@ -34,10 +34,20 @@ OM_uint32 gss_verify_mic(OM_uint32 *minor, - gss_ctx_id_t context_handle, + gss_ctx_id_t ctx, gss_buffer_t message_buffer, gss_buffer_t message_token, gss_qop_t *qop_state) { - GSSEAP_NOT_IMPLEMENTED; + gss_iov_buffer_desc iov[2]; + int conf_state; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer = *message_buffer; + + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[1].buffer = *message_token; + + return gssEapUnwrapOrVerifyMIC(minor, ctx, &conf_state, qop_state, + iov, 2, TOK_TYPE_MIC); } diff --git a/mech_eap/wrap_iov.c b/mech_eap/wrap_iov.c index 0b172f8..cd17e06 100644 --- a/mech_eap/wrap_iov.c +++ b/mech_eap/wrap_iov.c @@ -68,27 +68,27 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, gss_iov_buffer_t header; gss_iov_buffer_t padding; gss_iov_buffer_t trailer; - unsigned char acceptor_flag; + unsigned char acceptorFlag; unsigned char *outbuf = NULL; unsigned char *tbuf = NULL; - int key_usage; + int keyUsage; size_t rrc = 0; - unsigned int gss_headerlen, gss_trailerlen; - size_t data_length, assoc_data_length; + unsigned int gssHeaderLen, gssTrailerLen; + size_t dataLen, assocDataLen; 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) - ? KEY_USAGE_INITIATOR_SEAL - : KEY_USAGE_ACCEPTOR_SEAL) - : (CTX_IS_INITIATOR(ctx) - ? KEY_USAGE_INITIATOR_SIGN - : KEY_USAGE_ACCEPTOR_SIGN)); + acceptorFlag = CTX_IS_INITIATOR(ctx) ? 0 : TOK_FLAG_SENDER_IS_ACCEPTOR; + keyUsage = ((toktype == TOK_TYPE_WRAP) + ? (CTX_IS_INITIATOR(ctx) + ? KEY_USAGE_INITIATOR_SEAL + : KEY_USAGE_ACCEPTOR_SEAL) + : (CTX_IS_INITIATOR(ctx) + ? KEY_USAGE_INITIATOR_SIGN + : KEY_USAGE_ACCEPTOR_SIGN)); - gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length); + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen); header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); if (header == NULL) { @@ -103,68 +103,68 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); if (toktype == TOK_TYPE_WRAP && conf_req_flag) { - unsigned int k5_headerlen, k5_trailerlen, k5_padlen; + unsigned int krbHeaderLen, krbTrailerLen, krbPadLen; size_t ec = 0; - size_t conf_data_length = data_length - assoc_data_length; + size_t confDataLen = dataLen - assocDataLen; code = krb5_c_crypto_length(ctx->kerberosCtx, ctx->encryptionType, - KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen); if (code != 0) goto cleanup; code = krb5_c_padding_length(ctx->kerberosCtx, ctx->encryptionType, - conf_data_length + 16 /* E(Header) */, - &k5_padlen); + confDataLen + 16 /* E(Header) */, + &krbPadLen); if (code != 0) goto cleanup; - if (k5_padlen == 0 && (ctx->gssFlags & GSS_C_DCE_STYLE)) { + if (krbPadLen == 0 && (ctx->gssFlags & GSS_C_DCE_STYLE)) { /* Windows rejects AEAD tokens with non-zero EC */ code = krb5_c_block_size(ctx->kerberosCtx, ctx->encryptionType, &ec); if (code != 0) goto cleanup; } else - ec = k5_padlen; + ec = krbPadLen; code = krb5_c_crypto_length(ctx->kerberosCtx, ctx->encryptionType, - KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen); + KRB5_CRYPTO_TYPE_TRAILER, &krbTrailerLen); if (code != 0) goto cleanup; - gss_headerlen = 16 /* Header */ + k5_headerlen; - gss_trailerlen = ec + 16 /* E(Header) */ + k5_trailerlen; + gssHeaderLen = 16 /* Header */ + krbHeaderLen; + gssTrailerLen = ec + 16 /* E(Header) */ + krbTrailerLen; if (trailer == NULL) { - rrc = gss_trailerlen; + rrc = gssTrailerLen; /* Workaround for Windows bug where it rotates by EC + RRC */ if (ctx->gssFlags & GSS_C_DCE_STYLE) rrc -= ec; - gss_headerlen += gss_trailerlen; + gssHeaderLen += gssTrailerLen; } if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { - code = gssEapAllocIov(header, (size_t) gss_headerlen); - } else if (header->buffer.length < gss_headerlen) + code = gssEapAllocIov(header, (size_t)gssHeaderLen); + } else if (header->buffer.length < gssHeaderLen) code = KRB5_BAD_MSIZE; if (code != 0) goto cleanup; outbuf = (unsigned char *)header->buffer.value; - header->buffer.length = (size_t) gss_headerlen; + header->buffer.length = (size_t)gssHeaderLen; if (trailer != NULL) { if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) - code = gssEapAllocIov(trailer, (size_t) gss_trailerlen); - else if (trailer->buffer.length < gss_trailerlen) + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen); + else if (trailer->buffer.length < gssTrailerLen) code = KRB5_BAD_MSIZE; if (code != 0) goto cleanup; - trailer->buffer.length = (size_t) gss_trailerlen; + trailer->buffer.length = (size_t)gssTrailerLen; } /* TOK_ID */ store_uint16_be((uint16_t)toktype, outbuf); /* flags */ - outbuf[2] = (acceptor_flag + outbuf[2] = (acceptorFlag | (conf_req_flag ? TOK_FLAG_WRAP_CONFIDENTIAL : 0) | (0 ? TOK_FLAG_ACCEPTOR_SUBKEY : 0)); /* filler */ @@ -189,8 +189,8 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, code = gssEapEncrypt(ctx->kerberosCtx, ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0), - ec, rrc, ctx->encryptionKey, - key_usage, 0, iov, iov_count); + ec, rrc, ctx->rfc3961Key, + keyUsage, 0, iov, iov_count); if (code != 0) goto cleanup; @@ -201,44 +201,44 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, } else if (toktype == TOK_TYPE_WRAP && !conf_req_flag) { wrap_with_checksum: - gss_headerlen = 16; + gssHeaderLen = 16; code = krb5_c_crypto_length(ctx->kerberosCtx, ctx->encryptionType, KRB5_CRYPTO_TYPE_CHECKSUM, - &gss_trailerlen); + &gssTrailerLen); if (code != 0) goto cleanup; - assert(gss_trailerlen <= 0xFFFF); + assert(gssTrailerLen <= 0xFFFF); if (trailer == NULL) { - rrc = gss_trailerlen; - gss_headerlen += gss_trailerlen; + rrc = gssTrailerLen; + gssHeaderLen += gssTrailerLen; } if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) - code = gssEapAllocIov(header, (size_t) gss_headerlen); - else if (header->buffer.length < gss_headerlen) + code = gssEapAllocIov(header, (size_t)gssHeaderLen); + else if (header->buffer.length < gssHeaderLen) code = KRB5_BAD_MSIZE; if (code != 0) goto cleanup; outbuf = (unsigned char *)header->buffer.value; - header->buffer.length = (size_t) gss_headerlen; + header->buffer.length = (size_t)gssHeaderLen; if (trailer != NULL) { if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) - code = gssEapAllocIov(trailer, (size_t) gss_trailerlen); - else if (trailer->buffer.length < gss_trailerlen) + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen); + else if (trailer->buffer.length < gssTrailerLen) code = KRB5_BAD_MSIZE; if (code != 0) goto cleanup; - trailer->buffer.length = (size_t) gss_trailerlen; + trailer->buffer.length = (size_t)gssTrailerLen; } /* TOK_ID */ store_uint16_be((uint16_t)toktype, outbuf); /* flags */ - outbuf[2] = (acceptor_flag + outbuf[2] = (acceptorFlag | (0 ? TOK_FLAG_ACCEPTOR_SUBKEY : 0)); /* filler */ outbuf[3] = 0xFF; @@ -258,7 +258,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, store_64_be(ctx->sendSeq, outbuf + 8); code = gssEapSign(ctx->kerberosCtx, ctx->checksumType, - rrc, ctx->encryptionKey, key_usage, + rrc, ctx->rfc3961Key, keyUsage, iov, iov_count); if (code != 0) goto cleanup; @@ -267,7 +267,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor, if (toktype == TOK_TYPE_WRAP) { /* Fix up EC field */ - store_uint16_be(gss_trailerlen, outbuf + 4); + store_uint16_be(gssTrailerLen, outbuf + 4); /* Fix up RRC field */ store_uint16_be(rrc, outbuf + 6); } -- 2.1.4