Home | History | Annotate | Line # | Download | only in krb5
      1 /*	$NetBSD: get_mic.c,v 1.6 2023/06/19 21:41:43 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 - 2003 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "gsskrb5_locl.h"
     37 
     38 #ifdef HEIM_WEAK_CRYPTO
     39 
     40 static OM_uint32
     41 mic_des
     42            (OM_uint32 * minor_status,
     43             const gsskrb5_ctx ctx,
     44 	    krb5_context context,
     45             gss_qop_t qop_req,
     46             const gss_buffer_t message_buffer,
     47             gss_buffer_t message_token,
     48 	    krb5_keyblock *key
     49            )
     50 {
     51   u_char *p;
     52   EVP_MD_CTX *md5;
     53   u_char hash[16];
     54   DES_key_schedule schedule;
     55   EVP_CIPHER_CTX* des_ctx;
     56   DES_cblock deskey;
     57   DES_cblock zero;
     58   int32_t seq_number;
     59   size_t len, total_len;
     60 
     61   _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
     62 
     63   message_token->length = total_len;
     64   message_token->value  = malloc (total_len);
     65   if (message_token->value == NULL) {
     66     message_token->length = 0;
     67     *minor_status = ENOMEM;
     68     return GSS_S_FAILURE;
     69   }
     70 
     71   p = _gsskrb5_make_header(message_token->value,
     72 			      len,
     73 			      "\x01\x01", /* TOK_ID */
     74 			      GSS_KRB5_MECHANISM);
     75 
     76   memcpy (p, "\x00\x00", 2);	/* SGN_ALG = DES MAC MD5 */
     77   p += 2;
     78 
     79   memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */
     80   p += 4;
     81 
     82   /* Fill in later (SND-SEQ) */
     83   memset (p, 0, 16);
     84   p += 16;
     85 
     86   /* checksum */
     87   md5 = EVP_MD_CTX_create();
     88   EVP_DigestInit_ex(md5, EVP_md5(), NULL);
     89   EVP_DigestUpdate(md5, p - 24, 8);
     90   EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length);
     91   EVP_DigestFinal_ex(md5, hash, NULL);
     92   EVP_MD_CTX_destroy(md5);
     93 
     94   memset (&zero, 0, sizeof(zero));
     95   memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
     96   DES_set_key_unchecked (&deskey, &schedule);
     97   DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
     98 		 &schedule, &zero);
     99   memcpy (p - 8, hash, 8);	/* SGN_CKSUM */
    100 
    101   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
    102   /* sequence number */
    103   krb5_auth_con_getlocalseqnumber (context,
    104 				   ctx->auth_context,
    105 				   &seq_number);
    106 
    107   p -= 16;			/* SND_SEQ */
    108   p[0] = (seq_number >> 0)  & 0xFF;
    109   p[1] = (seq_number >> 8)  & 0xFF;
    110   p[2] = (seq_number >> 16) & 0xFF;
    111   p[3] = (seq_number >> 24) & 0xFF;
    112   memset (p + 4,
    113 	  (ctx->more_flags & LOCAL) ? 0 : 0xFF,
    114 	  4);
    115 
    116 
    117 #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    118   EVP_CIPHER_CTX des_ctxs;
    119   des_ctx = &des_ctxs;
    120   EVP_CIPHER_CTX_init(des_ctx);
    121 #else
    122   des_ctx = EVP_CIPHER_CTX_new();
    123 #endif
    124   EVP_CIPHER_CTX_init(des_ctx);
    125   if (!EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data,
    126       p + 8, 1)) {
    127       *minor_status = EINVAL;
    128       return GSS_S_FAILURE;
    129   }
    130   EVP_Cipher(des_ctx, p, p, 8);
    131 #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    132   EVP_CIPHER_CTX_cleanup(des_ctx);
    133 #else
    134   EVP_CIPHER_CTX_free(des_ctx);
    135 #endif
    136 
    137   krb5_auth_con_setlocalseqnumber (context,
    138 			       ctx->auth_context,
    139 			       ++seq_number);
    140   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    141 
    142   memset_s(deskey, sizeof(deskey), 0, sizeof(deskey));
    143   memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
    144 
    145   *minor_status = 0;
    146   return GSS_S_COMPLETE;
    147 }
    148 #endif
    149 
    150 static OM_uint32
    151 mic_des3
    152            (OM_uint32 * minor_status,
    153             const gsskrb5_ctx ctx,
    154 	    krb5_context context,
    155             gss_qop_t qop_req,
    156             const gss_buffer_t message_buffer,
    157             gss_buffer_t message_token,
    158 	    krb5_keyblock *key
    159            )
    160 {
    161   u_char *p;
    162   Checksum cksum;
    163   u_char seq[8];
    164 
    165   int32_t seq_number;
    166   size_t len, total_len;
    167 
    168   krb5_crypto crypto;
    169   krb5_error_code kret;
    170   krb5_data encdata;
    171   char *tmp;
    172   char ivec[8];
    173 
    174   _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM);
    175 
    176   message_token->length = total_len;
    177   message_token->value  = malloc (total_len);
    178   if (message_token->value == NULL) {
    179       message_token->length = 0;
    180       *minor_status = ENOMEM;
    181       return GSS_S_FAILURE;
    182   }
    183 
    184   p = _gsskrb5_make_header(message_token->value,
    185 			      len,
    186 			      "\x01\x01", /* TOK-ID */
    187 			      GSS_KRB5_MECHANISM);
    188 
    189   memcpy (p, "\x04\x00", 2);	/* SGN_ALG = HMAC SHA1 DES3-KD */
    190   p += 2;
    191 
    192   memcpy (p, "\xff\xff\xff\xff", 4); /* filler */
    193   p += 4;
    194 
    195   /* this should be done in parts */
    196 
    197   tmp = malloc (message_buffer->length + 8);
    198   if (tmp == NULL) {
    199       free (message_token->value);
    200       message_token->value = NULL;
    201       message_token->length = 0;
    202       *minor_status = ENOMEM;
    203       return GSS_S_FAILURE;
    204   }
    205   memcpy (tmp, p - 8, 8);
    206   memcpy (tmp + 8, message_buffer->value, message_buffer->length);
    207 
    208   kret = krb5_crypto_init(context, key, 0, &crypto);
    209   if (kret) {
    210       free (message_token->value);
    211       message_token->value = NULL;
    212       message_token->length = 0;
    213       free (tmp);
    214       *minor_status = kret;
    215       return GSS_S_FAILURE;
    216   }
    217 
    218   kret = krb5_create_checksum (context,
    219 			       crypto,
    220 			       KRB5_KU_USAGE_SIGN,
    221 			       0,
    222 			       tmp,
    223 			       message_buffer->length + 8,
    224 			       &cksum);
    225   free (tmp);
    226   krb5_crypto_destroy (context, crypto);
    227   if (kret) {
    228       free (message_token->value);
    229       message_token->value = NULL;
    230       message_token->length = 0;
    231       *minor_status = kret;
    232       return GSS_S_FAILURE;
    233   }
    234 
    235   memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
    236 
    237   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
    238   /* sequence number */
    239   krb5_auth_con_getlocalseqnumber (context,
    240 			       ctx->auth_context,
    241 			       &seq_number);
    242 
    243   seq[0] = (seq_number >> 0)  & 0xFF;
    244   seq[1] = (seq_number >> 8)  & 0xFF;
    245   seq[2] = (seq_number >> 16) & 0xFF;
    246   seq[3] = (seq_number >> 24) & 0xFF;
    247   memset (seq + 4,
    248 	  (ctx->more_flags & LOCAL) ? 0 : 0xFF,
    249 	  4);
    250 
    251   kret = krb5_crypto_init(context, key,
    252 			  ETYPE_DES3_CBC_NONE, &crypto);
    253   if (kret) {
    254       free (message_token->value);
    255       message_token->value = NULL;
    256       message_token->length = 0;
    257       *minor_status = kret;
    258       return GSS_S_FAILURE;
    259   }
    260 
    261   if (ctx->more_flags & COMPAT_OLD_DES3)
    262       memset(ivec, 0, 8);
    263   else
    264       memcpy(ivec, p + 8, 8);
    265 
    266   kret = krb5_encrypt_ivec (context,
    267 			    crypto,
    268 			    KRB5_KU_USAGE_SEQ,
    269 			    seq, 8, &encdata, ivec);
    270   krb5_crypto_destroy (context, crypto);
    271   if (kret) {
    272       free (message_token->value);
    273       message_token->value = NULL;
    274       message_token->length = 0;
    275       *minor_status = kret;
    276       return GSS_S_FAILURE;
    277   }
    278 
    279   assert (encdata.length == 8);
    280 
    281   memcpy (p, encdata.data, encdata.length);
    282   krb5_data_free (&encdata);
    283 
    284   krb5_auth_con_setlocalseqnumber (context,
    285 			       ctx->auth_context,
    286 			       ++seq_number);
    287   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    288 
    289   free_Checksum (&cksum);
    290   *minor_status = 0;
    291   return GSS_S_COMPLETE;
    292 }
    293 
    294 OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic
    295            (OM_uint32 * minor_status,
    296             gss_const_ctx_id_t context_handle,
    297             gss_qop_t qop_req,
    298             const gss_buffer_t message_buffer,
    299             gss_buffer_t message_token
    300            )
    301 {
    302   krb5_context context;
    303   const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
    304   krb5_keyblock *key;
    305   OM_uint32 ret;
    306 
    307   GSSAPI_KRB5_INIT (&context);
    308 
    309   if (ctx->more_flags & IS_CFX)
    310       return _gssapi_mic_cfx (minor_status, ctx, context, qop_req,
    311 			      message_buffer, message_token);
    312 
    313   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
    314   ret = _gsskrb5i_get_token_key(ctx, context, &key);
    315   HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    316   if (ret) {
    317       *minor_status = ret;
    318       return GSS_S_FAILURE;
    319   }
    320 
    321   switch (key->keytype) {
    322   case KRB5_ENCTYPE_DES_CBC_CRC :
    323   case KRB5_ENCTYPE_DES_CBC_MD4 :
    324   case KRB5_ENCTYPE_DES_CBC_MD5 :
    325 #ifdef HEIM_WEAK_CRYPTO
    326       ret = mic_des (minor_status, ctx, context, qop_req,
    327 		     message_buffer, message_token, key);
    328 #else
    329       ret = GSS_S_FAILURE;
    330 #endif
    331       break;
    332   case KRB5_ENCTYPE_DES3_CBC_MD5 :
    333   case KRB5_ENCTYPE_DES3_CBC_SHA1 :
    334       ret = mic_des3 (minor_status, ctx, context, qop_req,
    335 		      message_buffer, message_token, key);
    336       break;
    337   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5:
    338   case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56:
    339       ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req,
    340 				     message_buffer, message_token, key);
    341       break;
    342   default :
    343       abort();
    344       break;
    345   }
    346   krb5_free_keyblock (context, key);
    347   return ret;
    348 }
    349