1178825Sdfr/* 2233294Sstas * Copyright (c) 1997 - 2003 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "gsskrb5_locl.h" 35178825Sdfr 36233294Sstas#ifdef HEIM_WEAK_CRYPTO 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; 50233294Sstas EVP_MD_CTX *md5; 51178825Sdfr u_char hash[16]; 52178825Sdfr DES_key_schedule schedule; 53233294Sstas EVP_CIPHER_CTX des_ctx; 54178825Sdfr DES_cblock deskey; 55178825Sdfr DES_cblock zero; 56178825Sdfr int32_t seq_number; 57178825Sdfr size_t len, total_len; 58178825Sdfr 59178825Sdfr _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); 60178825Sdfr 61178825Sdfr message_token->length = total_len; 62178825Sdfr message_token->value = malloc (total_len); 63178825Sdfr if (message_token->value == NULL) { 64178825Sdfr message_token->length = 0; 65178825Sdfr *minor_status = ENOMEM; 66178825Sdfr return GSS_S_FAILURE; 67178825Sdfr } 68178825Sdfr 69178825Sdfr p = _gsskrb5_make_header(message_token->value, 70178825Sdfr len, 71178825Sdfr "\x01\x01", /* TOK_ID */ 72233294Sstas GSS_KRB5_MECHANISM); 73178825Sdfr 74178825Sdfr memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ 75178825Sdfr p += 2; 76178825Sdfr 77178825Sdfr memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ 78178825Sdfr p += 4; 79178825Sdfr 80178825Sdfr /* Fill in later (SND-SEQ) */ 81178825Sdfr memset (p, 0, 16); 82178825Sdfr p += 16; 83178825Sdfr 84178825Sdfr /* checksum */ 85233294Sstas md5 = EVP_MD_CTX_create(); 86233294Sstas EVP_DigestInit_ex(md5, EVP_md5(), NULL); 87233294Sstas EVP_DigestUpdate(md5, p - 24, 8); 88233294Sstas EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); 89233294Sstas EVP_DigestFinal_ex(md5, hash, NULL); 90233294Sstas EVP_MD_CTX_destroy(md5); 91178825Sdfr 92178825Sdfr memset (&zero, 0, sizeof(zero)); 93178825Sdfr memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 94233294Sstas DES_set_key_unchecked (&deskey, &schedule); 95178825Sdfr DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 96178825Sdfr &schedule, &zero); 97178825Sdfr memcpy (p - 8, hash, 8); /* SGN_CKSUM */ 98178825Sdfr 99178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 100178825Sdfr /* sequence number */ 101178825Sdfr krb5_auth_con_getlocalseqnumber (context, 102178825Sdfr ctx->auth_context, 103178825Sdfr &seq_number); 104178825Sdfr 105178825Sdfr p -= 16; /* SND_SEQ */ 106178825Sdfr p[0] = (seq_number >> 0) & 0xFF; 107178825Sdfr p[1] = (seq_number >> 8) & 0xFF; 108178825Sdfr p[2] = (seq_number >> 16) & 0xFF; 109178825Sdfr p[3] = (seq_number >> 24) & 0xFF; 110178825Sdfr memset (p + 4, 111178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 112178825Sdfr 4); 113178825Sdfr 114233294Sstas EVP_CIPHER_CTX_init(&des_ctx); 115233294Sstas EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); 116233294Sstas EVP_Cipher(&des_ctx, p, p, 8); 117233294Sstas EVP_CIPHER_CTX_cleanup(&des_ctx); 118178825Sdfr 119178825Sdfr krb5_auth_con_setlocalseqnumber (context, 120178825Sdfr ctx->auth_context, 121178825Sdfr ++seq_number); 122178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 123233294Sstas 124178825Sdfr memset (deskey, 0, sizeof(deskey)); 125178825Sdfr memset (&schedule, 0, sizeof(schedule)); 126233294Sstas 127178825Sdfr *minor_status = 0; 128178825Sdfr return GSS_S_COMPLETE; 129178825Sdfr} 130233294Sstas#endif 131178825Sdfr 132178825Sdfrstatic OM_uint32 133178825Sdfrmic_des3 134178825Sdfr (OM_uint32 * minor_status, 135178825Sdfr const gsskrb5_ctx ctx, 136178825Sdfr krb5_context context, 137178825Sdfr gss_qop_t qop_req, 138178825Sdfr const gss_buffer_t message_buffer, 139178825Sdfr gss_buffer_t message_token, 140178825Sdfr krb5_keyblock *key 141178825Sdfr ) 142178825Sdfr{ 143178825Sdfr u_char *p; 144178825Sdfr Checksum cksum; 145178825Sdfr u_char seq[8]; 146178825Sdfr 147178825Sdfr int32_t seq_number; 148178825Sdfr size_t len, total_len; 149178825Sdfr 150178825Sdfr krb5_crypto crypto; 151178825Sdfr krb5_error_code kret; 152178825Sdfr krb5_data encdata; 153178825Sdfr char *tmp; 154178825Sdfr char ivec[8]; 155178825Sdfr 156178825Sdfr _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); 157178825Sdfr 158178825Sdfr message_token->length = total_len; 159178825Sdfr message_token->value = malloc (total_len); 160178825Sdfr if (message_token->value == NULL) { 161178825Sdfr message_token->length = 0; 162178825Sdfr *minor_status = ENOMEM; 163178825Sdfr return GSS_S_FAILURE; 164178825Sdfr } 165178825Sdfr 166178825Sdfr p = _gsskrb5_make_header(message_token->value, 167178825Sdfr len, 168178825Sdfr "\x01\x01", /* TOK-ID */ 169178825Sdfr GSS_KRB5_MECHANISM); 170178825Sdfr 171178825Sdfr memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ 172178825Sdfr p += 2; 173178825Sdfr 174178825Sdfr memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ 175178825Sdfr p += 4; 176178825Sdfr 177178825Sdfr /* this should be done in parts */ 178178825Sdfr 179178825Sdfr tmp = malloc (message_buffer->length + 8); 180178825Sdfr if (tmp == NULL) { 181178825Sdfr free (message_token->value); 182178825Sdfr message_token->value = NULL; 183178825Sdfr message_token->length = 0; 184178825Sdfr *minor_status = ENOMEM; 185178825Sdfr return GSS_S_FAILURE; 186178825Sdfr } 187178825Sdfr memcpy (tmp, p - 8, 8); 188178825Sdfr memcpy (tmp + 8, message_buffer->value, message_buffer->length); 189178825Sdfr 190178825Sdfr kret = krb5_crypto_init(context, key, 0, &crypto); 191178825Sdfr if (kret) { 192178825Sdfr free (message_token->value); 193178825Sdfr message_token->value = NULL; 194178825Sdfr message_token->length = 0; 195178825Sdfr free (tmp); 196178825Sdfr *minor_status = kret; 197178825Sdfr return GSS_S_FAILURE; 198178825Sdfr } 199178825Sdfr 200178825Sdfr kret = krb5_create_checksum (context, 201178825Sdfr crypto, 202178825Sdfr KRB5_KU_USAGE_SIGN, 203178825Sdfr 0, 204178825Sdfr tmp, 205178825Sdfr message_buffer->length + 8, 206178825Sdfr &cksum); 207178825Sdfr free (tmp); 208178825Sdfr krb5_crypto_destroy (context, crypto); 209178825Sdfr if (kret) { 210178825Sdfr free (message_token->value); 211178825Sdfr message_token->value = NULL; 212178825Sdfr message_token->length = 0; 213178825Sdfr *minor_status = kret; 214178825Sdfr return GSS_S_FAILURE; 215178825Sdfr } 216178825Sdfr 217178825Sdfr memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 218178825Sdfr 219178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 220178825Sdfr /* sequence number */ 221178825Sdfr krb5_auth_con_getlocalseqnumber (context, 222178825Sdfr ctx->auth_context, 223178825Sdfr &seq_number); 224178825Sdfr 225178825Sdfr seq[0] = (seq_number >> 0) & 0xFF; 226178825Sdfr seq[1] = (seq_number >> 8) & 0xFF; 227178825Sdfr seq[2] = (seq_number >> 16) & 0xFF; 228178825Sdfr seq[3] = (seq_number >> 24) & 0xFF; 229178825Sdfr memset (seq + 4, 230178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 231178825Sdfr 4); 232178825Sdfr 233178825Sdfr kret = krb5_crypto_init(context, key, 234178825Sdfr ETYPE_DES3_CBC_NONE, &crypto); 235178825Sdfr if (kret) { 236178825Sdfr free (message_token->value); 237178825Sdfr message_token->value = NULL; 238178825Sdfr message_token->length = 0; 239178825Sdfr *minor_status = kret; 240178825Sdfr return GSS_S_FAILURE; 241178825Sdfr } 242178825Sdfr 243178825Sdfr if (ctx->more_flags & COMPAT_OLD_DES3) 244178825Sdfr memset(ivec, 0, 8); 245178825Sdfr else 246178825Sdfr memcpy(ivec, p + 8, 8); 247178825Sdfr 248178825Sdfr kret = krb5_encrypt_ivec (context, 249178825Sdfr crypto, 250178825Sdfr KRB5_KU_USAGE_SEQ, 251178825Sdfr seq, 8, &encdata, ivec); 252178825Sdfr krb5_crypto_destroy (context, crypto); 253178825Sdfr if (kret) { 254178825Sdfr free (message_token->value); 255178825Sdfr message_token->value = NULL; 256178825Sdfr message_token->length = 0; 257178825Sdfr *minor_status = kret; 258178825Sdfr return GSS_S_FAILURE; 259178825Sdfr } 260233294Sstas 261178825Sdfr assert (encdata.length == 8); 262178825Sdfr 263178825Sdfr memcpy (p, encdata.data, encdata.length); 264178825Sdfr krb5_data_free (&encdata); 265178825Sdfr 266178825Sdfr krb5_auth_con_setlocalseqnumber (context, 267178825Sdfr ctx->auth_context, 268178825Sdfr ++seq_number); 269178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 270233294Sstas 271178825Sdfr free_Checksum (&cksum); 272178825Sdfr *minor_status = 0; 273178825Sdfr return GSS_S_COMPLETE; 274178825Sdfr} 275178825Sdfr 276233294SstasOM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic 277178825Sdfr (OM_uint32 * minor_status, 278178825Sdfr const gss_ctx_id_t context_handle, 279178825Sdfr gss_qop_t qop_req, 280178825Sdfr const gss_buffer_t message_buffer, 281178825Sdfr gss_buffer_t message_token 282178825Sdfr ) 283178825Sdfr{ 284178825Sdfr krb5_context context; 285178825Sdfr const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 286178825Sdfr krb5_keyblock *key; 287178825Sdfr OM_uint32 ret; 288178825Sdfr krb5_keytype keytype; 289178825Sdfr 290178825Sdfr GSSAPI_KRB5_INIT (&context); 291178825Sdfr 292233294Sstas if (ctx->more_flags & IS_CFX) 293233294Sstas return _gssapi_mic_cfx (minor_status, ctx, context, qop_req, 294233294Sstas message_buffer, message_token); 295233294Sstas 296178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 297178825Sdfr ret = _gsskrb5i_get_token_key(ctx, context, &key); 298178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 299178825Sdfr if (ret) { 300178825Sdfr *minor_status = ret; 301178825Sdfr return GSS_S_FAILURE; 302178825Sdfr } 303178825Sdfr krb5_enctype_to_keytype (context, key->keytype, &keytype); 304178825Sdfr 305178825Sdfr switch (keytype) { 306178825Sdfr case KEYTYPE_DES : 307233294Sstas#ifdef HEIM_WEAK_CRYPTO 308178825Sdfr ret = mic_des (minor_status, ctx, context, qop_req, 309178825Sdfr message_buffer, message_token, key); 310233294Sstas#else 311233294Sstas ret = GSS_S_FAILURE; 312233294Sstas#endif 313178825Sdfr break; 314178825Sdfr case KEYTYPE_DES3 : 315178825Sdfr ret = mic_des3 (minor_status, ctx, context, qop_req, 316178825Sdfr message_buffer, message_token, key); 317178825Sdfr break; 318178825Sdfr case KEYTYPE_ARCFOUR: 319178825Sdfr case KEYTYPE_ARCFOUR_56: 320178825Sdfr ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, 321178825Sdfr message_buffer, message_token, key); 322178825Sdfr break; 323178825Sdfr default : 324233294Sstas abort(); 325178825Sdfr break; 326178825Sdfr } 327178825Sdfr krb5_free_keyblock (context, key); 328178825Sdfr return ret; 329178825Sdfr} 330