2 * Copyright (c) 2010, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include "gssapiP_eap.h"
35 #define INIT_IOV_DATA(_iov) do { (_iov)->buffer.value = NULL; \
36 (_iov)->buffer.length = 0; } \
40 gss_wrap_iov_length(OM_uint32 *minor,
45 gss_iov_buffer_desc *iov,
48 gss_iov_buffer_t header, trailer, padding;
49 size_t dataLength, assocDataLength;
50 size_t gssHeaderLen, gssPadLen, gssTrailerLen;
51 unsigned int krbHeaderLen = 0, krbTrailerLen = 0, krbPadLen = 0;
53 krb5_context krbContext;
57 if (qop_req != GSS_C_QOP_DEFAULT)
60 if (!CTX_IS_ESTABLISHED(ctx))
61 return GSS_S_NO_CONTEXT;
63 GSSEAP_KRB_INIT(&krbContext);
65 header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
70 INIT_IOV_DATA(header);
72 trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
73 if (trailer != NULL) {
74 INIT_IOV_DATA(trailer);
77 dce_style = ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0);
79 /* For CFX, EC is used instead of padding, and is placed in header or trailer */
80 padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
81 if (padding != NULL) {
82 INIT_IOV_DATA(padding);
85 gssEapIovMessageLength(iov, iov_count, &dataLength, &assocDataLength);
87 if (conf_req_flag && gssEapIsIntegrityOnly(iov, iov_count))
88 conf_req_flag = FALSE;
90 gssHeaderLen = gssPadLen = gssTrailerLen = 0;
92 code = krb5_c_crypto_length(krbContext, ctx->encryptionType,
94 KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM,
102 code = krb5_c_crypto_length(krbContext, ctx->encryptionType,
103 KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
106 return GSS_S_FAILURE;
110 gssHeaderLen = 16; /* Header */
112 gssHeaderLen += krbHeaderLen; /* Kerb-Header */
113 gssTrailerLen = 16 /* E(Header) */ + krbTrailerLen; /* Kerb-Trailer */
115 code = krb5_c_padding_length(krbContext, ctx->encryptionType,
116 dataLength - assocDataLength + 16 /* E(Header) */,
120 return GSS_S_FAILURE;
123 if (krbPadLen == 0 && dce_style) {
124 /* Windows rejects AEAD tokens with non-zero EC */
125 code = krb5_c_block_size(krbContext, ctx->encryptionType, &ec);
128 return GSS_S_FAILURE;
135 gssTrailerLen = krbTrailerLen; /* Kerb-Checksum */
138 dataLength += gssPadLen;
141 gssHeaderLen += gssTrailerLen;
143 trailer->buffer.length = gssTrailerLen;
145 assert(gssPadLen == 0 || padding != NULL);
148 padding->buffer.length = gssPadLen;
150 header->buffer.length = gssHeaderLen;
152 if (conf_state != NULL)
153 *conf_state = conf_req_flag;
156 return GSS_S_COMPLETE;