LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/krb5 - arcfour.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 472 755 62.5 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       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      294938 : arcfour_mic_key(krb5_context context, krb5_keyblock *key,
      72             :                 const void *cksum_data, size_t cksum_size,
      73             :                 void *key6_data, size_t key6_size)
      74             : {
      75           0 :     krb5_error_code ret;
      76             : 
      77           0 :     Checksum cksum_k5;
      78           0 :     krb5_keyblock key5;
      79           0 :     char k5_data[16];
      80             : 
      81           0 :     Checksum cksum_k6;
      82             : 
      83           0 :     char T[4];
      84             : 
      85      294938 :     memset(T, 0, 4);
      86      294938 :     cksum_k5.checksum.data = k5_data;
      87      294938 :     cksum_k5.checksum.length = sizeof(k5_data);
      88             : 
      89      294938 :     if (key->keytype == KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56) {
      90           0 :         char L40[14] = "fortybits";
      91             : 
      92           0 :         memcpy(L40 + 10, T, sizeof(T));
      93           0 :         ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
      94             :                         L40, 14, 0, key, &cksum_k5);
      95           0 :         memset(&k5_data[7], 0xAB, 9);
      96             :     } else {
      97      294938 :         ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
      98             :                         T, 4, 0, key, &cksum_k5);
      99             :     }
     100      294938 :     if (ret)
     101           0 :         return ret;
     102             : 
     103      294938 :     key5.keytype = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5;
     104      294938 :     key5.keyvalue = cksum_k5.checksum;
     105             : 
     106      294938 :     cksum_k6.checksum.data = key6_data;
     107      294938 :     cksum_k6.checksum.length = key6_size;
     108             : 
     109      294938 :     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      162640 : arcfour_mic_cksum_iov(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 gss_iov_buffer_desc *iov,
     121             :                       int iov_count,
     122             :                       const gss_iov_buffer_desc *padding)
     123             : {
     124           0 :     Checksum CKSUM;
     125           0 :     u_char *ptr;
     126           0 :     size_t len;
     127      162640 :     size_t ofs = 0;
     128           0 :     int i;
     129           0 :     krb5_crypto crypto;
     130           0 :     krb5_error_code ret;
     131             : 
     132      162640 :     assert(sgn_cksum_sz == 8);
     133             : 
     134      162640 :     len = l1 + l2;
     135             : 
     136      414176 :     for (i=0; i < iov_count; i++) {
     137      251536 :         switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
     138      221904 :         case GSS_IOV_BUFFER_TYPE_DATA:
     139             :         case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
     140      221904 :             break;
     141       29632 :         default:
     142       29632 :             continue;
     143             :         }
     144             : 
     145      221904 :         len += iov[i].buffer.length;
     146             :     }
     147             : 
     148      162640 :     if (padding) {
     149           0 :         len += padding->buffer.length;
     150             :     }
     151             : 
     152      162640 :     ptr = malloc(len);
     153      162640 :     if (ptr == NULL)
     154           0 :         return ENOMEM;
     155             : 
     156      162640 :     memcpy(ptr + ofs, v1, l1);
     157      162640 :     ofs += l1;
     158      162640 :     memcpy(ptr + ofs, v2, l2);
     159      162640 :     ofs += l2;
     160             : 
     161      414176 :     for (i=0; i < iov_count; i++) {
     162      251536 :         switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
     163      221904 :         case GSS_IOV_BUFFER_TYPE_DATA:
     164             :         case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
     165      221904 :             break;
     166       29632 :         default:
     167       29632 :             continue;
     168             :         }
     169             : 
     170      221904 :         if (iov[i].buffer.length > 0) {
     171      191526 :             assert(iov[i].buffer.value != NULL);
     172      191526 :             memcpy(ptr + ofs,
     173      191526 :                    iov[i].buffer.value,
     174      191526 :                    iov[i].buffer.length);
     175      191526 :             ofs += iov[i].buffer.length;
     176             :         }
     177             :     }
     178             : 
     179      162640 :     if (padding) {
     180           0 :         memcpy(ptr + ofs,
     181           0 :                padding->buffer.value,
     182           0 :                padding->buffer.length);
     183             :         /* ofs += padding->buffer.length; */
     184             :     }
     185             : 
     186      162640 :     ret = krb5_crypto_init(context, key, 0, &crypto);
     187      162640 :     if (ret) {
     188           0 :         free(ptr);
     189           0 :         return ret;
     190             :     }
     191             : 
     192      162640 :     ret = krb5_create_checksum(context,
     193             :                                crypto,
     194             :                                usage,
     195             :                                0,
     196             :                                ptr, len,
     197             :                                &CKSUM);
     198      162640 :     memset(ptr, 0, len);
     199      162640 :     free(ptr);
     200      162640 :     if (ret == 0) {
     201      162640 :         memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
     202      162640 :         free_Checksum(&CKSUM);
     203             :     }
     204      162640 :     krb5_crypto_destroy(context, crypto);
     205             : 
     206      162640 :     return ret;
     207             : }
     208             : 
     209             : static krb5_error_code
     210      133008 : arcfour_mic_cksum(krb5_context context,
     211             :                   krb5_keyblock *key, unsigned usage,
     212             :                   u_char *sgn_cksum, size_t sgn_cksum_sz,
     213             :                   const u_char *v1, size_t l1,
     214             :                   const void *v2, size_t l2,
     215             :                   const void *v3, size_t l3)
     216             : {
     217           0 :     gss_iov_buffer_desc iov;
     218             : 
     219      133008 :     iov.type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
     220      133008 :     iov.buffer.value = rk_UNCONST(v3);
     221      133008 :     iov.buffer.length = l3;
     222             : 
     223      133008 :     return arcfour_mic_cksum_iov(context, key, usage,
     224             :                                  sgn_cksum, sgn_cksum_sz,
     225             :                                  v1, l1, v2, l2,
     226             :                                  &iov, 1, NULL);
     227             : }
     228             : 
     229             : 
     230             : OM_uint32
     231       15169 : _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
     232             :                         const gsskrb5_ctx context_handle,
     233             :                         krb5_context context,
     234             :                         gss_qop_t qop_req,
     235             :                         const gss_buffer_t message_buffer,
     236             :                         gss_buffer_t message_token,
     237             :                         krb5_keyblock *key)
     238             : {
     239           0 :     krb5_error_code ret;
     240           0 :     int32_t seq_number;
     241           0 :     size_t len, total_len;
     242           0 :     u_char k6_data[16], *p0, *p;
     243           0 :     EVP_CIPHER_CTX rc4_key;
     244             : 
     245       15169 :     _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
     246             : 
     247       15169 :     message_token->length = total_len;
     248       15169 :     message_token->value  = malloc (total_len);
     249       15169 :     if (message_token->value == NULL) {
     250           0 :         *minor_status = ENOMEM;
     251           0 :         return GSS_S_FAILURE;
     252             :     }
     253             : 
     254       15169 :     p0 = _gssapi_make_mech_header(message_token->value,
     255             :                                   len,
     256             :                                   GSS_KRB5_MECHANISM);
     257       15169 :     p = p0;
     258             : 
     259       15169 :     *p++ = 0x01; /* TOK_ID */
     260       15169 :     *p++ = 0x01;
     261       15169 :     *p++ = 0x11; /* SGN_ALG */
     262       15169 :     *p++ = 0x00;
     263       15169 :     *p++ = 0xff; /* Filler */
     264       15169 :     *p++ = 0xff;
     265       15169 :     *p++ = 0xff;
     266       15169 :     *p++ = 0xff;
     267             : 
     268       15169 :     p = NULL;
     269             : 
     270       15169 :     ret = arcfour_mic_cksum(context,
     271             :                             key, KRB5_KU_USAGE_SIGN,
     272             :                             p0 + 16, 8,  /* SGN_CKSUM */
     273             :                             p0, 8, /* TOK_ID, SGN_ALG, Filer */
     274       15169 :                             message_buffer->value, message_buffer->length,
     275             :                             NULL, 0);
     276       15169 :     if (ret) {
     277           0 :         _gsskrb5_release_buffer(minor_status, message_token);
     278           0 :         *minor_status = ret;
     279           0 :         return GSS_S_FAILURE;
     280             :     }
     281             : 
     282       15169 :     ret = arcfour_mic_key(context, key,
     283       15169 :                           p0 + 16, 8, /* SGN_CKSUM */
     284             :                           k6_data, sizeof(k6_data));
     285       15169 :     if (ret) {
     286           0 :         _gsskrb5_release_buffer(minor_status, message_token);
     287           0 :         *minor_status = ret;
     288           0 :         return GSS_S_FAILURE;
     289             :     }
     290             : 
     291           0 :     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     292       15169 :     krb5_auth_con_getlocalseqnumber (context,
     293             :                                      context_handle->auth_context,
     294             :                                      &seq_number);
     295       15169 :     p = p0 + 8; /* SND_SEQ */
     296       15169 :     _gss_mg_encode_be_uint32(seq_number, p);
     297             : 
     298       15169 :     krb5_auth_con_setlocalseqnumber (context,
     299             :                                      context_handle->auth_context,
     300             :                                      ++seq_number);
     301           0 :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     302             : 
     303       15169 :     memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
     304             : 
     305       15169 :     EVP_CIPHER_CTX_init(&rc4_key);
     306       15169 :     EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
     307       15169 :     EVP_Cipher(&rc4_key, p, p, 8);
     308       15169 :     EVP_CIPHER_CTX_cleanup(&rc4_key);
     309             : 
     310       15169 :     memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
     311             : 
     312       15169 :     *minor_status = 0;
     313       15169 :     return GSS_S_COMPLETE;
     314             : }
     315             : 
     316             : 
     317             : OM_uint32
     318       15173 : _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
     319             :                            const gsskrb5_ctx context_handle,
     320             :                            krb5_context context,
     321             :                            const gss_buffer_t message_buffer,
     322             :                            const gss_buffer_t token_buffer,
     323             :                            gss_qop_t * qop_state,
     324             :                            krb5_keyblock *key,
     325             :                            const char *type)
     326             : {
     327           0 :     krb5_error_code ret;
     328           0 :     uint32_t seq_number;
     329           0 :     OM_uint32 omret;
     330           0 :     u_char SND_SEQ[8], cksum_data[8], *p;
     331           0 :     char k6_data[16];
     332           0 :     int cmp;
     333             : 
     334       15173 :     if (qop_state)
     335       15173 :         *qop_state = 0;
     336             : 
     337       15173 :     p = token_buffer->value;
     338       15173 :     omret = _gsskrb5_verify_header (&p,
     339             :                                        token_buffer->length,
     340             :                                        type,
     341             :                                        GSS_KRB5_MECHANISM);
     342       15173 :     if (omret)
     343           0 :         return omret;
     344             : 
     345       15173 :     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
     346           0 :         return GSS_S_BAD_SIG;
     347       15173 :     p += 2;
     348       15173 :     if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
     349           0 :         return GSS_S_BAD_MIC;
     350       15173 :     p += 4;
     351             : 
     352       15173 :     ret = arcfour_mic_cksum(context,
     353             :                             key, KRB5_KU_USAGE_SIGN,
     354             :                             cksum_data, sizeof(cksum_data),
     355       15173 :                             p - 8, 8,
     356       15173 :                             message_buffer->value, message_buffer->length,
     357             :                             NULL, 0);
     358       15173 :     if (ret) {
     359           0 :         *minor_status = ret;
     360           0 :         return GSS_S_FAILURE;
     361             :     }
     362             : 
     363       15173 :     ret = arcfour_mic_key(context, key,
     364             :                           cksum_data, sizeof(cksum_data),
     365             :                           k6_data, sizeof(k6_data));
     366       15173 :     if (ret) {
     367           0 :         *minor_status = ret;
     368           0 :         return GSS_S_FAILURE;
     369             :     }
     370             : 
     371       15173 :     cmp = (ct_memcmp(cksum_data, p + 8, 8) != 0);
     372       15173 :     if (cmp) {
     373           0 :         *minor_status = 0;
     374           0 :         return GSS_S_BAD_MIC;
     375             :     }
     376             : 
     377             :     {
     378           0 :         EVP_CIPHER_CTX rc4_key;
     379             : 
     380       15173 :         EVP_CIPHER_CTX_init(&rc4_key);
     381       15173 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
     382       15173 :         EVP_Cipher(&rc4_key, SND_SEQ, p, 8);
     383       15173 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
     384             : 
     385       15173 :         memset(k6_data, 0, sizeof(k6_data));
     386             :     }
     387             : 
     388       15173 :     _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
     389             : 
     390       15173 :     if (context_handle->more_flags & LOCAL)
     391        2528 :         cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
     392             :     else
     393       12645 :         cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
     394             : 
     395       15173 :     memset_s(SND_SEQ, sizeof(SND_SEQ), 0, sizeof(SND_SEQ));
     396       15173 :     if (cmp != 0) {
     397           0 :         *minor_status = 0;
     398           0 :         return GSS_S_BAD_MIC;
     399             :     }
     400             : 
     401           0 :     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     402       15173 :     omret = _gssapi_msg_order_check(context_handle->order, seq_number);
     403           0 :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     404       15173 :     if (omret)
     405           0 :         return omret;
     406             : 
     407       15173 :     *minor_status = 0;
     408       15173 :     return GSS_S_COMPLETE;
     409             : }
     410             : 
     411             : OM_uint32
     412       51333 : _gssapi_wrap_arcfour(OM_uint32 * minor_status,
     413             :                      const gsskrb5_ctx context_handle,
     414             :                      krb5_context context,
     415             :                      int conf_req_flag,
     416             :                      gss_qop_t qop_req,
     417             :                      const gss_buffer_t input_message_buffer,
     418             :                      int * conf_state,
     419             :                      gss_buffer_t output_message_buffer,
     420             :                      krb5_keyblock *key)
     421             : {
     422           0 :     u_char Klocaldata[16], k6_data[16], *p, *p0;
     423           0 :     size_t len, total_len, datalen;
     424           0 :     krb5_keyblock Klocal;
     425           0 :     krb5_error_code ret;
     426           0 :     int32_t seq_number;
     427             : 
     428       51333 :     if (conf_state)
     429       51333 :         *conf_state = 0;
     430             : 
     431       51333 :     datalen = input_message_buffer->length;
     432             : 
     433       51333 :     if (IS_DCE_STYLE(context_handle)) {
     434           0 :         len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     435           0 :         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     436           0 :         total_len += datalen;
     437             :     } else {
     438       51333 :         datalen += 1; /* padding */
     439       51333 :         len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     440       51333 :         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     441             :     }
     442             : 
     443       51333 :     output_message_buffer->length = total_len;
     444       51333 :     output_message_buffer->value  = malloc (total_len);
     445       51333 :     if (output_message_buffer->value == NULL) {
     446           0 :         *minor_status = ENOMEM;
     447           0 :         return GSS_S_FAILURE;
     448             :     }
     449             : 
     450       51333 :     p0 = _gssapi_make_mech_header(output_message_buffer->value,
     451             :                                   len,
     452             :                                   GSS_KRB5_MECHANISM);
     453       51333 :     p = p0;
     454             : 
     455       51333 :     *p++ = 0x02; /* TOK_ID */
     456       51333 :     *p++ = 0x01;
     457       51333 :     *p++ = 0x11; /* SGN_ALG */
     458       51333 :     *p++ = 0x00;
     459       51333 :     if (conf_req_flag) {
     460       51305 :         *p++ = 0x10; /* SEAL_ALG */
     461       51305 :         *p++ = 0x00;
     462             :     } else {
     463          28 :         *p++ = 0xff; /* SEAL_ALG */
     464          28 :         *p++ = 0xff;
     465             :     }
     466       51333 :     *p++ = 0xff; /* Filler */
     467       51333 :     *p++ = 0xff;
     468             : 
     469       51333 :     p = NULL;
     470             : 
     471           0 :     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     472       51333 :     krb5_auth_con_getlocalseqnumber (context,
     473             :                                      context_handle->auth_context,
     474             :                                      &seq_number);
     475             : 
     476       51333 :     _gss_mg_encode_be_uint32(seq_number, p0 + 8);
     477             : 
     478       51333 :     krb5_auth_con_setlocalseqnumber (context,
     479             :                                      context_handle->auth_context,
     480             :                                      ++seq_number);
     481           0 :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     482             : 
     483       51333 :     memset (p0 + 8 + 4,
     484       51333 :             (context_handle->more_flags & LOCAL) ? 0 : 0xff,
     485             :             4);
     486             : 
     487       51333 :     krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
     488             : 
     489             :     /* p points to data */
     490       51333 :     p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     491       51333 :     memcpy(p, input_message_buffer->value, input_message_buffer->length);
     492             : 
     493       51333 :     if (!IS_DCE_STYLE(context_handle))
     494       51333 :         p[input_message_buffer->length] = 1; /* padding */
     495             : 
     496       51333 :     ret = arcfour_mic_cksum(context,
     497             :                             key, KRB5_KU_USAGE_SEAL,
     498             :                             p0 + 16, 8, /* SGN_CKSUM */
     499             :                             p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
     500       51333 :                             p0 + 24, 8, /* Confounder */
     501       51333 :                             p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
     502             :                             datalen);
     503       51333 :     if (ret) {
     504           0 :         *minor_status = ret;
     505           0 :         _gsskrb5_release_buffer(minor_status, output_message_buffer);
     506           0 :         return GSS_S_FAILURE;
     507             :     }
     508             : 
     509             :     {
     510           0 :         int i;
     511             : 
     512       51333 :         Klocal.keytype = key->keytype;
     513       51333 :         Klocal.keyvalue.data = Klocaldata;
     514       51333 :         Klocal.keyvalue.length = sizeof(Klocaldata);
     515             : 
     516      872661 :         for (i = 0; i < 16; i++)
     517      821328 :             Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
     518             :     }
     519       51333 :     ret = arcfour_mic_key(context, &Klocal,
     520       51333 :                           p0 + 8, 4, /* SND_SEQ */
     521             :                           k6_data, sizeof(k6_data));
     522       51333 :     memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
     523       51333 :     if (ret) {
     524           0 :         _gsskrb5_release_buffer(minor_status, output_message_buffer);
     525           0 :         *minor_status = ret;
     526           0 :         return GSS_S_FAILURE;
     527             :     }
     528             : 
     529             : 
     530       51333 :     if(conf_req_flag) {
     531           0 :         EVP_CIPHER_CTX rc4_key;
     532             : 
     533       51305 :         EVP_CIPHER_CTX_init(&rc4_key);
     534       51305 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
     535       51305 :         EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen);
     536       51305 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
     537             :     }
     538       51333 :     memset(k6_data, 0, sizeof(k6_data));
     539             : 
     540       51333 :     ret = arcfour_mic_key(context, key,
     541       51333 :                           p0 + 16, 8, /* SGN_CKSUM */
     542             :                           k6_data, sizeof(k6_data));
     543       51333 :     if (ret) {
     544           0 :         _gsskrb5_release_buffer(minor_status, output_message_buffer);
     545           0 :         *minor_status = ret;
     546           0 :         return GSS_S_FAILURE;
     547             :     }
     548             : 
     549             :     {
     550           0 :         EVP_CIPHER_CTX rc4_key;
     551             : 
     552       51333 :         EVP_CIPHER_CTX_init(&rc4_key);
     553       51333 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
     554       51333 :         EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
     555       51333 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
     556       51333 :         memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
     557             :     }
     558             : 
     559       51333 :     if (conf_state)
     560       51333 :         *conf_state = conf_req_flag;
     561             : 
     562       51333 :     *minor_status = 0;
     563       51333 :     return GSS_S_COMPLETE;
     564             : }
     565             : 
     566       51333 : OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
     567             :                                  const gsskrb5_ctx context_handle,
     568             :                                  krb5_context context,
     569             :                                  const gss_buffer_t input_message_buffer,
     570             :                                  gss_buffer_t output_message_buffer,
     571             :                                  int *conf_state,
     572             :                                  gss_qop_t *qop_state,
     573             :                                  krb5_keyblock *key)
     574             : {
     575           0 :     u_char Klocaldata[16];
     576           0 :     krb5_keyblock Klocal;
     577           0 :     krb5_error_code ret;
     578           0 :     uint32_t seq_number;
     579           0 :     size_t datalen;
     580           0 :     OM_uint32 omret;
     581           0 :     u_char k6_data[16], SND_SEQ[8], Confounder[8];
     582           0 :     u_char cksum_data[8];
     583           0 :     u_char *p, *p0;
     584           0 :     int cmp;
     585           0 :     int conf_flag;
     586       51333 :     size_t padlen = 0, len;
     587             : 
     588       51333 :     if (conf_state)
     589       51333 :         *conf_state = 0;
     590       51333 :     if (qop_state)
     591       51333 :         *qop_state = 0;
     592             : 
     593       51333 :     p0 = input_message_buffer->value;
     594             : 
     595       51333 :     if (IS_DCE_STYLE(context_handle)) {
     596           0 :         len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
     597             :             GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
     598           0 :         if (input_message_buffer->length < len)
     599           0 :             return GSS_S_BAD_MECH;
     600             :     } else {
     601       51333 :         len = input_message_buffer->length;
     602             :     }
     603             : 
     604       51333 :     omret = _gssapi_verify_mech_header(&p0,
     605             :                                        len,
     606             :                                        GSS_KRB5_MECHANISM);
     607       51333 :     if (omret)
     608           0 :         return omret;
     609             : 
     610             :     /* length of mech header */
     611       51333 :     len = (p0 - (u_char *)input_message_buffer->value) +
     612             :         GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     613             : 
     614       51333 :     if (len > input_message_buffer->length)
     615           0 :         return GSS_S_BAD_MECH;
     616             : 
     617             :     /* length of data */
     618       51333 :     datalen = input_message_buffer->length - len;
     619             : 
     620       51333 :     p = p0;
     621             : 
     622       51333 :     if (memcmp(p, "\x02\x01", 2) != 0)
     623           0 :         return GSS_S_BAD_SIG;
     624       51333 :     p += 2;
     625       51333 :     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
     626           0 :         return GSS_S_BAD_SIG;
     627       51333 :     p += 2;
     628             : 
     629       51333 :     if (memcmp (p, "\x10\x00", 2) == 0)
     630       51305 :         conf_flag = 1;
     631          28 :     else if (memcmp (p, "\xff\xff", 2) == 0)
     632          28 :         conf_flag = 0;
     633             :     else
     634           0 :         return GSS_S_BAD_SIG;
     635             : 
     636       51333 :     p += 2;
     637       51333 :     if (memcmp (p, "\xff\xff", 2) != 0)
     638           0 :         return GSS_S_BAD_MIC;
     639       51333 :     p = NULL;
     640             : 
     641       51333 :     ret = arcfour_mic_key(context, key,
     642       51333 :                           p0 + 16, 8, /* SGN_CKSUM */
     643             :                           k6_data, sizeof(k6_data));
     644       51333 :     if (ret) {
     645           0 :         *minor_status = ret;
     646           0 :         return GSS_S_FAILURE;
     647             :     }
     648             : 
     649             :     {
     650           0 :         EVP_CIPHER_CTX rc4_key;
     651             : 
     652       51333 :         EVP_CIPHER_CTX_init(&rc4_key);
     653       51333 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
     654       51333 :         EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8);
     655       51333 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
     656       51333 :         memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
     657             :     }
     658             : 
     659       51333 :     _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
     660             : 
     661       51333 :     if (context_handle->more_flags & LOCAL)
     662       25669 :         cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
     663             :     else
     664       25664 :         cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
     665             : 
     666       51333 :     if (cmp != 0) {
     667           0 :         *minor_status = 0;
     668           0 :         return GSS_S_BAD_MIC;
     669             :     }
     670             : 
     671             :     {
     672           0 :         int i;
     673             : 
     674       51333 :         Klocal.keytype = key->keytype;
     675       51333 :         Klocal.keyvalue.data = Klocaldata;
     676       51333 :         Klocal.keyvalue.length = sizeof(Klocaldata);
     677             : 
     678      872661 :         for (i = 0; i < 16; i++)
     679      821328 :             Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
     680             :     }
     681       51333 :     ret = arcfour_mic_key(context, &Klocal,
     682             :                           SND_SEQ, 4,
     683             :                           k6_data, sizeof(k6_data));
     684       51333 :     memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
     685       51333 :     if (ret) {
     686           0 :         *minor_status = ret;
     687           0 :         return GSS_S_FAILURE;
     688             :     }
     689             : 
     690       51333 :     output_message_buffer->value = malloc(datalen);
     691       51333 :     if (output_message_buffer->value == NULL) {
     692           0 :         *minor_status = ENOMEM;
     693           0 :         return GSS_S_FAILURE;
     694             :     }
     695       51333 :     output_message_buffer->length = datalen;
     696             : 
     697       51333 :     if(conf_flag) {
     698           0 :         EVP_CIPHER_CTX rc4_key;
     699             : 
     700       51305 :         EVP_CIPHER_CTX_init(&rc4_key);
     701       51305 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
     702       51305 :         EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
     703       51305 :         EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
     704       51305 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
     705             :     } else {
     706          28 :         memcpy(Confounder, p0 + 24, 8); /* Confounder */
     707          28 :         memcpy(output_message_buffer->value,
     708          28 :                p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
     709             :                datalen);
     710             :     }
     711       51333 :     memset(k6_data, 0, sizeof(k6_data));
     712             : 
     713       51333 :     if (!IS_DCE_STYLE(context_handle)) {
     714       51333 :         ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
     715       51333 :         if (ret) {
     716           0 :             _gsskrb5_release_buffer(minor_status, output_message_buffer);
     717           0 :             *minor_status = 0;
     718           0 :             return ret;
     719             :         }
     720       51333 :         output_message_buffer->length -= padlen;
     721             :     }
     722             : 
     723       51333 :     ret = arcfour_mic_cksum(context,
     724             :                             key, KRB5_KU_USAGE_SEAL,
     725             :                             cksum_data, sizeof(cksum_data),
     726             :                             p0, 8,
     727             :                             Confounder, sizeof(Confounder),
     728       51333 :                             output_message_buffer->value,
     729       51333 :                             output_message_buffer->length + padlen);
     730       51333 :     if (ret) {
     731           0 :         _gsskrb5_release_buffer(minor_status, output_message_buffer);
     732           0 :         *minor_status = ret;
     733           0 :         return GSS_S_FAILURE;
     734             :     }
     735             : 
     736       51333 :     cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
     737       51333 :     if (cmp) {
     738           0 :         _gsskrb5_release_buffer(minor_status, output_message_buffer);
     739           0 :         *minor_status = 0;
     740           0 :         return GSS_S_BAD_MIC;
     741             :     }
     742             : 
     743           0 :     HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     744       51333 :     omret = _gssapi_msg_order_check(context_handle->order, seq_number);
     745           0 :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     746       51333 :     if (omret)
     747           0 :         return omret;
     748             : 
     749       51333 :     if (conf_state)
     750       51333 :         *conf_state = conf_flag;
     751             : 
     752       51333 :     *minor_status = 0;
     753       51333 :     return GSS_S_COMPLETE;
     754             : }
     755             : 
     756             : static OM_uint32
     757        1496 : max_wrap_length_arcfour(const gsskrb5_ctx ctx,
     758             :                         krb5_crypto crypto,
     759             :                         size_t input_length,
     760             :                         OM_uint32 *max_input_size)
     761             : {
     762             :     /*
     763             :      * if GSS_C_DCE_STYLE is in use:
     764             :      *  - we only need to encapsulate the WRAP token
     765             :      * However, since this is a fixed since, we just
     766             :      */
     767        1496 :     if (IS_DCE_STYLE(ctx)) {
     768           0 :         size_t len, total_len;
     769             : 
     770           0 :         len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     771           0 :         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     772             : 
     773           0 :         if (input_length < len)
     774           0 :             *max_input_size = 0;
     775             :         else
     776           0 :             *max_input_size = input_length - len;
     777             : 
     778             :     } else {
     779        1496 :         size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     780        1496 :         size_t blocksize = 8;
     781           0 :         size_t len, total_len;
     782             : 
     783        1496 :         len = 8 + input_length + blocksize + extrasize;
     784             : 
     785        1496 :         _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     786             : 
     787        1496 :         total_len -= input_length; /* token length */
     788        1496 :         if (total_len < input_length) {
     789        1496 :             *max_input_size = (input_length - total_len);
     790        1496 :             (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
     791             :         } else {
     792           0 :             *max_input_size = 0;
     793             :         }
     794             :     }
     795             : 
     796        1496 :     return GSS_S_COMPLETE;
     797             : }
     798             : 
     799             : OM_uint32
     800        1496 : _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
     801             :                           const gsskrb5_ctx ctx,
     802             :                           krb5_context context,
     803             :                           int conf_req_flag,
     804             :                           gss_qop_t qop_req,
     805             :                           OM_uint32 req_output_size,
     806             :                           OM_uint32 *max_input_size,
     807             :                           krb5_keyblock *key)
     808             : {
     809           0 :     krb5_error_code ret;
     810           0 :     krb5_crypto crypto;
     811             : 
     812        1496 :     ret = krb5_crypto_init(context, key, 0, &crypto);
     813        1496 :     if (ret != 0) {
     814           0 :         *minor_status = ret;
     815           0 :         return GSS_S_FAILURE;
     816             :     }
     817             : 
     818        1496 :     ret = max_wrap_length_arcfour(ctx, crypto,
     819             :                                   req_output_size, max_input_size);
     820        1496 :     if (ret != 0) {
     821           0 :         *minor_status = ret;
     822           0 :         krb5_crypto_destroy(context, crypto);
     823           0 :         return GSS_S_FAILURE;
     824             :     }
     825             : 
     826        1496 :     krb5_crypto_destroy(context, crypto);
     827             : 
     828        1496 :     return GSS_S_COMPLETE;
     829             : }
     830             : 
     831             : OM_uint32
     832         628 : _gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status,
     833             :                                 gsskrb5_ctx ctx,
     834             :                                 krb5_context context,
     835             :                                 int conf_req_flag,
     836             :                                 gss_qop_t qop_req,
     837             :                                 int *conf_state,
     838             :                                 gss_iov_buffer_desc *iov,
     839             :                                 int iov_count)
     840             : {
     841           0 :     OM_uint32 major_status;
     842         628 :     size_t data_len = 0;
     843           0 :     int i;
     844         628 :     gss_iov_buffer_desc *header = NULL;
     845         628 :     gss_iov_buffer_desc *padding = NULL;
     846         628 :     gss_iov_buffer_desc *trailer = NULL;
     847             : 
     848         628 :     *minor_status = 0;
     849             : 
     850        1884 :     for (i = 0; i < iov_count; i++) {
     851        1256 :         switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
     852           0 :         case GSS_IOV_BUFFER_TYPE_EMPTY:
     853           0 :             break;
     854         628 :         case GSS_IOV_BUFFER_TYPE_DATA:
     855         628 :             data_len += iov[i].buffer.length;
     856         628 :             break;
     857         628 :         case GSS_IOV_BUFFER_TYPE_HEADER:
     858         628 :             if (header != NULL) {
     859           0 :                 *minor_status = EINVAL;
     860           0 :                 return GSS_S_FAILURE;
     861             :             }
     862         628 :             header = &iov[i];
     863         628 :             break;
     864           0 :         case GSS_IOV_BUFFER_TYPE_TRAILER:
     865           0 :             if (trailer != NULL) {
     866           0 :                 *minor_status = EINVAL;
     867           0 :                 return GSS_S_FAILURE;
     868             :             }
     869           0 :             trailer = &iov[i];
     870           0 :             break;
     871           0 :         case GSS_IOV_BUFFER_TYPE_PADDING:
     872           0 :             if (padding != NULL) {
     873           0 :                 *minor_status = EINVAL;
     874           0 :                 return GSS_S_FAILURE;
     875             :             }
     876           0 :             padding = &iov[i];
     877           0 :             break;
     878           0 :         case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
     879           0 :             break;
     880           0 :         default:
     881           0 :             *minor_status = EINVAL;
     882           0 :             return GSS_S_FAILURE;
     883             :         }
     884             :     }
     885             : 
     886         628 :     if (header == NULL) {
     887           0 :         *minor_status = EINVAL;
     888           0 :         return GSS_S_FAILURE;
     889             :     }
     890             : 
     891         628 :     major_status = _gk_verify_buffers(minor_status, ctx, header,
     892             :                                       padding, trailer, FALSE);
     893         628 :     if (major_status != GSS_S_COMPLETE) {
     894           0 :             return major_status;
     895             :     }
     896             : 
     897         628 :     if (IS_DCE_STYLE(ctx)) {
     898         628 :         size_t len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     899           0 :         size_t total_len;
     900         628 :         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     901         628 :         header->buffer.length = total_len;
     902             :     } else {
     903           0 :         size_t len;
     904           0 :         size_t total_len;
     905           0 :         if (padding) {
     906           0 :             data_len += 1; /* padding */
     907             :         }
     908           0 :         len = data_len + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     909           0 :         _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
     910           0 :         header->buffer.length = total_len - data_len;
     911             :     }
     912             : 
     913         628 :     if (trailer) {
     914           0 :         trailer->buffer.length = 0;
     915             :     }
     916             : 
     917         628 :     if (padding) {
     918           0 :         padding->buffer.length = 1;
     919             :     }
     920             : 
     921         628 :     return GSS_S_COMPLETE;
     922             : }
     923             : 
     924             : OM_uint32
     925       17564 : _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
     926             :                          gsskrb5_ctx ctx,
     927             :                          krb5_context context,
     928             :                          int conf_req_flag,
     929             :                          int *conf_state,
     930             :                          gss_iov_buffer_desc *iov,
     931             :                          int iov_count,
     932             :                          krb5_keyblock *key)
     933             : {
     934           0 :     OM_uint32 major_status, junk;
     935           0 :     gss_iov_buffer_desc *header, *padding, *trailer;
     936           0 :     krb5_error_code kret;
     937           0 :     int32_t seq_number;
     938           0 :     u_char Klocaldata[16], k6_data[16], *p, *p0;
     939       17564 :     size_t make_len = 0;
     940       17564 :     size_t header_len = 0;
     941       17564 :     size_t data_len = 0;
     942           0 :     krb5_keyblock Klocal;
     943           0 :     int i;
     944             : 
     945       17564 :     header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
     946       17564 :     padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
     947       17564 :     trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
     948             : 
     949       17564 :     major_status = _gk_verify_buffers(minor_status, ctx, header,
     950             :                                       padding, trailer, FALSE);
     951       17564 :     if (major_status != GSS_S_COMPLETE) {
     952           0 :         return major_status;
     953             :     }
     954             : 
     955       87820 :     for (i = 0; i < iov_count; i++) {
     956       70256 :         switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
     957       17564 :         case GSS_IOV_BUFFER_TYPE_DATA:
     958       17564 :             break;
     959       52692 :         default:
     960       52692 :             continue;
     961             :         }
     962             : 
     963       17564 :         data_len += iov[i].buffer.length;
     964             :     }
     965             : 
     966       17564 :     if (padding) {
     967           0 :         data_len += 1;
     968             :     }
     969             : 
     970       17564 :     if (IS_DCE_STYLE(ctx)) {
     971           0 :         size_t unwrapped_len;
     972       17564 :         unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
     973       17564 :         _gssapi_encap_length(unwrapped_len,
     974             :                              &make_len,
     975             :                              &header_len,
     976             :                              GSS_KRB5_MECHANISM);
     977             :     } else {
     978           0 :         size_t unwrapped_len;
     979           0 :         unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + data_len;
     980           0 :         _gssapi_encap_length(unwrapped_len,
     981             :                              &make_len,
     982             :                              &header_len,
     983             :                              GSS_KRB5_MECHANISM);
     984           0 :         header_len -= data_len;
     985             :     }
     986             : 
     987       17564 :     if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
     988           0 :         major_status = _gk_allocate_buffer(minor_status, header,
     989             :                                            header_len);
     990           0 :         if (major_status != GSS_S_COMPLETE)
     991           0 :             goto failure;
     992       17564 :     } else if (header->buffer.length < header_len) {
     993           0 :         *minor_status = KRB5_BAD_MSIZE;
     994           0 :         major_status = GSS_S_FAILURE;
     995           0 :         goto failure;
     996             :     } else {
     997       17564 :         header->buffer.length = header_len;
     998             :     }
     999             : 
    1000       17564 :     if (padding) {
    1001           0 :         if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
    1002           0 :             major_status = _gk_allocate_buffer(minor_status, padding, 1);
    1003           0 :             if (major_status != GSS_S_COMPLETE)
    1004           0 :                 goto failure;
    1005           0 :         } else if (padding->buffer.length < 1) {
    1006           0 :             *minor_status = KRB5_BAD_MSIZE;
    1007           0 :             major_status = GSS_S_FAILURE;
    1008           0 :             goto failure;
    1009             :         } else {
    1010           0 :             padding->buffer.length = 1;
    1011             :         }
    1012           0 :         memset(padding->buffer.value, 1, 1);
    1013             :     }
    1014             : 
    1015       17564 :     if (trailer) {
    1016           0 :         trailer->buffer.length = 0;
    1017           0 :         trailer->buffer.value = NULL;
    1018             :     }
    1019             : 
    1020       17564 :     p0 = _gssapi_make_mech_header(header->buffer.value,
    1021             :                                   make_len,
    1022             :                                   GSS_KRB5_MECHANISM);
    1023       17564 :     p = p0;
    1024             : 
    1025       17564 :     *p++ = 0x02; /* TOK_ID */
    1026       17564 :     *p++ = 0x01;
    1027       17564 :     *p++ = 0x11; /* SGN_ALG */
    1028       17564 :     *p++ = 0x00;
    1029       17564 :     if (conf_req_flag) {
    1030       17564 :         *p++ = 0x10; /* SEAL_ALG */
    1031       17564 :         *p++ = 0x00;
    1032             :     } else {
    1033           0 :         *p++ = 0xff; /* SEAL_ALG */
    1034           0 :         *p++ = 0xff;
    1035             :     }
    1036       17564 :     *p++ = 0xff; /* Filler */
    1037       17564 :     *p++ = 0xff;
    1038             : 
    1039       17564 :     p = NULL;
    1040             : 
    1041           0 :     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
    1042       17564 :     krb5_auth_con_getlocalseqnumber(context,
    1043             :                                     ctx->auth_context,
    1044             :                                     &seq_number);
    1045       17564 :     _gss_mg_encode_be_uint32(seq_number, p0 + 8);
    1046             : 
    1047       17564 :     krb5_auth_con_setlocalseqnumber(context,
    1048             :                                     ctx->auth_context,
    1049             :                                     ++seq_number);
    1050           0 :     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    1051             : 
    1052       17564 :     memset(p0 + 8 + 4,
    1053       17564 :            (ctx->more_flags & LOCAL) ? 0 : 0xff,
    1054             :            4);
    1055             : 
    1056       17564 :     krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
    1057             : 
    1058             :     /* Sign Data */
    1059       17564 :     kret = arcfour_mic_cksum_iov(context,
    1060             :                                  key, KRB5_KU_USAGE_SEAL,
    1061             :                                  p0 + 16, 8, /* SGN_CKSUM */
    1062             :                                  p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
    1063       17564 :                                  p0 + 24, 8, /* Confounder */
    1064             :                                  iov, iov_count, /* Data + SignOnly */
    1065             :                                  padding); /* padding */
    1066       17564 :     if (kret) {
    1067           0 :         *minor_status = kret;
    1068           0 :         major_status = GSS_S_FAILURE;
    1069           0 :         goto failure;
    1070             :     }
    1071             : 
    1072       17564 :     Klocal.keytype = key->keytype;
    1073       17564 :     Klocal.keyvalue.data = Klocaldata;
    1074       17564 :     Klocal.keyvalue.length = sizeof(Klocaldata);
    1075             : 
    1076      298588 :     for (i = 0; i < 16; i++) {
    1077      281024 :         Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
    1078             :     }
    1079       17564 :     kret = arcfour_mic_key(context, &Klocal,
    1080       17564 :                            p0 + 8, 4, /* SND_SEQ */
    1081             :                            k6_data, sizeof(k6_data));
    1082       17564 :     memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
    1083       17564 :     if (kret) {
    1084           0 :         *minor_status = kret;
    1085           0 :         major_status = GSS_S_FAILURE;
    1086           0 :         goto failure;
    1087             :     }
    1088             : 
    1089       17564 :     if (conf_req_flag) {
    1090           0 :         EVP_CIPHER_CTX rc4_key;
    1091             : 
    1092       17564 :         EVP_CIPHER_CTX_init(&rc4_key);
    1093       17564 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
    1094             : 
    1095             :         /* Confounder */
    1096       17564 :         EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8);
    1097             : 
    1098             :         /* Seal Data */
    1099       87820 :         for (i=0; i < iov_count; i++) {
    1100       70256 :             switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
    1101       17564 :             case GSS_IOV_BUFFER_TYPE_DATA:
    1102       17564 :                 break;
    1103       52692 :             default:
    1104       52692 :                 continue;
    1105             :             }
    1106             : 
    1107       17564 :             EVP_Cipher(&rc4_key, iov[i].buffer.value,
    1108       17564 :                        iov[i].buffer.value, iov[i].buffer.length);
    1109             :         }
    1110             : 
    1111             :         /* Padding */
    1112       17564 :         if (padding) {
    1113           0 :             EVP_Cipher(&rc4_key, padding->buffer.value,
    1114           0 :                        padding->buffer.value, padding->buffer.length);
    1115             :         }
    1116             : 
    1117       17564 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
    1118             :     }
    1119       17564 :     memset(k6_data, 0, sizeof(k6_data));
    1120             : 
    1121       17564 :     kret = arcfour_mic_key(context, key,
    1122       17564 :                            p0 + 16, 8, /* SGN_CKSUM */
    1123             :                            k6_data, sizeof(k6_data));
    1124       17564 :     if (kret) {
    1125           0 :         *minor_status = kret;
    1126           0 :         major_status = GSS_S_FAILURE;
    1127           0 :         return major_status;
    1128             :     }
    1129             : 
    1130             :     {
    1131           0 :         EVP_CIPHER_CTX rc4_key;
    1132             : 
    1133       17564 :         EVP_CIPHER_CTX_init(&rc4_key);
    1134       17564 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
    1135       17564 :         EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */
    1136       17564 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
    1137             : 
    1138       17564 :         memset(k6_data, 0, sizeof(k6_data));
    1139             :     }
    1140             : 
    1141       17564 :     if (conf_state)
    1142       17564 :         *conf_state = conf_req_flag;
    1143             : 
    1144       17564 :     *minor_status = 0;
    1145       17564 :     return GSS_S_COMPLETE;
    1146             : 
    1147           0 : failure:
    1148             : 
    1149           0 :     gss_release_iov_buffer(&junk, iov, iov_count);
    1150             : 
    1151           0 :     return major_status;
    1152             : }
    1153             : 
    1154             : OM_uint32
    1155       12068 : _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
    1156             :                            gsskrb5_ctx ctx,
    1157             :                            krb5_context context,
    1158             :                            int *pconf_state,
    1159             :                            gss_qop_t *pqop_state,
    1160             :                            gss_iov_buffer_desc *iov,
    1161             :                            int iov_count,
    1162             :                            krb5_keyblock *key)
    1163             : {
    1164           0 :     OM_uint32 major_status;
    1165           0 :     gss_iov_buffer_desc *header, *padding, *trailer;
    1166           0 :     krb5_keyblock Klocal;
    1167           0 :     uint8_t Klocaldata[16];
    1168           0 :     uint8_t k6_data[16], snd_seq[8], Confounder[8];
    1169           0 :     uint8_t cksum_data[8];
    1170       12068 :     uint8_t *_p = NULL;
    1171           0 :     const uint8_t *p, *p0;
    1172       12068 :     size_t verify_len = 0;
    1173           0 :     uint32_t seq_number;
    1174       12068 :     size_t hlen = 0;
    1175           0 :     int conf_state;
    1176           0 :     int cmp;
    1177           0 :     size_t i;
    1178           0 :     krb5_error_code kret;
    1179           0 :     OM_uint32 ret;
    1180             : 
    1181       12068 :     if (pconf_state != NULL) {
    1182       12068 :         *pconf_state = 0;
    1183             :     }
    1184       12068 :     if (pqop_state != NULL) {
    1185       12068 :         *pqop_state = 0;
    1186             :     }
    1187             : 
    1188       12068 :     header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
    1189       12068 :     padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
    1190       12068 :     trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
    1191             : 
    1192             :     /* Check if the packet is correct */
    1193       12068 :     major_status = _gk_verify_buffers(minor_status,
    1194             :                                       ctx,
    1195             :                                       header,
    1196             :                                       padding,
    1197             :                                       trailer,
    1198             :                                       FALSE); /* behaves as stream cipher */
    1199       12068 :     if (major_status != GSS_S_COMPLETE) {
    1200           0 :         return major_status;
    1201             :     }
    1202             : 
    1203       12068 :     if (padding != NULL && padding->buffer.length != 1) {
    1204           0 :         *minor_status = EINVAL;
    1205           0 :         return GSS_S_FAILURE;
    1206             :     }
    1207             : 
    1208       12068 :     verify_len = header->buffer.length;
    1209             : 
    1210       12068 :     if (!IS_DCE_STYLE(ctx)) {
    1211           0 :         for (i = 0; i < iov_count; i++) {
    1212             :             /* length in header also includes data and padding */
    1213           0 :             if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA)
    1214           0 :                 verify_len += iov[i].buffer.length;
    1215             :         }
    1216             : 
    1217           0 :         if (padding)
    1218           0 :             verify_len += padding->buffer.length;
    1219             :     }
    1220             : 
    1221       12068 :     _p = header->buffer.value;
    1222             : 
    1223       12068 :     ret = _gssapi_verify_mech_header(&_p,
    1224             :                                      verify_len,
    1225             :                                      GSS_KRB5_MECHANISM);
    1226       12068 :     if (ret) {
    1227           0 :         return ret;
    1228             :     }
    1229       12068 :     p0 = _p;
    1230             : 
    1231             :     /* length of mech header */
    1232       12068 :     hlen = (p0 - (uint8_t *)header->buffer.value);
    1233       12068 :     hlen += GSS_ARCFOUR_WRAP_TOKEN_SIZE;
    1234             : 
    1235       12068 :     if (hlen > header->buffer.length) {
    1236           0 :         return GSS_S_BAD_MECH;
    1237             :     }
    1238             : 
    1239       12068 :     p = p0;
    1240             : 
    1241       12068 :     if (memcmp(p, "\x02\x01", 2) != 0)
    1242           0 :         return GSS_S_BAD_SIG;
    1243       12068 :     p += 2;
    1244       12068 :     if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
    1245           0 :         return GSS_S_BAD_SIG;
    1246       12068 :     p += 2;
    1247             : 
    1248       12068 :     if (memcmp (p, "\x10\x00", 2) == 0)
    1249       12068 :         conf_state = 1;
    1250           0 :     else if (memcmp (p, "\xff\xff", 2) == 0)
    1251           0 :         conf_state = 0;
    1252             :     else
    1253           0 :         return GSS_S_BAD_SIG;
    1254             : 
    1255       12068 :     p += 2;
    1256       12068 :     if (memcmp (p, "\xff\xff", 2) != 0)
    1257           0 :         return GSS_S_BAD_MIC;
    1258       12068 :     p = NULL;
    1259             : 
    1260       12068 :     kret = arcfour_mic_key(context,
    1261             :                            key,
    1262       12068 :                            p0 + 16, /* SGN_CKSUM */
    1263             :                            8,       /* SGN_CKSUM_LEN */
    1264             :                            k6_data,
    1265             :                            sizeof(k6_data));
    1266       12068 :     if (kret) {
    1267           0 :         *minor_status = kret;
    1268           0 :         return GSS_S_FAILURE;
    1269             :     }
    1270             : 
    1271             :     {
    1272           0 :         EVP_CIPHER_CTX rc4_key;
    1273             : 
    1274       12068 :         EVP_CIPHER_CTX_init(&rc4_key);
    1275       12068 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
    1276       12068 :         EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */
    1277       12068 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
    1278             : 
    1279       12068 :         memset(k6_data, 0, sizeof(k6_data));
    1280             :     }
    1281             : 
    1282       12068 :     _gss_mg_decode_be_uint32(snd_seq, &seq_number);
    1283             : 
    1284       12068 :     if (ctx->more_flags & LOCAL) {
    1285        4540 :         cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0);
    1286             :     } else {
    1287        7528 :         cmp = (ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4) != 0);
    1288             :     }
    1289       12068 :     if (cmp != 0) {
    1290           0 :         *minor_status = 0;
    1291           0 :         return GSS_S_BAD_MIC;
    1292             :     }
    1293             : 
    1294             :     /* keyblock */
    1295       12068 :     Klocal.keytype = key->keytype;
    1296       12068 :     Klocal.keyvalue.data = Klocaldata;
    1297       12068 :     Klocal.keyvalue.length = sizeof(Klocaldata);
    1298             : 
    1299      205156 :     for (i = 0; i < 16; i++) {
    1300      193088 :         Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
    1301             :     }
    1302             : 
    1303       12068 :     kret = arcfour_mic_key(context,
    1304             :                            &Klocal,
    1305             :                            snd_seq,
    1306             :                            4,
    1307             :                            k6_data, sizeof(k6_data));
    1308       12068 :     memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata));
    1309       12068 :     if (kret) {
    1310           0 :         *minor_status = kret;
    1311           0 :         return GSS_S_FAILURE;
    1312             :     }
    1313             : 
    1314       12068 :     if (conf_state == 1) {
    1315           0 :         EVP_CIPHER_CTX rc4_key;
    1316             : 
    1317       12068 :         EVP_CIPHER_CTX_init(&rc4_key);
    1318       12068 :         EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
    1319             : 
    1320             :         /* Confounder */
    1321       12068 :         EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
    1322             : 
    1323             :         /* Data */
    1324       60340 :         for (i = 0; i < iov_count; i++) {
    1325       48272 :             switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
    1326       12068 :             case GSS_IOV_BUFFER_TYPE_DATA:
    1327       12068 :                 break;
    1328       36204 :             default:
    1329       36204 :                 continue;
    1330             :             }
    1331             : 
    1332       12068 :             EVP_Cipher(&rc4_key, iov[i].buffer.value,
    1333       12068 :                        iov[i].buffer.value, iov[i].buffer.length);
    1334             :         }
    1335             : 
    1336             :         /* Padding */
    1337       12068 :         if (padding) {
    1338           0 :             EVP_Cipher(&rc4_key, padding->buffer.value,
    1339           0 :                        padding->buffer.value, padding->buffer.length);
    1340             :         }
    1341             : 
    1342       12068 :         EVP_CIPHER_CTX_cleanup(&rc4_key);
    1343             :     } else {
    1344             :         /* Confounder */
    1345           0 :         memcpy(Confounder, p0 + 24, 8);
    1346             :     }
    1347       12068 :     memset(k6_data, 0, sizeof(k6_data));
    1348             : 
    1349             :     /* Prepare the buffer for signing */
    1350       12068 :     kret = arcfour_mic_cksum_iov(context,
    1351             :                                  key, KRB5_KU_USAGE_SEAL,
    1352             :                                  cksum_data, sizeof(cksum_data),
    1353             :                                  p0, 8,
    1354             :                                  Confounder, sizeof(Confounder),
    1355             :                                  iov, iov_count,
    1356             :                                  padding);
    1357       12068 :     if (kret) {
    1358           0 :         *minor_status = kret;
    1359           0 :         return GSS_S_FAILURE;
    1360             :     }
    1361             : 
    1362       12068 :     cmp = (ct_memcmp(cksum_data, p0 + 16, 8) != 0); /* SGN_CKSUM */
    1363       12068 :     if (cmp) {
    1364           0 :         *minor_status = 0;
    1365           0 :         return GSS_S_BAD_MIC;
    1366             :     }
    1367             : 
    1368       12068 :     if (padding) {
    1369           0 :         size_t plen;
    1370             : 
    1371           0 :         ret = _gssapi_verify_pad(&padding->buffer, 1, &plen);
    1372           0 :         if (ret) {
    1373           0 :             *minor_status = 0;
    1374           0 :             return ret;
    1375             :         }
    1376             :     }
    1377             : 
    1378           0 :     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
    1379       12068 :     ret = _gssapi_msg_order_check(ctx->order, seq_number);
    1380           0 :     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    1381       12068 :     if (ret != 0) {
    1382           0 :         return ret;
    1383             :     }
    1384             : 
    1385       12068 :     if (pconf_state) {
    1386       12068 :         *pconf_state = conf_state;
    1387             :     }
    1388             : 
    1389       12068 :     *minor_status = 0;
    1390       12068 :     return GSS_S_COMPLETE;
    1391             : }

Generated by: LCOV version 1.14