get_mic.c revision 178825
1178825Sdfr/* 2178825Sdfr * Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 5178825Sdfr * 6178825Sdfr * Redistribution and use in source and binary forms, with or without 7178825Sdfr * modification, are permitted provided that the following conditions 8178825Sdfr * are met: 9178825Sdfr * 10178825Sdfr * 1. Redistributions of source code must retain the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 18178825Sdfr * may be used to endorse or promote products derived from this software 19178825Sdfr * without specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178825Sdfr * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "krb5/gsskrb5_locl.h" 35178825Sdfr 36178825SdfrRCSID("$Id: get_mic.c 19031 2006-11-13 18:02:57Z lha $"); 37178825Sdfr 38178825Sdfrstatic OM_uint32 39178825Sdfrmic_des 40178825Sdfr (OM_uint32 * minor_status, 41178825Sdfr const gsskrb5_ctx ctx, 42178825Sdfr krb5_context context, 43178825Sdfr gss_qop_t qop_req, 44178825Sdfr const gss_buffer_t message_buffer, 45178825Sdfr gss_buffer_t message_token, 46178825Sdfr krb5_keyblock *key 47178825Sdfr ) 48178825Sdfr{ 49178825Sdfr u_char *p; 50178825Sdfr MD5_CTX md5; 51178825Sdfr u_char hash[16]; 52178825Sdfr DES_key_schedule schedule; 53178825Sdfr DES_cblock deskey; 54178825Sdfr DES_cblock zero; 55178825Sdfr int32_t seq_number; 56178825Sdfr size_t len, total_len; 57178825Sdfr 58178825Sdfr _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); 59178825Sdfr 60178825Sdfr message_token->length = total_len; 61178825Sdfr message_token->value = malloc (total_len); 62178825Sdfr if (message_token->value == NULL) { 63178825Sdfr message_token->length = 0; 64178825Sdfr *minor_status = ENOMEM; 65178825Sdfr return GSS_S_FAILURE; 66178825Sdfr } 67178825Sdfr 68178825Sdfr p = _gsskrb5_make_header(message_token->value, 69178825Sdfr len, 70178825Sdfr "\x01\x01", /* TOK_ID */ 71178825Sdfr GSS_KRB5_MECHANISM); 72178825Sdfr 73178825Sdfr memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ 74178825Sdfr p += 2; 75178825Sdfr 76178825Sdfr memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ 77178825Sdfr p += 4; 78178825Sdfr 79178825Sdfr /* Fill in later (SND-SEQ) */ 80178825Sdfr memset (p, 0, 16); 81178825Sdfr p += 16; 82178825Sdfr 83178825Sdfr /* checksum */ 84178825Sdfr MD5_Init (&md5); 85178825Sdfr MD5_Update (&md5, p - 24, 8); 86178825Sdfr MD5_Update (&md5, message_buffer->value, message_buffer->length); 87178825Sdfr MD5_Final (hash, &md5); 88178825Sdfr 89178825Sdfr memset (&zero, 0, sizeof(zero)); 90178825Sdfr memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 91178825Sdfr DES_set_key (&deskey, &schedule); 92178825Sdfr DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 93178825Sdfr &schedule, &zero); 94178825Sdfr memcpy (p - 8, hash, 8); /* SGN_CKSUM */ 95178825Sdfr 96178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 97178825Sdfr /* sequence number */ 98178825Sdfr krb5_auth_con_getlocalseqnumber (context, 99178825Sdfr ctx->auth_context, 100178825Sdfr &seq_number); 101178825Sdfr 102178825Sdfr p -= 16; /* SND_SEQ */ 103178825Sdfr p[0] = (seq_number >> 0) & 0xFF; 104178825Sdfr p[1] = (seq_number >> 8) & 0xFF; 105178825Sdfr p[2] = (seq_number >> 16) & 0xFF; 106178825Sdfr p[3] = (seq_number >> 24) & 0xFF; 107178825Sdfr memset (p + 4, 108178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 109178825Sdfr 4); 110178825Sdfr 111178825Sdfr DES_set_key (&deskey, &schedule); 112178825Sdfr DES_cbc_encrypt ((void *)p, (void *)p, 8, 113178825Sdfr &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); 114178825Sdfr 115178825Sdfr krb5_auth_con_setlocalseqnumber (context, 116178825Sdfr ctx->auth_context, 117178825Sdfr ++seq_number); 118178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 119178825Sdfr 120178825Sdfr memset (deskey, 0, sizeof(deskey)); 121178825Sdfr memset (&schedule, 0, sizeof(schedule)); 122178825Sdfr 123178825Sdfr *minor_status = 0; 124178825Sdfr return GSS_S_COMPLETE; 125178825Sdfr} 126178825Sdfr 127178825Sdfrstatic OM_uint32 128178825Sdfrmic_des3 129178825Sdfr (OM_uint32 * minor_status, 130178825Sdfr const gsskrb5_ctx ctx, 131178825Sdfr krb5_context context, 132178825Sdfr gss_qop_t qop_req, 133178825Sdfr const gss_buffer_t message_buffer, 134178825Sdfr gss_buffer_t message_token, 135178825Sdfr krb5_keyblock *key 136178825Sdfr ) 137178825Sdfr{ 138178825Sdfr u_char *p; 139178825Sdfr Checksum cksum; 140178825Sdfr u_char seq[8]; 141178825Sdfr 142178825Sdfr int32_t seq_number; 143178825Sdfr size_t len, total_len; 144178825Sdfr 145178825Sdfr krb5_crypto crypto; 146178825Sdfr krb5_error_code kret; 147178825Sdfr krb5_data encdata; 148178825Sdfr char *tmp; 149178825Sdfr char ivec[8]; 150178825Sdfr 151178825Sdfr _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); 152178825Sdfr 153178825Sdfr message_token->length = total_len; 154178825Sdfr message_token->value = malloc (total_len); 155178825Sdfr if (message_token->value == NULL) { 156178825Sdfr message_token->length = 0; 157178825Sdfr *minor_status = ENOMEM; 158178825Sdfr return GSS_S_FAILURE; 159178825Sdfr } 160178825Sdfr 161178825Sdfr p = _gsskrb5_make_header(message_token->value, 162178825Sdfr len, 163178825Sdfr "\x01\x01", /* TOK-ID */ 164178825Sdfr GSS_KRB5_MECHANISM); 165178825Sdfr 166178825Sdfr memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ 167178825Sdfr p += 2; 168178825Sdfr 169178825Sdfr memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ 170178825Sdfr p += 4; 171178825Sdfr 172178825Sdfr /* this should be done in parts */ 173178825Sdfr 174178825Sdfr tmp = malloc (message_buffer->length + 8); 175178825Sdfr if (tmp == NULL) { 176178825Sdfr free (message_token->value); 177178825Sdfr message_token->value = NULL; 178178825Sdfr message_token->length = 0; 179178825Sdfr *minor_status = ENOMEM; 180178825Sdfr return GSS_S_FAILURE; 181178825Sdfr } 182178825Sdfr memcpy (tmp, p - 8, 8); 183178825Sdfr memcpy (tmp + 8, message_buffer->value, message_buffer->length); 184178825Sdfr 185178825Sdfr kret = krb5_crypto_init(context, key, 0, &crypto); 186178825Sdfr if (kret) { 187178825Sdfr free (message_token->value); 188178825Sdfr message_token->value = NULL; 189178825Sdfr message_token->length = 0; 190178825Sdfr free (tmp); 191178825Sdfr *minor_status = kret; 192178825Sdfr return GSS_S_FAILURE; 193178825Sdfr } 194178825Sdfr 195178825Sdfr kret = krb5_create_checksum (context, 196178825Sdfr crypto, 197178825Sdfr KRB5_KU_USAGE_SIGN, 198178825Sdfr 0, 199178825Sdfr tmp, 200178825Sdfr message_buffer->length + 8, 201178825Sdfr &cksum); 202178825Sdfr free (tmp); 203178825Sdfr krb5_crypto_destroy (context, crypto); 204178825Sdfr if (kret) { 205178825Sdfr free (message_token->value); 206178825Sdfr message_token->value = NULL; 207178825Sdfr message_token->length = 0; 208178825Sdfr *minor_status = kret; 209178825Sdfr return GSS_S_FAILURE; 210178825Sdfr } 211178825Sdfr 212178825Sdfr memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 213178825Sdfr 214178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 215178825Sdfr /* sequence number */ 216178825Sdfr krb5_auth_con_getlocalseqnumber (context, 217178825Sdfr ctx->auth_context, 218178825Sdfr &seq_number); 219178825Sdfr 220178825Sdfr seq[0] = (seq_number >> 0) & 0xFF; 221178825Sdfr seq[1] = (seq_number >> 8) & 0xFF; 222178825Sdfr seq[2] = (seq_number >> 16) & 0xFF; 223178825Sdfr seq[3] = (seq_number >> 24) & 0xFF; 224178825Sdfr memset (seq + 4, 225178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 226178825Sdfr 4); 227178825Sdfr 228178825Sdfr kret = krb5_crypto_init(context, key, 229178825Sdfr ETYPE_DES3_CBC_NONE, &crypto); 230178825Sdfr if (kret) { 231178825Sdfr free (message_token->value); 232178825Sdfr message_token->value = NULL; 233178825Sdfr message_token->length = 0; 234178825Sdfr *minor_status = kret; 235178825Sdfr return GSS_S_FAILURE; 236178825Sdfr } 237178825Sdfr 238178825Sdfr if (ctx->more_flags & COMPAT_OLD_DES3) 239178825Sdfr memset(ivec, 0, 8); 240178825Sdfr else 241178825Sdfr memcpy(ivec, p + 8, 8); 242178825Sdfr 243178825Sdfr kret = krb5_encrypt_ivec (context, 244178825Sdfr crypto, 245178825Sdfr KRB5_KU_USAGE_SEQ, 246178825Sdfr seq, 8, &encdata, ivec); 247178825Sdfr krb5_crypto_destroy (context, crypto); 248178825Sdfr if (kret) { 249178825Sdfr free (message_token->value); 250178825Sdfr message_token->value = NULL; 251178825Sdfr message_token->length = 0; 252178825Sdfr *minor_status = kret; 253178825Sdfr return GSS_S_FAILURE; 254178825Sdfr } 255178825Sdfr 256178825Sdfr assert (encdata.length == 8); 257178825Sdfr 258178825Sdfr memcpy (p, encdata.data, encdata.length); 259178825Sdfr krb5_data_free (&encdata); 260178825Sdfr 261178825Sdfr krb5_auth_con_setlocalseqnumber (context, 262178825Sdfr ctx->auth_context, 263178825Sdfr ++seq_number); 264178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 265178825Sdfr 266178825Sdfr free_Checksum (&cksum); 267178825Sdfr *minor_status = 0; 268178825Sdfr return GSS_S_COMPLETE; 269178825Sdfr} 270178825Sdfr 271178825SdfrOM_uint32 _gsskrb5_get_mic 272178825Sdfr (OM_uint32 * minor_status, 273178825Sdfr const gss_ctx_id_t context_handle, 274178825Sdfr gss_qop_t qop_req, 275178825Sdfr const gss_buffer_t message_buffer, 276178825Sdfr gss_buffer_t message_token 277178825Sdfr ) 278178825Sdfr{ 279178825Sdfr krb5_context context; 280178825Sdfr const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 281178825Sdfr krb5_keyblock *key; 282178825Sdfr OM_uint32 ret; 283178825Sdfr krb5_keytype keytype; 284178825Sdfr 285178825Sdfr GSSAPI_KRB5_INIT (&context); 286178825Sdfr 287178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 288178825Sdfr ret = _gsskrb5i_get_token_key(ctx, context, &key); 289178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 290178825Sdfr if (ret) { 291178825Sdfr *minor_status = ret; 292178825Sdfr return GSS_S_FAILURE; 293178825Sdfr } 294178825Sdfr krb5_enctype_to_keytype (context, key->keytype, &keytype); 295178825Sdfr 296178825Sdfr switch (keytype) { 297178825Sdfr case KEYTYPE_DES : 298178825Sdfr ret = mic_des (minor_status, ctx, context, qop_req, 299178825Sdfr message_buffer, message_token, key); 300178825Sdfr break; 301178825Sdfr case KEYTYPE_DES3 : 302178825Sdfr ret = mic_des3 (minor_status, ctx, context, qop_req, 303178825Sdfr message_buffer, message_token, key); 304178825Sdfr break; 305178825Sdfr case KEYTYPE_ARCFOUR: 306178825Sdfr case KEYTYPE_ARCFOUR_56: 307178825Sdfr ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, 308178825Sdfr message_buffer, message_token, key); 309178825Sdfr break; 310178825Sdfr default : 311178825Sdfr ret = _gssapi_mic_cfx (minor_status, ctx, context, qop_req, 312178825Sdfr message_buffer, message_token, key); 313178825Sdfr break; 314178825Sdfr } 315178825Sdfr krb5_free_keyblock (context, key); 316178825Sdfr return ret; 317178825Sdfr} 318