switch to use EVP interface instead of old crypto interface
[heimdal.git] / lib / gssapi / krb5 / unwrap.c
bloba8085c5c065aaaafda68d1efe0b536ba568c6c8a
1 /*
2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "gsskrb5_locl.h"
36 static OM_uint32
37 unwrap_des
38 (OM_uint32 * minor_status,
39 const gsskrb5_ctx context_handle,
40 const gss_buffer_t input_message_buffer,
41 gss_buffer_t output_message_buffer,
42 int * conf_state,
43 gss_qop_t * qop_state,
44 krb5_keyblock *key
47 u_char *p, *seq;
48 size_t len;
49 EVP_MD_CTX md5;
50 u_char hash[16];
51 EVP_CIPHER_CTX des_ctx;
52 DES_key_schedule schedule;
53 DES_cblock deskey;
54 DES_cblock zero;
55 int i;
56 uint32_t seq_number;
57 size_t padlength;
58 OM_uint32 ret;
59 int cstate;
60 int cmp;
61 int token_len;
63 if (IS_DCE_STYLE(context_handle)) {
64 token_len = 22 + 8 + 15; /* 45 */
65 } else {
66 token_len = input_message_buffer->length;
69 p = input_message_buffer->value;
70 ret = _gsskrb5_verify_header (&p,
71 token_len,
72 "\x02\x01",
73 GSS_KRB5_MECHANISM);
74 if (ret)
75 return ret;
77 if (memcmp (p, "\x00\x00", 2) != 0)
78 return GSS_S_BAD_SIG;
79 p += 2;
80 if (memcmp (p, "\x00\x00", 2) == 0) {
81 cstate = 1;
82 } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
83 cstate = 0;
84 } else
85 return GSS_S_BAD_MIC;
86 p += 2;
87 if(conf_state != NULL)
88 *conf_state = cstate;
89 if (memcmp (p, "\xff\xff", 2) != 0)
90 return GSS_S_DEFECTIVE_TOKEN;
91 p += 2;
92 p += 16;
94 len = p - (u_char *)input_message_buffer->value;
96 if(cstate) {
97 /* decrypt data */
98 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
100 for (i = 0; i < sizeof(deskey); ++i)
101 deskey[i] ^= 0xf0;
104 EVP_CIPHER_CTX_init(&des_ctx);
105 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0);
106 EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len);
107 EVP_CIPHER_CTX_cleanup(&des_ctx);
109 memset (&schedule, 0, sizeof(schedule));
112 if (IS_DCE_STYLE(context_handle)) {
113 padlength = 0;
114 } else {
115 /* check pad */
116 ret = _gssapi_verify_pad(input_message_buffer,
117 input_message_buffer->length - len,
118 &padlength);
119 if (ret)
120 return ret;
123 EVP_MD_CTX_init(&md5);
124 EVP_DigestInit_ex(&md5, EVP_md5(), NULL);
125 EVP_DigestUpdate(&md5, p - 24, 8);
126 EVP_DigestUpdate(&md5, p, input_message_buffer->length - len);
127 EVP_DigestFinal_ex(&md5, hash, NULL);
128 EVP_MD_CTX_cleanup(&md5);
130 memset (&zero, 0, sizeof(zero));
131 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
132 DES_set_key_unchecked (&deskey, &schedule);
133 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
134 &schedule, &zero);
135 if (ct_memcmp (p - 8, hash, 8) != 0)
136 return GSS_S_BAD_MIC;
138 /* verify sequence number */
140 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
142 p -= 16;
144 EVP_CIPHER_CTX_init(&des_ctx);
145 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
146 EVP_Cipher(&des_ctx, p, p, 8);
147 EVP_CIPHER_CTX_cleanup(&des_ctx);
149 memset (deskey, 0, sizeof(deskey));
150 memset (&schedule, 0, sizeof(schedule));
152 seq = p;
153 _gsskrb5_decode_om_uint32(seq, &seq_number);
155 if (context_handle->more_flags & LOCAL)
156 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
157 else
158 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
160 if (cmp != 0) {
161 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
162 return GSS_S_BAD_MIC;
165 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
166 if (ret) {
167 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
168 return ret;
171 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
173 /* copy out data */
175 output_message_buffer->length = input_message_buffer->length
176 - len - padlength - 8;
177 output_message_buffer->value = malloc(output_message_buffer->length);
178 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
179 return GSS_S_FAILURE;
180 memcpy (output_message_buffer->value,
181 p + 24,
182 output_message_buffer->length);
183 return GSS_S_COMPLETE;
186 static OM_uint32
187 unwrap_des3
188 (OM_uint32 * minor_status,
189 const gsskrb5_ctx context_handle,
190 krb5_context context,
191 const gss_buffer_t input_message_buffer,
192 gss_buffer_t output_message_buffer,
193 int * conf_state,
194 gss_qop_t * qop_state,
195 krb5_keyblock *key
198 u_char *p;
199 size_t len;
200 u_char *seq;
201 krb5_data seq_data;
202 u_char cksum[20];
203 uint32_t seq_number;
204 size_t padlength;
205 OM_uint32 ret;
206 int cstate;
207 krb5_crypto crypto;
208 Checksum csum;
209 int cmp;
210 int token_len;
212 if (IS_DCE_STYLE(context_handle)) {
213 token_len = 34 + 8 + 15; /* 57 */
214 } else {
215 token_len = input_message_buffer->length;
218 p = input_message_buffer->value;
219 ret = _gsskrb5_verify_header (&p,
220 token_len,
221 "\x02\x01",
222 GSS_KRB5_MECHANISM);
223 if (ret)
224 return ret;
226 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
227 return GSS_S_BAD_SIG;
228 p += 2;
229 if (ct_memcmp (p, "\x02\x00", 2) == 0) {
230 cstate = 1;
231 } else if (ct_memcmp (p, "\xff\xff", 2) == 0) {
232 cstate = 0;
233 } else
234 return GSS_S_BAD_MIC;
235 p += 2;
236 if(conf_state != NULL)
237 *conf_state = cstate;
238 if (ct_memcmp (p, "\xff\xff", 2) != 0)
239 return GSS_S_DEFECTIVE_TOKEN;
240 p += 2;
241 p += 28;
243 len = p - (u_char *)input_message_buffer->value;
245 if(cstate) {
246 /* decrypt data */
247 krb5_data tmp;
249 ret = krb5_crypto_init(context, key,
250 ETYPE_DES3_CBC_NONE, &crypto);
251 if (ret) {
252 *minor_status = ret;
253 return GSS_S_FAILURE;
255 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
256 p, input_message_buffer->length - len, &tmp);
257 krb5_crypto_destroy(context, crypto);
258 if (ret) {
259 *minor_status = ret;
260 return GSS_S_FAILURE;
262 assert (tmp.length == input_message_buffer->length - len);
264 memcpy (p, tmp.data, tmp.length);
265 krb5_data_free(&tmp);
268 if (IS_DCE_STYLE(context_handle)) {
269 padlength = 0;
270 } else {
271 /* check pad */
272 ret = _gssapi_verify_pad(input_message_buffer,
273 input_message_buffer->length - len,
274 &padlength);
275 if (ret)
276 return ret;
279 /* verify sequence number */
281 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
283 p -= 28;
285 ret = krb5_crypto_init(context, key,
286 ETYPE_DES3_CBC_NONE, &crypto);
287 if (ret) {
288 *minor_status = ret;
289 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
290 return GSS_S_FAILURE;
293 DES_cblock ivec;
295 memcpy(&ivec, p + 8, 8);
296 ret = krb5_decrypt_ivec (context,
297 crypto,
298 KRB5_KU_USAGE_SEQ,
299 p, 8, &seq_data,
300 &ivec);
302 krb5_crypto_destroy (context, crypto);
303 if (ret) {
304 *minor_status = ret;
305 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
306 return GSS_S_FAILURE;
308 if (seq_data.length != 8) {
309 krb5_data_free (&seq_data);
310 *minor_status = 0;
311 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
312 return GSS_S_BAD_MIC;
315 seq = seq_data.data;
316 _gsskrb5_decode_om_uint32(seq, &seq_number);
318 if (context_handle->more_flags & LOCAL)
319 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
320 else
321 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
323 krb5_data_free (&seq_data);
324 if (cmp != 0) {
325 *minor_status = 0;
326 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
327 return GSS_S_BAD_MIC;
330 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
331 if (ret) {
332 *minor_status = 0;
333 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
334 return ret;
337 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
339 /* verify checksum */
341 memcpy (cksum, p + 8, 20);
343 memcpy (p + 20, p - 8, 8);
345 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
346 csum.checksum.length = 20;
347 csum.checksum.data = cksum;
349 ret = krb5_crypto_init(context, key, 0, &crypto);
350 if (ret) {
351 *minor_status = ret;
352 return GSS_S_FAILURE;
355 ret = krb5_verify_checksum (context, crypto,
356 KRB5_KU_USAGE_SIGN,
357 p + 20,
358 input_message_buffer->length - len + 8,
359 &csum);
360 krb5_crypto_destroy (context, crypto);
361 if (ret) {
362 *minor_status = ret;
363 return GSS_S_FAILURE;
366 /* copy out data */
368 output_message_buffer->length = input_message_buffer->length
369 - len - padlength - 8;
370 output_message_buffer->value = malloc(output_message_buffer->length);
371 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
372 return GSS_S_FAILURE;
373 memcpy (output_message_buffer->value,
374 p + 36,
375 output_message_buffer->length);
376 return GSS_S_COMPLETE;
379 OM_uint32 _gsskrb5_unwrap
380 (OM_uint32 * minor_status,
381 const gss_ctx_id_t context_handle,
382 const gss_buffer_t input_message_buffer,
383 gss_buffer_t output_message_buffer,
384 int * conf_state,
385 gss_qop_t * qop_state
388 krb5_keyblock *key;
389 krb5_context context;
390 OM_uint32 ret;
391 krb5_keytype keytype;
392 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
394 output_message_buffer->value = NULL;
395 output_message_buffer->length = 0;
396 if (qop_state != NULL)
397 *qop_state = GSS_C_QOP_DEFAULT;
399 GSSAPI_KRB5_INIT (&context);
401 if (ctx->more_flags & IS_CFX)
402 return _gssapi_unwrap_cfx (minor_status, ctx, context,
403 input_message_buffer, output_message_buffer,
404 conf_state, qop_state);
406 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
407 ret = _gsskrb5i_get_token_key(ctx, context, &key);
408 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
409 if (ret) {
410 *minor_status = ret;
411 return GSS_S_FAILURE;
413 krb5_enctype_to_keytype (context, key->keytype, &keytype);
415 *minor_status = 0;
417 switch (keytype) {
418 case KEYTYPE_DES :
419 ret = unwrap_des (minor_status, ctx,
420 input_message_buffer, output_message_buffer,
421 conf_state, qop_state, key);
422 break;
423 case KEYTYPE_DES3 :
424 ret = unwrap_des3 (minor_status, ctx, context,
425 input_message_buffer, output_message_buffer,
426 conf_state, qop_state, key);
427 break;
428 case KEYTYPE_ARCFOUR:
429 case KEYTYPE_ARCFOUR_56:
430 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
431 input_message_buffer, output_message_buffer,
432 conf_state, qop_state, key);
433 break;
434 default :
435 abort();
436 break;
438 krb5_free_keyblock (context, key);
439 return ret;