Line data Source code
1 : /*
2 : * Copyright (c) 2003 - 2006 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 : /*
37 : * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
38 : *
39 : * The arcfour message have the following formats:
40 : *
41 : * MIC token
42 : * TOK_ID[2] = 01 01
43 : * SGN_ALG[2] = 11 00
44 : * Filler[4]
45 : * SND_SEQ[8]
46 : * SGN_CKSUM[8]
47 : *
48 : * WRAP token
49 : * TOK_ID[2] = 02 01
50 : * SGN_ALG[2];
51 : * SEAL_ALG[2]
52 : * Filler[2]
53 : * SND_SEQ[2]
54 : * SGN_CKSUM[8]
55 : * Confounder[8]
56 : */
57 :
58 : /*
59 : * WRAP in DCE-style have a fixed size header, the oid and length over
60 : * the WRAP header is a total of
61 : * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE +
62 : * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead,
63 : * remember the 2 bytes from APPL [0] SEQ).
64 : */
65 :
66 : #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
67 : #define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13
68 :
69 :
70 : static krb5_error_code
71 294938 : arcfour_mic_key(krb5_context context, krb5_keyblock *key,
72 : const void *cksum_data, size_t cksum_size,
73 : void *key6_data, size_t key6_size)
74 : {
75 0 : krb5_error_code ret;
76 :
77 0 : Checksum cksum_k5;
78 0 : krb5_keyblock key5;
79 0 : char k5_data[16];
80 :
81 0 : Checksum cksum_k6;
82 :
83 0 : char T[4];
84 :
85 294938 : memset(T, 0, 4);
86 294938 : cksum_k5.checksum.data = k5_data;
87 294938 : cksum_k5.checksum.length = sizeof(k5_data);
88 :
89 294938 : if (key->keytype == KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56) {
90 0 : char L40[14] = "fortybits";
91 :
92 0 : memcpy(L40 + 10, T, sizeof(T));
93 0 : ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
94 : L40, 14, 0, key, &cksum_k5);
95 0 : memset(&k5_data[7], 0xAB, 9);
96 : } else {
97 294938 : ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
98 : T, 4, 0, key, &cksum_k5);
99 : }
100 294938 : if (ret)
101 0 : return ret;
102 :
103 294938 : key5.keytype = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5;
104 294938 : key5.keyvalue = cksum_k5.checksum;
105 :
106 294938 : cksum_k6.checksum.data = key6_data;
107 294938 : cksum_k6.checksum.length = key6_size;
108 :
109 294938 : return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
110 : cksum_data, cksum_size, 0, &key5, &cksum_k6);
111 : }
112 :
113 :
114 : static krb5_error_code
115 162640 : arcfour_mic_cksum_iov(krb5_context context,
116 : krb5_keyblock *key, unsigned usage,
117 : u_char *sgn_cksum, size_t sgn_cksum_sz,
118 : const u_char *v1, size_t l1,
119 : const void *v2, size_t l2,
120 : const gss_iov_buffer_desc *iov,
121 : int iov_count,
122 : const gss_iov_buffer_desc *padding)
123 : {
124 0 : Checksum CKSUM;
125 0 : u_char *ptr;
126 0 : size_t len;
127 162640 : size_t ofs = 0;
128 0 : int i;
129 0 : krb5_crypto crypto;
130 0 : krb5_error_code ret;
131 :
132 162640 : assert(sgn_cksum_sz == 8);
133 :
134 162640 : len = l1 + l2;
135 :
136 414176 : for (i=0; i < iov_count; i++) {
137 251536 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
138 221904 : case GSS_IOV_BUFFER_TYPE_DATA:
139 : case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
140 221904 : break;
141 29632 : default:
142 29632 : continue;
143 : }
144 :
145 221904 : len += iov[i].buffer.length;
146 : }
147 :
148 162640 : if (padding) {
149 0 : len += padding->buffer.length;
150 : }
151 :
152 162640 : ptr = malloc(len);
153 162640 : if (ptr == NULL)
154 0 : return ENOMEM;
155 :
156 162640 : memcpy(ptr + ofs, v1, l1);
157 162640 : ofs += l1;
158 162640 : memcpy(ptr + ofs, v2, l2);
159 162640 : ofs += l2;
160 :
161 414176 : for (i=0; i < iov_count; i++) {
162 251536 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
163 221904 : case GSS_IOV_BUFFER_TYPE_DATA:
164 : case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
165 221904 : break;
166 29632 : default:
167 29632 : continue;
168 : }
169 :
170 221904 : if (iov[i].buffer.length > 0) {
171 191526 : assert(iov[i].buffer.value != NULL);
172 191526 : memcpy(ptr + ofs,
173 191526 : iov[i].buffer.value,
174 191526 : iov[i].buffer.length);
175 191526 : ofs += iov[i].buffer.length;
176 : }
177 : }
178 :
179 162640 : if (padding) {
180 0 : memcpy(ptr + ofs,
181 0 : padding->buffer.value,
182 0 : padding->buffer.length);
183 : /* ofs += padding->buffer.length; */
184 : }
185 :
186 162640 : ret = krb5_crypto_init(context, key, 0, &crypto);
187 162640 : if (ret) {
188 0 : free(ptr);
189 0 : return ret;
190 : }
191 :
192 162640 : ret = krb5_create_checksum(context,
193 : crypto,
194 : usage,
195 : 0,
196 : ptr, len,
197 : &CKSUM);
198 162640 : memset(ptr, 0, len);
199 162640 : free(ptr);
200 162640 : if (ret == 0) {
201 162640 : memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
202 162640 : free_Checksum(&CKSUM);
203 : }
204 162640 : krb5_crypto_destroy(context, crypto);
205 :
206 162640 : return ret;
207 : }
208 :
209 : static krb5_error_code
210 133008 : arcfour_mic_cksum(krb5_context context,
211 : krb5_keyblock *key, unsigned usage,
212 : u_char *sgn_cksum, size_t sgn_cksum_sz,
213 : const u_char *v1, size_t l1,
214 : const void *v2, size_t l2,
215 : const void *v3, size_t l3)
216 : {
217 0 : gss_iov_buffer_desc iov;
218 :
219 133008 : iov.type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
220 133008 : iov.buffer.value = rk_UNCONST(v3);
221 133008 : iov.buffer.length = l3;
222 :
223 133008 : return arcfour_mic_cksum_iov(context, key, usage,
224 : sgn_cksum, sgn_cksum_sz,
225 : v1, l1, v2, l2,
226 : &iov, 1, NULL);
227 : }
228 :
229 :
230 : OM_uint32
231 15169 : _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
232 : const gsskrb5_ctx context_handle,
233 : krb5_context context,
234 : gss_qop_t qop_req,
235 : const gss_buffer_t message_buffer,
236 : gss_buffer_t message_token,
237 : krb5_keyblock *key)
238 : {
239 0 : krb5_error_code ret;
240 0 : int32_t seq_number;
241 0 : size_t len, total_len;
242 0 : u_char k6_data[16], *p0, *p;
243 0 : EVP_CIPHER_CTX rc4_key;
244 :
245 15169 : _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
246 :
247 15169 : message_token->length = total_len;
248 15169 : message_token->value = malloc (total_len);
249 15169 : if (message_token->value == NULL) {
250 0 : *minor_status = ENOMEM;
251 0 : return GSS_S_FAILURE;
252 : }
253 :
254 15169 : p0 = _gssapi_make_mech_header(message_token->value,
255 : len,
256 : GSS_KRB5_MECHANISM);
257 15169 : p = p0;
258 :
259 15169 : *p++ = 0x01; /* TOK_ID */
260 15169 : *p++ = 0x01;
261 15169 : *p++ = 0x11; /* SGN_ALG */
262 15169 : *p++ = 0x00;
263 15169 : *p++ = 0xff; /* Filler */
264 15169 : *p++ = 0xff;
265 15169 : *p++ = 0xff;
266 15169 : *p++ = 0xff;
267 :
268 15169 : p = NULL;
269 :
270 15169 : ret = arcfour_mic_cksum(context,
271 : key, KRB5_KU_USAGE_SIGN,
272 : p0 + 16, 8, /* SGN_CKSUM */
273 : p0, 8, /* TOK_ID, SGN_ALG, Filer */
274 15169 : message_buffer->value, message_buffer->length,
275 : NULL, 0);
276 15169 : if (ret) {
277 0 : _gsskrb5_release_buffer(minor_status, message_token);
278 0 : *minor_status = ret;
279 0 : return GSS_S_FAILURE;
280 : }
281 :
282 15169 : ret = arcfour_mic_key(context, key,
283 15169 : p0 + 16, 8, /* SGN_CKSUM */
284 : k6_data, sizeof(k6_data));
285 15169 : if (ret) {
286 0 : _gsskrb5_release_buffer(minor_status, message_token);
287 0 : *minor_status = ret;
288 0 : return GSS_S_FAILURE;
289 : }
290 :
291 0 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
292 15169 : krb5_auth_con_getlocalseqnumber (context,
293 : context_handle->auth_context,
294 : &seq_number);
295 15169 : p = p0 + 8; /* SND_SEQ */
296 15169 : _gss_mg_encode_be_uint32(seq_number, p);
297 :
298 15169 : krb5_auth_con_setlocalseqnumber (context,
299 : context_handle->auth_context,
300 : ++seq_number);
301 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
302 :
303 15169 : memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
304 :
305 15169 : EVP_CIPHER_CTX_init(&rc4_key);
306 15169 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
307 15169 : EVP_Cipher(&rc4_key, p, p, 8);
308 15169 : EVP_CIPHER_CTX_cleanup(&rc4_key);
309 :
310 15169 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
311 :
312 15169 : *minor_status = 0;
313 15169 : return GSS_S_COMPLETE;
314 : }
315 :
316 :
317 : OM_uint32
318 15173 : _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
319 : const gsskrb5_ctx context_handle,
320 : krb5_context context,
321 : const gss_buffer_t message_buffer,
322 : const gss_buffer_t token_buffer,
323 : gss_qop_t * qop_state,
324 : krb5_keyblock *key,
325 : const char *type)
326 : {
327 0 : krb5_error_code ret;
328 0 : uint32_t seq_number;
329 0 : OM_uint32 omret;
330 0 : u_char SND_SEQ[8], cksum_data[8], *p;
331 0 : char k6_data[16];
332 0 : int cmp;
333 :
334 15173 : if (qop_state)
335 15173 : *qop_state = 0;
336 :
337 15173 : p = token_buffer->value;
338 15173 : omret = _gsskrb5_verify_header (&p,
339 : token_buffer->length,
340 : type,
341 : GSS_KRB5_MECHANISM);
342 15173 : if (omret)
343 0 : return omret;
344 :
345 15173 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
346 0 : return GSS_S_BAD_SIG;
347 15173 : p += 2;
348 15173 : if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
349 0 : return GSS_S_BAD_MIC;
350 15173 : p += 4;
351 :
352 15173 : ret = arcfour_mic_cksum(context,
353 : key, KRB5_KU_USAGE_SIGN,
354 : cksum_data, sizeof(cksum_data),
355 15173 : p - 8, 8,
356 15173 : message_buffer->value, message_buffer->length,
357 : NULL, 0);
358 15173 : if (ret) {
359 0 : *minor_status = ret;
360 0 : return GSS_S_FAILURE;
361 : }
362 :
363 15173 : ret = arcfour_mic_key(context, key,
364 : cksum_data, sizeof(cksum_data),
365 : k6_data, sizeof(k6_data));
366 15173 : if (ret) {
367 0 : *minor_status = ret;
368 0 : return GSS_S_FAILURE;
369 : }
370 :
371 15173 : cmp = (ct_memcmp(cksum_data, p + 8, 8) != 0);
372 15173 : if (cmp) {
373 0 : *minor_status = 0;
374 0 : return GSS_S_BAD_MIC;
375 : }
376 :
377 : {
378 0 : EVP_CIPHER_CTX rc4_key;
379 :
380 15173 : EVP_CIPHER_CTX_init(&rc4_key);
381 15173 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
382 15173 : EVP_Cipher(&rc4_key, SND_SEQ, p, 8);
383 15173 : EVP_CIPHER_CTX_cleanup(&rc4_key);
384 :
385 15173 : memset(k6_data, 0, sizeof(k6_data));
386 : }
387 :
388 15173 : _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
389 :
390 15173 : if (context_handle->more_flags & LOCAL)
391 2528 : cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
392 : else
393 12645 : cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
394 :
395 15173 : memset_s(SND_SEQ, sizeof(SND_SEQ), 0, sizeof(SND_SEQ));
396 15173 : if (cmp != 0) {
397 0 : *minor_status = 0;
398 0 : return GSS_S_BAD_MIC;
399 : }
400 :
401 0 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
402 15173 : omret = _gssapi_msg_order_check(context_handle->order, seq_number);
403 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
404 15173 : if (omret)
405 0 : return omret;
406 :
407 15173 : *minor_status = 0;
408 15173 : return GSS_S_COMPLETE;
409 : }
410 :
411 : OM_uint32
412 51333 : _gssapi_wrap_arcfour(OM_uint32 * minor_status,
413 : const gsskrb5_ctx context_handle,
414 : krb5_context context,
415 : int conf_req_flag,
416 : gss_qop_t qop_req,
417 : const gss_buffer_t input_message_buffer,
418 : int * conf_state,
419 : gss_buffer_t output_message_buffer,
420 : krb5_keyblock *key)
421 : {
422 0 : u_char Klocaldata[16], k6_data[16], *p, *p0;
423 0 : size_t len, total_len, datalen;
424 0 : krb5_keyblock Klocal;
425 0 : krb5_error_code ret;
426 0 : int32_t seq_number;
427 :
428 51333 : if (conf_state)
429 51333 : *conf_state = 0;
430 :
431 51333 : datalen = input_message_buffer->length;
432 :
433 51333 : if (IS_DCE_STYLE(context_handle)) {
434 0 : len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
435 0 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
436 0 : total_len += datalen;
437 : } else {
438 51333 : datalen += 1; /* padding */
439 51333 : len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
440 51333 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
441 : }
442 :
443 51333 : output_message_buffer->length = total_len;
444 51333 : output_message_buffer->value = malloc (total_len);
445 51333 : if (output_message_buffer->value == NULL) {
446 0 : *minor_status = ENOMEM;
447 0 : return GSS_S_FAILURE;
448 : }
449 :
450 51333 : p0 = _gssapi_make_mech_header(output_message_buffer->value,
451 : len,
452 : GSS_KRB5_MECHANISM);
453 51333 : p = p0;
454 :
455 51333 : *p++ = 0x02; /* TOK_ID */
456 51333 : *p++ = 0x01;
457 51333 : *p++ = 0x11; /* SGN_ALG */
458 51333 : *p++ = 0x00;
459 51333 : if (conf_req_flag) {
460 51305 : *p++ = 0x10; /* SEAL_ALG */
461 51305 : *p++ = 0x00;
462 : } else {
463 28 : *p++ = 0xff; /* SEAL_ALG */
464 28 : *p++ = 0xff;
465 : }
466 51333 : *p++ = 0xff; /* Filler */
467 51333 : *p++ = 0xff;
468 :
469 51333 : p = NULL;
470 :
471 0 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
472 51333 : krb5_auth_con_getlocalseqnumber (context,
473 : context_handle->auth_context,
474 : &seq_number);
475 :
476 51333 : _gss_mg_encode_be_uint32(seq_number, p0 + 8);
477 :
478 51333 : krb5_auth_con_setlocalseqnumber (context,
479 : context_handle->auth_context,
480 : ++seq_number);
481 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
482 :
483 51333 : memset (p0 + 8 + 4,
484 51333 : (context_handle->more_flags & LOCAL) ? 0 : 0xff,
485 : 4);
486 :
487 51333 : krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
488 :
489 : /* p points to data */
490 51333 : p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
491 51333 : memcpy(p, input_message_buffer->value, input_message_buffer->length);
492 :
493 51333 : if (!IS_DCE_STYLE(context_handle))
494 51333 : p[input_message_buffer->length] = 1; /* padding */
495 :
496 51333 : ret = arcfour_mic_cksum(context,
497 : key, KRB5_KU_USAGE_SEAL,
498 : p0 + 16, 8, /* SGN_CKSUM */
499 : p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
500 51333 : p0 + 24, 8, /* Confounder */
501 51333 : p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
502 : datalen);
503 51333 : if (ret) {
504 0 : *minor_status = ret;
505 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
506 0 : return GSS_S_FAILURE;
507 : }
508 :
509 : {
510 0 : int i;
511 :
512 51333 : Klocal.keytype = key->keytype;
513 51333 : Klocal.keyvalue.data = Klocaldata;
514 51333 : Klocal.keyvalue.length = sizeof(Klocaldata);
515 :
516 872661 : for (i = 0; i < 16; i++)
517 821328 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
518 : }
519 51333 : ret = arcfour_mic_key(context, &Klocal,
520 51333 : p0 + 8, 4, /* SND_SEQ */
521 : k6_data, sizeof(k6_data));
522 51333 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
523 51333 : if (ret) {
524 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
525 0 : *minor_status = ret;
526 0 : return GSS_S_FAILURE;
527 : }
528 :
529 :
530 51333 : if(conf_req_flag) {
531 0 : EVP_CIPHER_CTX rc4_key;
532 :
533 51305 : EVP_CIPHER_CTX_init(&rc4_key);
534 51305 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
535 51305 : EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen);
536 51305 : EVP_CIPHER_CTX_cleanup(&rc4_key);
537 : }
538 51333 : memset(k6_data, 0, sizeof(k6_data));
539 :
540 51333 : ret = arcfour_mic_key(context, key,
541 51333 : p0 + 16, 8, /* SGN_CKSUM */
542 : k6_data, sizeof(k6_data));
543 51333 : if (ret) {
544 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
545 0 : *minor_status = ret;
546 0 : return GSS_S_FAILURE;
547 : }
548 :
549 : {
550 0 : EVP_CIPHER_CTX rc4_key;
551 :
552 51333 : EVP_CIPHER_CTX_init(&rc4_key);
553 51333 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
554 51333 : EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
555 51333 : EVP_CIPHER_CTX_cleanup(&rc4_key);
556 51333 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
557 : }
558 :
559 51333 : if (conf_state)
560 51333 : *conf_state = conf_req_flag;
561 :
562 51333 : *minor_status = 0;
563 51333 : return GSS_S_COMPLETE;
564 : }
565 :
566 51333 : OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
567 : const gsskrb5_ctx context_handle,
568 : krb5_context context,
569 : const gss_buffer_t input_message_buffer,
570 : gss_buffer_t output_message_buffer,
571 : int *conf_state,
572 : gss_qop_t *qop_state,
573 : krb5_keyblock *key)
574 : {
575 0 : u_char Klocaldata[16];
576 0 : krb5_keyblock Klocal;
577 0 : krb5_error_code ret;
578 0 : uint32_t seq_number;
579 0 : size_t datalen;
580 0 : OM_uint32 omret;
581 0 : u_char k6_data[16], SND_SEQ[8], Confounder[8];
582 0 : u_char cksum_data[8];
583 0 : u_char *p, *p0;
584 0 : int cmp;
585 0 : int conf_flag;
586 51333 : size_t padlen = 0, len;
587 :
588 51333 : if (conf_state)
589 51333 : *conf_state = 0;
590 51333 : if (qop_state)
591 51333 : *qop_state = 0;
592 :
593 51333 : p0 = input_message_buffer->value;
594 :
595 51333 : if (IS_DCE_STYLE(context_handle)) {
596 0 : len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
597 : GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
598 0 : if (input_message_buffer->length < len)
599 0 : return GSS_S_BAD_MECH;
600 : } else {
601 51333 : len = input_message_buffer->length;
602 : }
603 :
604 51333 : omret = _gssapi_verify_mech_header(&p0,
605 : len,
606 : GSS_KRB5_MECHANISM);
607 51333 : if (omret)
608 0 : return omret;
609 :
610 : /* length of mech header */
611 51333 : len = (p0 - (u_char *)input_message_buffer->value) +
612 : GSS_ARCFOUR_WRAP_TOKEN_SIZE;
613 :
614 51333 : if (len > input_message_buffer->length)
615 0 : return GSS_S_BAD_MECH;
616 :
617 : /* length of data */
618 51333 : datalen = input_message_buffer->length - len;
619 :
620 51333 : p = p0;
621 :
622 51333 : if (memcmp(p, "\x02\x01", 2) != 0)
623 0 : return GSS_S_BAD_SIG;
624 51333 : p += 2;
625 51333 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
626 0 : return GSS_S_BAD_SIG;
627 51333 : p += 2;
628 :
629 51333 : if (memcmp (p, "\x10\x00", 2) == 0)
630 51305 : conf_flag = 1;
631 28 : else if (memcmp (p, "\xff\xff", 2) == 0)
632 28 : conf_flag = 0;
633 : else
634 0 : return GSS_S_BAD_SIG;
635 :
636 51333 : p += 2;
637 51333 : if (memcmp (p, "\xff\xff", 2) != 0)
638 0 : return GSS_S_BAD_MIC;
639 51333 : p = NULL;
640 :
641 51333 : ret = arcfour_mic_key(context, key,
642 51333 : p0 + 16, 8, /* SGN_CKSUM */
643 : k6_data, sizeof(k6_data));
644 51333 : if (ret) {
645 0 : *minor_status = ret;
646 0 : return GSS_S_FAILURE;
647 : }
648 :
649 : {
650 0 : EVP_CIPHER_CTX rc4_key;
651 :
652 51333 : EVP_CIPHER_CTX_init(&rc4_key);
653 51333 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
654 51333 : EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8);
655 51333 : EVP_CIPHER_CTX_cleanup(&rc4_key);
656 51333 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
657 : }
658 :
659 51333 : _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
660 :
661 51333 : if (context_handle->more_flags & LOCAL)
662 25669 : cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
663 : else
664 25664 : cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
665 :
666 51333 : if (cmp != 0) {
667 0 : *minor_status = 0;
668 0 : return GSS_S_BAD_MIC;
669 : }
670 :
671 : {
672 0 : int i;
673 :
674 51333 : Klocal.keytype = key->keytype;
675 51333 : Klocal.keyvalue.data = Klocaldata;
676 51333 : Klocal.keyvalue.length = sizeof(Klocaldata);
677 :
678 872661 : for (i = 0; i < 16; i++)
679 821328 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
680 : }
681 51333 : ret = arcfour_mic_key(context, &Klocal,
682 : SND_SEQ, 4,
683 : k6_data, sizeof(k6_data));
684 51333 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
685 51333 : if (ret) {
686 0 : *minor_status = ret;
687 0 : return GSS_S_FAILURE;
688 : }
689 :
690 51333 : output_message_buffer->value = malloc(datalen);
691 51333 : if (output_message_buffer->value == NULL) {
692 0 : *minor_status = ENOMEM;
693 0 : return GSS_S_FAILURE;
694 : }
695 51333 : output_message_buffer->length = datalen;
696 :
697 51333 : if(conf_flag) {
698 0 : EVP_CIPHER_CTX rc4_key;
699 :
700 51305 : EVP_CIPHER_CTX_init(&rc4_key);
701 51305 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
702 51305 : EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
703 51305 : EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
704 51305 : EVP_CIPHER_CTX_cleanup(&rc4_key);
705 : } else {
706 28 : memcpy(Confounder, p0 + 24, 8); /* Confounder */
707 28 : memcpy(output_message_buffer->value,
708 28 : p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
709 : datalen);
710 : }
711 51333 : memset(k6_data, 0, sizeof(k6_data));
712 :
713 51333 : if (!IS_DCE_STYLE(context_handle)) {
714 51333 : ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
715 51333 : if (ret) {
716 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
717 0 : *minor_status = 0;
718 0 : return ret;
719 : }
720 51333 : output_message_buffer->length -= padlen;
721 : }
722 :
723 51333 : ret = arcfour_mic_cksum(context,
724 : key, KRB5_KU_USAGE_SEAL,
725 : cksum_data, sizeof(cksum_data),
726 : p0, 8,
727 : Confounder, sizeof(Confounder),
728 51333 : output_message_buffer->value,
729 51333 : output_message_buffer->length + padlen);
730 51333 : if (ret) {
731 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
732 0 : *minor_status = ret;
733 0 : return GSS_S_FAILURE;
734 : }
735 :
736 51333 : cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
737 51333 : if (cmp) {
738 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
739 0 : *minor_status = 0;
740 0 : return GSS_S_BAD_MIC;
741 : }
742 :
743 0 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
744 51333 : omret = _gssapi_msg_order_check(context_handle->order, seq_number);
745 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
746 51333 : if (omret)
747 0 : return omret;
748 :
749 51333 : if (conf_state)
750 51333 : *conf_state = conf_flag;
751 :
752 51333 : *minor_status = 0;
753 51333 : return GSS_S_COMPLETE;
754 : }
755 :
756 : static OM_uint32
757 1496 : max_wrap_length_arcfour(const gsskrb5_ctx ctx,
758 : krb5_crypto crypto,
759 : size_t input_length,
760 : OM_uint32 *max_input_size)
761 : {
762 : /*
763 : * if GSS_C_DCE_STYLE is in use:
764 : * - we only need to encapsulate the WRAP token
765 : * However, since this is a fixed since, we just
766 : */
767 1496 : if (IS_DCE_STYLE(ctx)) {
768 0 : size_t len, total_len;
769 :
770 0 : len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
771 0 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
772 :
773 0 : if (input_length < len)
774 0 : *max_input_size = 0;
775 : else
776 0 : *max_input_size = input_length - len;
777 :
778 : } else {
779 1496 : size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
780 1496 : size_t blocksize = 8;
781 0 : size_t len, total_len;
782 :
783 1496 : len = 8 + input_length + blocksize + extrasize;
784 :
785 1496 : _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
786 :
787 1496 : total_len -= input_length; /* token length */
788 1496 : if (total_len < input_length) {
789 1496 : *max_input_size = (input_length - total_len);
790 1496 : (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
791 : } else {
792 0 : *max_input_size = 0;
793 : }
794 : }
795 :
796 1496 : return GSS_S_COMPLETE;
797 : }
798 :
799 : OM_uint32
800 1496 : _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
801 : const gsskrb5_ctx ctx,
802 : krb5_context context,
803 : int conf_req_flag,
804 : gss_qop_t qop_req,
805 : OM_uint32 req_output_size,
806 : OM_uint32 *max_input_size,
807 : krb5_keyblock *key)
808 : {
809 0 : krb5_error_code ret;
810 0 : krb5_crypto crypto;
811 :
812 1496 : ret = krb5_crypto_init(context, key, 0, &crypto);
813 1496 : if (ret != 0) {
814 0 : *minor_status = ret;
815 0 : return GSS_S_FAILURE;
816 : }
817 :
818 1496 : ret = max_wrap_length_arcfour(ctx, crypto,
819 : req_output_size, max_input_size);
820 1496 : if (ret != 0) {
821 0 : *minor_status = ret;
822 0 : krb5_crypto_destroy(context, crypto);
823 0 : return GSS_S_FAILURE;
824 : }
825 :
826 1496 : krb5_crypto_destroy(context, crypto);
827 :
828 1496 : return GSS_S_COMPLETE;
829 : }
830 :
831 : OM_uint32
832 628 : _gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status,
833 : gsskrb5_ctx ctx,
834 : krb5_context context,
835 : int conf_req_flag,
836 : gss_qop_t qop_req,
837 : int *conf_state,
838 : gss_iov_buffer_desc *iov,
839 : int iov_count)
840 : {
841 0 : OM_uint32 major_status;
842 628 : size_t data_len = 0;
843 0 : int i;
844 628 : gss_iov_buffer_desc *header = NULL;
845 628 : gss_iov_buffer_desc *padding = NULL;
846 628 : gss_iov_buffer_desc *trailer = NULL;
847 :
848 628 : *minor_status = 0;
849 :
850 1884 : for (i = 0; i < iov_count; i++) {
851 1256 : switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
852 0 : case GSS_IOV_BUFFER_TYPE_EMPTY:
853 0 : break;
854 628 : case GSS_IOV_BUFFER_TYPE_DATA:
855 628 : data_len += iov[i].buffer.length;
856 628 : break;
857 628 : case GSS_IOV_BUFFER_TYPE_HEADER:
858 628 : if (header != NULL) {
859 0 : *minor_status = EINVAL;
860 0 : return GSS_S_FAILURE;
861 : }
862 628 : header = &iov[i];
863 628 : break;
864 0 : case GSS_IOV_BUFFER_TYPE_TRAILER:
865 0 : if (trailer != NULL) {
866 0 : *minor_status = EINVAL;
867 0 : return GSS_S_FAILURE;
868 : }
869 0 : trailer = &iov[i];
870 0 : break;
871 0 : case GSS_IOV_BUFFER_TYPE_PADDING:
872 0 : if (padding != NULL) {
873 0 : *minor_status = EINVAL;
874 0 : return GSS_S_FAILURE;
875 : }
876 0 : padding = &iov[i];
877 0 : break;
878 0 : case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
879 0 : break;
880 0 : default:
881 0 : *minor_status = EINVAL;
882 0 : return GSS_S_FAILURE;
883 : }
884 : }
885 :
886 628 : if (header == NULL) {
887 0 : *minor_status = EINVAL;
888 0 : return GSS_S_FAILURE;
889 : }
890 :
891 628 : major_status = _gk_verify_buffers(minor_status, ctx, header,
892 : padding, trailer, FALSE);
893 628 : if (major_status != GSS_S_COMPLETE) {
894 0 : return major_status;
895 : }
896 :
897 628 : if (IS_DCE_STYLE(ctx)) {
898 628 : size_t len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
899 0 : size_t total_len;
900 628 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
901 628 : header->buffer.length = total_len;
902 : } else {
903 0 : size_t len;
904 0 : size_t total_len;
905 0 : if (padding) {
906 0 : data_len += 1; /* padding */
907 : }
908 0 : len = data_len + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
909 0 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
910 0 : header->buffer.length = total_len - data_len;
911 : }
912 :
913 628 : if (trailer) {
914 0 : trailer->buffer.length = 0;
915 : }
916 :
917 628 : if (padding) {
918 0 : padding->buffer.length = 1;
919 : }
920 :
921 628 : return GSS_S_COMPLETE;
922 : }
923 :
924 : OM_uint32
925 17564 : _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
926 : gsskrb5_ctx ctx,
927 : krb5_context context,
928 : int conf_req_flag,
929 : int *conf_state,
930 : gss_iov_buffer_desc *iov,
931 : int iov_count,
932 : krb5_keyblock *key)
933 : {
934 0 : OM_uint32 major_status, junk;
935 0 : gss_iov_buffer_desc *header, *padding, *trailer;
936 0 : krb5_error_code kret;
937 0 : int32_t seq_number;
938 0 : u_char Klocaldata[16], k6_data[16], *p, *p0;
939 17564 : size_t make_len = 0;
940 17564 : size_t header_len = 0;
941 17564 : size_t data_len = 0;
942 0 : krb5_keyblock Klocal;
943 0 : int i;
944 :
945 17564 : header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
946 17564 : padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
947 17564 : trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
948 :
949 17564 : major_status = _gk_verify_buffers(minor_status, ctx, header,
950 : padding, trailer, FALSE);
951 17564 : if (major_status != GSS_S_COMPLETE) {
952 0 : return major_status;
953 : }
954 :
955 87820 : for (i = 0; i < iov_count; i++) {
956 70256 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
957 17564 : case GSS_IOV_BUFFER_TYPE_DATA:
958 17564 : break;
959 52692 : default:
960 52692 : continue;
961 : }
962 :
963 17564 : data_len += iov[i].buffer.length;
964 : }
965 :
966 17564 : if (padding) {
967 0 : data_len += 1;
968 : }
969 :
970 17564 : if (IS_DCE_STYLE(ctx)) {
971 0 : size_t unwrapped_len;
972 17564 : unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
973 17564 : _gssapi_encap_length(unwrapped_len,
974 : &make_len,
975 : &header_len,
976 : GSS_KRB5_MECHANISM);
977 : } else {
978 0 : size_t unwrapped_len;
979 0 : unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + data_len;
980 0 : _gssapi_encap_length(unwrapped_len,
981 : &make_len,
982 : &header_len,
983 : GSS_KRB5_MECHANISM);
984 0 : header_len -= data_len;
985 : }
986 :
987 17564 : if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
988 0 : major_status = _gk_allocate_buffer(minor_status, header,
989 : header_len);
990 0 : if (major_status != GSS_S_COMPLETE)
991 0 : goto failure;
992 17564 : } else if (header->buffer.length < header_len) {
993 0 : *minor_status = KRB5_BAD_MSIZE;
994 0 : major_status = GSS_S_FAILURE;
995 0 : goto failure;
996 : } else {
997 17564 : header->buffer.length = header_len;
998 : }
999 :
1000 17564 : if (padding) {
1001 0 : if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
1002 0 : major_status = _gk_allocate_buffer(minor_status, padding, 1);
1003 0 : if (major_status != GSS_S_COMPLETE)
1004 0 : goto failure;
1005 0 : } else if (padding->buffer.length < 1) {
1006 0 : *minor_status = KRB5_BAD_MSIZE;
1007 0 : major_status = GSS_S_FAILURE;
1008 0 : goto failure;
1009 : } else {
1010 0 : padding->buffer.length = 1;
1011 : }
1012 0 : memset(padding->buffer.value, 1, 1);
1013 : }
1014 :
1015 17564 : if (trailer) {
1016 0 : trailer->buffer.length = 0;
1017 0 : trailer->buffer.value = NULL;
1018 : }
1019 :
1020 17564 : p0 = _gssapi_make_mech_header(header->buffer.value,
1021 : make_len,
1022 : GSS_KRB5_MECHANISM);
1023 17564 : p = p0;
1024 :
1025 17564 : *p++ = 0x02; /* TOK_ID */
1026 17564 : *p++ = 0x01;
1027 17564 : *p++ = 0x11; /* SGN_ALG */
1028 17564 : *p++ = 0x00;
1029 17564 : if (conf_req_flag) {
1030 17564 : *p++ = 0x10; /* SEAL_ALG */
1031 17564 : *p++ = 0x00;
1032 : } else {
1033 0 : *p++ = 0xff; /* SEAL_ALG */
1034 0 : *p++ = 0xff;
1035 : }
1036 17564 : *p++ = 0xff; /* Filler */
1037 17564 : *p++ = 0xff;
1038 :
1039 17564 : p = NULL;
1040 :
1041 0 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
1042 17564 : krb5_auth_con_getlocalseqnumber(context,
1043 : ctx->auth_context,
1044 : &seq_number);
1045 17564 : _gss_mg_encode_be_uint32(seq_number, p0 + 8);
1046 :
1047 17564 : krb5_auth_con_setlocalseqnumber(context,
1048 : ctx->auth_context,
1049 : ++seq_number);
1050 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
1051 :
1052 17564 : memset(p0 + 8 + 4,
1053 17564 : (ctx->more_flags & LOCAL) ? 0 : 0xff,
1054 : 4);
1055 :
1056 17564 : krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
1057 :
1058 : /* Sign Data */
1059 17564 : kret = arcfour_mic_cksum_iov(context,
1060 : key, KRB5_KU_USAGE_SEAL,
1061 : p0 + 16, 8, /* SGN_CKSUM */
1062 : p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
1063 17564 : p0 + 24, 8, /* Confounder */
1064 : iov, iov_count, /* Data + SignOnly */
1065 : padding); /* padding */
1066 17564 : if (kret) {
1067 0 : *minor_status = kret;
1068 0 : major_status = GSS_S_FAILURE;
1069 0 : goto failure;
1070 : }
1071 :
1072 17564 : Klocal.keytype = key->keytype;
1073 17564 : Klocal.keyvalue.data = Klocaldata;
1074 17564 : Klocal.keyvalue.length = sizeof(Klocaldata);
1075 :
1076 298588 : for (i = 0; i < 16; i++) {
1077 281024 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
1078 : }
1079 17564 : kret = arcfour_mic_key(context, &Klocal,
1080 17564 : p0 + 8, 4, /* SND_SEQ */
1081 : k6_data, sizeof(k6_data));
1082 17564 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
1083 17564 : if (kret) {
1084 0 : *minor_status = kret;
1085 0 : major_status = GSS_S_FAILURE;
1086 0 : goto failure;
1087 : }
1088 :
1089 17564 : if (conf_req_flag) {
1090 0 : EVP_CIPHER_CTX rc4_key;
1091 :
1092 17564 : EVP_CIPHER_CTX_init(&rc4_key);
1093 17564 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1094 :
1095 : /* Confounder */
1096 17564 : EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8);
1097 :
1098 : /* Seal Data */
1099 87820 : for (i=0; i < iov_count; i++) {
1100 70256 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
1101 17564 : case GSS_IOV_BUFFER_TYPE_DATA:
1102 17564 : break;
1103 52692 : default:
1104 52692 : continue;
1105 : }
1106 :
1107 17564 : EVP_Cipher(&rc4_key, iov[i].buffer.value,
1108 17564 : iov[i].buffer.value, iov[i].buffer.length);
1109 : }
1110 :
1111 : /* Padding */
1112 17564 : if (padding) {
1113 0 : EVP_Cipher(&rc4_key, padding->buffer.value,
1114 0 : padding->buffer.value, padding->buffer.length);
1115 : }
1116 :
1117 17564 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1118 : }
1119 17564 : memset(k6_data, 0, sizeof(k6_data));
1120 :
1121 17564 : kret = arcfour_mic_key(context, key,
1122 17564 : p0 + 16, 8, /* SGN_CKSUM */
1123 : k6_data, sizeof(k6_data));
1124 17564 : if (kret) {
1125 0 : *minor_status = kret;
1126 0 : major_status = GSS_S_FAILURE;
1127 0 : return major_status;
1128 : }
1129 :
1130 : {
1131 0 : EVP_CIPHER_CTX rc4_key;
1132 :
1133 17564 : EVP_CIPHER_CTX_init(&rc4_key);
1134 17564 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1135 17564 : EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */
1136 17564 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1137 :
1138 17564 : memset(k6_data, 0, sizeof(k6_data));
1139 : }
1140 :
1141 17564 : if (conf_state)
1142 17564 : *conf_state = conf_req_flag;
1143 :
1144 17564 : *minor_status = 0;
1145 17564 : return GSS_S_COMPLETE;
1146 :
1147 0 : failure:
1148 :
1149 0 : gss_release_iov_buffer(&junk, iov, iov_count);
1150 :
1151 0 : return major_status;
1152 : }
1153 :
1154 : OM_uint32
1155 12068 : _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
1156 : gsskrb5_ctx ctx,
1157 : krb5_context context,
1158 : int *pconf_state,
1159 : gss_qop_t *pqop_state,
1160 : gss_iov_buffer_desc *iov,
1161 : int iov_count,
1162 : krb5_keyblock *key)
1163 : {
1164 0 : OM_uint32 major_status;
1165 0 : gss_iov_buffer_desc *header, *padding, *trailer;
1166 0 : krb5_keyblock Klocal;
1167 0 : uint8_t Klocaldata[16];
1168 0 : uint8_t k6_data[16], snd_seq[8], Confounder[8];
1169 0 : uint8_t cksum_data[8];
1170 12068 : uint8_t *_p = NULL;
1171 0 : const uint8_t *p, *p0;
1172 12068 : size_t verify_len = 0;
1173 0 : uint32_t seq_number;
1174 12068 : size_t hlen = 0;
1175 0 : int conf_state;
1176 0 : int cmp;
1177 0 : size_t i;
1178 0 : krb5_error_code kret;
1179 0 : OM_uint32 ret;
1180 :
1181 12068 : if (pconf_state != NULL) {
1182 12068 : *pconf_state = 0;
1183 : }
1184 12068 : if (pqop_state != NULL) {
1185 12068 : *pqop_state = 0;
1186 : }
1187 :
1188 12068 : header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
1189 12068 : padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
1190 12068 : trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
1191 :
1192 : /* Check if the packet is correct */
1193 12068 : major_status = _gk_verify_buffers(minor_status,
1194 : ctx,
1195 : header,
1196 : padding,
1197 : trailer,
1198 : FALSE); /* behaves as stream cipher */
1199 12068 : if (major_status != GSS_S_COMPLETE) {
1200 0 : return major_status;
1201 : }
1202 :
1203 12068 : if (padding != NULL && padding->buffer.length != 1) {
1204 0 : *minor_status = EINVAL;
1205 0 : return GSS_S_FAILURE;
1206 : }
1207 :
1208 12068 : verify_len = header->buffer.length;
1209 :
1210 12068 : if (!IS_DCE_STYLE(ctx)) {
1211 0 : for (i = 0; i < iov_count; i++) {
1212 : /* length in header also includes data and padding */
1213 0 : if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA)
1214 0 : verify_len += iov[i].buffer.length;
1215 : }
1216 :
1217 0 : if (padding)
1218 0 : verify_len += padding->buffer.length;
1219 : }
1220 :
1221 12068 : _p = header->buffer.value;
1222 :
1223 12068 : ret = _gssapi_verify_mech_header(&_p,
1224 : verify_len,
1225 : GSS_KRB5_MECHANISM);
1226 12068 : if (ret) {
1227 0 : return ret;
1228 : }
1229 12068 : p0 = _p;
1230 :
1231 : /* length of mech header */
1232 12068 : hlen = (p0 - (uint8_t *)header->buffer.value);
1233 12068 : hlen += GSS_ARCFOUR_WRAP_TOKEN_SIZE;
1234 :
1235 12068 : if (hlen > header->buffer.length) {
1236 0 : return GSS_S_BAD_MECH;
1237 : }
1238 :
1239 12068 : p = p0;
1240 :
1241 12068 : if (memcmp(p, "\x02\x01", 2) != 0)
1242 0 : return GSS_S_BAD_SIG;
1243 12068 : p += 2;
1244 12068 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
1245 0 : return GSS_S_BAD_SIG;
1246 12068 : p += 2;
1247 :
1248 12068 : if (memcmp (p, "\x10\x00", 2) == 0)
1249 12068 : conf_state = 1;
1250 0 : else if (memcmp (p, "\xff\xff", 2) == 0)
1251 0 : conf_state = 0;
1252 : else
1253 0 : return GSS_S_BAD_SIG;
1254 :
1255 12068 : p += 2;
1256 12068 : if (memcmp (p, "\xff\xff", 2) != 0)
1257 0 : return GSS_S_BAD_MIC;
1258 12068 : p = NULL;
1259 :
1260 12068 : kret = arcfour_mic_key(context,
1261 : key,
1262 12068 : p0 + 16, /* SGN_CKSUM */
1263 : 8, /* SGN_CKSUM_LEN */
1264 : k6_data,
1265 : sizeof(k6_data));
1266 12068 : if (kret) {
1267 0 : *minor_status = kret;
1268 0 : return GSS_S_FAILURE;
1269 : }
1270 :
1271 : {
1272 0 : EVP_CIPHER_CTX rc4_key;
1273 :
1274 12068 : EVP_CIPHER_CTX_init(&rc4_key);
1275 12068 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1276 12068 : EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */
1277 12068 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1278 :
1279 12068 : memset(k6_data, 0, sizeof(k6_data));
1280 : }
1281 :
1282 12068 : _gss_mg_decode_be_uint32(snd_seq, &seq_number);
1283 :
1284 12068 : if (ctx->more_flags & LOCAL) {
1285 4540 : cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0);
1286 : } else {
1287 7528 : cmp = (ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4) != 0);
1288 : }
1289 12068 : if (cmp != 0) {
1290 0 : *minor_status = 0;
1291 0 : return GSS_S_BAD_MIC;
1292 : }
1293 :
1294 : /* keyblock */
1295 12068 : Klocal.keytype = key->keytype;
1296 12068 : Klocal.keyvalue.data = Klocaldata;
1297 12068 : Klocal.keyvalue.length = sizeof(Klocaldata);
1298 :
1299 205156 : for (i = 0; i < 16; i++) {
1300 193088 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
1301 : }
1302 :
1303 12068 : kret = arcfour_mic_key(context,
1304 : &Klocal,
1305 : snd_seq,
1306 : 4,
1307 : k6_data, sizeof(k6_data));
1308 12068 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
1309 12068 : if (kret) {
1310 0 : *minor_status = kret;
1311 0 : return GSS_S_FAILURE;
1312 : }
1313 :
1314 12068 : if (conf_state == 1) {
1315 0 : EVP_CIPHER_CTX rc4_key;
1316 :
1317 12068 : EVP_CIPHER_CTX_init(&rc4_key);
1318 12068 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1319 :
1320 : /* Confounder */
1321 12068 : EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
1322 :
1323 : /* Data */
1324 60340 : for (i = 0; i < iov_count; i++) {
1325 48272 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
1326 12068 : case GSS_IOV_BUFFER_TYPE_DATA:
1327 12068 : break;
1328 36204 : default:
1329 36204 : continue;
1330 : }
1331 :
1332 12068 : EVP_Cipher(&rc4_key, iov[i].buffer.value,
1333 12068 : iov[i].buffer.value, iov[i].buffer.length);
1334 : }
1335 :
1336 : /* Padding */
1337 12068 : if (padding) {
1338 0 : EVP_Cipher(&rc4_key, padding->buffer.value,
1339 0 : padding->buffer.value, padding->buffer.length);
1340 : }
1341 :
1342 12068 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1343 : } else {
1344 : /* Confounder */
1345 0 : memcpy(Confounder, p0 + 24, 8);
1346 : }
1347 12068 : memset(k6_data, 0, sizeof(k6_data));
1348 :
1349 : /* Prepare the buffer for signing */
1350 12068 : kret = arcfour_mic_cksum_iov(context,
1351 : key, KRB5_KU_USAGE_SEAL,
1352 : cksum_data, sizeof(cksum_data),
1353 : p0, 8,
1354 : Confounder, sizeof(Confounder),
1355 : iov, iov_count,
1356 : padding);
1357 12068 : if (kret) {
1358 0 : *minor_status = kret;
1359 0 : return GSS_S_FAILURE;
1360 : }
1361 :
1362 12068 : cmp = (ct_memcmp(cksum_data, p0 + 16, 8) != 0); /* SGN_CKSUM */
1363 12068 : if (cmp) {
1364 0 : *minor_status = 0;
1365 0 : return GSS_S_BAD_MIC;
1366 : }
1367 :
1368 12068 : if (padding) {
1369 0 : size_t plen;
1370 :
1371 0 : ret = _gssapi_verify_pad(&padding->buffer, 1, &plen);
1372 0 : if (ret) {
1373 0 : *minor_status = 0;
1374 0 : return ret;
1375 : }
1376 : }
1377 :
1378 0 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
1379 12068 : ret = _gssapi_msg_order_check(ctx->order, seq_number);
1380 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
1381 12068 : if (ret != 0) {
1382 0 : return ret;
1383 : }
1384 :
1385 12068 : if (pconf_state) {
1386 12068 : *pconf_state = conf_state;
1387 : }
1388 :
1389 12068 : *minor_status = 0;
1390 12068 : return GSS_S_COMPLETE;
1391 : }
|