Remove building with NOCRYPTO option
[minix.git] / crypto / external / bsd / heimdal / dist / lib / gssapi / krb5 / unwrap.c
blob0b134e7e1b7e99b33b9adf11f94e78789e37e6ee
1 /* $NetBSD: unwrap.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
3 /*
4 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "gsskrb5_locl.h"
38 #ifdef HEIM_WEAK_CRYPTO
40 static OM_uint32
41 unwrap_des
42 (OM_uint32 * minor_status,
43 const gsskrb5_ctx context_handle,
44 const gss_buffer_t input_message_buffer,
45 gss_buffer_t output_message_buffer,
46 int * conf_state,
47 gss_qop_t * qop_state,
48 krb5_keyblock *key
51 u_char *p, *seq;
52 size_t len;
53 EVP_MD_CTX *md5;
54 u_char hash[16];
55 EVP_CIPHER_CTX des_ctx;
56 DES_key_schedule schedule;
57 DES_cblock deskey;
58 DES_cblock zero;
59 size_t i;
60 uint32_t seq_number;
61 size_t padlength;
62 OM_uint32 ret;
63 int cstate;
64 int cmp;
65 int token_len;
67 if (IS_DCE_STYLE(context_handle)) {
68 token_len = 22 + 8 + 15; /* 45 */
69 } else {
70 token_len = input_message_buffer->length;
73 p = input_message_buffer->value;
74 ret = _gsskrb5_verify_header (&p,
75 token_len,
76 "\x02\x01",
77 GSS_KRB5_MECHANISM);
78 if (ret)
79 return ret;
81 if (memcmp (p, "\x00\x00", 2) != 0)
82 return GSS_S_BAD_SIG;
83 p += 2;
84 if (memcmp (p, "\x00\x00", 2) == 0) {
85 cstate = 1;
86 } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
87 cstate = 0;
88 } else
89 return GSS_S_BAD_MIC;
90 p += 2;
91 if(conf_state != NULL)
92 *conf_state = cstate;
93 if (memcmp (p, "\xff\xff", 2) != 0)
94 return GSS_S_DEFECTIVE_TOKEN;
95 p += 2;
96 p += 16;
98 len = p - (u_char *)input_message_buffer->value;
100 if(cstate) {
101 /* decrypt data */
102 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
103 memset (&zero, 0, sizeof(zero));
105 for (i = 0; i < sizeof(deskey); ++i)
106 deskey[i] ^= 0xf0;
109 EVP_CIPHER_CTX_init(&des_ctx);
110 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0);
111 EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len);
112 EVP_CIPHER_CTX_cleanup(&des_ctx);
114 memset (&schedule, 0, sizeof(schedule));
117 if (IS_DCE_STYLE(context_handle)) {
118 padlength = 0;
119 } else {
120 /* check pad */
121 ret = _gssapi_verify_pad(input_message_buffer,
122 input_message_buffer->length - len,
123 &padlength);
124 if (ret)
125 return ret;
128 md5 = EVP_MD_CTX_create();
129 EVP_DigestInit_ex(md5, EVP_md5(), NULL);
130 EVP_DigestUpdate(md5, p - 24, 8);
131 EVP_DigestUpdate(md5, p, input_message_buffer->length - len);
132 EVP_DigestFinal_ex(md5, hash, NULL);
133 EVP_MD_CTX_destroy(md5);
135 memset (&zero, 0, sizeof(zero));
136 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
137 DES_set_key_unchecked (&deskey, &schedule);
138 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
139 &schedule, &zero);
140 if (ct_memcmp (p - 8, hash, 8) != 0)
141 return GSS_S_BAD_MIC;
143 /* verify sequence number */
145 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
147 p -= 16;
149 EVP_CIPHER_CTX_init(&des_ctx);
150 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
151 EVP_Cipher(&des_ctx, p, p, 8);
152 EVP_CIPHER_CTX_cleanup(&des_ctx);
154 memset (deskey, 0, sizeof(deskey));
155 memset (&schedule, 0, sizeof(schedule));
157 seq = p;
158 _gsskrb5_decode_om_uint32(seq, &seq_number);
160 if (context_handle->more_flags & LOCAL)
161 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
162 else
163 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
165 if (cmp != 0) {
166 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
167 return GSS_S_BAD_MIC;
170 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
171 if (ret) {
172 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
173 return ret;
176 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
178 /* copy out data */
180 output_message_buffer->length = input_message_buffer->length
181 - len - padlength - 8;
182 output_message_buffer->value = malloc(output_message_buffer->length);
183 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
184 return GSS_S_FAILURE;
185 memcpy (output_message_buffer->value,
186 p + 24,
187 output_message_buffer->length);
188 return GSS_S_COMPLETE;
190 #endif
192 static OM_uint32
193 unwrap_des3
194 (OM_uint32 * minor_status,
195 const gsskrb5_ctx context_handle,
196 krb5_context context,
197 const gss_buffer_t input_message_buffer,
198 gss_buffer_t output_message_buffer,
199 int * conf_state,
200 gss_qop_t * qop_state,
201 krb5_keyblock *key
204 u_char *p;
205 size_t len;
206 u_char *seq;
207 krb5_data seq_data;
208 u_char cksum[20];
209 uint32_t seq_number;
210 size_t padlength;
211 OM_uint32 ret;
212 int cstate;
213 krb5_crypto crypto;
214 Checksum csum;
215 int cmp;
216 int token_len;
218 if (IS_DCE_STYLE(context_handle)) {
219 token_len = 34 + 8 + 15; /* 57 */
220 } else {
221 token_len = input_message_buffer->length;
224 p = input_message_buffer->value;
225 ret = _gsskrb5_verify_header (&p,
226 token_len,
227 "\x02\x01",
228 GSS_KRB5_MECHANISM);
229 if (ret)
230 return ret;
232 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
233 return GSS_S_BAD_SIG;
234 p += 2;
235 if (ct_memcmp (p, "\x02\x00", 2) == 0) {
236 cstate = 1;
237 } else if (ct_memcmp (p, "\xff\xff", 2) == 0) {
238 cstate = 0;
239 } else
240 return GSS_S_BAD_MIC;
241 p += 2;
242 if(conf_state != NULL)
243 *conf_state = cstate;
244 if (ct_memcmp (p, "\xff\xff", 2) != 0)
245 return GSS_S_DEFECTIVE_TOKEN;
246 p += 2;
247 p += 28;
249 len = p - (u_char *)input_message_buffer->value;
251 if(cstate) {
252 /* decrypt data */
253 krb5_data tmp;
255 ret = krb5_crypto_init(context, key,
256 ETYPE_DES3_CBC_NONE, &crypto);
257 if (ret) {
258 *minor_status = ret;
259 return GSS_S_FAILURE;
261 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
262 p, input_message_buffer->length - len, &tmp);
263 krb5_crypto_destroy(context, crypto);
264 if (ret) {
265 *minor_status = ret;
266 return GSS_S_FAILURE;
268 assert (tmp.length == input_message_buffer->length - len);
270 memcpy (p, tmp.data, tmp.length);
271 krb5_data_free(&tmp);
274 if (IS_DCE_STYLE(context_handle)) {
275 padlength = 0;
276 } else {
277 /* check pad */
278 ret = _gssapi_verify_pad(input_message_buffer,
279 input_message_buffer->length - len,
280 &padlength);
281 if (ret)
282 return ret;
285 /* verify sequence number */
287 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
289 p -= 28;
291 ret = krb5_crypto_init(context, key,
292 ETYPE_DES3_CBC_NONE, &crypto);
293 if (ret) {
294 *minor_status = ret;
295 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
296 return GSS_S_FAILURE;
299 DES_cblock ivec;
301 memcpy(&ivec, p + 8, 8);
302 ret = krb5_decrypt_ivec (context,
303 crypto,
304 KRB5_KU_USAGE_SEQ,
305 p, 8, &seq_data,
306 &ivec);
308 krb5_crypto_destroy (context, crypto);
309 if (ret) {
310 *minor_status = ret;
311 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
312 return GSS_S_FAILURE;
314 if (seq_data.length != 8) {
315 krb5_data_free (&seq_data);
316 *minor_status = 0;
317 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
318 return GSS_S_BAD_MIC;
321 seq = seq_data.data;
322 _gsskrb5_decode_om_uint32(seq, &seq_number);
324 if (context_handle->more_flags & LOCAL)
325 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
326 else
327 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
329 krb5_data_free (&seq_data);
330 if (cmp != 0) {
331 *minor_status = 0;
332 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
333 return GSS_S_BAD_MIC;
336 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
337 if (ret) {
338 *minor_status = 0;
339 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
340 return ret;
343 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
345 /* verify checksum */
347 memcpy (cksum, p + 8, 20);
349 memcpy (p + 20, p - 8, 8);
351 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
352 csum.checksum.length = 20;
353 csum.checksum.data = cksum;
355 ret = krb5_crypto_init(context, key, 0, &crypto);
356 if (ret) {
357 *minor_status = ret;
358 return GSS_S_FAILURE;
361 ret = krb5_verify_checksum (context, crypto,
362 KRB5_KU_USAGE_SIGN,
363 p + 20,
364 input_message_buffer->length - len + 8,
365 &csum);
366 krb5_crypto_destroy (context, crypto);
367 if (ret) {
368 *minor_status = ret;
369 return GSS_S_FAILURE;
372 /* copy out data */
374 output_message_buffer->length = input_message_buffer->length
375 - len - padlength - 8;
376 output_message_buffer->value = malloc(output_message_buffer->length);
377 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
378 return GSS_S_FAILURE;
379 memcpy (output_message_buffer->value,
380 p + 36,
381 output_message_buffer->length);
382 return GSS_S_COMPLETE;
385 OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap
386 (OM_uint32 * minor_status,
387 const gss_ctx_id_t context_handle,
388 const gss_buffer_t input_message_buffer,
389 gss_buffer_t output_message_buffer,
390 int * conf_state,
391 gss_qop_t * qop_state
394 krb5_keyblock *key;
395 krb5_context context;
396 OM_uint32 ret;
397 krb5_keytype keytype;
398 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
400 output_message_buffer->value = NULL;
401 output_message_buffer->length = 0;
402 if (qop_state != NULL)
403 *qop_state = GSS_C_QOP_DEFAULT;
405 GSSAPI_KRB5_INIT (&context);
407 if (ctx->more_flags & IS_CFX)
408 return _gssapi_unwrap_cfx (minor_status, ctx, context,
409 input_message_buffer, output_message_buffer,
410 conf_state, qop_state);
412 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
413 ret = _gsskrb5i_get_token_key(ctx, context, &key);
414 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
415 if (ret) {
416 *minor_status = ret;
417 return GSS_S_FAILURE;
419 krb5_enctype_to_keytype (context, key->keytype, &keytype);
421 *minor_status = 0;
423 switch (keytype) {
424 case KEYTYPE_DES :
425 #ifdef HEIM_WEAK_CRYPTO
426 ret = unwrap_des (minor_status, ctx,
427 input_message_buffer, output_message_buffer,
428 conf_state, qop_state, key);
429 #else
430 ret = GSS_S_FAILURE;
431 #endif
432 break;
433 case KEYTYPE_DES3 :
434 ret = unwrap_des3 (minor_status, ctx, context,
435 input_message_buffer, output_message_buffer,
436 conf_state, qop_state, key);
437 break;
438 case KEYTYPE_ARCFOUR:
439 case KEYTYPE_ARCFOUR_56:
440 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
441 input_message_buffer, output_message_buffer,
442 conf_state, qop_state, key);
443 break;
444 default :
445 abort();
446 break;
448 krb5_free_keyblock (context, key);
449 return ret;