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

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

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