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 287262 : 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 287262 : memset(T, 0, 4);
86 287262 : cksum_k5.checksum.data = k5_data;
87 287262 : cksum_k5.checksum.length = sizeof(k5_data);
88 :
89 287262 : 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 287262 : ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
98 : T, 4, 0, key, &cksum_k5);
99 : }
100 287262 : if (ret)
101 0 : return ret;
102 :
103 287262 : key5.keytype = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5;
104 287262 : key5.keyvalue = cksum_k5.checksum;
105 :
106 287262 : cksum_k6.checksum.data = key6_data;
107 287262 : cksum_k6.checksum.length = key6_size;
108 :
109 287262 : 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 158772 : 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 158772 : size_t ofs = 0;
128 0 : int i;
129 0 : krb5_crypto crypto;
130 0 : krb5_error_code ret;
131 :
132 158772 : assert(sgn_cksum_sz == 8);
133 :
134 158772 : len = l1 + l2;
135 :
136 406332 : for (i=0; i < iov_count; i++) {
137 247560 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
138 217964 : case GSS_IOV_BUFFER_TYPE_DATA:
139 : case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
140 217964 : break;
141 29596 : default:
142 29596 : continue;
143 : }
144 :
145 217964 : len += iov[i].buffer.length;
146 : }
147 :
148 158772 : if (padding) {
149 0 : len += padding->buffer.length;
150 : }
151 :
152 158772 : ptr = malloc(len);
153 158772 : if (ptr == NULL)
154 0 : return ENOMEM;
155 :
156 158772 : memcpy(ptr + ofs, v1, l1);
157 158772 : ofs += l1;
158 158772 : memcpy(ptr + ofs, v2, l2);
159 158772 : ofs += l2;
160 :
161 406332 : for (i=0; i < iov_count; i++) {
162 247560 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
163 217964 : case GSS_IOV_BUFFER_TYPE_DATA:
164 : case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
165 217964 : break;
166 29596 : default:
167 29596 : continue;
168 : }
169 :
170 217964 : if (iov[i].buffer.length > 0) {
171 187646 : assert(iov[i].buffer.value != NULL);
172 187646 : memcpy(ptr + ofs,
173 187646 : iov[i].buffer.value,
174 187646 : iov[i].buffer.length);
175 187646 : ofs += iov[i].buffer.length;
176 : }
177 : }
178 :
179 158772 : 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 158772 : ret = krb5_crypto_init(context, key, 0, &crypto);
187 158772 : if (ret) {
188 0 : free(ptr);
189 0 : return ret;
190 : }
191 :
192 158772 : ret = krb5_create_checksum(context,
193 : crypto,
194 : usage,
195 : 0,
196 : ptr, len,
197 : &CKSUM);
198 158772 : memset(ptr, 0, len);
199 158772 : free(ptr);
200 158772 : if (ret == 0) {
201 158772 : memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
202 158772 : free_Checksum(&CKSUM);
203 : }
204 158772 : krb5_crypto_destroy(context, crypto);
205 :
206 158772 : return ret;
207 : }
208 :
209 : static krb5_error_code
210 129176 : 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 129176 : iov.type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
220 129176 : iov.buffer.value = rk_UNCONST(v3);
221 129176 : iov.buffer.length = l3;
222 :
223 129176 : 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 15139 : _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 15139 : _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
246 :
247 15139 : message_token->length = total_len;
248 15139 : message_token->value = malloc (total_len);
249 15139 : if (message_token->value == NULL) {
250 0 : *minor_status = ENOMEM;
251 0 : return GSS_S_FAILURE;
252 : }
253 :
254 15139 : p0 = _gssapi_make_mech_header(message_token->value,
255 : len,
256 : GSS_KRB5_MECHANISM);
257 15139 : p = p0;
258 :
259 15139 : *p++ = 0x01; /* TOK_ID */
260 15139 : *p++ = 0x01;
261 15139 : *p++ = 0x11; /* SGN_ALG */
262 15139 : *p++ = 0x00;
263 15139 : *p++ = 0xff; /* Filler */
264 15139 : *p++ = 0xff;
265 15139 : *p++ = 0xff;
266 15139 : *p++ = 0xff;
267 :
268 15139 : p = NULL;
269 :
270 15139 : 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 15139 : message_buffer->value, message_buffer->length,
275 : NULL, 0);
276 15139 : 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 15139 : ret = arcfour_mic_key(context, key,
283 15139 : p0 + 16, 8, /* SGN_CKSUM */
284 : k6_data, sizeof(k6_data));
285 15139 : 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 15139 : krb5_auth_con_getlocalseqnumber (context,
293 : context_handle->auth_context,
294 : &seq_number);
295 15139 : p = p0 + 8; /* SND_SEQ */
296 15139 : _gss_mg_encode_be_uint32(seq_number, p);
297 :
298 15139 : 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 15139 : memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
304 :
305 15139 : EVP_CIPHER_CTX_init(&rc4_key);
306 15139 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
307 15139 : EVP_Cipher(&rc4_key, p, p, 8);
308 15139 : EVP_CIPHER_CTX_cleanup(&rc4_key);
309 :
310 15139 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
311 :
312 15139 : *minor_status = 0;
313 15139 : return GSS_S_COMPLETE;
314 : }
315 :
316 :
317 : OM_uint32
318 15143 : _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 15143 : if (qop_state)
335 15143 : *qop_state = 0;
336 :
337 15143 : p = token_buffer->value;
338 15143 : omret = _gsskrb5_verify_header (&p,
339 : token_buffer->length,
340 : type,
341 : GSS_KRB5_MECHANISM);
342 15143 : if (omret)
343 0 : return omret;
344 :
345 15143 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
346 0 : return GSS_S_BAD_SIG;
347 15143 : p += 2;
348 15143 : if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
349 0 : return GSS_S_BAD_MIC;
350 15143 : p += 4;
351 :
352 15143 : ret = arcfour_mic_cksum(context,
353 : key, KRB5_KU_USAGE_SIGN,
354 : cksum_data, sizeof(cksum_data),
355 15143 : p - 8, 8,
356 15143 : message_buffer->value, message_buffer->length,
357 : NULL, 0);
358 15143 : if (ret) {
359 0 : *minor_status = ret;
360 0 : return GSS_S_FAILURE;
361 : }
362 :
363 15143 : ret = arcfour_mic_key(context, key,
364 : cksum_data, sizeof(cksum_data),
365 : k6_data, sizeof(k6_data));
366 15143 : if (ret) {
367 0 : *minor_status = ret;
368 0 : return GSS_S_FAILURE;
369 : }
370 :
371 15143 : cmp = (ct_memcmp(cksum_data, p + 8, 8) != 0);
372 15143 : 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 15143 : EVP_CIPHER_CTX_init(&rc4_key);
381 15143 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
382 15143 : EVP_Cipher(&rc4_key, SND_SEQ, p, 8);
383 15143 : EVP_CIPHER_CTX_cleanup(&rc4_key);
384 :
385 15143 : memset(k6_data, 0, sizeof(k6_data));
386 : }
387 :
388 15143 : _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
389 :
390 15143 : if (context_handle->more_flags & LOCAL)
391 2523 : cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
392 : else
393 12620 : cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
394 :
395 15143 : memset_s(SND_SEQ, sizeof(SND_SEQ), 0, sizeof(SND_SEQ));
396 15143 : 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 15143 : omret = _gssapi_msg_order_check(context_handle->order, seq_number);
403 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
404 15143 : if (omret)
405 0 : return omret;
406 :
407 15143 : *minor_status = 0;
408 15143 : return GSS_S_COMPLETE;
409 : }
410 :
411 : OM_uint32
412 49447 : _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 49447 : if (conf_state)
429 49447 : *conf_state = 0;
430 :
431 49447 : datalen = input_message_buffer->length;
432 :
433 49447 : 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 49447 : datalen += 1; /* padding */
439 49447 : len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
440 49447 : _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
441 : }
442 :
443 49447 : output_message_buffer->length = total_len;
444 49447 : output_message_buffer->value = malloc (total_len);
445 49447 : if (output_message_buffer->value == NULL) {
446 0 : *minor_status = ENOMEM;
447 0 : return GSS_S_FAILURE;
448 : }
449 :
450 49447 : p0 = _gssapi_make_mech_header(output_message_buffer->value,
451 : len,
452 : GSS_KRB5_MECHANISM);
453 49447 : p = p0;
454 :
455 49447 : *p++ = 0x02; /* TOK_ID */
456 49447 : *p++ = 0x01;
457 49447 : *p++ = 0x11; /* SGN_ALG */
458 49447 : *p++ = 0x00;
459 49447 : if (conf_req_flag) {
460 49419 : *p++ = 0x10; /* SEAL_ALG */
461 49419 : *p++ = 0x00;
462 : } else {
463 28 : *p++ = 0xff; /* SEAL_ALG */
464 28 : *p++ = 0xff;
465 : }
466 49447 : *p++ = 0xff; /* Filler */
467 49447 : *p++ = 0xff;
468 :
469 49447 : p = NULL;
470 :
471 0 : HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
472 49447 : krb5_auth_con_getlocalseqnumber (context,
473 : context_handle->auth_context,
474 : &seq_number);
475 :
476 49447 : _gss_mg_encode_be_uint32(seq_number, p0 + 8);
477 :
478 49447 : 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 49447 : memset (p0 + 8 + 4,
484 49447 : (context_handle->more_flags & LOCAL) ? 0 : 0xff,
485 : 4);
486 :
487 49447 : krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
488 :
489 : /* p points to data */
490 49447 : p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
491 49447 : memcpy(p, input_message_buffer->value, input_message_buffer->length);
492 :
493 49447 : if (!IS_DCE_STYLE(context_handle))
494 49447 : p[input_message_buffer->length] = 1; /* padding */
495 :
496 49447 : 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 49447 : p0 + 24, 8, /* Confounder */
501 49447 : p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
502 : datalen);
503 49447 : 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 49447 : Klocal.keytype = key->keytype;
513 49447 : Klocal.keyvalue.data = Klocaldata;
514 49447 : Klocal.keyvalue.length = sizeof(Klocaldata);
515 :
516 840599 : for (i = 0; i < 16; i++)
517 791152 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
518 : }
519 49447 : ret = arcfour_mic_key(context, &Klocal,
520 49447 : p0 + 8, 4, /* SND_SEQ */
521 : k6_data, sizeof(k6_data));
522 49447 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
523 49447 : 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 49447 : if(conf_req_flag) {
531 0 : EVP_CIPHER_CTX rc4_key;
532 :
533 49419 : EVP_CIPHER_CTX_init(&rc4_key);
534 49419 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
535 49419 : EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen);
536 49419 : EVP_CIPHER_CTX_cleanup(&rc4_key);
537 : }
538 49447 : memset(k6_data, 0, sizeof(k6_data));
539 :
540 49447 : ret = arcfour_mic_key(context, key,
541 49447 : p0 + 16, 8, /* SGN_CKSUM */
542 : k6_data, sizeof(k6_data));
543 49447 : 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 49447 : EVP_CIPHER_CTX_init(&rc4_key);
553 49447 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
554 49447 : EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
555 49447 : EVP_CIPHER_CTX_cleanup(&rc4_key);
556 49447 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
557 : }
558 :
559 49447 : if (conf_state)
560 49447 : *conf_state = conf_req_flag;
561 :
562 49447 : *minor_status = 0;
563 49447 : return GSS_S_COMPLETE;
564 : }
565 :
566 49447 : 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 49447 : size_t padlen = 0, len;
587 :
588 49447 : if (conf_state)
589 49447 : *conf_state = 0;
590 49447 : if (qop_state)
591 49447 : *qop_state = 0;
592 :
593 49447 : p0 = input_message_buffer->value;
594 :
595 49447 : 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 49447 : len = input_message_buffer->length;
602 : }
603 :
604 49447 : omret = _gssapi_verify_mech_header(&p0,
605 : len,
606 : GSS_KRB5_MECHANISM);
607 49447 : if (omret)
608 0 : return omret;
609 :
610 : /* length of mech header */
611 49447 : len = (p0 - (u_char *)input_message_buffer->value) +
612 : GSS_ARCFOUR_WRAP_TOKEN_SIZE;
613 :
614 49447 : if (len > input_message_buffer->length)
615 0 : return GSS_S_BAD_MECH;
616 :
617 : /* length of data */
618 49447 : datalen = input_message_buffer->length - len;
619 :
620 49447 : p = p0;
621 :
622 49447 : if (memcmp(p, "\x02\x01", 2) != 0)
623 0 : return GSS_S_BAD_SIG;
624 49447 : p += 2;
625 49447 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
626 0 : return GSS_S_BAD_SIG;
627 49447 : p += 2;
628 :
629 49447 : if (memcmp (p, "\x10\x00", 2) == 0)
630 49419 : 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 49447 : p += 2;
637 49447 : if (memcmp (p, "\xff\xff", 2) != 0)
638 0 : return GSS_S_BAD_MIC;
639 49447 : p = NULL;
640 :
641 49447 : ret = arcfour_mic_key(context, key,
642 49447 : p0 + 16, 8, /* SGN_CKSUM */
643 : k6_data, sizeof(k6_data));
644 49447 : 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 49447 : EVP_CIPHER_CTX_init(&rc4_key);
653 49447 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
654 49447 : EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8);
655 49447 : EVP_CIPHER_CTX_cleanup(&rc4_key);
656 49447 : memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
657 : }
658 :
659 49447 : _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
660 :
661 49447 : if (context_handle->more_flags & LOCAL)
662 24726 : cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
663 : else
664 24721 : cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
665 :
666 49447 : if (cmp != 0) {
667 0 : *minor_status = 0;
668 0 : return GSS_S_BAD_MIC;
669 : }
670 :
671 : {
672 0 : int i;
673 :
674 49447 : Klocal.keytype = key->keytype;
675 49447 : Klocal.keyvalue.data = Klocaldata;
676 49447 : Klocal.keyvalue.length = sizeof(Klocaldata);
677 :
678 840599 : for (i = 0; i < 16; i++)
679 791152 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
680 : }
681 49447 : ret = arcfour_mic_key(context, &Klocal,
682 : SND_SEQ, 4,
683 : k6_data, sizeof(k6_data));
684 49447 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
685 49447 : if (ret) {
686 0 : *minor_status = ret;
687 0 : return GSS_S_FAILURE;
688 : }
689 :
690 49447 : output_message_buffer->value = malloc(datalen);
691 49447 : if (output_message_buffer->value == NULL) {
692 0 : *minor_status = ENOMEM;
693 0 : return GSS_S_FAILURE;
694 : }
695 49447 : output_message_buffer->length = datalen;
696 :
697 49447 : if(conf_flag) {
698 0 : EVP_CIPHER_CTX rc4_key;
699 :
700 49419 : EVP_CIPHER_CTX_init(&rc4_key);
701 49419 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
702 49419 : EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
703 49419 : EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
704 49419 : 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 49447 : memset(k6_data, 0, sizeof(k6_data));
712 :
713 49447 : if (!IS_DCE_STYLE(context_handle)) {
714 49447 : ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
715 49447 : if (ret) {
716 0 : _gsskrb5_release_buffer(minor_status, output_message_buffer);
717 0 : *minor_status = 0;
718 0 : return ret;
719 : }
720 49447 : output_message_buffer->length -= padlen;
721 : }
722 :
723 49447 : 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 49447 : output_message_buffer->value,
729 49447 : output_message_buffer->length + padlen);
730 49447 : 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 49447 : cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
737 49447 : 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 49447 : omret = _gssapi_msg_order_check(context_handle->order, seq_number);
745 0 : HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
746 49447 : if (omret)
747 0 : return omret;
748 :
749 49447 : if (conf_state)
750 49447 : *conf_state = conf_flag;
751 :
752 49447 : *minor_status = 0;
753 49447 : 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 17546 : _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 17546 : size_t make_len = 0;
940 17546 : size_t header_len = 0;
941 17546 : size_t data_len = 0;
942 0 : krb5_keyblock Klocal;
943 0 : int i;
944 :
945 17546 : header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
946 17546 : padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
947 17546 : trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
948 :
949 17546 : major_status = _gk_verify_buffers(minor_status, ctx, header,
950 : padding, trailer, FALSE);
951 17546 : if (major_status != GSS_S_COMPLETE) {
952 0 : return major_status;
953 : }
954 :
955 87730 : for (i = 0; i < iov_count; i++) {
956 70184 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
957 17546 : case GSS_IOV_BUFFER_TYPE_DATA:
958 17546 : break;
959 52638 : default:
960 52638 : continue;
961 : }
962 :
963 17546 : data_len += iov[i].buffer.length;
964 : }
965 :
966 17546 : if (padding) {
967 0 : data_len += 1;
968 : }
969 :
970 17546 : if (IS_DCE_STYLE(ctx)) {
971 0 : size_t unwrapped_len;
972 17546 : unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
973 17546 : _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 17546 : 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 17546 : } 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 17546 : header->buffer.length = header_len;
998 : }
999 :
1000 17546 : 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 17546 : if (trailer) {
1016 0 : trailer->buffer.length = 0;
1017 0 : trailer->buffer.value = NULL;
1018 : }
1019 :
1020 17546 : p0 = _gssapi_make_mech_header(header->buffer.value,
1021 : make_len,
1022 : GSS_KRB5_MECHANISM);
1023 17546 : p = p0;
1024 :
1025 17546 : *p++ = 0x02; /* TOK_ID */
1026 17546 : *p++ = 0x01;
1027 17546 : *p++ = 0x11; /* SGN_ALG */
1028 17546 : *p++ = 0x00;
1029 17546 : if (conf_req_flag) {
1030 17546 : *p++ = 0x10; /* SEAL_ALG */
1031 17546 : *p++ = 0x00;
1032 : } else {
1033 0 : *p++ = 0xff; /* SEAL_ALG */
1034 0 : *p++ = 0xff;
1035 : }
1036 17546 : *p++ = 0xff; /* Filler */
1037 17546 : *p++ = 0xff;
1038 :
1039 17546 : p = NULL;
1040 :
1041 0 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
1042 17546 : krb5_auth_con_getlocalseqnumber(context,
1043 : ctx->auth_context,
1044 : &seq_number);
1045 17546 : _gss_mg_encode_be_uint32(seq_number, p0 + 8);
1046 :
1047 17546 : krb5_auth_con_setlocalseqnumber(context,
1048 : ctx->auth_context,
1049 : ++seq_number);
1050 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
1051 :
1052 17546 : memset(p0 + 8 + 4,
1053 17546 : (ctx->more_flags & LOCAL) ? 0 : 0xff,
1054 : 4);
1055 :
1056 17546 : krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
1057 :
1058 : /* Sign Data */
1059 17546 : 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 17546 : p0 + 24, 8, /* Confounder */
1064 : iov, iov_count, /* Data + SignOnly */
1065 : padding); /* padding */
1066 17546 : if (kret) {
1067 0 : *minor_status = kret;
1068 0 : major_status = GSS_S_FAILURE;
1069 0 : goto failure;
1070 : }
1071 :
1072 17546 : Klocal.keytype = key->keytype;
1073 17546 : Klocal.keyvalue.data = Klocaldata;
1074 17546 : Klocal.keyvalue.length = sizeof(Klocaldata);
1075 :
1076 298282 : for (i = 0; i < 16; i++) {
1077 280736 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
1078 : }
1079 17546 : kret = arcfour_mic_key(context, &Klocal,
1080 17546 : p0 + 8, 4, /* SND_SEQ */
1081 : k6_data, sizeof(k6_data));
1082 17546 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
1083 17546 : if (kret) {
1084 0 : *minor_status = kret;
1085 0 : major_status = GSS_S_FAILURE;
1086 0 : goto failure;
1087 : }
1088 :
1089 17546 : if (conf_req_flag) {
1090 0 : EVP_CIPHER_CTX rc4_key;
1091 :
1092 17546 : EVP_CIPHER_CTX_init(&rc4_key);
1093 17546 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1094 :
1095 : /* Confounder */
1096 17546 : EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8);
1097 :
1098 : /* Seal Data */
1099 87730 : for (i=0; i < iov_count; i++) {
1100 70184 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
1101 17546 : case GSS_IOV_BUFFER_TYPE_DATA:
1102 17546 : break;
1103 52638 : default:
1104 52638 : continue;
1105 : }
1106 :
1107 17546 : EVP_Cipher(&rc4_key, iov[i].buffer.value,
1108 17546 : iov[i].buffer.value, iov[i].buffer.length);
1109 : }
1110 :
1111 : /* Padding */
1112 17546 : if (padding) {
1113 0 : EVP_Cipher(&rc4_key, padding->buffer.value,
1114 0 : padding->buffer.value, padding->buffer.length);
1115 : }
1116 :
1117 17546 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1118 : }
1119 17546 : memset(k6_data, 0, sizeof(k6_data));
1120 :
1121 17546 : kret = arcfour_mic_key(context, key,
1122 17546 : p0 + 16, 8, /* SGN_CKSUM */
1123 : k6_data, sizeof(k6_data));
1124 17546 : 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 17546 : EVP_CIPHER_CTX_init(&rc4_key);
1134 17546 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1135 17546 : EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */
1136 17546 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1137 :
1138 17546 : memset(k6_data, 0, sizeof(k6_data));
1139 : }
1140 :
1141 17546 : if (conf_state)
1142 17546 : *conf_state = conf_req_flag;
1143 :
1144 17546 : *minor_status = 0;
1145 17546 : 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 12050 : _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 12050 : uint8_t *_p = NULL;
1171 0 : const uint8_t *p, *p0;
1172 12050 : size_t verify_len = 0;
1173 0 : uint32_t seq_number;
1174 12050 : 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 12050 : if (pconf_state != NULL) {
1182 12050 : *pconf_state = 0;
1183 : }
1184 12050 : if (pqop_state != NULL) {
1185 12050 : *pqop_state = 0;
1186 : }
1187 :
1188 12050 : header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
1189 12050 : padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
1190 12050 : trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
1191 :
1192 : /* Check if the packet is correct */
1193 12050 : major_status = _gk_verify_buffers(minor_status,
1194 : ctx,
1195 : header,
1196 : padding,
1197 : trailer,
1198 : FALSE); /* behaves as stream cipher */
1199 12050 : if (major_status != GSS_S_COMPLETE) {
1200 0 : return major_status;
1201 : }
1202 :
1203 12050 : if (padding != NULL && padding->buffer.length != 1) {
1204 0 : *minor_status = EINVAL;
1205 0 : return GSS_S_FAILURE;
1206 : }
1207 :
1208 12050 : verify_len = header->buffer.length;
1209 :
1210 12050 : 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 12050 : _p = header->buffer.value;
1222 :
1223 12050 : ret = _gssapi_verify_mech_header(&_p,
1224 : verify_len,
1225 : GSS_KRB5_MECHANISM);
1226 12050 : if (ret) {
1227 0 : return ret;
1228 : }
1229 12050 : p0 = _p;
1230 :
1231 : /* length of mech header */
1232 12050 : hlen = (p0 - (uint8_t *)header->buffer.value);
1233 12050 : hlen += GSS_ARCFOUR_WRAP_TOKEN_SIZE;
1234 :
1235 12050 : if (hlen > header->buffer.length) {
1236 0 : return GSS_S_BAD_MECH;
1237 : }
1238 :
1239 12050 : p = p0;
1240 :
1241 12050 : if (memcmp(p, "\x02\x01", 2) != 0)
1242 0 : return GSS_S_BAD_SIG;
1243 12050 : p += 2;
1244 12050 : if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
1245 0 : return GSS_S_BAD_SIG;
1246 12050 : p += 2;
1247 :
1248 12050 : if (memcmp (p, "\x10\x00", 2) == 0)
1249 12050 : 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 12050 : p += 2;
1256 12050 : if (memcmp (p, "\xff\xff", 2) != 0)
1257 0 : return GSS_S_BAD_MIC;
1258 12050 : p = NULL;
1259 :
1260 12050 : kret = arcfour_mic_key(context,
1261 : key,
1262 12050 : p0 + 16, /* SGN_CKSUM */
1263 : 8, /* SGN_CKSUM_LEN */
1264 : k6_data,
1265 : sizeof(k6_data));
1266 12050 : 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 12050 : EVP_CIPHER_CTX_init(&rc4_key);
1275 12050 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1276 12050 : EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */
1277 12050 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1278 :
1279 12050 : memset(k6_data, 0, sizeof(k6_data));
1280 : }
1281 :
1282 12050 : _gss_mg_decode_be_uint32(snd_seq, &seq_number);
1283 :
1284 12050 : if (ctx->more_flags & LOCAL) {
1285 4533 : cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0);
1286 : } else {
1287 7517 : cmp = (ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4) != 0);
1288 : }
1289 12050 : if (cmp != 0) {
1290 0 : *minor_status = 0;
1291 0 : return GSS_S_BAD_MIC;
1292 : }
1293 :
1294 : /* keyblock */
1295 12050 : Klocal.keytype = key->keytype;
1296 12050 : Klocal.keyvalue.data = Klocaldata;
1297 12050 : Klocal.keyvalue.length = sizeof(Klocaldata);
1298 :
1299 204850 : for (i = 0; i < 16; i++) {
1300 192800 : Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
1301 : }
1302 :
1303 12050 : kret = arcfour_mic_key(context,
1304 : &Klocal,
1305 : snd_seq,
1306 : 4,
1307 : k6_data, sizeof(k6_data));
1308 12050 : memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
1309 12050 : if (kret) {
1310 0 : *minor_status = kret;
1311 0 : return GSS_S_FAILURE;
1312 : }
1313 :
1314 12050 : if (conf_state == 1) {
1315 0 : EVP_CIPHER_CTX rc4_key;
1316 :
1317 12050 : EVP_CIPHER_CTX_init(&rc4_key);
1318 12050 : EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
1319 :
1320 : /* Confounder */
1321 12050 : EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
1322 :
1323 : /* Data */
1324 60250 : for (i = 0; i < iov_count; i++) {
1325 48200 : switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
1326 12050 : case GSS_IOV_BUFFER_TYPE_DATA:
1327 12050 : break;
1328 36150 : default:
1329 36150 : continue;
1330 : }
1331 :
1332 12050 : EVP_Cipher(&rc4_key, iov[i].buffer.value,
1333 12050 : iov[i].buffer.value, iov[i].buffer.length);
1334 : }
1335 :
1336 : /* Padding */
1337 12050 : if (padding) {
1338 0 : EVP_Cipher(&rc4_key, padding->buffer.value,
1339 0 : padding->buffer.value, padding->buffer.length);
1340 : }
1341 :
1342 12050 : EVP_CIPHER_CTX_cleanup(&rc4_key);
1343 : } else {
1344 : /* Confounder */
1345 0 : memcpy(Confounder, p0 + 24, 8);
1346 : }
1347 12050 : memset(k6_data, 0, sizeof(k6_data));
1348 :
1349 : /* Prepare the buffer for signing */
1350 12050 : 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 12050 : if (kret) {
1358 0 : *minor_status = kret;
1359 0 : return GSS_S_FAILURE;
1360 : }
1361 :
1362 12050 : cmp = (ct_memcmp(cksum_data, p0 + 16, 8) != 0); /* SGN_CKSUM */
1363 12050 : if (cmp) {
1364 0 : *minor_status = 0;
1365 0 : return GSS_S_BAD_MIC;
1366 : }
1367 :
1368 12050 : 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 12050 : ret = _gssapi_msg_order_check(ctx->order, seq_number);
1380 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
1381 12050 : if (ret != 0) {
1382 0 : return ret;
1383 : }
1384 :
1385 12050 : if (pconf_state) {
1386 12050 : *pconf_state = conf_state;
1387 : }
1388 :
1389 12050 : *minor_status = 0;
1390 12050 : return GSS_S_COMPLETE;
1391 : }
|