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