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 | arcfour_mic_key(krb5_context context, krb5_keyblock *key,
|
---|
72 | void *cksum_data, size_t cksum_size,
|
---|
73 | void *key6_data, size_t key6_size)
|
---|
74 | {
|
---|
75 | krb5_error_code ret;
|
---|
76 |
|
---|
77 | Checksum cksum_k5;
|
---|
78 | krb5_keyblock key5;
|
---|
79 | char k5_data[16];
|
---|
80 |
|
---|
81 | Checksum cksum_k6;
|
---|
82 |
|
---|
83 | char T[4];
|
---|
84 |
|
---|
85 | memset(T, 0, 4);
|
---|
86 | cksum_k5.checksum.data = k5_data;
|
---|
87 | cksum_k5.checksum.length = sizeof(k5_data);
|
---|
88 |
|
---|
89 | if (key->keytype == ENCTYPE_ARCFOUR_HMAC_MD5_56) {
|
---|
90 | char L40[14] = "fortybits";
|
---|
91 |
|
---|
92 | memcpy(L40 + 10, T, sizeof(T));
|
---|
93 | ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
|
---|
94 | L40, 14, 0, key, &cksum_k5);
|
---|
95 | memset(&k5_data[7], 0xAB, 9);
|
---|
96 | } else {
|
---|
97 | ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
|
---|
98 | T, 4, 0, key, &cksum_k5);
|
---|
99 | }
|
---|
100 | if (ret)
|
---|
101 | return ret;
|
---|
102 |
|
---|
103 | key5.keytype = ENCTYPE_ARCFOUR_HMAC_MD5;
|
---|
104 | key5.keyvalue = cksum_k5.checksum;
|
---|
105 |
|
---|
106 | cksum_k6.checksum.data = key6_data;
|
---|
107 | cksum_k6.checksum.length = key6_size;
|
---|
108 |
|
---|
109 | 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 | arcfour_mic_cksum(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 void *v3, size_t l3)
|
---|
121 | {
|
---|
122 | Checksum CKSUM;
|
---|
123 | u_char *ptr;
|
---|
124 | size_t len;
|
---|
125 | krb5_crypto crypto;
|
---|
126 | krb5_error_code ret;
|
---|
127 |
|
---|
128 | assert(sgn_cksum_sz == 8);
|
---|
129 |
|
---|
130 | len = l1 + l2 + l3;
|
---|
131 |
|
---|
132 | ptr = malloc(len);
|
---|
133 | if (ptr == NULL)
|
---|
134 | return ENOMEM;
|
---|
135 |
|
---|
136 | memcpy(ptr, v1, l1);
|
---|
137 | memcpy(ptr + l1, v2, l2);
|
---|
138 | memcpy(ptr + l1 + l2, v3, l3);
|
---|
139 |
|
---|
140 | ret = krb5_crypto_init(context, key, 0, &crypto);
|
---|
141 | if (ret) {
|
---|
142 | free(ptr);
|
---|
143 | return ret;
|
---|
144 | }
|
---|
145 |
|
---|
146 | ret = krb5_create_checksum(context,
|
---|
147 | crypto,
|
---|
148 | usage,
|
---|
149 | 0,
|
---|
150 | ptr, len,
|
---|
151 | &CKSUM);
|
---|
152 | free(ptr);
|
---|
153 | if (ret == 0) {
|
---|
154 | memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
|
---|
155 | free_Checksum(&CKSUM);
|
---|
156 | }
|
---|
157 | krb5_crypto_destroy(context, crypto);
|
---|
158 |
|
---|
159 | return ret;
|
---|
160 | }
|
---|
161 |
|
---|
162 |
|
---|
163 | OM_uint32
|
---|
164 | _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
|
---|
165 | const gsskrb5_ctx context_handle,
|
---|
166 | krb5_context context,
|
---|
167 | gss_qop_t qop_req,
|
---|
168 | const gss_buffer_t message_buffer,
|
---|
169 | gss_buffer_t message_token,
|
---|
170 | krb5_keyblock *key)
|
---|
171 | {
|
---|
172 | krb5_error_code ret;
|
---|
173 | int32_t seq_number;
|
---|
174 | size_t len, total_len;
|
---|
175 | u_char k6_data[16], *p0, *p;
|
---|
176 | EVP_CIPHER_CTX rc4_key;
|
---|
177 |
|
---|
178 | _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
|
---|
179 |
|
---|
180 | message_token->length = total_len;
|
---|
181 | message_token->value = malloc (total_len);
|
---|
182 | if (message_token->value == NULL) {
|
---|
183 | *minor_status = ENOMEM;
|
---|
184 | return GSS_S_FAILURE;
|
---|
185 | }
|
---|
186 |
|
---|
187 | p0 = _gssapi_make_mech_header(message_token->value,
|
---|
188 | len,
|
---|
189 | GSS_KRB5_MECHANISM);
|
---|
190 | p = p0;
|
---|
191 |
|
---|
192 | *p++ = 0x01; /* TOK_ID */
|
---|
193 | *p++ = 0x01;
|
---|
194 | *p++ = 0x11; /* SGN_ALG */
|
---|
195 | *p++ = 0x00;
|
---|
196 | *p++ = 0xff; /* Filler */
|
---|
197 | *p++ = 0xff;
|
---|
198 | *p++ = 0xff;
|
---|
199 | *p++ = 0xff;
|
---|
200 |
|
---|
201 | p = NULL;
|
---|
202 |
|
---|
203 | ret = arcfour_mic_cksum(context,
|
---|
204 | key, KRB5_KU_USAGE_SIGN,
|
---|
205 | p0 + 16, 8, /* SGN_CKSUM */
|
---|
206 | p0, 8, /* TOK_ID, SGN_ALG, Filer */
|
---|
207 | message_buffer->value, message_buffer->length,
|
---|
208 | NULL, 0);
|
---|
209 | if (ret) {
|
---|
210 | _gsskrb5_release_buffer(minor_status, message_token);
|
---|
211 | *minor_status = ret;
|
---|
212 | return GSS_S_FAILURE;
|
---|
213 | }
|
---|
214 |
|
---|
215 | ret = arcfour_mic_key(context, key,
|
---|
216 | p0 + 16, 8, /* SGN_CKSUM */
|
---|
217 | k6_data, sizeof(k6_data));
|
---|
218 | if (ret) {
|
---|
219 | _gsskrb5_release_buffer(minor_status, message_token);
|
---|
220 | *minor_status = ret;
|
---|
221 | return GSS_S_FAILURE;
|
---|
222 | }
|
---|
223 |
|
---|
224 | HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
|
---|
225 | krb5_auth_con_getlocalseqnumber (context,
|
---|
226 | context_handle->auth_context,
|
---|
227 | &seq_number);
|
---|
228 | p = p0 + 8; /* SND_SEQ */
|
---|
229 | _gsskrb5_encode_be_om_uint32(seq_number, p);
|
---|
230 |
|
---|
231 | krb5_auth_con_setlocalseqnumber (context,
|
---|
232 | context_handle->auth_context,
|
---|
233 | ++seq_number);
|
---|
234 | HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
|
---|
235 |
|
---|
236 | memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
|
---|
237 |
|
---|
238 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
239 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
---|
240 | EVP_Cipher(&rc4_key, p, p, 8);
|
---|
241 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
242 |
|
---|
243 | memset(k6_data, 0, sizeof(k6_data));
|
---|
244 |
|
---|
245 | *minor_status = 0;
|
---|
246 | return GSS_S_COMPLETE;
|
---|
247 | }
|
---|
248 |
|
---|
249 |
|
---|
250 | OM_uint32
|
---|
251 | _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
|
---|
252 | const gsskrb5_ctx context_handle,
|
---|
253 | krb5_context context,
|
---|
254 | const gss_buffer_t message_buffer,
|
---|
255 | const gss_buffer_t token_buffer,
|
---|
256 | gss_qop_t * qop_state,
|
---|
257 | krb5_keyblock *key,
|
---|
258 | const char *type)
|
---|
259 | {
|
---|
260 | krb5_error_code ret;
|
---|
261 | uint32_t seq_number;
|
---|
262 | OM_uint32 omret;
|
---|
263 | u_char SND_SEQ[8], cksum_data[8], *p;
|
---|
264 | char k6_data[16];
|
---|
265 | int cmp;
|
---|
266 |
|
---|
267 | if (qop_state)
|
---|
268 | *qop_state = 0;
|
---|
269 |
|
---|
270 | p = token_buffer->value;
|
---|
271 | omret = _gsskrb5_verify_header (&p,
|
---|
272 | token_buffer->length,
|
---|
273 | type,
|
---|
274 | GSS_KRB5_MECHANISM);
|
---|
275 | if (omret)
|
---|
276 | return omret;
|
---|
277 |
|
---|
278 | if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
|
---|
279 | return GSS_S_BAD_SIG;
|
---|
280 | p += 2;
|
---|
281 | if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
|
---|
282 | return GSS_S_BAD_MIC;
|
---|
283 | p += 4;
|
---|
284 |
|
---|
285 | ret = arcfour_mic_cksum(context,
|
---|
286 | key, KRB5_KU_USAGE_SIGN,
|
---|
287 | cksum_data, sizeof(cksum_data),
|
---|
288 | p - 8, 8,
|
---|
289 | message_buffer->value, message_buffer->length,
|
---|
290 | NULL, 0);
|
---|
291 | if (ret) {
|
---|
292 | *minor_status = ret;
|
---|
293 | return GSS_S_FAILURE;
|
---|
294 | }
|
---|
295 |
|
---|
296 | ret = arcfour_mic_key(context, key,
|
---|
297 | cksum_data, sizeof(cksum_data),
|
---|
298 | k6_data, sizeof(k6_data));
|
---|
299 | if (ret) {
|
---|
300 | *minor_status = ret;
|
---|
301 | return GSS_S_FAILURE;
|
---|
302 | }
|
---|
303 |
|
---|
304 | cmp = ct_memcmp(cksum_data, p + 8, 8);
|
---|
305 | if (cmp) {
|
---|
306 | *minor_status = 0;
|
---|
307 | return GSS_S_BAD_MIC;
|
---|
308 | }
|
---|
309 |
|
---|
310 | {
|
---|
311 | EVP_CIPHER_CTX rc4_key;
|
---|
312 |
|
---|
313 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
314 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
|
---|
315 | EVP_Cipher(&rc4_key, SND_SEQ, p, 8);
|
---|
316 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
317 |
|
---|
318 | memset(k6_data, 0, sizeof(k6_data));
|
---|
319 | }
|
---|
320 |
|
---|
321 | _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
|
---|
322 |
|
---|
323 | if (context_handle->more_flags & LOCAL)
|
---|
324 | cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
|
---|
325 | else
|
---|
326 | cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
|
---|
327 |
|
---|
328 | memset(SND_SEQ, 0, sizeof(SND_SEQ));
|
---|
329 | if (cmp != 0) {
|
---|
330 | *minor_status = 0;
|
---|
331 | return GSS_S_BAD_MIC;
|
---|
332 | }
|
---|
333 |
|
---|
334 | HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
|
---|
335 | omret = _gssapi_msg_order_check(context_handle->order, seq_number);
|
---|
336 | HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
|
---|
337 | if (omret)
|
---|
338 | return omret;
|
---|
339 |
|
---|
340 | *minor_status = 0;
|
---|
341 | return GSS_S_COMPLETE;
|
---|
342 | }
|
---|
343 |
|
---|
344 | OM_uint32
|
---|
345 | _gssapi_wrap_arcfour(OM_uint32 * minor_status,
|
---|
346 | const gsskrb5_ctx context_handle,
|
---|
347 | krb5_context context,
|
---|
348 | int conf_req_flag,
|
---|
349 | gss_qop_t qop_req,
|
---|
350 | const gss_buffer_t input_message_buffer,
|
---|
351 | int * conf_state,
|
---|
352 | gss_buffer_t output_message_buffer,
|
---|
353 | krb5_keyblock *key)
|
---|
354 | {
|
---|
355 | u_char Klocaldata[16], k6_data[16], *p, *p0;
|
---|
356 | size_t len, total_len, datalen;
|
---|
357 | krb5_keyblock Klocal;
|
---|
358 | krb5_error_code ret;
|
---|
359 | int32_t seq_number;
|
---|
360 |
|
---|
361 | if (conf_state)
|
---|
362 | *conf_state = 0;
|
---|
363 |
|
---|
364 | datalen = input_message_buffer->length;
|
---|
365 |
|
---|
366 | if (IS_DCE_STYLE(context_handle)) {
|
---|
367 | len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
368 | _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
---|
369 | total_len += datalen;
|
---|
370 | } else {
|
---|
371 | datalen += 1; /* padding */
|
---|
372 | len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
373 | _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
---|
374 | }
|
---|
375 |
|
---|
376 | output_message_buffer->length = total_len;
|
---|
377 | output_message_buffer->value = malloc (total_len);
|
---|
378 | if (output_message_buffer->value == NULL) {
|
---|
379 | *minor_status = ENOMEM;
|
---|
380 | return GSS_S_FAILURE;
|
---|
381 | }
|
---|
382 |
|
---|
383 | p0 = _gssapi_make_mech_header(output_message_buffer->value,
|
---|
384 | len,
|
---|
385 | GSS_KRB5_MECHANISM);
|
---|
386 | p = p0;
|
---|
387 |
|
---|
388 | *p++ = 0x02; /* TOK_ID */
|
---|
389 | *p++ = 0x01;
|
---|
390 | *p++ = 0x11; /* SGN_ALG */
|
---|
391 | *p++ = 0x00;
|
---|
392 | if (conf_req_flag) {
|
---|
393 | *p++ = 0x10; /* SEAL_ALG */
|
---|
394 | *p++ = 0x00;
|
---|
395 | } else {
|
---|
396 | *p++ = 0xff; /* SEAL_ALG */
|
---|
397 | *p++ = 0xff;
|
---|
398 | }
|
---|
399 | *p++ = 0xff; /* Filler */
|
---|
400 | *p++ = 0xff;
|
---|
401 |
|
---|
402 | p = NULL;
|
---|
403 |
|
---|
404 | HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
|
---|
405 | krb5_auth_con_getlocalseqnumber (context,
|
---|
406 | context_handle->auth_context,
|
---|
407 | &seq_number);
|
---|
408 |
|
---|
409 | _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
|
---|
410 |
|
---|
411 | krb5_auth_con_setlocalseqnumber (context,
|
---|
412 | context_handle->auth_context,
|
---|
413 | ++seq_number);
|
---|
414 | HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
|
---|
415 |
|
---|
416 | memset (p0 + 8 + 4,
|
---|
417 | (context_handle->more_flags & LOCAL) ? 0 : 0xff,
|
---|
418 | 4);
|
---|
419 |
|
---|
420 | krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
|
---|
421 |
|
---|
422 | /* p points to data */
|
---|
423 | p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
424 | memcpy(p, input_message_buffer->value, input_message_buffer->length);
|
---|
425 |
|
---|
426 | if (!IS_DCE_STYLE(context_handle))
|
---|
427 | p[input_message_buffer->length] = 1; /* padding */
|
---|
428 |
|
---|
429 | ret = arcfour_mic_cksum(context,
|
---|
430 | key, KRB5_KU_USAGE_SEAL,
|
---|
431 | p0 + 16, 8, /* SGN_CKSUM */
|
---|
432 | p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
|
---|
433 | p0 + 24, 8, /* Confounder */
|
---|
434 | p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
|
---|
435 | datalen);
|
---|
436 | if (ret) {
|
---|
437 | *minor_status = ret;
|
---|
438 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
439 | return GSS_S_FAILURE;
|
---|
440 | }
|
---|
441 |
|
---|
442 | {
|
---|
443 | int i;
|
---|
444 |
|
---|
445 | Klocal.keytype = key->keytype;
|
---|
446 | Klocal.keyvalue.data = Klocaldata;
|
---|
447 | Klocal.keyvalue.length = sizeof(Klocaldata);
|
---|
448 |
|
---|
449 | for (i = 0; i < 16; i++)
|
---|
450 | Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
|
---|
451 | }
|
---|
452 | ret = arcfour_mic_key(context, &Klocal,
|
---|
453 | p0 + 8, 4, /* SND_SEQ */
|
---|
454 | k6_data, sizeof(k6_data));
|
---|
455 | memset(Klocaldata, 0, sizeof(Klocaldata));
|
---|
456 | if (ret) {
|
---|
457 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
458 | *minor_status = ret;
|
---|
459 | return GSS_S_FAILURE;
|
---|
460 | }
|
---|
461 |
|
---|
462 |
|
---|
463 | if(conf_req_flag) {
|
---|
464 | EVP_CIPHER_CTX rc4_key;
|
---|
465 |
|
---|
466 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
467 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
---|
468 | EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen);
|
---|
469 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
470 | }
|
---|
471 | memset(k6_data, 0, sizeof(k6_data));
|
---|
472 |
|
---|
473 | ret = arcfour_mic_key(context, key,
|
---|
474 | p0 + 16, 8, /* SGN_CKSUM */
|
---|
475 | k6_data, sizeof(k6_data));
|
---|
476 | if (ret) {
|
---|
477 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
478 | *minor_status = ret;
|
---|
479 | return GSS_S_FAILURE;
|
---|
480 | }
|
---|
481 |
|
---|
482 | {
|
---|
483 | EVP_CIPHER_CTX rc4_key;
|
---|
484 |
|
---|
485 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
486 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
---|
487 | EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
|
---|
488 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
489 | memset(k6_data, 0, sizeof(k6_data));
|
---|
490 | }
|
---|
491 |
|
---|
492 | if (conf_state)
|
---|
493 | *conf_state = conf_req_flag;
|
---|
494 |
|
---|
495 | *minor_status = 0;
|
---|
496 | return GSS_S_COMPLETE;
|
---|
497 | }
|
---|
498 |
|
---|
499 | OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
|
---|
500 | const gsskrb5_ctx context_handle,
|
---|
501 | krb5_context context,
|
---|
502 | const gss_buffer_t input_message_buffer,
|
---|
503 | gss_buffer_t output_message_buffer,
|
---|
504 | int *conf_state,
|
---|
505 | gss_qop_t *qop_state,
|
---|
506 | krb5_keyblock *key)
|
---|
507 | {
|
---|
508 | u_char Klocaldata[16];
|
---|
509 | krb5_keyblock Klocal;
|
---|
510 | krb5_error_code ret;
|
---|
511 | uint32_t seq_number;
|
---|
512 | size_t datalen;
|
---|
513 | OM_uint32 omret;
|
---|
514 | u_char k6_data[16], SND_SEQ[8], Confounder[8];
|
---|
515 | u_char cksum_data[8];
|
---|
516 | u_char *p, *p0;
|
---|
517 | int cmp;
|
---|
518 | int conf_flag;
|
---|
519 | size_t padlen = 0, len;
|
---|
520 |
|
---|
521 | if (conf_state)
|
---|
522 | *conf_state = 0;
|
---|
523 | if (qop_state)
|
---|
524 | *qop_state = 0;
|
---|
525 |
|
---|
526 | p0 = input_message_buffer->value;
|
---|
527 |
|
---|
528 | if (IS_DCE_STYLE(context_handle)) {
|
---|
529 | len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
|
---|
530 | GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
|
---|
531 | if (input_message_buffer->length < len)
|
---|
532 | return GSS_S_BAD_MECH;
|
---|
533 | } else {
|
---|
534 | len = input_message_buffer->length;
|
---|
535 | }
|
---|
536 |
|
---|
537 | omret = _gssapi_verify_mech_header(&p0,
|
---|
538 | len,
|
---|
539 | GSS_KRB5_MECHANISM);
|
---|
540 | if (omret)
|
---|
541 | return omret;
|
---|
542 |
|
---|
543 | /* length of mech header */
|
---|
544 | len = (p0 - (u_char *)input_message_buffer->value) +
|
---|
545 | GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
546 |
|
---|
547 | if (len > input_message_buffer->length)
|
---|
548 | return GSS_S_BAD_MECH;
|
---|
549 |
|
---|
550 | /* length of data */
|
---|
551 | datalen = input_message_buffer->length - len;
|
---|
552 |
|
---|
553 | p = p0;
|
---|
554 |
|
---|
555 | if (memcmp(p, "\x02\x01", 2) != 0)
|
---|
556 | return GSS_S_BAD_SIG;
|
---|
557 | p += 2;
|
---|
558 | if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
|
---|
559 | return GSS_S_BAD_SIG;
|
---|
560 | p += 2;
|
---|
561 |
|
---|
562 | if (memcmp (p, "\x10\x00", 2) == 0)
|
---|
563 | conf_flag = 1;
|
---|
564 | else if (memcmp (p, "\xff\xff", 2) == 0)
|
---|
565 | conf_flag = 0;
|
---|
566 | else
|
---|
567 | return GSS_S_BAD_SIG;
|
---|
568 |
|
---|
569 | p += 2;
|
---|
570 | if (memcmp (p, "\xff\xff", 2) != 0)
|
---|
571 | return GSS_S_BAD_MIC;
|
---|
572 | p = NULL;
|
---|
573 |
|
---|
574 | ret = arcfour_mic_key(context, key,
|
---|
575 | p0 + 16, 8, /* SGN_CKSUM */
|
---|
576 | k6_data, sizeof(k6_data));
|
---|
577 | if (ret) {
|
---|
578 | *minor_status = ret;
|
---|
579 | return GSS_S_FAILURE;
|
---|
580 | }
|
---|
581 |
|
---|
582 | {
|
---|
583 | EVP_CIPHER_CTX rc4_key;
|
---|
584 |
|
---|
585 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
586 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
---|
587 | EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8);
|
---|
588 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
589 | memset(k6_data, 0, sizeof(k6_data));
|
---|
590 | }
|
---|
591 |
|
---|
592 | _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
|
---|
593 |
|
---|
594 | if (context_handle->more_flags & LOCAL)
|
---|
595 | cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
|
---|
596 | else
|
---|
597 | cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
|
---|
598 |
|
---|
599 | if (cmp != 0) {
|
---|
600 | *minor_status = 0;
|
---|
601 | return GSS_S_BAD_MIC;
|
---|
602 | }
|
---|
603 |
|
---|
604 | {
|
---|
605 | int i;
|
---|
606 |
|
---|
607 | Klocal.keytype = key->keytype;
|
---|
608 | Klocal.keyvalue.data = Klocaldata;
|
---|
609 | Klocal.keyvalue.length = sizeof(Klocaldata);
|
---|
610 |
|
---|
611 | for (i = 0; i < 16; i++)
|
---|
612 | Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
|
---|
613 | }
|
---|
614 | ret = arcfour_mic_key(context, &Klocal,
|
---|
615 | SND_SEQ, 4,
|
---|
616 | k6_data, sizeof(k6_data));
|
---|
617 | memset(Klocaldata, 0, sizeof(Klocaldata));
|
---|
618 | if (ret) {
|
---|
619 | *minor_status = ret;
|
---|
620 | return GSS_S_FAILURE;
|
---|
621 | }
|
---|
622 |
|
---|
623 | output_message_buffer->value = malloc(datalen);
|
---|
624 | if (output_message_buffer->value == NULL) {
|
---|
625 | *minor_status = ENOMEM;
|
---|
626 | return GSS_S_FAILURE;
|
---|
627 | }
|
---|
628 | output_message_buffer->length = datalen;
|
---|
629 |
|
---|
630 | if(conf_flag) {
|
---|
631 | EVP_CIPHER_CTX rc4_key;
|
---|
632 |
|
---|
633 | EVP_CIPHER_CTX_init(&rc4_key);
|
---|
634 | EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
---|
635 | EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
|
---|
636 | EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
|
---|
637 | EVP_CIPHER_CTX_cleanup(&rc4_key);
|
---|
638 | } else {
|
---|
639 | memcpy(Confounder, p0 + 24, 8); /* Confounder */
|
---|
640 | memcpy(output_message_buffer->value,
|
---|
641 | p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
|
---|
642 | datalen);
|
---|
643 | }
|
---|
644 | memset(k6_data, 0, sizeof(k6_data));
|
---|
645 |
|
---|
646 | if (!IS_DCE_STYLE(context_handle)) {
|
---|
647 | ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
|
---|
648 | if (ret) {
|
---|
649 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
650 | *minor_status = 0;
|
---|
651 | return ret;
|
---|
652 | }
|
---|
653 | output_message_buffer->length -= padlen;
|
---|
654 | }
|
---|
655 |
|
---|
656 | ret = arcfour_mic_cksum(context,
|
---|
657 | key, KRB5_KU_USAGE_SEAL,
|
---|
658 | cksum_data, sizeof(cksum_data),
|
---|
659 | p0, 8,
|
---|
660 | Confounder, sizeof(Confounder),
|
---|
661 | output_message_buffer->value,
|
---|
662 | output_message_buffer->length + padlen);
|
---|
663 | if (ret) {
|
---|
664 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
665 | *minor_status = ret;
|
---|
666 | return GSS_S_FAILURE;
|
---|
667 | }
|
---|
668 |
|
---|
669 | cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
|
---|
670 | if (cmp) {
|
---|
671 | _gsskrb5_release_buffer(minor_status, output_message_buffer);
|
---|
672 | *minor_status = 0;
|
---|
673 | return GSS_S_BAD_MIC;
|
---|
674 | }
|
---|
675 |
|
---|
676 | HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
|
---|
677 | omret = _gssapi_msg_order_check(context_handle->order, seq_number);
|
---|
678 | HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
|
---|
679 | if (omret)
|
---|
680 | return omret;
|
---|
681 |
|
---|
682 | if (conf_state)
|
---|
683 | *conf_state = conf_flag;
|
---|
684 |
|
---|
685 | *minor_status = 0;
|
---|
686 | return GSS_S_COMPLETE;
|
---|
687 | }
|
---|
688 |
|
---|
689 | static OM_uint32
|
---|
690 | max_wrap_length_arcfour(const gsskrb5_ctx ctx,
|
---|
691 | krb5_crypto crypto,
|
---|
692 | size_t input_length,
|
---|
693 | OM_uint32 *max_input_size)
|
---|
694 | {
|
---|
695 | /*
|
---|
696 | * if GSS_C_DCE_STYLE is in use:
|
---|
697 | * - we only need to encapsulate the WRAP token
|
---|
698 | * However, since this is a fixed since, we just
|
---|
699 | */
|
---|
700 | if (IS_DCE_STYLE(ctx)) {
|
---|
701 | size_t len, total_len;
|
---|
702 |
|
---|
703 | len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
704 | _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
---|
705 |
|
---|
706 | if (input_length < len)
|
---|
707 | *max_input_size = 0;
|
---|
708 | else
|
---|
709 | *max_input_size = input_length - len;
|
---|
710 |
|
---|
711 | } else {
|
---|
712 | size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
---|
713 | size_t blocksize = 8;
|
---|
714 | size_t len, total_len;
|
---|
715 |
|
---|
716 | len = 8 + input_length + blocksize + extrasize;
|
---|
717 |
|
---|
718 | _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
---|
719 |
|
---|
720 | total_len -= input_length; /* token length */
|
---|
721 | if (total_len < input_length) {
|
---|
722 | *max_input_size = (input_length - total_len);
|
---|
723 | (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
|
---|
724 | } else {
|
---|
725 | *max_input_size = 0;
|
---|
726 | }
|
---|
727 | }
|
---|
728 |
|
---|
729 | return GSS_S_COMPLETE;
|
---|
730 | }
|
---|
731 |
|
---|
732 | OM_uint32
|
---|
733 | _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
|
---|
734 | const gsskrb5_ctx ctx,
|
---|
735 | krb5_context context,
|
---|
736 | int conf_req_flag,
|
---|
737 | gss_qop_t qop_req,
|
---|
738 | OM_uint32 req_output_size,
|
---|
739 | OM_uint32 *max_input_size,
|
---|
740 | krb5_keyblock *key)
|
---|
741 | {
|
---|
742 | krb5_error_code ret;
|
---|
743 | krb5_crypto crypto;
|
---|
744 |
|
---|
745 | ret = krb5_crypto_init(context, key, 0, &crypto);
|
---|
746 | if (ret != 0) {
|
---|
747 | *minor_status = ret;
|
---|
748 | return GSS_S_FAILURE;
|
---|
749 | }
|
---|
750 |
|
---|
751 | ret = max_wrap_length_arcfour(ctx, crypto,
|
---|
752 | req_output_size, max_input_size);
|
---|
753 | if (ret != 0) {
|
---|
754 | *minor_status = ret;
|
---|
755 | krb5_crypto_destroy(context, crypto);
|
---|
756 | return GSS_S_FAILURE;
|
---|
757 | }
|
---|
758 |
|
---|
759 | krb5_crypto_destroy(context, crypto);
|
---|
760 |
|
---|
761 | return GSS_S_COMPLETE;
|
---|
762 | }
|
---|