1 /* $NetBSD: unwrap.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
2
3 /*
4 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
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.
18 *
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.
22 *
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.
34 */
35
36 #include "gsskrb5_locl.h"
37
38 #ifdef HEIM_WEAK_CRYPTO
39
40 static OM_uint32
unwrap_des(OM_uint32 * minor_status,const gsskrb5_ctx context_handle,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state,krb5_keyblock * key)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
49 )
50 {
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;
66
67 if (IS_DCE_STYLE(context_handle)) {
68 token_len = 22 + 8 + 15; /* 45 */
69 } else {
70 token_len = input_message_buffer->length;
71 }
72
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;
80
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;
97
98 len = p - (u_char *)input_message_buffer->value;
99
100 if(cstate) {
101 /* decrypt data */
102 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
103 memset (&zero, 0, sizeof(zero));
104
105 for (i = 0; i < sizeof(deskey); ++i)
106 deskey[i] ^= 0xf0;
107
108
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);
113
114 memset (&schedule, 0, sizeof(schedule));
115 }
116
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;
126 }
127
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);
134
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;
142
143 /* verify sequence number */
144
145 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
146
147 p -= 16;
148
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);
153
154 memset (deskey, 0, sizeof(deskey));
155 memset (&schedule, 0, sizeof(schedule));
156
157 seq = p;
158 _gsskrb5_decode_om_uint32(seq, &seq_number);
159
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);
164
165 if (cmp != 0) {
166 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
167 return GSS_S_BAD_MIC;
168 }
169
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;
174 }
175
176 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
177
178 /* copy out data */
179
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;
189 }
190 #endif
191
192 static OM_uint32
unwrap_des3(OM_uint32 * minor_status,const gsskrb5_ctx context_handle,krb5_context context,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state,krb5_keyblock * key)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
202 )
203 {
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;
217
218 if (IS_DCE_STYLE(context_handle)) {
219 token_len = 34 + 8 + 15; /* 57 */
220 } else {
221 token_len = input_message_buffer->length;
222 }
223
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;
231
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;
248
249 len = p - (u_char *)input_message_buffer->value;
250
251 if(cstate) {
252 /* decrypt data */
253 krb5_data tmp;
254
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;
260 }
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;
267 }
268 assert (tmp.length == input_message_buffer->length - len);
269
270 memcpy (p, tmp.data, tmp.length);
271 krb5_data_free(&tmp);
272 }
273
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;
283 }
284
285 /* verify sequence number */
286
287 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
288
289 p -= 28;
290
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;
297 }
298 {
299 DES_cblock ivec;
300
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);
307 }
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;
313 }
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;
319 }
320
321 seq = seq_data.data;
322 _gsskrb5_decode_om_uint32(seq, &seq_number);
323
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);
328
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;
334 }
335
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;
341 }
342
343 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
344
345 /* verify checksum */
346
347 memcpy (cksum, p + 8, 20);
348
349 memcpy (p + 20, p - 8, 8);
350
351 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
352 csum.checksum.length = 20;
353 csum.checksum.data = cksum;
354
355 ret = krb5_crypto_init(context, key, 0, &crypto);
356 if (ret) {
357 *minor_status = ret;
358 return GSS_S_FAILURE;
359 }
360
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;
370 }
371
372 /* copy out data */
373
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;
383 }
384
_gsskrb5_unwrap(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state)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
392 )
393 {
394 krb5_keyblock *key;
395 krb5_context context;
396 OM_uint32 ret;
397 krb5_keytype keytype;
398 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
399
400 output_message_buffer->value = NULL;
401 output_message_buffer->length = 0;
402 if (qop_state != NULL)
403 *qop_state = GSS_C_QOP_DEFAULT;
404
405 GSSAPI_KRB5_INIT (&context);
406
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);
411
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;
418 }
419 krb5_enctype_to_keytype (context, key->keytype, &keytype);
420
421 *minor_status = 0;
422
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;
447 }
448 krb5_free_keyblock (context, key);
449 return ret;
450 }
451