1 /* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */ 2 3 /* 4 * Copyright 1996 by Sun Microsystems, Inc. 5 * 6 * Permission to use, copy, modify, distribute, and sell this software 7 * and its documentation for any purpose is hereby granted without fee, 8 * provided that the above copyright notice appears in all copies and 9 * that both that copyright notice and this permission notice appear in 10 * supporting documentation, and that the name of Sun Microsystems not be used 11 * in advertising or publicity pertaining to distribution of the software 12 * without specific, written prior permission. Sun Microsystems makes no 13 * representations about the suitability of this software for any 14 * purpose. It is provided "as is" without express or implied warranty. 15 * 16 * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 20 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 * PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25 /* 26 * glue routine for gss_wrap_aead 27 */ 28 29 #include "mglueP.h" 30 31 static OM_uint32 32 val_wrap_aead_args( 33 OM_uint32 *minor_status, 34 gss_ctx_id_t context_handle, 35 int conf_req_flag, 36 gss_qop_t qop_req, 37 gss_buffer_t input_assoc_buffer, 38 gss_buffer_t input_payload_buffer, 39 int *conf_state, 40 gss_buffer_t output_message_buffer) 41 { 42 43 /* Initialize outputs. */ 44 45 if (minor_status != NULL) 46 *minor_status = 0; 47 48 /* Validate arguments. */ 49 50 if (minor_status == NULL) 51 return (GSS_S_CALL_INACCESSIBLE_WRITE); 52 53 if (context_handle == GSS_C_NO_CONTEXT) 54 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); 55 56 if (input_payload_buffer == GSS_C_NO_BUFFER) 57 return (GSS_S_CALL_INACCESSIBLE_READ); 58 59 if (output_message_buffer == GSS_C_NO_BUFFER) 60 return (GSS_S_CALL_INACCESSIBLE_WRITE); 61 62 return (GSS_S_COMPLETE); 63 } 64 65 static OM_uint32 66 gssint_wrap_aead_iov_shim(gss_mechanism mech, 67 OM_uint32 *minor_status, 68 gss_ctx_id_t context_handle, 69 int conf_req_flag, 70 gss_qop_t qop_req, 71 gss_buffer_t input_assoc_buffer, 72 gss_buffer_t input_payload_buffer, 73 int *conf_state, 74 gss_buffer_t output_message_buffer) 75 { 76 gss_iov_buffer_desc iov[5]; 77 OM_uint32 status; 78 size_t offset; 79 int i = 0, iov_count; 80 81 /* HEADER | SIGN_ONLY_DATA | DATA | PADDING | TRAILER */ 82 83 iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; 84 iov[i].buffer.value = NULL; 85 iov[i].buffer.length = 0; 86 i++; 87 88 if (input_assoc_buffer != GSS_C_NO_BUFFER) { 89 iov[i].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 90 iov[i].buffer = *input_assoc_buffer; 91 i++; 92 } 93 94 iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; 95 iov[i].buffer = *input_payload_buffer; 96 i++; 97 98 iov[i].type = GSS_IOV_BUFFER_TYPE_PADDING; 99 iov[i].buffer.value = NULL; 100 iov[i].buffer.length = 0; 101 i++; 102 103 iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER; 104 iov[i].buffer.value = NULL; 105 iov[i].buffer.length = 0; 106 i++; 107 108 iov_count = i; 109 110 assert(mech->gss_wrap_iov_length); 111 112 status = mech->gss_wrap_iov_length(minor_status, context_handle, 113 conf_req_flag, qop_req, 114 NULL, iov, iov_count); 115 if (status != GSS_S_COMPLETE) { 116 map_error(minor_status, mech); 117 return status; 118 } 119 120 /* Format output token (does not include associated data) */ 121 for (i = 0, output_message_buffer->length = 0; i < iov_count; i++) { 122 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) 123 continue; 124 125 output_message_buffer->length += iov[i].buffer.length; 126 } 127 128 output_message_buffer->value = gssalloc_malloc(output_message_buffer->length); 129 if (output_message_buffer->value == NULL) { 130 *minor_status = ENOMEM; 131 return GSS_S_FAILURE; 132 } 133 134 i = 0, offset = 0; 135 136 /* HEADER */ 137 iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; 138 offset += iov[i].buffer.length; 139 i++; 140 141 /* SIGN_ONLY_DATA */ 142 if (input_assoc_buffer != GSS_C_NO_BUFFER) 143 i++; 144 145 /* DATA */ 146 iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; 147 offset += iov[i].buffer.length; 148 149 memcpy(iov[i].buffer.value, input_payload_buffer->value, iov[i].buffer.length); 150 i++; 151 152 /* PADDING */ 153 iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; 154 offset += iov[i].buffer.length; 155 i++; 156 157 /* TRAILER */ 158 iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; 159 offset += iov[i].buffer.length; 160 i++; 161 162 assert(offset == output_message_buffer->length); 163 164 assert(mech->gss_wrap_iov); 165 166 status = mech->gss_wrap_iov(minor_status, context_handle, 167 conf_req_flag, qop_req, 168 conf_state, iov, iov_count); 169 if (status != GSS_S_COMPLETE) { 170 OM_uint32 minor; 171 172 map_error(minor_status, mech); 173 gss_release_buffer(&minor, output_message_buffer); 174 } 175 176 return status; 177 } 178 179 OM_uint32 180 gssint_wrap_aead(gss_mechanism mech, OM_uint32 *minor_status, 181 gss_union_ctx_id_t ctx, int conf_req_flag, gss_qop_t qop_req, 182 gss_buffer_t input_assoc_buffer, 183 gss_buffer_t input_payload_buffer, 184 int *conf_state, gss_buffer_t output_message_buffer) 185 { 186 /* EXPORT DELETE START */ 187 OM_uint32 status; 188 189 assert(ctx != NULL); 190 assert(mech != NULL); 191 192 if (mech->gss_wrap_aead) { 193 status = mech->gss_wrap_aead(minor_status, 194 ctx->internal_ctx_id, 195 conf_req_flag, 196 qop_req, 197 input_assoc_buffer, 198 input_payload_buffer, 199 conf_state, 200 output_message_buffer); 201 if (status != GSS_S_COMPLETE) 202 map_error(minor_status, mech); 203 } else if (mech->gss_wrap_iov && mech->gss_wrap_iov_length) { 204 status = gssint_wrap_aead_iov_shim(mech, 205 minor_status, 206 ctx->internal_ctx_id, 207 conf_req_flag, 208 qop_req, 209 input_assoc_buffer, 210 input_payload_buffer, 211 conf_state, 212 output_message_buffer); 213 } else 214 status = GSS_S_UNAVAILABLE; 215 216 /* EXPORT DELETE END */ 217 218 return status; 219 } 220 221 OM_uint32 KRB5_CALLCONV 222 gss_wrap_aead ( 223 OM_uint32 * minor_status, 224 gss_ctx_id_t context_handle, 225 int conf_req_flag, 226 gss_qop_t qop_req, 227 gss_buffer_t input_assoc_buffer, 228 gss_buffer_t input_payload_buffer, 229 int * conf_state, 230 gss_buffer_t output_message_buffer) 231 { 232 OM_uint32 status; 233 gss_mechanism mech; 234 gss_union_ctx_id_t ctx; 235 236 status = val_wrap_aead_args(minor_status, context_handle, 237 conf_req_flag, qop_req, 238 input_assoc_buffer, input_payload_buffer, 239 conf_state, output_message_buffer); 240 if (status != GSS_S_COMPLETE) 241 return (status); 242 243 /* 244 * select the approprate underlying mechanism routine and 245 * call it. 246 */ 247 ctx = (gss_union_ctx_id_t)context_handle; 248 if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) 249 return (GSS_S_NO_CONTEXT); 250 mech = gssint_get_mechanism (ctx->mech_type); 251 if (!mech) 252 return (GSS_S_BAD_MECH); 253 254 return gssint_wrap_aead(mech, minor_status, ctx, 255 conf_req_flag, qop_req, 256 input_assoc_buffer, input_payload_buffer, 257 conf_state, output_message_buffer); 258 } 259