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 * lib/gssapi/krb5/k5sealv3iov.c
35 * Copyright 2008 by the Massachusetts Institute of Technology.
36 * All Rights Reserved.
38 * Export of this software from the United States of America may
39 * require a specific license from the United States Government.
40 * It is the responsibility of any person or organization contemplating
41 * export to obtain such a license before exporting.
43 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
44 * distribute this software and its documentation for any purpose and
45 * without fee is hereby granted, provided that the above copyright
46 * notice appear in all copies and that both that copyright notice and
47 * this permission notice appear in supporting documentation, and that
48 * the name of M.I.T. not be used in advertising or publicity pertaining
49 * to distribution of the software without specific, written prior
50 * permission. Furthermore if you modify this software you must label
51 * your software as modified software and not distribute it in such a
52 * fashion that it might be confused with the original M.I.T. software.
53 * M.I.T. makes no representations about the suitability of
54 * this software for any purpose. It is provided "as is" without express
55 * or implied warranty.
60 #include "gssapiP_eap.h"
63 gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
67 gss_iov_buffer_desc *iov,
69 enum gss_eap_token_type toktype)
72 gss_iov_buffer_t header;
73 gss_iov_buffer_t padding;
74 gss_iov_buffer_t trailer;
75 unsigned char acceptor_flag;
76 unsigned char *ptr = NULL;
79 size_t data_length, assoc_data_length;
82 krb5_cksumtype cksumtype;
87 if (qop_state != NULL)
88 *qop_state = GSS_C_QOP_DEFAULT;
90 if (!CTX_IS_ESTABLISHED(ctx))
91 return GSS_S_NO_CONTEXT;
93 header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
94 assert(header != NULL);
96 padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
97 if (padding != NULL && padding->buffer.length != 0)
98 return GSS_S_DEFECTIVE_TOKEN;
100 trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
102 acceptor_flag = CTX_IS_INITIATOR(ctx) ? TOK_FLAG_SENDER_IS_ACCEPTOR : 0;
103 key_usage = (toktype == TOK_TYPE_WRAP
104 ? (!CTX_IS_INITIATOR(ctx)
105 ? KRB_USAGE_INITIATOR_SEAL
106 : KRB_USAGE_ACCEPTOR_SEAL)
107 : (!CTX_IS_INITIATOR(ctx)
108 ? KRB_USAGE_INITIATOR_SIGN
109 : KRB_USAGE_ACCEPTOR_SIGN));
111 gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length);
113 ptr = (unsigned char *)header->buffer.value;
115 if (header->buffer.length < 16) {
117 return GSS_S_DEFECTIVE_TOKEN;
120 if ((ptr[2] & TOK_FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
121 return GSS_S_BAD_SIG;
124 if (ptr[2] & TOK_FLAG_ACCEPTOR_SUBKEY) {
125 return GSS_S_BAD_SIG;
128 if (toktype == TOK_TYPE_WRAP) {
129 unsigned int k5_trailerlen;
131 if (load_16_be(ptr) != TOK_TYPE_WRAP)
133 conf_flag = ((ptr[2] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
136 ec = load_16_be(ptr + 4);
137 rrc = load_16_be(ptr + 6);
138 seqnum = load_64_be(ptr + 8);
140 code = krb5_c_crypto_length(ctx->kerberosCtx,
141 KRB_KEYTYPE(ctx->encryptionKey),
142 conf_flag ? KRB5_CRYPTO_TYPE_TRAILER :
143 KRB5_CRYPTO_TYPE_CHECKSUM,
146 *minor_status = code;
147 return GSS_S_FAILURE;
151 if (trailer == NULL) {
152 size_t desired_rrc = k5_trailerlen;
155 desired_rrc += 16; /* E(Header) */
157 if ((ctx->gssFlags & GSS_C_DCE_STYLE) == 0)
161 /* According to MS, we only need to deal with a fixed RRC for DCE */
162 if (rrc != desired_rrc)
164 } else if (rrc != 0) {
169 unsigned char *althdr;
172 code = gssEapDecrypt(ctx->kerberosCtx,
173 ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0),
174 ec, rrc, ctx->encryptionKey,
175 key_usage, 0, iov, iov_count);
177 *minor_status = code;
178 return GSS_S_BAD_SIG;
181 /* Validate header integrity */
183 althdr = (unsigned char *)header->buffer.value + 16 + ec;
185 althdr = (unsigned char *)trailer->buffer.value + ec;
187 if (load_16_be(althdr) != TOK_TYPE_WRAP
188 || althdr[2] != ptr[2]
189 || althdr[3] != ptr[3]
190 || memcmp(althdr + 8, ptr + 8, 8) != 0) {
192 return GSS_S_BAD_SIG;
195 /* Verify checksum: note EC is checksum size here, not padding */
196 if (ec != k5_trailerlen)
199 /* Zero EC, RRC before computing checksum */
200 store_16_be(0, ptr + 4);
201 store_16_be(0, ptr + 6);
203 code = gssEapVerify(ctx->kerberosCtx, cksumtype, rrc,
204 ctx->encryptionKey, key_usage,
205 iov, iov_count, &valid);
206 if (code != 0 || valid == FALSE) {
207 *minor_status = code;
208 return GSS_S_BAD_SIG;
212 code = g_order_check(&ctx->seqState, seqnum);
213 } else if (toktype == TOK_TYPE_MIC) {
214 if (load_16_be(ptr) != TOK_TYPE_MIC)
220 seqnum = load_64_be(ptr + 8);
222 code = gssEapVerify(ctx->kerberosCtx, cksumtype, 0,
223 ctx->encryptionKey, key_usage,
224 iov, iov_count, &valid);
225 if (code != 0 || valid == FALSE) {
226 *minor_status = code;
227 return GSS_S_BAD_SIG;
229 code = g_order_check(&ctx->seqState, seqnum);
230 } else if (toktype == TOK_TYPE_DELETE) {
231 if (load_16_be(ptr) != TOK_TYPE_DELETE)
240 if (conf_state != NULL)
241 *conf_state = conf_flag;
248 return GSS_S_DEFECTIVE_TOKEN;
252 gss_unwrap_iov(OM_uint32 *minor,
255 gss_qop_t *qop_state,
256 gss_iov_buffer_desc *iov,
259 return gssEapUnwrapOrVerifyMIC(minor, ctx,
260 iov, iov_count, conf_state,
261 qop_state, TOK_TYPE_WRAP);