LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/krb5 - unwrap.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 116 159 73.0 %
Date: 2024-04-13 12:30:31 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2004 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             : #ifdef HEIM_WEAK_CRYPTO
      37             : 
      38             : static OM_uint32
      39             : unwrap_des
      40             :            (OM_uint32 * minor_status,
      41             :             const gsskrb5_ctx context_handle,
      42             :             const gss_buffer_t input_message_buffer,
      43             :             gss_buffer_t output_message_buffer,
      44             :             int * conf_state,
      45             :             gss_qop_t * qop_state,
      46             :             krb5_keyblock *key
      47             :            )
      48             : {
      49             :   u_char *p, *seq;
      50             :   size_t len;
      51             :   EVP_MD_CTX *md5;
      52             :   u_char hash[16];
      53             :   EVP_CIPHER_CTX des_ctx;
      54             :   DES_key_schedule schedule;
      55             :   DES_cblock deskey;
      56             :   DES_cblock zero;
      57             :   size_t i;
      58             :   uint32_t seq_number;
      59             :   size_t padlength;
      60             :   OM_uint32 ret;
      61             :   int cstate;
      62             :   int cmp;
      63             :   int token_len;
      64             : 
      65             :   if (IS_DCE_STYLE(context_handle)) {
      66             :      token_len = 22 + 8 + 15; /* 45 */
      67             :      if (input_message_buffer->length < token_len)
      68             :           return GSS_S_BAD_MECH;
      69             :   } else {
      70             :      token_len = input_message_buffer->length;
      71             :   }
      72             : 
      73             :   p = input_message_buffer->value;
      74             :   ret = _gsskrb5_verify_header (&p,
      75             :                                    token_len,
      76             :                                    "\x02\x01",
      77             :                                    GSS_KRB5_MECHANISM);
      78             :   if (ret)
      79             :       return ret;
      80             : 
      81             :   len = (p - (u_char *)input_message_buffer->value)
      82             :       + 22 + 8;
      83             :   if (input_message_buffer->length < len)
      84             :       return GSS_S_BAD_MECH;
      85             : 
      86             :   if (memcmp (p, "\x00\x00", 2) != 0)
      87             :     return GSS_S_BAD_SIG;
      88             :   p += 2;
      89             :   if (memcmp (p, "\x00\x00", 2) == 0) {
      90             :       cstate = 1;
      91             :   } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
      92             :       cstate = 0;
      93             :   } else
      94             :       return GSS_S_BAD_MIC;
      95             :   p += 2;
      96             :   if(conf_state != NULL)
      97             :       *conf_state = cstate;
      98             :   if (memcmp (p, "\xff\xff", 2) != 0)
      99             :     return GSS_S_DEFECTIVE_TOKEN;
     100             :   p += 2;
     101             :   p += 16;
     102             : 
     103             :   len = p - (u_char *)input_message_buffer->value;
     104             : 
     105             :   if(cstate) {
     106             :       /* decrypt data */
     107             :       memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
     108             :       memset (&zero, 0, sizeof(zero));
     109             : 
     110             :       for (i = 0; i < sizeof(deskey); ++i)
     111             :           deskey[i] ^= 0xf0;
     112             : 
     113             : 
     114             :       EVP_CIPHER_CTX_init(&des_ctx);
     115             :       EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0);
     116             :       EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len);
     117             :       EVP_CIPHER_CTX_cleanup(&des_ctx);
     118             : 
     119             :       memset (&deskey, 0, sizeof(deskey));
     120             :   }
     121             : 
     122             :   if (IS_DCE_STYLE(context_handle)) {
     123             :     padlength = 0;
     124             :   } else {
     125             :     /* check pad */
     126             :     ret = _gssapi_verify_pad(input_message_buffer,
     127             :                              input_message_buffer->length - len - 8,
     128             :                              &padlength);
     129             :     if (ret)
     130             :         return ret;
     131             :   }
     132             : 
     133             :   md5 = EVP_MD_CTX_create();
     134             :   EVP_DigestInit_ex(md5, EVP_md5(), NULL);
     135             :   EVP_DigestUpdate(md5, p - 24, 8);
     136             :   EVP_DigestUpdate(md5, p, input_message_buffer->length - len);
     137             :   EVP_DigestFinal_ex(md5, hash, NULL);
     138             :   EVP_MD_CTX_destroy(md5);
     139             : 
     140             :   memset (&zero, 0, sizeof(zero));
     141             :   memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
     142             :   DES_set_key_unchecked (&deskey, &schedule);
     143             :   DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
     144             :                  &schedule, &zero);
     145             :   if (ct_memcmp (p - 8, hash, 8) != 0) {
     146             :     memset_s(&deskey, sizeof(deskey), 0, sizeof(deskey));
     147             :     memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
     148             :     return GSS_S_BAD_MIC;
     149             :   }
     150             : 
     151             :   /* verify sequence number */
     152             : 
     153             :   HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     154             : 
     155             :   p -= 16;
     156             : 
     157             :   EVP_CIPHER_CTX_init(&des_ctx);
     158             :   EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
     159             :   EVP_Cipher(&des_ctx, p, p, 8);
     160             :   EVP_CIPHER_CTX_cleanup(&des_ctx);
     161             : 
     162             :   memset (deskey, 0, sizeof(deskey));
     163             :   memset (&schedule, 0, sizeof(schedule));
     164             : 
     165             :   seq = p;
     166             :   _gss_mg_decode_be_uint32(seq, &seq_number);
     167             : 
     168             :   if (context_handle->more_flags & LOCAL)
     169             :       cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
     170             :   else
     171             :       cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
     172             : 
     173             :   if (cmp != 0) {
     174             :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     175             :     return GSS_S_BAD_MIC;
     176             :   }
     177             : 
     178             :   ret = _gssapi_msg_order_check(context_handle->order, seq_number);
     179             :   if (ret) {
     180             :     HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     181             :     return ret;
     182             :   }
     183             : 
     184             :   HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     185             : 
     186             :   /* copy out data */
     187             : 
     188             :   output_message_buffer->length = input_message_buffer->length
     189             :     - len - padlength - 8;
     190             :   output_message_buffer->value  = malloc(output_message_buffer->length);
     191             :   if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
     192             :       return GSS_S_FAILURE;
     193             :   if (output_message_buffer->value != NULL)
     194             :       memcpy (output_message_buffer->value,
     195             :               p + 24,
     196             :               output_message_buffer->length);
     197             :   return GSS_S_COMPLETE;
     198             : }
     199             : #endif
     200             : 
     201             : static OM_uint32
     202          15 : unwrap_des3
     203             :            (OM_uint32 * minor_status,
     204             :             const gsskrb5_ctx context_handle,
     205             :             krb5_context context,
     206             :             const gss_buffer_t input_message_buffer,
     207             :             gss_buffer_t output_message_buffer,
     208             :             int * conf_state,
     209             :             gss_qop_t * qop_state,
     210             :             krb5_keyblock *key
     211             :            )
     212             : {
     213          15 :   u_char *p;
     214          15 :   size_t len;
     215          15 :   u_char *seq;
     216          15 :   krb5_data seq_data;
     217          15 :   u_char cksum[20];
     218          15 :   uint32_t seq_number;
     219          15 :   size_t padlength;
     220          15 :   OM_uint32 ret;
     221          15 :   int cstate;
     222          15 :   krb5_crypto crypto;
     223          15 :   Checksum csum;
     224          15 :   int cmp;
     225          15 :   int token_len;
     226             : 
     227          15 :   if (IS_DCE_STYLE(context_handle)) {
     228           4 :      token_len = 34 + 8 + 15; /* 57 */
     229           4 :      if (input_message_buffer->length < token_len)
     230           0 :           return GSS_S_BAD_MECH;
     231             :   } else {
     232          11 :      token_len = input_message_buffer->length;
     233             :   }
     234             : 
     235          13 :   p = input_message_buffer->value;
     236          13 :   ret = _gsskrb5_verify_header (&p,
     237             :                                    token_len,
     238             :                                    "\x02\x01",
     239             :                                    GSS_KRB5_MECHANISM);
     240          13 :   if (ret)
     241           0 :       return ret;
     242             : 
     243          11 :   len = (p - (u_char *)input_message_buffer->value)
     244          11 :       + 34 + 8;
     245          11 :   if (input_message_buffer->length < len)
     246           0 :       return GSS_S_BAD_MECH;
     247             : 
     248           8 :   if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
     249           0 :     return GSS_S_BAD_SIG;
     250           8 :   p += 2;
     251           8 :   if (ct_memcmp (p, "\x02\x00", 2) == 0) {
     252           0 :     cstate = 1;
     253           5 :   } else if (ct_memcmp (p, "\xff\xff", 2) == 0) {
     254           0 :     cstate = 0;
     255             :   } else
     256           0 :     return GSS_S_BAD_MIC;
     257           8 :   p += 2;
     258           8 :   if(conf_state != NULL)
     259           8 :     *conf_state = cstate;
     260           8 :   if (ct_memcmp (p, "\xff\xff", 2) != 0)
     261           0 :     return GSS_S_DEFECTIVE_TOKEN;
     262           8 :   p += 2;
     263           8 :   p += 28;
     264             : 
     265           8 :   len = p - (u_char *)input_message_buffer->value;
     266             : 
     267           8 :   if(cstate) {
     268             :       /* decrypt data */
     269           3 :       krb5_data tmp;
     270             : 
     271           3 :       ret = krb5_crypto_init(context, key,
     272             :                              ETYPE_DES3_CBC_NONE, &crypto);
     273           3 :       if (ret) {
     274           0 :           *minor_status = ret;
     275           0 :           return GSS_S_FAILURE;
     276             :       }
     277           6 :       ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
     278           3 :                          p, input_message_buffer->length - len, &tmp);
     279           3 :       krb5_crypto_destroy(context, crypto);
     280           3 :       if (ret) {
     281           0 :           *minor_status = ret;
     282           0 :           return GSS_S_FAILURE;
     283             :       }
     284           3 :       assert (tmp.length == input_message_buffer->length - len);
     285             : 
     286           3 :       memcpy (p, tmp.data, tmp.length);
     287           3 :       krb5_data_free(&tmp);
     288             :   }
     289             : 
     290           8 :   if (IS_DCE_STYLE(context_handle)) {
     291           2 :     padlength = 0;
     292             :   } else {
     293             :     /* check pad */
     294          12 :     ret = _gssapi_verify_pad(input_message_buffer,
     295           6 :                              input_message_buffer->length - len - 8,
     296             :                              &padlength);
     297           6 :     if (ret)
     298           0 :         return ret;
     299             :   }
     300             : 
     301             :   /* verify sequence number */
     302             : 
     303           6 :   HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
     304             : 
     305           6 :   p -= 28;
     306             : 
     307           6 :   ret = krb5_crypto_init(context, key,
     308             :                          ETYPE_DES3_CBC_NONE, &crypto);
     309           6 :   if (ret) {
     310           0 :       *minor_status = ret;
     311           0 :       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     312           0 :       return GSS_S_FAILURE;
     313             :   }
     314             :   {
     315           6 :       DES_cblock ivec;
     316             : 
     317           6 :       memcpy(&ivec, p + 8, 8);
     318           6 :       ret = krb5_decrypt_ivec (context,
     319             :                                crypto,
     320             :                                KRB5_KU_USAGE_SEQ,
     321             :                                p, 8, &seq_data,
     322             :                                &ivec);
     323             :   }
     324           6 :   krb5_crypto_destroy (context, crypto);
     325           6 :   if (ret) {
     326           0 :       *minor_status = ret;
     327           0 :       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     328           0 :       return GSS_S_FAILURE;
     329             :   }
     330           6 :   if (seq_data.length != 8) {
     331           0 :       krb5_data_free (&seq_data);
     332           0 :       *minor_status = 0;
     333           0 :       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     334           0 :       return GSS_S_BAD_MIC;
     335             :   }
     336             : 
     337           6 :   seq = seq_data.data;
     338           6 :   _gss_mg_decode_be_uint32(seq, &seq_number);
     339             : 
     340           6 :   if (context_handle->more_flags & LOCAL)
     341           0 :       cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
     342             :   else
     343           6 :       cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
     344             : 
     345           6 :   krb5_data_free (&seq_data);
     346           6 :   if (cmp != 0) {
     347           0 :       *minor_status = 0;
     348           0 :       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     349           0 :       return GSS_S_BAD_MIC;
     350             :   }
     351             : 
     352           6 :   ret = _gssapi_msg_order_check(context_handle->order, seq_number);
     353           6 :   if (ret) {
     354           0 :       *minor_status = 0;
     355           0 :       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     356           0 :       return ret;
     357             :   }
     358             : 
     359           6 :   HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
     360             : 
     361             :   /* verify checksum */
     362             : 
     363           6 :   memcpy (cksum, p + 8, 20);
     364             : 
     365           6 :   memcpy (p + 20, p - 8, 8);
     366             : 
     367           6 :   csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
     368           6 :   csum.checksum.length = 20;
     369           6 :   csum.checksum.data   = cksum;
     370             : 
     371           6 :   ret = krb5_crypto_init(context, key, 0, &crypto);
     372           6 :   if (ret) {
     373           0 :       *minor_status = ret;
     374           0 :       return GSS_S_FAILURE;
     375             :   }
     376             : 
     377          12 :   ret = krb5_verify_checksum (context, crypto,
     378             :                               KRB5_KU_USAGE_SIGN,
     379           6 :                               p + 20,
     380           6 :                               input_message_buffer->length - len + 8,
     381             :                               &csum);
     382           6 :   krb5_crypto_destroy (context, crypto);
     383           6 :   if (ret) {
     384           0 :       *minor_status = ret;
     385           0 :       return GSS_S_FAILURE;
     386             :   }
     387             : 
     388             :   /* copy out data */
     389             : 
     390           6 :   output_message_buffer->length = input_message_buffer->length
     391           6 :     - len - padlength - 8;
     392           6 :   output_message_buffer->value  = malloc(output_message_buffer->length);
     393           6 :   if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
     394           0 :       return GSS_S_FAILURE;
     395           6 :   if (output_message_buffer->value != NULL)
     396          21 :       memcpy (output_message_buffer->value,
     397           6 :               p + 36,
     398             :               output_message_buffer->length);
     399           0 :   return GSS_S_COMPLETE;
     400             : }
     401             : 
     402      725466 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap
     403             :            (OM_uint32 * minor_status,
     404             :             gss_const_ctx_id_t context_handle,
     405             :             const gss_buffer_t input_message_buffer,
     406             :             gss_buffer_t output_message_buffer,
     407             :             int * conf_state,
     408             :             gss_qop_t * qop_state
     409             :            )
     410             : {
     411         945 :   krb5_keyblock *key;
     412         945 :   krb5_context context;
     413         945 :   OM_uint32 ret;
     414      725466 :   gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
     415             : 
     416      725466 :   output_message_buffer->value = NULL;
     417      725466 :   output_message_buffer->length = 0;
     418      725466 :   if (qop_state != NULL)
     419      725466 :       *qop_state = GSS_C_QOP_DEFAULT;
     420             : 
     421      725466 :   GSSAPI_KRB5_INIT (&context);
     422             : 
     423      725466 :   if (ctx->more_flags & IS_CFX)
     424      676004 :       return _gssapi_unwrap_cfx (minor_status, ctx, context,
     425             :                                  input_message_buffer, output_message_buffer,
     426             :                                  conf_state, qop_state);
     427             : 
     428          15 :   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
     429       49462 :   ret = _gsskrb5i_get_token_key(ctx, context, &key);
     430          15 :   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
     431       49462 :   if (ret) {
     432           0 :       *minor_status = ret;
     433           0 :       return GSS_S_FAILURE;
     434             :   }
     435             : 
     436       49462 :   *minor_status = 0;
     437             : 
     438       49462 :   switch (key->keytype) {
     439           0 :   case KRB5_ENCTYPE_DES_CBC_CRC :
     440             :   case KRB5_ENCTYPE_DES_CBC_MD4 :
     441             :   case KRB5_ENCTYPE_DES_CBC_MD5 :
     442             : #ifdef HEIM_WEAK_CRYPTO
     443             :       ret = unwrap_des (minor_status, ctx,
     444             :                         input_message_buffer, output_message_buffer,
     445             :                         conf_state, qop_state, key);
     446             : #else
     447           0 :       ret = GSS_S_FAILURE;
     448             : #endif
     449           0 :       break;
     450          15 :   case KRB5_ENCTYPE_DES3_CBC_MD5 :
     451             :   case KRB5_ENCTYPE_DES3_CBC_SHA1 :
     452          15 :       ret = unwrap_des3 (minor_status, ctx, context,
     453             :                          input_message_buffer, output_message_buffer,
     454             :                          conf_state, qop_state, key);
     455          15 :       break;
     456       49447 :   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5:
     457             :   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56:
     458       49447 :       ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
     459             :                                     input_message_buffer, output_message_buffer,
     460             :                                     conf_state, qop_state, key);
     461       49447 :       break;
     462           0 :   default :
     463           0 :       abort();
     464          15 :       break;
     465             :   }
     466       49462 :   krb5_free_keyblock (context, key);
     467       49462 :   return ret;
     468             : }

Generated by: LCOV version 1.14