Implement gss_wrap_iov, gss_unwrap_iov for CFX type encryption types.
[heimdal.git] / lib / gssapi / krb5 / arcfour.c
blobe7331b0119c4988f92f9db12bebbc16d2c8115dc
1 /*
2 * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "gsskrb5_locl.h"
37 * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
39 * The arcfour message have the following formats:
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]
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]
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).
66 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
67 #define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13
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)
75 krb5_error_code ret;
77 Checksum cksum_k5;
78 krb5_keyblock key5;
79 char k5_data[16];
81 Checksum cksum_k6;
83 char T[4];
85 memset(T, 0, 4);
86 cksum_k5.checksum.data = k5_data;
87 cksum_k5.checksum.length = sizeof(k5_data);
89 if (key->keytype == KEYTYPE_ARCFOUR_56) {
90 char L40[14] = "fortybits";
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);
100 if (ret)
101 return ret;
103 key5.keytype = KEYTYPE_ARCFOUR;
104 key5.keyvalue = cksum_k5.checksum;
106 cksum_k6.checksum.data = key6_data;
107 cksum_k6.checksum.length = key6_size;
109 return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
110 cksum_data, cksum_size, 0, &key5, &cksum_k6);
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)
122 Checksum CKSUM;
123 u_char *ptr;
124 size_t len;
125 krb5_crypto crypto;
126 krb5_error_code ret;
128 assert(sgn_cksum_sz == 8);
130 len = l1 + l2 + l3;
132 ptr = malloc(len);
133 if (ptr == NULL)
134 return ENOMEM;
136 memcpy(ptr, v1, l1);
137 memcpy(ptr + l1, v2, l2);
138 memcpy(ptr + l1 + l2, v3, l3);
140 ret = krb5_crypto_init(context, key, 0, &crypto);
141 if (ret) {
142 free(ptr);
143 return ret;
146 ret = krb5_create_checksum(context,
147 crypto,
148 usage,
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);
157 krb5_crypto_destroy(context, crypto);
159 return ret;
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)
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 RC4_KEY rc4_key;
178 _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
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;
187 p0 = _gssapi_make_mech_header(message_token->value,
188 len,
189 GSS_KRB5_MECHANISM);
190 p = p0;
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;
201 p = NULL;
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;
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;
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);
231 krb5_auth_con_setlocalseqnumber (context,
232 context_handle->auth_context,
233 ++seq_number);
234 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
236 memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
238 RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
239 RC4 (&rc4_key, 8, p, p);
241 memset(&rc4_key, 0, sizeof(rc4_key));
242 memset(k6_data, 0, sizeof(k6_data));
244 *minor_status = 0;
245 return GSS_S_COMPLETE;
249 OM_uint32
250 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
251 const gsskrb5_ctx context_handle,
252 krb5_context context,
253 const gss_buffer_t message_buffer,
254 const gss_buffer_t token_buffer,
255 gss_qop_t * qop_state,
256 krb5_keyblock *key,
257 char *type)
259 krb5_error_code ret;
260 uint32_t seq_number;
261 OM_uint32 omret;
262 u_char SND_SEQ[8], cksum_data[8], *p;
263 char k6_data[16];
264 int cmp;
266 if (qop_state)
267 *qop_state = 0;
269 p = token_buffer->value;
270 omret = _gsskrb5_verify_header (&p,
271 token_buffer->length,
272 (u_char *)type,
273 GSS_KRB5_MECHANISM);
274 if (omret)
275 return omret;
277 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
278 return GSS_S_BAD_SIG;
279 p += 2;
280 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
281 return GSS_S_BAD_MIC;
282 p += 4;
284 ret = arcfour_mic_cksum(context,
285 key, KRB5_KU_USAGE_SIGN,
286 cksum_data, sizeof(cksum_data),
287 p - 8, 8,
288 message_buffer->value, message_buffer->length,
289 NULL, 0);
290 if (ret) {
291 *minor_status = ret;
292 return GSS_S_FAILURE;
295 ret = arcfour_mic_key(context, key,
296 cksum_data, sizeof(cksum_data),
297 k6_data, sizeof(k6_data));
298 if (ret) {
299 *minor_status = ret;
300 return GSS_S_FAILURE;
303 cmp = memcmp(cksum_data, p + 8, 8);
304 if (cmp) {
305 *minor_status = 0;
306 return GSS_S_BAD_MIC;
310 RC4_KEY rc4_key;
312 RC4_set_key (&rc4_key, sizeof(k6_data), (void*)k6_data);
313 RC4 (&rc4_key, 8, p, SND_SEQ);
315 memset(&rc4_key, 0, sizeof(rc4_key));
316 memset(k6_data, 0, sizeof(k6_data));
319 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
321 if (context_handle->more_flags & LOCAL)
322 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
323 else
324 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
326 memset(SND_SEQ, 0, sizeof(SND_SEQ));
327 if (cmp != 0) {
328 *minor_status = 0;
329 return GSS_S_BAD_MIC;
332 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
333 omret = _gssapi_msg_order_check(context_handle->order, seq_number);
334 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
335 if (omret)
336 return omret;
338 *minor_status = 0;
339 return GSS_S_COMPLETE;
342 OM_uint32
343 _gssapi_wrap_arcfour(OM_uint32 * minor_status,
344 const gsskrb5_ctx context_handle,
345 krb5_context context,
346 int conf_req_flag,
347 gss_qop_t qop_req,
348 const gss_buffer_t input_message_buffer,
349 int * conf_state,
350 gss_buffer_t output_message_buffer,
351 krb5_keyblock *key)
353 u_char Klocaldata[16], k6_data[16], *p, *p0;
354 size_t len, total_len, datalen;
355 krb5_keyblock Klocal;
356 krb5_error_code ret;
357 int32_t seq_number;
359 if (conf_state)
360 *conf_state = 0;
362 datalen = input_message_buffer->length;
364 if (IS_DCE_STYLE(context_handle)) {
365 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
366 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
367 total_len += datalen;
368 } else {
369 datalen += 1; /* padding */
370 len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
371 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
374 output_message_buffer->length = total_len;
375 output_message_buffer->value = malloc (total_len);
376 if (output_message_buffer->value == NULL) {
377 *minor_status = ENOMEM;
378 return GSS_S_FAILURE;
381 p0 = _gssapi_make_mech_header(output_message_buffer->value,
382 len,
383 GSS_KRB5_MECHANISM);
384 p = p0;
386 *p++ = 0x02; /* TOK_ID */
387 *p++ = 0x01;
388 *p++ = 0x11; /* SGN_ALG */
389 *p++ = 0x00;
390 if (conf_req_flag) {
391 *p++ = 0x10; /* SEAL_ALG */
392 *p++ = 0x00;
393 } else {
394 *p++ = 0xff; /* SEAL_ALG */
395 *p++ = 0xff;
397 *p++ = 0xff; /* Filler */
398 *p++ = 0xff;
400 p = NULL;
402 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
403 krb5_auth_con_getlocalseqnumber (context,
404 context_handle->auth_context,
405 &seq_number);
407 _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
409 krb5_auth_con_setlocalseqnumber (context,
410 context_handle->auth_context,
411 ++seq_number);
412 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
414 memset (p0 + 8 + 4,
415 (context_handle->more_flags & LOCAL) ? 0 : 0xff,
418 krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
420 /* p points to data */
421 p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
422 memcpy(p, input_message_buffer->value, input_message_buffer->length);
424 if (!IS_DCE_STYLE(context_handle))
425 p[input_message_buffer->length] = 1; /* padding */
427 ret = arcfour_mic_cksum(context,
428 key, KRB5_KU_USAGE_SEAL,
429 p0 + 16, 8, /* SGN_CKSUM */
430 p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
431 p0 + 24, 8, /* Confounder */
432 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
433 datalen);
434 if (ret) {
435 *minor_status = ret;
436 _gsskrb5_release_buffer(minor_status, output_message_buffer);
437 return GSS_S_FAILURE;
441 int i;
443 Klocal.keytype = key->keytype;
444 Klocal.keyvalue.data = Klocaldata;
445 Klocal.keyvalue.length = sizeof(Klocaldata);
447 for (i = 0; i < 16; i++)
448 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
450 ret = arcfour_mic_key(context, &Klocal,
451 p0 + 8, 4, /* SND_SEQ */
452 k6_data, sizeof(k6_data));
453 memset(Klocaldata, 0, sizeof(Klocaldata));
454 if (ret) {
455 _gsskrb5_release_buffer(minor_status, output_message_buffer);
456 *minor_status = ret;
457 return GSS_S_FAILURE;
461 if(conf_req_flag) {
462 RC4_KEY rc4_key;
464 RC4_set_key (&rc4_key, sizeof(k6_data), (void *)k6_data);
465 /* XXX ? */
466 RC4 (&rc4_key, 8 + datalen, p0 + 24, p0 + 24); /* Confounder + data */
467 memset(&rc4_key, 0, sizeof(rc4_key));
469 memset(k6_data, 0, sizeof(k6_data));
471 ret = arcfour_mic_key(context, key,
472 p0 + 16, 8, /* SGN_CKSUM */
473 k6_data, sizeof(k6_data));
474 if (ret) {
475 _gsskrb5_release_buffer(minor_status, output_message_buffer);
476 *minor_status = ret;
477 return GSS_S_FAILURE;
481 RC4_KEY rc4_key;
483 RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
484 RC4 (&rc4_key, 8, p0 + 8, p0 + 8); /* SND_SEQ */
485 memset(&rc4_key, 0, sizeof(rc4_key));
486 memset(k6_data, 0, sizeof(k6_data));
489 if (conf_state)
490 *conf_state = conf_req_flag;
492 *minor_status = 0;
493 return GSS_S_COMPLETE;
496 OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
497 const gsskrb5_ctx context_handle,
498 krb5_context context,
499 const gss_buffer_t input_message_buffer,
500 gss_buffer_t output_message_buffer,
501 int *conf_state,
502 gss_qop_t *qop_state,
503 krb5_keyblock *key)
505 u_char Klocaldata[16];
506 krb5_keyblock Klocal;
507 krb5_error_code ret;
508 uint32_t seq_number;
509 size_t datalen;
510 OM_uint32 omret;
511 u_char k6_data[16], SND_SEQ[8], Confounder[8];
512 u_char cksum_data[8];
513 u_char *p, *p0;
514 int cmp;
515 int conf_flag;
516 size_t padlen = 0, len;
518 if (conf_state)
519 *conf_state = 0;
520 if (qop_state)
521 *qop_state = 0;
523 p0 = input_message_buffer->value;
525 if (IS_DCE_STYLE(context_handle)) {
526 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
527 GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
528 if (input_message_buffer->length < len)
529 return GSS_S_BAD_MECH;
530 } else {
531 len = input_message_buffer->length;
534 omret = _gssapi_verify_mech_header(&p0,
535 len,
536 GSS_KRB5_MECHANISM);
537 if (omret)
538 return omret;
540 /* length of mech header */
541 len = (p0 - (u_char *)input_message_buffer->value) +
542 GSS_ARCFOUR_WRAP_TOKEN_SIZE;
544 if (len > input_message_buffer->length)
545 return GSS_S_BAD_MECH;
547 /* length of data */
548 datalen = input_message_buffer->length - len;
550 p = p0;
552 if (memcmp(p, "\x02\x01", 2) != 0)
553 return GSS_S_BAD_SIG;
554 p += 2;
555 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
556 return GSS_S_BAD_SIG;
557 p += 2;
559 if (memcmp (p, "\x10\x00", 2) == 0)
560 conf_flag = 1;
561 else if (memcmp (p, "\xff\xff", 2) == 0)
562 conf_flag = 0;
563 else
564 return GSS_S_BAD_SIG;
566 p += 2;
567 if (memcmp (p, "\xff\xff", 2) != 0)
568 return GSS_S_BAD_MIC;
569 p = NULL;
571 ret = arcfour_mic_key(context, key,
572 p0 + 16, 8, /* SGN_CKSUM */
573 k6_data, sizeof(k6_data));
574 if (ret) {
575 *minor_status = ret;
576 return GSS_S_FAILURE;
580 RC4_KEY rc4_key;
582 RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
583 RC4 (&rc4_key, 8, p0 + 8, SND_SEQ); /* SND_SEQ */
584 memset(&rc4_key, 0, sizeof(rc4_key));
585 memset(k6_data, 0, sizeof(k6_data));
588 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
590 if (context_handle->more_flags & LOCAL)
591 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
592 else
593 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
595 if (cmp != 0) {
596 *minor_status = 0;
597 return GSS_S_BAD_MIC;
601 int i;
603 Klocal.keytype = key->keytype;
604 Klocal.keyvalue.data = Klocaldata;
605 Klocal.keyvalue.length = sizeof(Klocaldata);
607 for (i = 0; i < 16; i++)
608 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
610 ret = arcfour_mic_key(context, &Klocal,
611 SND_SEQ, 4,
612 k6_data, sizeof(k6_data));
613 memset(Klocaldata, 0, sizeof(Klocaldata));
614 if (ret) {
615 *minor_status = ret;
616 return GSS_S_FAILURE;
619 output_message_buffer->value = malloc(datalen);
620 if (output_message_buffer->value == NULL) {
621 *minor_status = ENOMEM;
622 return GSS_S_FAILURE;
624 output_message_buffer->length = datalen;
626 if(conf_flag) {
627 RC4_KEY rc4_key;
629 RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
630 RC4 (&rc4_key, 8, p0 + 24, Confounder); /* Confounder */
631 RC4 (&rc4_key, datalen, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
632 output_message_buffer->value);
633 memset(&rc4_key, 0, sizeof(rc4_key));
634 } else {
635 memcpy(Confounder, p0 + 24, 8); /* Confounder */
636 memcpy(output_message_buffer->value,
637 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
638 datalen);
640 memset(k6_data, 0, sizeof(k6_data));
642 if (!IS_DCE_STYLE(context_handle)) {
643 ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
644 if (ret) {
645 _gsskrb5_release_buffer(minor_status, output_message_buffer);
646 *minor_status = 0;
647 return ret;
649 output_message_buffer->length -= padlen;
652 ret = arcfour_mic_cksum(context,
653 key, KRB5_KU_USAGE_SEAL,
654 cksum_data, sizeof(cksum_data),
655 p0, 8,
656 Confounder, sizeof(Confounder),
657 output_message_buffer->value,
658 output_message_buffer->length + padlen);
659 if (ret) {
660 _gsskrb5_release_buffer(minor_status, output_message_buffer);
661 *minor_status = ret;
662 return GSS_S_FAILURE;
665 cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
666 if (cmp) {
667 _gsskrb5_release_buffer(minor_status, output_message_buffer);
668 *minor_status = 0;
669 return GSS_S_BAD_MIC;
672 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
673 omret = _gssapi_msg_order_check(context_handle->order, seq_number);
674 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
675 if (omret)
676 return omret;
678 if (conf_state)
679 *conf_state = conf_flag;
681 *minor_status = 0;
682 return GSS_S_COMPLETE;
685 static OM_uint32
686 max_wrap_length_arcfour(const gsskrb5_ctx ctx,
687 krb5_crypto crypto,
688 size_t input_length,
689 OM_uint32 *max_input_size)
692 * if GSS_C_DCE_STYLE is in use:
693 * - we only need to encapsulate the WRAP token
694 * However, since this is a fixed since, we just
696 if (IS_DCE_STYLE(ctx)) {
697 size_t len, total_len;
699 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
700 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
702 if (input_length < len)
703 *max_input_size = 0;
704 else
705 *max_input_size = input_length - len;
707 } else {
708 size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
709 size_t blocksize = 8;
710 size_t len, total_len;
712 len = 8 + input_length + blocksize + extrasize;
714 _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
716 total_len -= input_length; /* token length */
717 if (total_len < input_length) {
718 *max_input_size = (input_length - total_len);
719 (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
720 } else {
721 *max_input_size = 0;
725 return GSS_S_COMPLETE;
728 OM_uint32
729 _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
730 const gsskrb5_ctx ctx,
731 krb5_context context,
732 int conf_req_flag,
733 gss_qop_t qop_req,
734 OM_uint32 req_output_size,
735 OM_uint32 *max_input_size,
736 krb5_keyblock *key)
738 krb5_error_code ret;
739 krb5_crypto crypto;
741 ret = krb5_crypto_init(context, key, 0, &crypto);
742 if (ret != 0) {
743 *minor_status = ret;
744 return GSS_S_FAILURE;
747 ret = max_wrap_length_arcfour(ctx, crypto,
748 req_output_size, max_input_size);
749 if (ret != 0) {
750 *minor_status = ret;
751 krb5_crypto_destroy(context, crypto);
752 return GSS_S_FAILURE;
755 krb5_crypto_destroy(context, crypto);
757 return GSS_S_COMPLETE;