xref: /minix3/crypto/external/bsd/heimdal/dist/lib/gssapi/krb5/arcfour.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: arcfour.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc  *
19ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc  *    without specific prior written permission.
22ebfedea0SLionel Sambuc  *
23ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34ebfedea0SLionel Sambuc  */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc #include "gsskrb5_locl.h"
37ebfedea0SLionel Sambuc 
38ebfedea0SLionel Sambuc /*
39ebfedea0SLionel Sambuc  * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
40ebfedea0SLionel Sambuc  *
41ebfedea0SLionel Sambuc  * The arcfour message have the following formats:
42ebfedea0SLionel Sambuc  *
43ebfedea0SLionel Sambuc  * MIC token
44ebfedea0SLionel Sambuc  * 	TOK_ID[2] = 01 01
45ebfedea0SLionel Sambuc  *	SGN_ALG[2] = 11 00
46ebfedea0SLionel Sambuc  *	Filler[4]
47ebfedea0SLionel Sambuc  *	SND_SEQ[8]
48ebfedea0SLionel Sambuc  *	SGN_CKSUM[8]
49ebfedea0SLionel Sambuc  *
50ebfedea0SLionel Sambuc  * WRAP token
51ebfedea0SLionel Sambuc  *	TOK_ID[2] = 02 01
52ebfedea0SLionel Sambuc  *	SGN_ALG[2];
53ebfedea0SLionel Sambuc  *	SEAL_ALG[2]
54ebfedea0SLionel Sambuc  *	Filler[2]
55ebfedea0SLionel Sambuc  *	SND_SEQ[2]
56ebfedea0SLionel Sambuc  *	SGN_CKSUM[8]
57ebfedea0SLionel Sambuc  *	Confounder[8]
58ebfedea0SLionel Sambuc  */
59ebfedea0SLionel Sambuc 
60ebfedea0SLionel Sambuc /*
61ebfedea0SLionel Sambuc  * WRAP in DCE-style have a fixed size header, the oid and length over
62ebfedea0SLionel Sambuc  * the WRAP header is a total of
63ebfedea0SLionel Sambuc  * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE +
64ebfedea0SLionel Sambuc  * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead,
65ebfedea0SLionel Sambuc  * remember the 2 bytes from APPL [0] SEQ).
66ebfedea0SLionel Sambuc  */
67ebfedea0SLionel Sambuc 
68ebfedea0SLionel Sambuc #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
69ebfedea0SLionel Sambuc #define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13
70ebfedea0SLionel Sambuc 
71ebfedea0SLionel Sambuc 
72ebfedea0SLionel Sambuc static krb5_error_code
arcfour_mic_key(krb5_context context,krb5_keyblock * key,void * cksum_data,size_t cksum_size,void * key6_data,size_t key6_size)73ebfedea0SLionel Sambuc arcfour_mic_key(krb5_context context, krb5_keyblock *key,
74ebfedea0SLionel Sambuc 		void *cksum_data, size_t cksum_size,
75ebfedea0SLionel Sambuc 		void *key6_data, size_t key6_size)
76ebfedea0SLionel Sambuc {
77ebfedea0SLionel Sambuc     krb5_error_code ret;
78ebfedea0SLionel Sambuc 
79ebfedea0SLionel Sambuc     Checksum cksum_k5;
80ebfedea0SLionel Sambuc     krb5_keyblock key5;
81ebfedea0SLionel Sambuc     char k5_data[16];
82ebfedea0SLionel Sambuc 
83ebfedea0SLionel Sambuc     Checksum cksum_k6;
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc     char T[4];
86ebfedea0SLionel Sambuc 
87ebfedea0SLionel Sambuc     memset(T, 0, 4);
88ebfedea0SLionel Sambuc     cksum_k5.checksum.data = k5_data;
89ebfedea0SLionel Sambuc     cksum_k5.checksum.length = sizeof(k5_data);
90ebfedea0SLionel Sambuc 
91*0a6a1f1dSLionel Sambuc     if (key->keytype == ENCTYPE_ARCFOUR_HMAC_MD5_56) {
92ebfedea0SLionel Sambuc 	char L40[14] = "fortybits";
93ebfedea0SLionel Sambuc 
94ebfedea0SLionel Sambuc 	memcpy(L40 + 10, T, sizeof(T));
95ebfedea0SLionel Sambuc 	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
96ebfedea0SLionel Sambuc 			L40, 14, 0, key, &cksum_k5);
97ebfedea0SLionel Sambuc 	memset(&k5_data[7], 0xAB, 9);
98ebfedea0SLionel Sambuc     } else {
99ebfedea0SLionel Sambuc 	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
100ebfedea0SLionel Sambuc 			T, 4, 0, key, &cksum_k5);
101ebfedea0SLionel Sambuc     }
102ebfedea0SLionel Sambuc     if (ret)
103ebfedea0SLionel Sambuc 	return ret;
104ebfedea0SLionel Sambuc 
105*0a6a1f1dSLionel Sambuc     key5.keytype = ENCTYPE_ARCFOUR_HMAC_MD5;
106ebfedea0SLionel Sambuc     key5.keyvalue = cksum_k5.checksum;
107ebfedea0SLionel Sambuc 
108ebfedea0SLionel Sambuc     cksum_k6.checksum.data = key6_data;
109ebfedea0SLionel Sambuc     cksum_k6.checksum.length = key6_size;
110ebfedea0SLionel Sambuc 
111ebfedea0SLionel Sambuc     return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
112ebfedea0SLionel Sambuc 		     cksum_data, cksum_size, 0, &key5, &cksum_k6);
113ebfedea0SLionel Sambuc }
114ebfedea0SLionel Sambuc 
115ebfedea0SLionel Sambuc 
116ebfedea0SLionel Sambuc 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)117ebfedea0SLionel Sambuc arcfour_mic_cksum(krb5_context context,
118ebfedea0SLionel Sambuc 		  krb5_keyblock *key, unsigned usage,
119ebfedea0SLionel Sambuc 		  u_char *sgn_cksum, size_t sgn_cksum_sz,
120ebfedea0SLionel Sambuc 		  const u_char *v1, size_t l1,
121ebfedea0SLionel Sambuc 		  const void *v2, size_t l2,
122ebfedea0SLionel Sambuc 		  const void *v3, size_t l3)
123ebfedea0SLionel Sambuc {
124ebfedea0SLionel Sambuc     Checksum CKSUM;
125ebfedea0SLionel Sambuc     u_char *ptr;
126ebfedea0SLionel Sambuc     size_t len;
127ebfedea0SLionel Sambuc     krb5_crypto crypto;
128ebfedea0SLionel Sambuc     krb5_error_code ret;
129ebfedea0SLionel Sambuc 
130ebfedea0SLionel Sambuc     assert(sgn_cksum_sz == 8);
131ebfedea0SLionel Sambuc 
132ebfedea0SLionel Sambuc     len = l1 + l2 + l3;
133ebfedea0SLionel Sambuc 
134ebfedea0SLionel Sambuc     ptr = malloc(len);
135ebfedea0SLionel Sambuc     if (ptr == NULL)
136ebfedea0SLionel Sambuc 	return ENOMEM;
137ebfedea0SLionel Sambuc 
138ebfedea0SLionel Sambuc     memcpy(ptr, v1, l1);
139ebfedea0SLionel Sambuc     memcpy(ptr + l1, v2, l2);
140ebfedea0SLionel Sambuc     memcpy(ptr + l1 + l2, v3, l3);
141ebfedea0SLionel Sambuc 
142ebfedea0SLionel Sambuc     ret = krb5_crypto_init(context, key, 0, &crypto);
143ebfedea0SLionel Sambuc     if (ret) {
144ebfedea0SLionel Sambuc 	free(ptr);
145ebfedea0SLionel Sambuc 	return ret;
146ebfedea0SLionel Sambuc     }
147ebfedea0SLionel Sambuc 
148ebfedea0SLionel Sambuc     ret = krb5_create_checksum(context,
149ebfedea0SLionel Sambuc 			       crypto,
150ebfedea0SLionel Sambuc 			       usage,
151ebfedea0SLionel Sambuc 			       0,
152ebfedea0SLionel Sambuc 			       ptr, len,
153ebfedea0SLionel Sambuc 			       &CKSUM);
154ebfedea0SLionel Sambuc     free(ptr);
155ebfedea0SLionel Sambuc     if (ret == 0) {
156ebfedea0SLionel Sambuc 	memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
157ebfedea0SLionel Sambuc 	free_Checksum(&CKSUM);
158ebfedea0SLionel Sambuc     }
159ebfedea0SLionel Sambuc     krb5_crypto_destroy(context, crypto);
160ebfedea0SLionel Sambuc 
161ebfedea0SLionel Sambuc     return ret;
162ebfedea0SLionel Sambuc }
163ebfedea0SLionel Sambuc 
164ebfedea0SLionel Sambuc 
165ebfedea0SLionel Sambuc 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)166ebfedea0SLionel Sambuc _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
167ebfedea0SLionel Sambuc 			const gsskrb5_ctx context_handle,
168ebfedea0SLionel Sambuc 			krb5_context context,
169ebfedea0SLionel Sambuc 			gss_qop_t qop_req,
170ebfedea0SLionel Sambuc 			const gss_buffer_t message_buffer,
171ebfedea0SLionel Sambuc 			gss_buffer_t message_token,
172ebfedea0SLionel Sambuc 			krb5_keyblock *key)
173ebfedea0SLionel Sambuc {
174ebfedea0SLionel Sambuc     krb5_error_code ret;
175ebfedea0SLionel Sambuc     int32_t seq_number;
176ebfedea0SLionel Sambuc     size_t len, total_len;
177ebfedea0SLionel Sambuc     u_char k6_data[16], *p0, *p;
178ebfedea0SLionel Sambuc     EVP_CIPHER_CTX rc4_key;
179ebfedea0SLionel Sambuc 
180ebfedea0SLionel Sambuc     _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
181ebfedea0SLionel Sambuc 
182ebfedea0SLionel Sambuc     message_token->length = total_len;
183ebfedea0SLionel Sambuc     message_token->value  = malloc (total_len);
184ebfedea0SLionel Sambuc     if (message_token->value == NULL) {
185ebfedea0SLionel Sambuc 	*minor_status = ENOMEM;
186ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
187ebfedea0SLionel Sambuc     }
188ebfedea0SLionel Sambuc 
189ebfedea0SLionel Sambuc     p0 = _gssapi_make_mech_header(message_token->value,
190ebfedea0SLionel Sambuc 				  len,
191ebfedea0SLionel Sambuc 				  GSS_KRB5_MECHANISM);
192ebfedea0SLionel Sambuc     p = p0;
193ebfedea0SLionel Sambuc 
194ebfedea0SLionel Sambuc     *p++ = 0x01; /* TOK_ID */
195ebfedea0SLionel Sambuc     *p++ = 0x01;
196ebfedea0SLionel Sambuc     *p++ = 0x11; /* SGN_ALG */
197ebfedea0SLionel Sambuc     *p++ = 0x00;
198ebfedea0SLionel Sambuc     *p++ = 0xff; /* Filler */
199ebfedea0SLionel Sambuc     *p++ = 0xff;
200ebfedea0SLionel Sambuc     *p++ = 0xff;
201ebfedea0SLionel Sambuc     *p++ = 0xff;
202ebfedea0SLionel Sambuc 
203ebfedea0SLionel Sambuc     p = NULL;
204ebfedea0SLionel Sambuc 
205ebfedea0SLionel Sambuc     ret = arcfour_mic_cksum(context,
206ebfedea0SLionel Sambuc 			    key, KRB5_KU_USAGE_SIGN,
207ebfedea0SLionel Sambuc 			    p0 + 16, 8,  /* SGN_CKSUM */
208ebfedea0SLionel Sambuc 			    p0, 8, /* TOK_ID, SGN_ALG, Filer */
209ebfedea0SLionel Sambuc 			    message_buffer->value, message_buffer->length,
210ebfedea0SLionel Sambuc 			    NULL, 0);
211ebfedea0SLionel Sambuc     if (ret) {
212ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, message_token);
213ebfedea0SLionel Sambuc 	*minor_status = ret;
214ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
215ebfedea0SLionel Sambuc     }
216ebfedea0SLionel Sambuc 
217ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, key,
218ebfedea0SLionel Sambuc 			  p0 + 16, 8, /* SGN_CKSUM */
219ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
220ebfedea0SLionel Sambuc     if (ret) {
221ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, message_token);
222ebfedea0SLionel Sambuc 	*minor_status = ret;
223ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
224ebfedea0SLionel Sambuc     }
225ebfedea0SLionel Sambuc 
226ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
227ebfedea0SLionel Sambuc     krb5_auth_con_getlocalseqnumber (context,
228ebfedea0SLionel Sambuc 				     context_handle->auth_context,
229ebfedea0SLionel Sambuc 				     &seq_number);
230ebfedea0SLionel Sambuc     p = p0 + 8; /* SND_SEQ */
231ebfedea0SLionel Sambuc     _gsskrb5_encode_be_om_uint32(seq_number, p);
232ebfedea0SLionel Sambuc 
233ebfedea0SLionel Sambuc     krb5_auth_con_setlocalseqnumber (context,
234ebfedea0SLionel Sambuc 				     context_handle->auth_context,
235ebfedea0SLionel Sambuc 				     ++seq_number);
236ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
237ebfedea0SLionel Sambuc 
238ebfedea0SLionel Sambuc     memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
239ebfedea0SLionel Sambuc 
240ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_init(&rc4_key);
241ebfedea0SLionel Sambuc     EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
242ebfedea0SLionel Sambuc     EVP_Cipher(&rc4_key, p, p, 8);
243ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_cleanup(&rc4_key);
244ebfedea0SLionel Sambuc 
245ebfedea0SLionel Sambuc     memset(k6_data, 0, sizeof(k6_data));
246ebfedea0SLionel Sambuc 
247ebfedea0SLionel Sambuc     *minor_status = 0;
248ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
249ebfedea0SLionel Sambuc }
250ebfedea0SLionel Sambuc 
251ebfedea0SLionel Sambuc 
252ebfedea0SLionel Sambuc 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)253ebfedea0SLionel Sambuc _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
254ebfedea0SLionel Sambuc 			   const gsskrb5_ctx context_handle,
255ebfedea0SLionel Sambuc 			   krb5_context context,
256ebfedea0SLionel Sambuc 			   const gss_buffer_t message_buffer,
257ebfedea0SLionel Sambuc 			   const gss_buffer_t token_buffer,
258ebfedea0SLionel Sambuc 			   gss_qop_t * qop_state,
259ebfedea0SLionel Sambuc 			   krb5_keyblock *key,
260*0a6a1f1dSLionel Sambuc 			   const char *type)
261ebfedea0SLionel Sambuc {
262ebfedea0SLionel Sambuc     krb5_error_code ret;
263ebfedea0SLionel Sambuc     uint32_t seq_number;
264ebfedea0SLionel Sambuc     OM_uint32 omret;
265ebfedea0SLionel Sambuc     u_char SND_SEQ[8], cksum_data[8], *p;
266ebfedea0SLionel Sambuc     char k6_data[16];
267ebfedea0SLionel Sambuc     int cmp;
268ebfedea0SLionel Sambuc 
269ebfedea0SLionel Sambuc     if (qop_state)
270ebfedea0SLionel Sambuc 	*qop_state = 0;
271ebfedea0SLionel Sambuc 
272ebfedea0SLionel Sambuc     p = token_buffer->value;
273ebfedea0SLionel Sambuc     omret = _gsskrb5_verify_header (&p,
274ebfedea0SLionel Sambuc 				       token_buffer->length,
275*0a6a1f1dSLionel Sambuc 				       type,
276ebfedea0SLionel Sambuc 				       GSS_KRB5_MECHANISM);
277ebfedea0SLionel Sambuc     if (omret)
278ebfedea0SLionel Sambuc 	return omret;
279ebfedea0SLionel Sambuc 
280ebfedea0SLionel Sambuc     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
281ebfedea0SLionel Sambuc 	return GSS_S_BAD_SIG;
282ebfedea0SLionel Sambuc     p += 2;
283ebfedea0SLionel Sambuc     if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
284ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
285ebfedea0SLionel Sambuc     p += 4;
286ebfedea0SLionel Sambuc 
287ebfedea0SLionel Sambuc     ret = arcfour_mic_cksum(context,
288ebfedea0SLionel Sambuc 			    key, KRB5_KU_USAGE_SIGN,
289ebfedea0SLionel Sambuc 			    cksum_data, sizeof(cksum_data),
290ebfedea0SLionel Sambuc 			    p - 8, 8,
291ebfedea0SLionel Sambuc 			    message_buffer->value, message_buffer->length,
292ebfedea0SLionel Sambuc 			    NULL, 0);
293ebfedea0SLionel Sambuc     if (ret) {
294ebfedea0SLionel Sambuc 	*minor_status = ret;
295ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
296ebfedea0SLionel Sambuc     }
297ebfedea0SLionel Sambuc 
298ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, key,
299ebfedea0SLionel Sambuc 			  cksum_data, sizeof(cksum_data),
300ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
301ebfedea0SLionel Sambuc     if (ret) {
302ebfedea0SLionel Sambuc 	*minor_status = ret;
303ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
304ebfedea0SLionel Sambuc     }
305ebfedea0SLionel Sambuc 
306ebfedea0SLionel Sambuc     cmp = ct_memcmp(cksum_data, p + 8, 8);
307ebfedea0SLionel Sambuc     if (cmp) {
308ebfedea0SLionel Sambuc 	*minor_status = 0;
309ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
310ebfedea0SLionel Sambuc     }
311ebfedea0SLionel Sambuc 
312ebfedea0SLionel Sambuc     {
313ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX rc4_key;
314ebfedea0SLionel Sambuc 
315ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_init(&rc4_key);
316ebfedea0SLionel Sambuc 	EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
317ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, SND_SEQ, p, 8);
318ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&rc4_key);
319ebfedea0SLionel Sambuc 
320ebfedea0SLionel Sambuc 	memset(k6_data, 0, sizeof(k6_data));
321ebfedea0SLionel Sambuc     }
322ebfedea0SLionel Sambuc 
323ebfedea0SLionel Sambuc     _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
324ebfedea0SLionel Sambuc 
325ebfedea0SLionel Sambuc     if (context_handle->more_flags & LOCAL)
326ebfedea0SLionel Sambuc 	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
327ebfedea0SLionel Sambuc     else
328ebfedea0SLionel Sambuc 	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc     memset(SND_SEQ, 0, sizeof(SND_SEQ));
331ebfedea0SLionel Sambuc     if (cmp != 0) {
332ebfedea0SLionel Sambuc 	*minor_status = 0;
333ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
334ebfedea0SLionel Sambuc     }
335ebfedea0SLionel Sambuc 
336ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
337ebfedea0SLionel Sambuc     omret = _gssapi_msg_order_check(context_handle->order, seq_number);
338ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
339ebfedea0SLionel Sambuc     if (omret)
340ebfedea0SLionel Sambuc 	return omret;
341ebfedea0SLionel Sambuc 
342ebfedea0SLionel Sambuc     *minor_status = 0;
343ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
344ebfedea0SLionel Sambuc }
345ebfedea0SLionel Sambuc 
346ebfedea0SLionel Sambuc 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)347ebfedea0SLionel Sambuc _gssapi_wrap_arcfour(OM_uint32 * minor_status,
348ebfedea0SLionel Sambuc 		     const gsskrb5_ctx context_handle,
349ebfedea0SLionel Sambuc 		     krb5_context context,
350ebfedea0SLionel Sambuc 		     int conf_req_flag,
351ebfedea0SLionel Sambuc 		     gss_qop_t qop_req,
352ebfedea0SLionel Sambuc 		     const gss_buffer_t input_message_buffer,
353ebfedea0SLionel Sambuc 		     int * conf_state,
354ebfedea0SLionel Sambuc 		     gss_buffer_t output_message_buffer,
355ebfedea0SLionel Sambuc 		     krb5_keyblock *key)
356ebfedea0SLionel Sambuc {
357ebfedea0SLionel Sambuc     u_char Klocaldata[16], k6_data[16], *p, *p0;
358ebfedea0SLionel Sambuc     size_t len, total_len, datalen;
359ebfedea0SLionel Sambuc     krb5_keyblock Klocal;
360ebfedea0SLionel Sambuc     krb5_error_code ret;
361ebfedea0SLionel Sambuc     int32_t seq_number;
362ebfedea0SLionel Sambuc 
363ebfedea0SLionel Sambuc     if (conf_state)
364ebfedea0SLionel Sambuc 	*conf_state = 0;
365ebfedea0SLionel Sambuc 
366ebfedea0SLionel Sambuc     datalen = input_message_buffer->length;
367ebfedea0SLionel Sambuc 
368ebfedea0SLionel Sambuc     if (IS_DCE_STYLE(context_handle)) {
369ebfedea0SLionel Sambuc 	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
370ebfedea0SLionel Sambuc 	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
371ebfedea0SLionel Sambuc 	total_len += datalen;
372ebfedea0SLionel Sambuc     } else {
373ebfedea0SLionel Sambuc 	datalen += 1; /* padding */
374ebfedea0SLionel Sambuc 	len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
375ebfedea0SLionel Sambuc 	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
376ebfedea0SLionel Sambuc     }
377ebfedea0SLionel Sambuc 
378ebfedea0SLionel Sambuc     output_message_buffer->length = total_len;
379ebfedea0SLionel Sambuc     output_message_buffer->value  = malloc (total_len);
380ebfedea0SLionel Sambuc     if (output_message_buffer->value == NULL) {
381ebfedea0SLionel Sambuc 	*minor_status = ENOMEM;
382ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
383ebfedea0SLionel Sambuc     }
384ebfedea0SLionel Sambuc 
385ebfedea0SLionel Sambuc     p0 = _gssapi_make_mech_header(output_message_buffer->value,
386ebfedea0SLionel Sambuc 				  len,
387ebfedea0SLionel Sambuc 				  GSS_KRB5_MECHANISM);
388ebfedea0SLionel Sambuc     p = p0;
389ebfedea0SLionel Sambuc 
390ebfedea0SLionel Sambuc     *p++ = 0x02; /* TOK_ID */
391ebfedea0SLionel Sambuc     *p++ = 0x01;
392ebfedea0SLionel Sambuc     *p++ = 0x11; /* SGN_ALG */
393ebfedea0SLionel Sambuc     *p++ = 0x00;
394ebfedea0SLionel Sambuc     if (conf_req_flag) {
395ebfedea0SLionel Sambuc 	*p++ = 0x10; /* SEAL_ALG */
396ebfedea0SLionel Sambuc 	*p++ = 0x00;
397ebfedea0SLionel Sambuc     } else {
398ebfedea0SLionel Sambuc 	*p++ = 0xff; /* SEAL_ALG */
399ebfedea0SLionel Sambuc 	*p++ = 0xff;
400ebfedea0SLionel Sambuc     }
401ebfedea0SLionel Sambuc     *p++ = 0xff; /* Filler */
402ebfedea0SLionel Sambuc     *p++ = 0xff;
403ebfedea0SLionel Sambuc 
404ebfedea0SLionel Sambuc     p = NULL;
405ebfedea0SLionel Sambuc 
406ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
407ebfedea0SLionel Sambuc     krb5_auth_con_getlocalseqnumber (context,
408ebfedea0SLionel Sambuc 				     context_handle->auth_context,
409ebfedea0SLionel Sambuc 				     &seq_number);
410ebfedea0SLionel Sambuc 
411ebfedea0SLionel Sambuc     _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
412ebfedea0SLionel Sambuc 
413ebfedea0SLionel Sambuc     krb5_auth_con_setlocalseqnumber (context,
414ebfedea0SLionel Sambuc 				     context_handle->auth_context,
415ebfedea0SLionel Sambuc 				     ++seq_number);
416ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
417ebfedea0SLionel Sambuc 
418ebfedea0SLionel Sambuc     memset (p0 + 8 + 4,
419ebfedea0SLionel Sambuc 	    (context_handle->more_flags & LOCAL) ? 0 : 0xff,
420ebfedea0SLionel Sambuc 	    4);
421ebfedea0SLionel Sambuc 
422ebfedea0SLionel Sambuc     krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
423ebfedea0SLionel Sambuc 
424ebfedea0SLionel Sambuc     /* p points to data */
425ebfedea0SLionel Sambuc     p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
426ebfedea0SLionel Sambuc     memcpy(p, input_message_buffer->value, input_message_buffer->length);
427ebfedea0SLionel Sambuc 
428ebfedea0SLionel Sambuc     if (!IS_DCE_STYLE(context_handle))
429ebfedea0SLionel Sambuc 	p[input_message_buffer->length] = 1; /* padding */
430ebfedea0SLionel Sambuc 
431ebfedea0SLionel Sambuc     ret = arcfour_mic_cksum(context,
432ebfedea0SLionel Sambuc 			    key, KRB5_KU_USAGE_SEAL,
433ebfedea0SLionel Sambuc 			    p0 + 16, 8, /* SGN_CKSUM */
434ebfedea0SLionel Sambuc 			    p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
435ebfedea0SLionel Sambuc 			    p0 + 24, 8, /* Confounder */
436ebfedea0SLionel Sambuc 			    p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
437ebfedea0SLionel Sambuc 			    datalen);
438ebfedea0SLionel Sambuc     if (ret) {
439ebfedea0SLionel Sambuc 	*minor_status = ret;
440ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, output_message_buffer);
441ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
442ebfedea0SLionel Sambuc     }
443ebfedea0SLionel Sambuc 
444ebfedea0SLionel Sambuc     {
445ebfedea0SLionel Sambuc 	int i;
446ebfedea0SLionel Sambuc 
447ebfedea0SLionel Sambuc 	Klocal.keytype = key->keytype;
448ebfedea0SLionel Sambuc 	Klocal.keyvalue.data = Klocaldata;
449ebfedea0SLionel Sambuc 	Klocal.keyvalue.length = sizeof(Klocaldata);
450ebfedea0SLionel Sambuc 
451ebfedea0SLionel Sambuc 	for (i = 0; i < 16; i++)
452ebfedea0SLionel Sambuc 	    Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
453ebfedea0SLionel Sambuc     }
454ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, &Klocal,
455ebfedea0SLionel Sambuc 			  p0 + 8, 4, /* SND_SEQ */
456ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
457ebfedea0SLionel Sambuc     memset(Klocaldata, 0, sizeof(Klocaldata));
458ebfedea0SLionel Sambuc     if (ret) {
459ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, output_message_buffer);
460ebfedea0SLionel Sambuc 	*minor_status = ret;
461ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
462ebfedea0SLionel Sambuc     }
463ebfedea0SLionel Sambuc 
464ebfedea0SLionel Sambuc 
465ebfedea0SLionel Sambuc     if(conf_req_flag) {
466ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX rc4_key;
467ebfedea0SLionel Sambuc 
468ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_init(&rc4_key);
469ebfedea0SLionel Sambuc 	EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
470ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen);
471ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&rc4_key);
472ebfedea0SLionel Sambuc     }
473ebfedea0SLionel Sambuc     memset(k6_data, 0, sizeof(k6_data));
474ebfedea0SLionel Sambuc 
475ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, key,
476ebfedea0SLionel Sambuc 			  p0 + 16, 8, /* SGN_CKSUM */
477ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
478ebfedea0SLionel Sambuc     if (ret) {
479ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, output_message_buffer);
480ebfedea0SLionel Sambuc 	*minor_status = ret;
481ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
482ebfedea0SLionel Sambuc     }
483ebfedea0SLionel Sambuc 
484ebfedea0SLionel Sambuc     {
485ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX rc4_key;
486ebfedea0SLionel Sambuc 
487ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_init(&rc4_key);
488ebfedea0SLionel Sambuc 	EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
489ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
490ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&rc4_key);
491ebfedea0SLionel Sambuc 	memset(k6_data, 0, sizeof(k6_data));
492ebfedea0SLionel Sambuc     }
493ebfedea0SLionel Sambuc 
494ebfedea0SLionel Sambuc     if (conf_state)
495ebfedea0SLionel Sambuc 	*conf_state = conf_req_flag;
496ebfedea0SLionel Sambuc 
497ebfedea0SLionel Sambuc     *minor_status = 0;
498ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
499ebfedea0SLionel Sambuc }
500ebfedea0SLionel Sambuc 
_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)501ebfedea0SLionel Sambuc OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
502ebfedea0SLionel Sambuc 				 const gsskrb5_ctx context_handle,
503ebfedea0SLionel Sambuc 				 krb5_context context,
504ebfedea0SLionel Sambuc 				 const gss_buffer_t input_message_buffer,
505ebfedea0SLionel Sambuc 				 gss_buffer_t output_message_buffer,
506ebfedea0SLionel Sambuc 				 int *conf_state,
507ebfedea0SLionel Sambuc 				 gss_qop_t *qop_state,
508ebfedea0SLionel Sambuc 				 krb5_keyblock *key)
509ebfedea0SLionel Sambuc {
510ebfedea0SLionel Sambuc     u_char Klocaldata[16];
511ebfedea0SLionel Sambuc     krb5_keyblock Klocal;
512ebfedea0SLionel Sambuc     krb5_error_code ret;
513ebfedea0SLionel Sambuc     uint32_t seq_number;
514ebfedea0SLionel Sambuc     size_t datalen;
515ebfedea0SLionel Sambuc     OM_uint32 omret;
516ebfedea0SLionel Sambuc     u_char k6_data[16], SND_SEQ[8], Confounder[8];
517ebfedea0SLionel Sambuc     u_char cksum_data[8];
518ebfedea0SLionel Sambuc     u_char *p, *p0;
519ebfedea0SLionel Sambuc     int cmp;
520ebfedea0SLionel Sambuc     int conf_flag;
521ebfedea0SLionel Sambuc     size_t padlen = 0, len;
522ebfedea0SLionel Sambuc 
523ebfedea0SLionel Sambuc     if (conf_state)
524ebfedea0SLionel Sambuc 	*conf_state = 0;
525ebfedea0SLionel Sambuc     if (qop_state)
526ebfedea0SLionel Sambuc 	*qop_state = 0;
527ebfedea0SLionel Sambuc 
528ebfedea0SLionel Sambuc     p0 = input_message_buffer->value;
529ebfedea0SLionel Sambuc 
530ebfedea0SLionel Sambuc     if (IS_DCE_STYLE(context_handle)) {
531ebfedea0SLionel Sambuc 	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
532ebfedea0SLionel Sambuc 	    GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
533ebfedea0SLionel Sambuc 	if (input_message_buffer->length < len)
534ebfedea0SLionel Sambuc 	    return GSS_S_BAD_MECH;
535ebfedea0SLionel Sambuc     } else {
536ebfedea0SLionel Sambuc 	len = input_message_buffer->length;
537ebfedea0SLionel Sambuc     }
538ebfedea0SLionel Sambuc 
539ebfedea0SLionel Sambuc     omret = _gssapi_verify_mech_header(&p0,
540ebfedea0SLionel Sambuc 				       len,
541ebfedea0SLionel Sambuc 				       GSS_KRB5_MECHANISM);
542ebfedea0SLionel Sambuc     if (omret)
543ebfedea0SLionel Sambuc 	return omret;
544ebfedea0SLionel Sambuc 
545ebfedea0SLionel Sambuc     /* length of mech header */
546ebfedea0SLionel Sambuc     len = (p0 - (u_char *)input_message_buffer->value) +
547ebfedea0SLionel Sambuc 	GSS_ARCFOUR_WRAP_TOKEN_SIZE;
548ebfedea0SLionel Sambuc 
549ebfedea0SLionel Sambuc     if (len > input_message_buffer->length)
550ebfedea0SLionel Sambuc 	return GSS_S_BAD_MECH;
551ebfedea0SLionel Sambuc 
552ebfedea0SLionel Sambuc     /* length of data */
553ebfedea0SLionel Sambuc     datalen = input_message_buffer->length - len;
554ebfedea0SLionel Sambuc 
555ebfedea0SLionel Sambuc     p = p0;
556ebfedea0SLionel Sambuc 
557ebfedea0SLionel Sambuc     if (memcmp(p, "\x02\x01", 2) != 0)
558ebfedea0SLionel Sambuc 	return GSS_S_BAD_SIG;
559ebfedea0SLionel Sambuc     p += 2;
560ebfedea0SLionel Sambuc     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
561ebfedea0SLionel Sambuc 	return GSS_S_BAD_SIG;
562ebfedea0SLionel Sambuc     p += 2;
563ebfedea0SLionel Sambuc 
564ebfedea0SLionel Sambuc     if (memcmp (p, "\x10\x00", 2) == 0)
565ebfedea0SLionel Sambuc 	conf_flag = 1;
566ebfedea0SLionel Sambuc     else if (memcmp (p, "\xff\xff", 2) == 0)
567ebfedea0SLionel Sambuc 	conf_flag = 0;
568ebfedea0SLionel Sambuc     else
569ebfedea0SLionel Sambuc 	return GSS_S_BAD_SIG;
570ebfedea0SLionel Sambuc 
571ebfedea0SLionel Sambuc     p += 2;
572ebfedea0SLionel Sambuc     if (memcmp (p, "\xff\xff", 2) != 0)
573ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
574ebfedea0SLionel Sambuc     p = NULL;
575ebfedea0SLionel Sambuc 
576ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, key,
577ebfedea0SLionel Sambuc 			  p0 + 16, 8, /* SGN_CKSUM */
578ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
579ebfedea0SLionel Sambuc     if (ret) {
580ebfedea0SLionel Sambuc 	*minor_status = ret;
581ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
582ebfedea0SLionel Sambuc     }
583ebfedea0SLionel Sambuc 
584ebfedea0SLionel Sambuc     {
585ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX rc4_key;
586ebfedea0SLionel Sambuc 
587ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_init(&rc4_key);
588ebfedea0SLionel Sambuc 	EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
589ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8);
590ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&rc4_key);
591ebfedea0SLionel Sambuc 	memset(k6_data, 0, sizeof(k6_data));
592ebfedea0SLionel Sambuc     }
593ebfedea0SLionel Sambuc 
594ebfedea0SLionel Sambuc     _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
595ebfedea0SLionel Sambuc 
596ebfedea0SLionel Sambuc     if (context_handle->more_flags & LOCAL)
597ebfedea0SLionel Sambuc 	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
598ebfedea0SLionel Sambuc     else
599ebfedea0SLionel Sambuc 	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
600ebfedea0SLionel Sambuc 
601ebfedea0SLionel Sambuc     if (cmp != 0) {
602ebfedea0SLionel Sambuc 	*minor_status = 0;
603ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
604ebfedea0SLionel Sambuc     }
605ebfedea0SLionel Sambuc 
606ebfedea0SLionel Sambuc     {
607ebfedea0SLionel Sambuc 	int i;
608ebfedea0SLionel Sambuc 
609ebfedea0SLionel Sambuc 	Klocal.keytype = key->keytype;
610ebfedea0SLionel Sambuc 	Klocal.keyvalue.data = Klocaldata;
611ebfedea0SLionel Sambuc 	Klocal.keyvalue.length = sizeof(Klocaldata);
612ebfedea0SLionel Sambuc 
613ebfedea0SLionel Sambuc 	for (i = 0; i < 16; i++)
614ebfedea0SLionel Sambuc 	    Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
615ebfedea0SLionel Sambuc     }
616ebfedea0SLionel Sambuc     ret = arcfour_mic_key(context, &Klocal,
617ebfedea0SLionel Sambuc 			  SND_SEQ, 4,
618ebfedea0SLionel Sambuc 			  k6_data, sizeof(k6_data));
619ebfedea0SLionel Sambuc     memset(Klocaldata, 0, sizeof(Klocaldata));
620ebfedea0SLionel Sambuc     if (ret) {
621ebfedea0SLionel Sambuc 	*minor_status = ret;
622ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
623ebfedea0SLionel Sambuc     }
624ebfedea0SLionel Sambuc 
625ebfedea0SLionel Sambuc     output_message_buffer->value = malloc(datalen);
626ebfedea0SLionel Sambuc     if (output_message_buffer->value == NULL) {
627ebfedea0SLionel Sambuc 	*minor_status = ENOMEM;
628ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
629ebfedea0SLionel Sambuc     }
630ebfedea0SLionel Sambuc     output_message_buffer->length = datalen;
631ebfedea0SLionel Sambuc 
632ebfedea0SLionel Sambuc     if(conf_flag) {
633ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX rc4_key;
634ebfedea0SLionel Sambuc 
635ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_init(&rc4_key);
636ebfedea0SLionel Sambuc 	EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
637ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
638ebfedea0SLionel Sambuc 	EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
639ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&rc4_key);
640ebfedea0SLionel Sambuc     } else {
641ebfedea0SLionel Sambuc 	memcpy(Confounder, p0 + 24, 8); /* Confounder */
642ebfedea0SLionel Sambuc 	memcpy(output_message_buffer->value,
643ebfedea0SLionel Sambuc 	       p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
644ebfedea0SLionel Sambuc 	       datalen);
645ebfedea0SLionel Sambuc     }
646ebfedea0SLionel Sambuc     memset(k6_data, 0, sizeof(k6_data));
647ebfedea0SLionel Sambuc 
648ebfedea0SLionel Sambuc     if (!IS_DCE_STYLE(context_handle)) {
649ebfedea0SLionel Sambuc 	ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
650ebfedea0SLionel Sambuc 	if (ret) {
651ebfedea0SLionel Sambuc 	    _gsskrb5_release_buffer(minor_status, output_message_buffer);
652ebfedea0SLionel Sambuc 	    *minor_status = 0;
653ebfedea0SLionel Sambuc 	    return ret;
654ebfedea0SLionel Sambuc 	}
655ebfedea0SLionel Sambuc 	output_message_buffer->length -= padlen;
656ebfedea0SLionel Sambuc     }
657ebfedea0SLionel Sambuc 
658ebfedea0SLionel Sambuc     ret = arcfour_mic_cksum(context,
659ebfedea0SLionel Sambuc 			    key, KRB5_KU_USAGE_SEAL,
660ebfedea0SLionel Sambuc 			    cksum_data, sizeof(cksum_data),
661ebfedea0SLionel Sambuc 			    p0, 8,
662ebfedea0SLionel Sambuc 			    Confounder, sizeof(Confounder),
663ebfedea0SLionel Sambuc 			    output_message_buffer->value,
664ebfedea0SLionel Sambuc 			    output_message_buffer->length + padlen);
665ebfedea0SLionel Sambuc     if (ret) {
666ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, output_message_buffer);
667ebfedea0SLionel Sambuc 	*minor_status = ret;
668ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
669ebfedea0SLionel Sambuc     }
670ebfedea0SLionel Sambuc 
671ebfedea0SLionel Sambuc     cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
672ebfedea0SLionel Sambuc     if (cmp) {
673ebfedea0SLionel Sambuc 	_gsskrb5_release_buffer(minor_status, output_message_buffer);
674ebfedea0SLionel Sambuc 	*minor_status = 0;
675ebfedea0SLionel Sambuc 	return GSS_S_BAD_MIC;
676ebfedea0SLionel Sambuc     }
677ebfedea0SLionel Sambuc 
678ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
679ebfedea0SLionel Sambuc     omret = _gssapi_msg_order_check(context_handle->order, seq_number);
680ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
681ebfedea0SLionel Sambuc     if (omret)
682ebfedea0SLionel Sambuc 	return omret;
683ebfedea0SLionel Sambuc 
684ebfedea0SLionel Sambuc     if (conf_state)
685ebfedea0SLionel Sambuc 	*conf_state = conf_flag;
686ebfedea0SLionel Sambuc 
687ebfedea0SLionel Sambuc     *minor_status = 0;
688ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
689ebfedea0SLionel Sambuc }
690ebfedea0SLionel Sambuc 
691ebfedea0SLionel Sambuc static OM_uint32
max_wrap_length_arcfour(const gsskrb5_ctx ctx,krb5_crypto crypto,size_t input_length,OM_uint32 * max_input_size)692ebfedea0SLionel Sambuc max_wrap_length_arcfour(const gsskrb5_ctx ctx,
693ebfedea0SLionel Sambuc 			krb5_crypto crypto,
694ebfedea0SLionel Sambuc 			size_t input_length,
695ebfedea0SLionel Sambuc 			OM_uint32 *max_input_size)
696ebfedea0SLionel Sambuc {
697ebfedea0SLionel Sambuc     /*
698ebfedea0SLionel Sambuc      * if GSS_C_DCE_STYLE is in use:
699ebfedea0SLionel Sambuc      *  - we only need to encapsulate the WRAP token
700ebfedea0SLionel Sambuc      * However, since this is a fixed since, we just
701ebfedea0SLionel Sambuc      */
702ebfedea0SLionel Sambuc     if (IS_DCE_STYLE(ctx)) {
703ebfedea0SLionel Sambuc 	size_t len, total_len;
704ebfedea0SLionel Sambuc 
705ebfedea0SLionel Sambuc 	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
706ebfedea0SLionel Sambuc 	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
707ebfedea0SLionel Sambuc 
708ebfedea0SLionel Sambuc 	if (input_length < len)
709ebfedea0SLionel Sambuc 	    *max_input_size = 0;
710ebfedea0SLionel Sambuc 	else
711ebfedea0SLionel Sambuc 	    *max_input_size = input_length - len;
712ebfedea0SLionel Sambuc 
713ebfedea0SLionel Sambuc     } else {
714ebfedea0SLionel Sambuc 	size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
715ebfedea0SLionel Sambuc 	size_t blocksize = 8;
716ebfedea0SLionel Sambuc 	size_t len, total_len;
717ebfedea0SLionel Sambuc 
718ebfedea0SLionel Sambuc 	len = 8 + input_length + blocksize + extrasize;
719ebfedea0SLionel Sambuc 
720ebfedea0SLionel Sambuc 	_gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
721ebfedea0SLionel Sambuc 
722ebfedea0SLionel Sambuc 	total_len -= input_length; /* token length */
723ebfedea0SLionel Sambuc 	if (total_len < input_length) {
724ebfedea0SLionel Sambuc 	    *max_input_size = (input_length - total_len);
725ebfedea0SLionel Sambuc 	    (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
726ebfedea0SLionel Sambuc 	} else {
727ebfedea0SLionel Sambuc 	    *max_input_size = 0;
728ebfedea0SLionel Sambuc 	}
729ebfedea0SLionel Sambuc     }
730ebfedea0SLionel Sambuc 
731ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
732ebfedea0SLionel Sambuc }
733ebfedea0SLionel Sambuc 
734ebfedea0SLionel Sambuc 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)735ebfedea0SLionel Sambuc _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
736ebfedea0SLionel Sambuc 			  const gsskrb5_ctx ctx,
737ebfedea0SLionel Sambuc 			  krb5_context context,
738ebfedea0SLionel Sambuc 			  int conf_req_flag,
739ebfedea0SLionel Sambuc 			  gss_qop_t qop_req,
740ebfedea0SLionel Sambuc 			  OM_uint32 req_output_size,
741ebfedea0SLionel Sambuc 			  OM_uint32 *max_input_size,
742ebfedea0SLionel Sambuc 			  krb5_keyblock *key)
743ebfedea0SLionel Sambuc {
744ebfedea0SLionel Sambuc     krb5_error_code ret;
745ebfedea0SLionel Sambuc     krb5_crypto crypto;
746ebfedea0SLionel Sambuc 
747ebfedea0SLionel Sambuc     ret = krb5_crypto_init(context, key, 0, &crypto);
748ebfedea0SLionel Sambuc     if (ret != 0) {
749ebfedea0SLionel Sambuc 	*minor_status = ret;
750ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
751ebfedea0SLionel Sambuc     }
752ebfedea0SLionel Sambuc 
753ebfedea0SLionel Sambuc     ret = max_wrap_length_arcfour(ctx, crypto,
754ebfedea0SLionel Sambuc 				  req_output_size, max_input_size);
755ebfedea0SLionel Sambuc     if (ret != 0) {
756ebfedea0SLionel Sambuc 	*minor_status = ret;
757ebfedea0SLionel Sambuc 	krb5_crypto_destroy(context, crypto);
758ebfedea0SLionel Sambuc 	return GSS_S_FAILURE;
759ebfedea0SLionel Sambuc     }
760ebfedea0SLionel Sambuc 
761ebfedea0SLionel Sambuc     krb5_crypto_destroy(context, crypto);
762ebfedea0SLionel Sambuc 
763ebfedea0SLionel Sambuc     return GSS_S_COMPLETE;
764ebfedea0SLionel Sambuc }
765