root/source4/heimdal/lib/gssapi/krb5/arcfour.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. arcfour_mic_key
  2. arcfour_mic_cksum
  3. _gssapi_get_mic_arcfour
  4. _gssapi_verify_mic_arcfour
  5. _gssapi_wrap_arcfour
  6. _gssapi_unwrap_arcfour
  7. max_wrap_length_arcfour
  8. _gssapi_wrap_size_arcfour

   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 "krb5/gsskrb5_locl.h"
  35 
  36 RCSID("$Id$");
  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
  73 arcfour_mic_key(krb5_context context, krb5_keyblock *key,
     /* [<][>][^][v][top][bottom][index][help] */
  74                 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 == KEYTYPE_ARCFOUR_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 = KEYTYPE_ARCFOUR;
 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
 117 arcfour_mic_cksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 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 void *v3, size_t l3)
 123 {
 124     Checksum CKSUM;
 125     u_char *ptr;
 126     size_t len;
 127     krb5_crypto crypto;
 128     krb5_error_code ret;
 129 
 130     assert(sgn_cksum_sz == 8);
 131 
 132     len = l1 + l2 + l3;
 133 
 134     ptr = malloc(len);
 135     if (ptr == NULL)
 136         return ENOMEM;
 137 
 138     memcpy(ptr, v1, l1);
 139     memcpy(ptr + l1, v2, l2);
 140     memcpy(ptr + l1 + l2, v3, l3);
 141 
 142     ret = krb5_crypto_init(context, key, 0, &crypto);
 143     if (ret) {
 144         free(ptr);
 145         return ret;
 146     }
 147 
 148     ret = krb5_create_checksum(context,
 149                                crypto,
 150                                usage,
 151                                0,
 152                                ptr, len,
 153                                &CKSUM);
 154     free(ptr);
 155     if (ret == 0) {
 156         memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
 157         free_Checksum(&CKSUM);
 158     }
 159     krb5_crypto_destroy(context, crypto);
 160 
 161     return ret;
 162 }
 163 
 164 
 165 OM_uint32
 166 _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
 167                         const gsskrb5_ctx context_handle,
 168                         krb5_context context,
 169                         gss_qop_t qop_req,
 170                         const gss_buffer_t message_buffer,
 171                         gss_buffer_t message_token,
 172                         krb5_keyblock *key)
 173 {
 174     krb5_error_code ret;
 175     int32_t seq_number;
 176     size_t len, total_len;
 177     u_char k6_data[16], *p0, *p;
 178     RC4_KEY rc4_key;
 179 
 180     _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
 181 
 182     message_token->length = total_len;
 183     message_token->value  = malloc (total_len);
 184     if (message_token->value == NULL) {
 185         *minor_status = ENOMEM;
 186         return GSS_S_FAILURE;
 187     }
 188 
 189     p0 = _gssapi_make_mech_header(message_token->value,
 190                                   len,
 191                                   GSS_KRB5_MECHANISM);
 192     p = p0;
 193 
 194     *p++ = 0x01; /* TOK_ID */
 195     *p++ = 0x01;
 196     *p++ = 0x11; /* SGN_ALG */
 197     *p++ = 0x00;
 198     *p++ = 0xff; /* Filler */
 199     *p++ = 0xff;
 200     *p++ = 0xff;
 201     *p++ = 0xff;
 202 
 203     p = NULL;
 204 
 205     ret = arcfour_mic_cksum(context,
 206                             key, KRB5_KU_USAGE_SIGN,
 207                             p0 + 16, 8,  /* SGN_CKSUM */
 208                             p0, 8, /* TOK_ID, SGN_ALG, Filer */
 209                             message_buffer->value, message_buffer->length,
 210                             NULL, 0);
 211     if (ret) {
 212         _gsskrb5_release_buffer(minor_status, message_token);
 213         *minor_status = ret;
 214         return GSS_S_FAILURE;
 215     }
 216 
 217     ret = arcfour_mic_key(context, key,
 218                           p0 + 16, 8, /* SGN_CKSUM */
 219                           k6_data, sizeof(k6_data));
 220     if (ret) {
 221         _gsskrb5_release_buffer(minor_status, message_token);
 222         *minor_status = ret;
 223         return GSS_S_FAILURE;
 224     }
 225 
 226     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
 227     krb5_auth_con_getlocalseqnumber (context,
 228                                      context_handle->auth_context,
 229                                      &seq_number);
 230     p = p0 + 8; /* SND_SEQ */
 231     _gsskrb5_encode_be_om_uint32(seq_number, p);
 232 
 233     krb5_auth_con_setlocalseqnumber (context,
 234                                      context_handle->auth_context,
 235                                      ++seq_number);
 236     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 237 
 238     memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
 239 
 240     RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
 241     RC4 (&rc4_key, 8, p, p);
 242         
 243     memset(&rc4_key, 0, sizeof(rc4_key));
 244     memset(k6_data, 0, sizeof(k6_data));
 245 
 246     *minor_status = 0;
 247     return GSS_S_COMPLETE;
 248 }
 249 
 250 
 251 OM_uint32
 252 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
 253                            const gsskrb5_ctx context_handle,
 254                            krb5_context context,
 255                            const gss_buffer_t message_buffer,
 256                            const gss_buffer_t token_buffer,
 257                            gss_qop_t * qop_state,
 258                            krb5_keyblock *key,
 259                            char *type)
 260 {
 261     krb5_error_code ret;
 262     uint32_t seq_number;
 263     OM_uint32 omret;
 264     u_char SND_SEQ[8], cksum_data[8], *p;
 265     char k6_data[16];
 266     int cmp;
 267 
 268     if (qop_state)
 269         *qop_state = 0;
 270 
 271     p = token_buffer->value;
 272     omret = _gsskrb5_verify_header (&p,
 273                                        token_buffer->length,
 274                                        (u_char *)type,
 275                                        GSS_KRB5_MECHANISM);
 276     if (omret)
 277         return omret;
 278 
 279     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
 280         return GSS_S_BAD_SIG;
 281     p += 2;
 282     if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
 283         return GSS_S_BAD_MIC;
 284     p += 4;
 285 
 286     ret = arcfour_mic_cksum(context,
 287                             key, KRB5_KU_USAGE_SIGN,
 288                             cksum_data, sizeof(cksum_data),
 289                             p - 8, 8,
 290                             message_buffer->value, message_buffer->length,
 291                             NULL, 0);
 292     if (ret) {
 293         *minor_status = ret;
 294         return GSS_S_FAILURE;
 295     }
 296 
 297     ret = arcfour_mic_key(context, key,
 298                           cksum_data, sizeof(cksum_data),
 299                           k6_data, sizeof(k6_data));
 300     if (ret) {
 301         *minor_status = ret;
 302         return GSS_S_FAILURE;
 303     }
 304 
 305     cmp = memcmp(cksum_data, p + 8, 8);
 306     if (cmp) {
 307         *minor_status = 0;
 308         return GSS_S_BAD_MIC;
 309     }
 310 
 311     {
 312         RC4_KEY rc4_key;
 313         
 314         RC4_set_key (&rc4_key, sizeof(k6_data), (void*)k6_data);
 315         RC4 (&rc4_key, 8, p, SND_SEQ);
 316         
 317         memset(&rc4_key, 0, sizeof(rc4_key));
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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         RC4_KEY rc4_key;
 465 
 466         RC4_set_key (&rc4_key, sizeof(k6_data), (void *)k6_data);
 467         /* XXX ? */
 468         RC4 (&rc4_key, 8 + datalen, p0 + 24, p0 + 24); /* Confounder + data */
 469         memset(&rc4_key, 0, sizeof(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         RC4_KEY rc4_key;
 484         
 485         RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
 486         RC4 (&rc4_key, 8, p0 + 8, p0 + 8); /* SND_SEQ */
 487         memset(&rc4_key, 0, sizeof(rc4_key));
 488         memset(k6_data, 0, sizeof(k6_data));
 489     }
 490 
 491     if (conf_state)
 492         *conf_state = conf_req_flag;
 493 
 494     *minor_status = 0;
 495     return GSS_S_COMPLETE;
 496 }
 497 
 498 OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
 499                                  const gsskrb5_ctx context_handle,
 500                                  krb5_context context,
 501                                  const gss_buffer_t input_message_buffer,
 502                                  gss_buffer_t output_message_buffer,
 503                                  int *conf_state,
 504                                  gss_qop_t *qop_state,
 505                                  krb5_keyblock *key)
 506 {
 507     u_char Klocaldata[16];
 508     krb5_keyblock Klocal;
 509     krb5_error_code ret;
 510     uint32_t seq_number;
 511     size_t datalen;
 512     OM_uint32 omret;
 513     u_char k6_data[16], SND_SEQ[8], Confounder[8];
 514     u_char cksum_data[8];
 515     u_char *p, *p0;
 516     int cmp;
 517     int conf_flag;
 518     size_t padlen = 0, len;
 519 
 520     if (conf_state)
 521         *conf_state = 0;
 522     if (qop_state)
 523         *qop_state = 0;
 524 
 525     p0 = input_message_buffer->value;
 526 
 527     if (IS_DCE_STYLE(context_handle)) {
 528         len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
 529             GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
 530         if (input_message_buffer->length < len)
 531             return GSS_S_BAD_MECH;
 532     } else {
 533         len = input_message_buffer->length;
 534     }
 535 
 536     omret = _gssapi_verify_mech_header(&p0,
 537                                        len,
 538                                        GSS_KRB5_MECHANISM);
 539     if (omret)
 540         return omret;
 541 
 542     /* length of mech header */
 543     len = (p0 - (u_char *)input_message_buffer->value) +
 544         GSS_ARCFOUR_WRAP_TOKEN_SIZE;
 545 
 546     if (len > input_message_buffer->length)
 547         return GSS_S_BAD_MECH;
 548 
 549     /* length of data */
 550     datalen = input_message_buffer->length - len;
 551 
 552     p = p0;
 553 
 554     if (memcmp(p, "\x02\x01", 2) != 0)
 555         return GSS_S_BAD_SIG;
 556     p += 2;
 557     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
 558         return GSS_S_BAD_SIG;
 559     p += 2;
 560 
 561     if (memcmp (p, "\x10\x00", 2) == 0)
 562         conf_flag = 1;
 563     else if (memcmp (p, "\xff\xff", 2) == 0)
 564         conf_flag = 0;
 565     else
 566         return GSS_S_BAD_SIG;
 567 
 568     p += 2;
 569     if (memcmp (p, "\xff\xff", 2) != 0)
 570         return GSS_S_BAD_MIC;
 571     p = NULL;
 572 
 573     ret = arcfour_mic_key(context, key,
 574                           p0 + 16, 8, /* SGN_CKSUM */
 575                           k6_data, sizeof(k6_data));
 576     if (ret) {
 577         *minor_status = ret;
 578         return GSS_S_FAILURE;
 579     }
 580 
 581     {
 582         RC4_KEY rc4_key;
 583         
 584         RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
 585         RC4 (&rc4_key, 8, p0 + 8, SND_SEQ); /* SND_SEQ */
 586         memset(&rc4_key, 0, sizeof(rc4_key));
 587         memset(k6_data, 0, sizeof(k6_data));
 588     }
 589 
 590     _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
 591 
 592     if (context_handle->more_flags & LOCAL)
 593         cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
 594     else
 595         cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
 596 
 597     if (cmp != 0) {
 598         *minor_status = 0;
 599         return GSS_S_BAD_MIC;
 600     }
 601 
 602     {
 603         int i;
 604 
 605         Klocal.keytype = key->keytype;
 606         Klocal.keyvalue.data = Klocaldata;
 607         Klocal.keyvalue.length = sizeof(Klocaldata);
 608 
 609         for (i = 0; i < 16; i++)
 610             Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
 611     }
 612     ret = arcfour_mic_key(context, &Klocal,
 613                           SND_SEQ, 4,
 614                           k6_data, sizeof(k6_data));
 615     memset(Klocaldata, 0, sizeof(Klocaldata));
 616     if (ret) {
 617         *minor_status = ret;
 618         return GSS_S_FAILURE;
 619     }
 620 
 621     output_message_buffer->value = malloc(datalen);
 622     if (output_message_buffer->value == NULL) {
 623         *minor_status = ENOMEM;
 624         return GSS_S_FAILURE;
 625     }
 626     output_message_buffer->length = datalen;
 627 
 628     if(conf_flag) {
 629         RC4_KEY rc4_key;
 630 
 631         RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
 632         RC4 (&rc4_key, 8, p0 + 24, Confounder); /* Confounder */
 633         RC4 (&rc4_key, datalen, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
 634              output_message_buffer->value);
 635         memset(&rc4_key, 0, sizeof(rc4_key));
 636     } else {
 637         memcpy(Confounder, p0 + 24, 8); /* Confounder */
 638         memcpy(output_message_buffer->value,
 639                p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
 640                datalen);
 641     }
 642     memset(k6_data, 0, sizeof(k6_data));
 643 
 644     if (!IS_DCE_STYLE(context_handle)) {
 645         ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
 646         if (ret) {
 647             _gsskrb5_release_buffer(minor_status, output_message_buffer);
 648             *minor_status = 0;
 649             return ret;
 650         }
 651         output_message_buffer->length -= padlen;
 652     }
 653 
 654     ret = arcfour_mic_cksum(context,
 655                             key, KRB5_KU_USAGE_SEAL,
 656                             cksum_data, sizeof(cksum_data),
 657                             p0, 8,
 658                             Confounder, sizeof(Confounder),
 659                             output_message_buffer->value,
 660                             output_message_buffer->length + padlen);
 661     if (ret) {
 662         _gsskrb5_release_buffer(minor_status, output_message_buffer);
 663         *minor_status = ret;
 664         return GSS_S_FAILURE;
 665     }
 666 
 667     cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
 668     if (cmp) {
 669         _gsskrb5_release_buffer(minor_status, output_message_buffer);
 670         *minor_status = 0;
 671         return GSS_S_BAD_MIC;
 672     }
 673 
 674     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
 675     omret = _gssapi_msg_order_check(context_handle->order, seq_number);
 676     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 677     if (omret)
 678         return omret;
 679 
 680     if (conf_state)
 681         *conf_state = conf_flag;
 682 
 683     *minor_status = 0;
 684     return GSS_S_COMPLETE;
 685 }
 686 
 687 static OM_uint32
 688 max_wrap_length_arcfour(const gsskrb5_ctx ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 689                         krb5_crypto crypto,
 690                         size_t input_length,
 691                         OM_uint32 *max_input_size)
 692 {
 693     /*
 694      * if GSS_C_DCE_STYLE is in use:
 695      *  - we only need to encapsulate the WRAP token
 696      * However, since this is a fixed since, we just
 697      */
 698     if (IS_DCE_STYLE(ctx)) {
 699         size_t len, total_len;
 700 
 701         len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
 702         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
 703 
 704         if (input_length < len)
 705             *max_input_size = 0;
 706         else
 707             *max_input_size = input_length - len;
 708 
 709     } else {
 710         size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
 711         size_t blocksize = 8;
 712         size_t len, total_len;
 713 
 714         len = 8 + input_length + blocksize + extrasize;
 715 
 716         _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
 717 
 718         total_len -= input_length; /* token length */
 719         if (total_len < input_length) {
 720             *max_input_size = (input_length - total_len);
 721             (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
 722         } else {
 723             *max_input_size = 0;
 724         }
 725     }
 726 
 727     return GSS_S_COMPLETE;
 728 }
 729 
 730 OM_uint32
 731 _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
     /* [<][>][^][v][top][bottom][index][help] */
 732                           const gsskrb5_ctx ctx,
 733                           krb5_context context,
 734                           int conf_req_flag,
 735                           gss_qop_t qop_req,
 736                           OM_uint32 req_output_size,
 737                           OM_uint32 *max_input_size,
 738                           krb5_keyblock *key)
 739 {
 740     krb5_error_code ret;
 741     krb5_crypto crypto;
 742 
 743     ret = krb5_crypto_init(context, key, 0, &crypto);
 744     if (ret != 0) {
 745         *minor_status = ret;
 746         return GSS_S_FAILURE;
 747     }
 748 
 749     ret = max_wrap_length_arcfour(ctx, crypto,
 750                                   req_output_size, max_input_size);
 751     if (ret != 0) {
 752         *minor_status = ret;
 753         krb5_crypto_destroy(context, crypto);
 754         return GSS_S_FAILURE;
 755     }
 756 
 757     krb5_crypto_destroy(context, crypto);
 758 
 759     return GSS_S_COMPLETE;
 760 }

/* [<][>][^][v][top][bottom][index][help] */