Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
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.
16 : *
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.
20 : *
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.
32 : */
33 :
34 : #include "gsskrb5_locl.h"
35 :
36 : #ifdef HEIM_WEAK_CRYPTO
37 :
38 : static OM_uint32
39 : unwrap_des
40 : (OM_uint32 * minor_status,
41 : const gsskrb5_ctx context_handle,
42 : const gss_buffer_t input_message_buffer,
43 : gss_buffer_t output_message_buffer,
44 : int * conf_state,
45 : gss_qop_t * qop_state,
46 : krb5_keyblock *key
47 : )
48 : {
49 : u_char *p, *seq;
50 : size_t len;
51 : EVP_MD_CTX *md5;
52 : u_char hash[16];
53 : EVP_CIPHER_CTX des_ctx;
54 : DES_key_schedule schedule;
55 : DES_cblock deskey;
56 : DES_cblock zero;
57 : size_t i;
58 : uint32_t seq_number;
59 : size_t padlength;
60 : OM_uint32 ret;
61 : int cstate;
62 : int cmp;
63 : int token_len;
64 :
65 : if (IS_DCE_STYLE(context_handle)) {
66 : token_len = 22 + 8 + 15; /* 45 */
67 : if (input_message_buffer->length < token_len)
68 : return GSS_S_BAD_MECH;
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 : len = (p - (u_char *)input_message_buffer->value)
82 : + 22 + 8;
83 : if (input_message_buffer->length < len)
84 : return GSS_S_BAD_MECH;
85 :
86 : if (memcmp (p, "\x00\x00", 2) != 0)
87 : return GSS_S_BAD_SIG;
88 : p += 2;
89 : if (memcmp (p, "\x00\x00", 2) == 0) {
90 : cstate = 1;
91 : } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
92 : cstate = 0;
93 : } else
94 : return GSS_S_BAD_MIC;
95 : p += 2;
96 : if(conf_state != NULL)
97 : *conf_state = cstate;
98 : if (memcmp (p, "\xff\xff", 2) != 0)
99 : return GSS_S_DEFECTIVE_TOKEN;
100 : p += 2;
101 : p += 16;
102 :
103 : len = p - (u_char *)input_message_buffer->value;
104 :
105 : if(cstate) {
106 : /* decrypt data */
107 : memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
108 : memset (&zero, 0, sizeof(zero));
109 :
110 : for (i = 0; i < sizeof(deskey); ++i)
111 : deskey[i] ^= 0xf0;
112 :
113 :
114 : EVP_CIPHER_CTX_init(&des_ctx);
115 : EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0);
116 : EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len);
117 : EVP_CIPHER_CTX_cleanup(&des_ctx);
118 :
119 : memset (&deskey, 0, sizeof(deskey));
120 : }
121 :
122 : if (IS_DCE_STYLE(context_handle)) {
123 : padlength = 0;
124 : } else {
125 : /* check pad */
126 : ret = _gssapi_verify_pad(input_message_buffer,
127 : input_message_buffer->length - len - 8,
128 : &padlength);
129 : if (ret)
130 : return ret;
131 : }
132 :
133 : md5 = EVP_MD_CTX_create();
134 : EVP_DigestInit_ex(md5, EVP_md5(), NULL);
135 : EVP_DigestUpdate(md5, p - 24, 8);
136 : EVP_DigestUpdate(md5, p, input_message_buffer->length - len);
137 : EVP_DigestFinal_ex(md5, hash, NULL);
138 : EVP_MD_CTX_destroy(md5);
139 :
140 : memset (&zero, 0, sizeof(zero));
141 : memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
142 : DES_set_key_unchecked (&deskey, &schedule);
143 : DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
144 : &schedule, &zero);
145 : if (ct_memcmp (p - 8, hash, 8) != 0) {
146 : memset_s(&deskey, sizeof(deskey), 0, sizeof(deskey));
147 : memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
148 : return GSS_S_BAD_MIC;
149 : }
150 :
151 : /* verify sequence number */
152 :
153 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
154 :
155 : p -= 16;
156 :
157 : EVP_CIPHER_CTX_init(&des_ctx);
158 : EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
159 : EVP_Cipher(&des_ctx, p, p, 8);
160 : EVP_CIPHER_CTX_cleanup(&des_ctx);
161 :
162 : memset (deskey, 0, sizeof(deskey));
163 : memset (&schedule, 0, sizeof(schedule));
164 :
165 : seq = p;
166 : _gss_mg_decode_be_uint32(seq, &seq_number);
167 :
168 : if (context_handle->more_flags & LOCAL)
169 : cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
170 : else
171 : cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
172 :
173 : if (cmp != 0) {
174 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
175 : return GSS_S_BAD_MIC;
176 : }
177 :
178 : ret = _gssapi_msg_order_check(context_handle->order, seq_number);
179 : if (ret) {
180 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
181 : return ret;
182 : }
183 :
184 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
185 :
186 : /* copy out data */
187 :
188 : output_message_buffer->length = input_message_buffer->length
189 : - len - padlength - 8;
190 : output_message_buffer->value = malloc(output_message_buffer->length);
191 : if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
192 : return GSS_S_FAILURE;
193 : if (output_message_buffer->value != NULL)
194 : memcpy (output_message_buffer->value,
195 : p + 24,
196 : output_message_buffer->length);
197 : return GSS_S_COMPLETE;
198 : }
199 : #endif
200 :
201 : static OM_uint32
202 15 : unwrap_des3
203 : (OM_uint32 * minor_status,
204 : const gsskrb5_ctx context_handle,
205 : krb5_context context,
206 : const gss_buffer_t input_message_buffer,
207 : gss_buffer_t output_message_buffer,
208 : int * conf_state,
209 : gss_qop_t * qop_state,
210 : krb5_keyblock *key
211 : )
212 : {
213 15 : u_char *p;
214 15 : size_t len;
215 15 : u_char *seq;
216 15 : krb5_data seq_data;
217 15 : u_char cksum[20];
218 15 : uint32_t seq_number;
219 15 : size_t padlength;
220 15 : OM_uint32 ret;
221 15 : int cstate;
222 15 : krb5_crypto crypto;
223 15 : Checksum csum;
224 15 : int cmp;
225 15 : int token_len;
226 :
227 15 : if (IS_DCE_STYLE(context_handle)) {
228 4 : token_len = 34 + 8 + 15; /* 57 */
229 4 : if (input_message_buffer->length < token_len)
230 0 : return GSS_S_BAD_MECH;
231 : } else {
232 11 : token_len = input_message_buffer->length;
233 : }
234 :
235 13 : p = input_message_buffer->value;
236 13 : ret = _gsskrb5_verify_header (&p,
237 : token_len,
238 : "\x02\x01",
239 : GSS_KRB5_MECHANISM);
240 13 : if (ret)
241 0 : return ret;
242 :
243 11 : len = (p - (u_char *)input_message_buffer->value)
244 11 : + 34 + 8;
245 11 : if (input_message_buffer->length < len)
246 0 : return GSS_S_BAD_MECH;
247 :
248 8 : if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
249 0 : return GSS_S_BAD_SIG;
250 8 : p += 2;
251 8 : if (ct_memcmp (p, "\x02\x00", 2) == 0) {
252 0 : cstate = 1;
253 5 : } else if (ct_memcmp (p, "\xff\xff", 2) == 0) {
254 0 : cstate = 0;
255 : } else
256 0 : return GSS_S_BAD_MIC;
257 8 : p += 2;
258 8 : if(conf_state != NULL)
259 8 : *conf_state = cstate;
260 8 : if (ct_memcmp (p, "\xff\xff", 2) != 0)
261 0 : return GSS_S_DEFECTIVE_TOKEN;
262 8 : p += 2;
263 8 : p += 28;
264 :
265 8 : len = p - (u_char *)input_message_buffer->value;
266 :
267 8 : if(cstate) {
268 : /* decrypt data */
269 3 : krb5_data tmp;
270 :
271 3 : ret = krb5_crypto_init(context, key,
272 : ETYPE_DES3_CBC_NONE, &crypto);
273 3 : if (ret) {
274 0 : *minor_status = ret;
275 0 : return GSS_S_FAILURE;
276 : }
277 6 : ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
278 3 : p, input_message_buffer->length - len, &tmp);
279 3 : krb5_crypto_destroy(context, crypto);
280 3 : if (ret) {
281 0 : *minor_status = ret;
282 0 : return GSS_S_FAILURE;
283 : }
284 3 : assert (tmp.length == input_message_buffer->length - len);
285 :
286 3 : memcpy (p, tmp.data, tmp.length);
287 3 : krb5_data_free(&tmp);
288 : }
289 :
290 8 : if (IS_DCE_STYLE(context_handle)) {
291 2 : padlength = 0;
292 : } else {
293 : /* check pad */
294 12 : ret = _gssapi_verify_pad(input_message_buffer,
295 6 : input_message_buffer->length - len - 8,
296 : &padlength);
297 6 : if (ret)
298 0 : return ret;
299 : }
300 :
301 : /* verify sequence number */
302 :
303 6 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
304 :
305 6 : p -= 28;
306 :
307 6 : ret = krb5_crypto_init(context, key,
308 : ETYPE_DES3_CBC_NONE, &crypto);
309 6 : if (ret) {
310 0 : *minor_status = ret;
311 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
312 0 : return GSS_S_FAILURE;
313 : }
314 : {
315 6 : DES_cblock ivec;
316 :
317 6 : memcpy(&ivec, p + 8, 8);
318 6 : ret = krb5_decrypt_ivec (context,
319 : crypto,
320 : KRB5_KU_USAGE_SEQ,
321 : p, 8, &seq_data,
322 : &ivec);
323 : }
324 6 : krb5_crypto_destroy (context, crypto);
325 6 : if (ret) {
326 0 : *minor_status = ret;
327 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
328 0 : return GSS_S_FAILURE;
329 : }
330 6 : if (seq_data.length != 8) {
331 0 : krb5_data_free (&seq_data);
332 0 : *minor_status = 0;
333 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
334 0 : return GSS_S_BAD_MIC;
335 : }
336 :
337 6 : seq = seq_data.data;
338 6 : _gss_mg_decode_be_uint32(seq, &seq_number);
339 :
340 6 : if (context_handle->more_flags & LOCAL)
341 0 : cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
342 : else
343 6 : cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
344 :
345 6 : krb5_data_free (&seq_data);
346 6 : if (cmp != 0) {
347 0 : *minor_status = 0;
348 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
349 0 : return GSS_S_BAD_MIC;
350 : }
351 :
352 6 : ret = _gssapi_msg_order_check(context_handle->order, seq_number);
353 6 : if (ret) {
354 0 : *minor_status = 0;
355 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
356 0 : return ret;
357 : }
358 :
359 6 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
360 :
361 : /* verify checksum */
362 :
363 6 : memcpy (cksum, p + 8, 20);
364 :
365 6 : memcpy (p + 20, p - 8, 8);
366 :
367 6 : csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
368 6 : csum.checksum.length = 20;
369 6 : csum.checksum.data = cksum;
370 :
371 6 : ret = krb5_crypto_init(context, key, 0, &crypto);
372 6 : if (ret) {
373 0 : *minor_status = ret;
374 0 : return GSS_S_FAILURE;
375 : }
376 :
377 12 : ret = krb5_verify_checksum (context, crypto,
378 : KRB5_KU_USAGE_SIGN,
379 6 : p + 20,
380 6 : input_message_buffer->length - len + 8,
381 : &csum);
382 6 : krb5_crypto_destroy (context, crypto);
383 6 : if (ret) {
384 0 : *minor_status = ret;
385 0 : return GSS_S_FAILURE;
386 : }
387 :
388 : /* copy out data */
389 :
390 6 : output_message_buffer->length = input_message_buffer->length
391 6 : - len - padlength - 8;
392 6 : output_message_buffer->value = malloc(output_message_buffer->length);
393 6 : if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
394 0 : return GSS_S_FAILURE;
395 6 : if (output_message_buffer->value != NULL)
396 21 : memcpy (output_message_buffer->value,
397 6 : p + 36,
398 : output_message_buffer->length);
399 0 : return GSS_S_COMPLETE;
400 : }
401 :
402 744366 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap
403 : (OM_uint32 * minor_status,
404 : gss_const_ctx_id_t context_handle,
405 : const gss_buffer_t input_message_buffer,
406 : gss_buffer_t output_message_buffer,
407 : int * conf_state,
408 : gss_qop_t * qop_state
409 : )
410 : {
411 945 : krb5_keyblock *key;
412 945 : krb5_context context;
413 945 : OM_uint32 ret;
414 744366 : gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
415 :
416 744366 : output_message_buffer->value = NULL;
417 744366 : output_message_buffer->length = 0;
418 744366 : if (qop_state != NULL)
419 744366 : *qop_state = GSS_C_QOP_DEFAULT;
420 :
421 744366 : GSSAPI_KRB5_INIT (&context);
422 :
423 744366 : if (ctx->more_flags & IS_CFX)
424 693018 : return _gssapi_unwrap_cfx (minor_status, ctx, context,
425 : input_message_buffer, output_message_buffer,
426 : conf_state, qop_state);
427 :
428 15 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
429 51348 : ret = _gsskrb5i_get_token_key(ctx, context, &key);
430 15 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
431 51348 : if (ret) {
432 0 : *minor_status = ret;
433 0 : return GSS_S_FAILURE;
434 : }
435 :
436 51348 : *minor_status = 0;
437 :
438 51348 : switch (key->keytype) {
439 0 : case KRB5_ENCTYPE_DES_CBC_CRC :
440 : case KRB5_ENCTYPE_DES_CBC_MD4 :
441 : case KRB5_ENCTYPE_DES_CBC_MD5 :
442 : #ifdef HEIM_WEAK_CRYPTO
443 : ret = unwrap_des (minor_status, ctx,
444 : input_message_buffer, output_message_buffer,
445 : conf_state, qop_state, key);
446 : #else
447 0 : ret = GSS_S_FAILURE;
448 : #endif
449 0 : break;
450 15 : case KRB5_ENCTYPE_DES3_CBC_MD5 :
451 : case KRB5_ENCTYPE_DES3_CBC_SHA1 :
452 15 : ret = unwrap_des3 (minor_status, ctx, context,
453 : input_message_buffer, output_message_buffer,
454 : conf_state, qop_state, key);
455 15 : break;
456 51333 : case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5:
457 : case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56:
458 51333 : ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
459 : input_message_buffer, output_message_buffer,
460 : conf_state, qop_state, key);
461 51333 : break;
462 0 : default :
463 0 : abort();
464 15 : break;
465 : }
466 51348 : krb5_free_keyblock (context, key);
467 51348 : return ret;
468 : }
|