X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=blobdiff_plain;f=unwrap_iov.c;h=3cec4f09b02e7bbe2aa32f993a65c4c12855f31c;hp=264e137f41dad24353e8f9ade53851e9938abe0a;hb=6800e2157097202a9e1e8ff414fb484ef4607bde;hpb=2726871e0ab92938b385d2a1e6deef44ecb208b8 diff --git a/unwrap_iov.c b/unwrap_iov.c index 264e137..3cec4f0 100644 --- a/unwrap_iov.c +++ b/unwrap_iov.c @@ -29,10 +29,226 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +/* + * lib/gssapi/krb5/k5sealv3iov.c + * + * Copyright 2008 by the 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. + * + * + */ #include "gssapiP_eap.h" 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) +{ + OM_uint32 code; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + unsigned char acceptor_flag; + unsigned char *ptr = NULL; + int key_usage; + size_t rrc, ec; + size_t data_length, assoc_data_length; + uint64_t seqnum; + krb5_boolean valid; + krb5_cksumtype cksumtype; + int conf_flag = 0; + + *minor_status = 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); + + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL && padding->buffer.length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + 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) + ? KRB_USAGE_INITIATOR_SEAL + : KRB_USAGE_ACCEPTOR_SEAL) + : (!CTX_IS_INITIATOR(ctx) + ? KRB_USAGE_INITIATOR_SIGN + : KRB_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; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((ptr[2] & TOK_FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { + return GSS_S_BAD_SIG; + } + + if (ptr[2] & TOK_FLAG_ACCEPTOR_SUBKEY) { + return GSS_S_BAD_SIG; + } + + if (toktype == TOK_TYPE_WRAP) { + unsigned int k5_trailerlen; + + if (load_16_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); + + code = krb5_c_crypto_length(ctx->kerberosCtx, + KRB_KEYTYPE(ctx->encryptionKey), + conf_flag ? KRB5_CRYPTO_TYPE_TRAILER : + KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + /* Deal with RRC */ + if (trailer == NULL) { + size_t desired_rrc = k5_trailerlen; + + if (conf_flag) { + desired_rrc += 16; /* E(Header) */ + + if ((ctx->gssFlags & GSS_C_DCE_STYLE) == 0) + desired_rrc += ec; + } + + /* According to MS, we only need to deal with a fixed RRC for DCE */ + if (rrc != desired_rrc) + goto defective; + } else if (rrc != 0) { + goto defective; + } + + if (conf_flag) { + unsigned char *althdr; + + /* Decrypt */ + code = gssEapDecrypt(ctx->kerberosCtx, + ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0), + ec, rrc, ctx->encryptionKey, + key_usage, 0, iov, iov_count); + if (code != 0) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + + /* Validate header integrity */ + if (trailer == NULL) + althdr = (unsigned char *)header->buffer.value + 16 + ec; + else + althdr = (unsigned char *)trailer->buffer.value + ec; + + if (load_16_be(althdr) != TOK_TYPE_WRAP + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] + || memcmp(althdr + 8, ptr + 8, 8) != 0) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + } else { + /* Verify checksum: note EC is checksum size here, not padding */ + if (ec != k5_trailerlen) + goto defective; + + /* Zero EC, RRC before computing checksum */ + store_16_be(0, ptr + 4); + store_16_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; + return GSS_S_BAD_SIG; + } + } + + code = g_order_check(&ctx->seqState, seqnum); + } else if (toktype == TOK_TYPE_MIC) { + if (load_16_be(ptr) != TOK_TYPE_MIC) + goto defective; + + verify_mic_1: + if (ptr[3] != 0xFF) + goto defective; + seqnum = load_64_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; + return GSS_S_BAD_SIG; + } + code = g_order_check(&ctx->seqState, seqnum); + } else if (toktype == TOK_TYPE_DELETE) { + if (load_16_be(ptr) != TOK_TYPE_DELETE) + goto defective; + goto verify_mic_1; + } else { + goto defective; + } + + *minor_status = 0; + + if (conf_state != NULL) + *conf_state = conf_flag; + + return code; + +defective: + *minor_status = 0; + + return GSS_S_DEFECTIVE_TOKEN; +} + +OM_uint32 gss_unwrap_iov(OM_uint32 *minor, gss_ctx_id_t ctx, int *conf_state, @@ -40,5 +256,8 @@ gss_unwrap_iov(OM_uint32 *minor, gss_iov_buffer_desc *iov, int iov_count) { - GSSEAP_NOT_IMPLEMENTED; + return gssEapUnwrapOrVerifyMIC(minor, ctx, + iov, iov_count, conf_state, + qop_state, TOK_TYPE_WRAP); + }