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