2 * Copyright (c) 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "gsskrb5_locl.h"
39 iov_allocate(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count)
43 for (i = 0; i < iov_count; i++) {
44 if (GSS_IOV_BUFFER_FLAGS(iov[i].type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE){
45 void *ptr = malloc(iov[i].buffer.length);
48 if (iov[i].buffer.value)
49 memcpy(ptr, iov[i].buffer.value, iov[i].buffer.length);
50 iov[i].buffer.value = ptr;
51 iov[i].type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
54 return GSS_S_COMPLETE;
58 iov_map(OM_uint32 *minor_status,
59 const gss_iov_buffer_desc *iov,
61 krb5_crypto_iov *data)
65 for (i = 0; i < iov_count; i++) {
66 switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
67 case GSS_IOV_BUFFER_TYPE_EMPTY:
68 data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
70 case GSS_IOV_BUFFER_TYPE_DATA:
71 data[i].flags = KRB5_CRYPTO_TYPE_DATA;
73 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
74 data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
76 case GSS_IOV_BUFFER_TYPE_HEADER:
77 data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
79 case GSS_IOV_BUFFER_TYPE_TRAILER:
80 data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
82 case GSS_IOV_BUFFER_TYPE_PADDING:
83 data[i].flags = KRB5_CRYPTO_TYPE_PADDING;
85 case GSS_IOV_BUFFER_TYPE_STREAM:
89 *minor_status = EINVAL;
92 data[i].data.data = iov[i].buffer.value;
93 data[i].data.length = iov[i].buffer.length;
95 return GSS_S_COMPLETE;
98 OM_uint32 GSSAPI_LIB_FUNCTION
99 _gk_wrap_iov(OM_uint32 * minor_status,
100 gss_ctx_id_t context_handle,
104 gss_iov_buffer_desc *iov,
107 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
108 krb5_context context;
109 OM_uint32 major_status, junk;
110 krb5_crypto_iov *data;
114 GSSAPI_KRB5_INIT (&context);
116 major_status = iov_allocate(minor_status, iov, iov_count);
117 if (major_status != GSS_S_COMPLETE)
120 data = calloc(iov_count, sizeof(data[0]));
122 gss_release_iov_buffer(&junk, iov, iov_count);
123 *minor_status = ENOMEM;
124 return GSS_S_FAILURE;
127 major_status = iov_map(minor_status, iov, iov_count, data);
128 if (major_status != GSS_S_COMPLETE) {
129 gss_release_iov_buffer(&junk, iov, iov_count);
134 if (ctx->more_flags & LOCAL) {
135 usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
137 usage = KRB5_KU_USAGE_INITIATOR_SIGN;
140 ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage,
141 data, iov_count, NULL);
144 gss_release_iov_buffer(&junk, iov, iov_count);
146 return GSS_S_FAILURE;
150 return GSS_S_COMPLETE;
153 OM_uint32 GSSAPI_LIB_FUNCTION
154 _gk_unwrap_iov(OM_uint32 *minor_status,
155 gss_ctx_id_t context_handle,
157 gss_qop_t *qop_state,
158 gss_iov_buffer_desc *iov,
161 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
162 krb5_context context;
164 OM_uint32 major_status, junk;
165 krb5_crypto_iov *data;
168 GSSAPI_KRB5_INIT (&context);
170 major_status = iov_allocate(minor_status, iov, iov_count);
171 if (major_status != GSS_S_COMPLETE)
174 data = calloc(iov_count, sizeof(data[0]));
176 gss_release_iov_buffer(&junk, iov, iov_count);
177 *minor_status = ENOMEM;
178 return GSS_S_FAILURE;
181 major_status = iov_map(minor_status, iov, iov_count, data);
182 if (major_status != GSS_S_COMPLETE) {
183 gss_release_iov_buffer(&junk, iov, iov_count);
188 if (ctx->more_flags & LOCAL) {
189 usage = KRB5_KU_USAGE_INITIATOR_SIGN;
191 usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
194 ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage,
195 data, iov_count, NULL);
199 gss_release_iov_buffer(&junk, iov, iov_count);
200 return GSS_S_FAILURE;
204 return GSS_S_COMPLETE;
207 OM_uint32 GSSAPI_LIB_FUNCTION
208 _gk_wrap_iov_length(OM_uint32 * minor_status,
209 gss_ctx_id_t context_handle,
213 gss_iov_buffer_desc *iov,
216 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
217 krb5_context context;
220 size_t *padding = NULL;
222 GSSAPI_KRB5_INIT (&context);
225 for (size = 0, i = 0; i < iov_count; i++) {
226 switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
227 case GSS_IOV_BUFFER_TYPE_EMPTY:
229 case GSS_IOV_BUFFER_TYPE_DATA:
230 size += iov[i].buffer.length;
232 case GSS_IOV_BUFFER_TYPE_HEADER:
233 iov[i].buffer.length =
234 krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER);
235 size += iov[i].buffer.length;
237 case GSS_IOV_BUFFER_TYPE_TRAILER:
238 iov[i].buffer.length =
239 krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER);
240 size += iov[i].buffer.length;
242 case GSS_IOV_BUFFER_TYPE_PADDING:
243 if (padding != NULL) {
245 return GSS_S_FAILURE;
247 padding = &iov[i].buffer.length;
249 case GSS_IOV_BUFFER_TYPE_STREAM:
250 size += iov[i].buffer.length;
252 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
255 *minor_status = EINVAL;
256 return GSS_S_FAILURE;
260 size_t pad = krb5_crypto_length(context, ctx->crypto,
261 KRB5_CRYPTO_TYPE_PADDING);
263 *padding = pad - (size % pad);
270 return GSS_S_COMPLETE;