1c19800e8SDoug Rabson /* 2ae771770SStanislav 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 34ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35c19800e8SDoug Rabson 36ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO 37c19800e8SDoug Rabson 38c19800e8SDoug Rabson static OM_uint32 39c19800e8SDoug Rabson verify_mic_des 40c19800e8SDoug Rabson (OM_uint32 * minor_status, 41c19800e8SDoug Rabson const gsskrb5_ctx context_handle, 42c19800e8SDoug Rabson krb5_context context, 43c19800e8SDoug Rabson const gss_buffer_t message_buffer, 44c19800e8SDoug Rabson const gss_buffer_t token_buffer, 45c19800e8SDoug Rabson gss_qop_t * qop_state, 46c19800e8SDoug Rabson krb5_keyblock *key, 47ae771770SStanislav Sedov const char *type 48c19800e8SDoug Rabson ) 49c19800e8SDoug Rabson { 50c19800e8SDoug Rabson u_char *p; 51ae771770SStanislav Sedov EVP_MD_CTX *md5; 52c19800e8SDoug Rabson u_char hash[16], *seq; 53c19800e8SDoug Rabson DES_key_schedule schedule; 54*e4456411SJohn Baldwin EVP_CIPHER_CTX *des_ctx; 55c19800e8SDoug Rabson DES_cblock zero; 56c19800e8SDoug Rabson DES_cblock deskey; 57c19800e8SDoug Rabson uint32_t seq_number; 58c19800e8SDoug Rabson OM_uint32 ret; 59c19800e8SDoug Rabson int cmp; 60c19800e8SDoug Rabson 61c19800e8SDoug Rabson p = token_buffer->value; 62c19800e8SDoug Rabson ret = _gsskrb5_verify_header (&p, 63c19800e8SDoug Rabson token_buffer->length, 64c19800e8SDoug Rabson type, 65c19800e8SDoug Rabson GSS_KRB5_MECHANISM); 66c19800e8SDoug Rabson if (ret) 67c19800e8SDoug Rabson return ret; 68c19800e8SDoug Rabson 69c19800e8SDoug Rabson if (memcmp(p, "\x00\x00", 2) != 0) 70c19800e8SDoug Rabson return GSS_S_BAD_SIG; 71c19800e8SDoug Rabson p += 2; 72c19800e8SDoug Rabson if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 73c19800e8SDoug Rabson return GSS_S_BAD_MIC; 74c19800e8SDoug Rabson p += 4; 75c19800e8SDoug Rabson p += 16; 76c19800e8SDoug Rabson 77c19800e8SDoug Rabson /* verify checksum */ 78ae771770SStanislav Sedov md5 = EVP_MD_CTX_create(); 79ae771770SStanislav Sedov EVP_DigestInit_ex(md5, EVP_md5(), NULL); 80ae771770SStanislav Sedov EVP_DigestUpdate(md5, p - 24, 8); 81ae771770SStanislav Sedov EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); 82ae771770SStanislav Sedov EVP_DigestFinal_ex(md5, hash, NULL); 83ae771770SStanislav Sedov EVP_MD_CTX_destroy(md5); 84c19800e8SDoug Rabson 85c19800e8SDoug Rabson memset (&zero, 0, sizeof(zero)); 86c19800e8SDoug Rabson memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 87c19800e8SDoug Rabson 88ae771770SStanislav Sedov DES_set_key_unchecked (&deskey, &schedule); 89c19800e8SDoug Rabson DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 90c19800e8SDoug Rabson &schedule, &zero); 91ae771770SStanislav Sedov if (ct_memcmp (p - 8, hash, 8) != 0) { 92c19800e8SDoug Rabson memset (deskey, 0, sizeof(deskey)); 93c19800e8SDoug Rabson memset (&schedule, 0, sizeof(schedule)); 94c19800e8SDoug Rabson return GSS_S_BAD_MIC; 95c19800e8SDoug Rabson } 96c19800e8SDoug Rabson 97c19800e8SDoug Rabson /* verify sequence number */ 98c19800e8SDoug Rabson 99*e4456411SJohn Baldwin des_ctx = EVP_CIPHER_CTX_new(); 100*e4456411SJohn Baldwin if (des_ctx == NULL) { 101*e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey)); 102*e4456411SJohn Baldwin memset (&schedule, 0, sizeof(schedule)); 103*e4456411SJohn Baldwin *minor_status = ENOMEM; 104*e4456411SJohn Baldwin return GSS_S_FAILURE; 105*e4456411SJohn Baldwin } 106*e4456411SJohn Baldwin 107c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 108c19800e8SDoug Rabson 109c19800e8SDoug Rabson p -= 16; 110ae771770SStanislav Sedov 111*e4456411SJohn Baldwin EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); 112*e4456411SJohn Baldwin EVP_Cipher(des_ctx, p, p, 8); 113*e4456411SJohn Baldwin EVP_CIPHER_CTX_free(des_ctx); 114c19800e8SDoug Rabson 115c19800e8SDoug Rabson memset (deskey, 0, sizeof(deskey)); 116c19800e8SDoug Rabson memset (&schedule, 0, sizeof(schedule)); 117c19800e8SDoug Rabson 118c19800e8SDoug Rabson seq = p; 119c19800e8SDoug Rabson _gsskrb5_decode_om_uint32(seq, &seq_number); 120c19800e8SDoug Rabson 121c19800e8SDoug Rabson if (context_handle->more_flags & LOCAL) 122ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 123c19800e8SDoug Rabson else 124ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 125c19800e8SDoug Rabson 126c19800e8SDoug Rabson if (cmp != 0) { 127c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 128c19800e8SDoug Rabson return GSS_S_BAD_MIC; 129c19800e8SDoug Rabson } 130c19800e8SDoug Rabson 131c19800e8SDoug Rabson ret = _gssapi_msg_order_check(context_handle->order, seq_number); 132c19800e8SDoug Rabson if (ret) { 133c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 134c19800e8SDoug Rabson return ret; 135c19800e8SDoug Rabson } 136c19800e8SDoug Rabson 137c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 138c19800e8SDoug Rabson 139c19800e8SDoug Rabson return GSS_S_COMPLETE; 140c19800e8SDoug Rabson } 141ae771770SStanislav Sedov #endif 142c19800e8SDoug Rabson 143c19800e8SDoug Rabson static OM_uint32 144c19800e8SDoug Rabson verify_mic_des3 145c19800e8SDoug Rabson (OM_uint32 * minor_status, 146c19800e8SDoug Rabson const gsskrb5_ctx context_handle, 147c19800e8SDoug Rabson krb5_context context, 148c19800e8SDoug Rabson const gss_buffer_t message_buffer, 149c19800e8SDoug Rabson const gss_buffer_t token_buffer, 150c19800e8SDoug Rabson gss_qop_t * qop_state, 151c19800e8SDoug Rabson krb5_keyblock *key, 152ae771770SStanislav Sedov const char *type 153c19800e8SDoug Rabson ) 154c19800e8SDoug Rabson { 155c19800e8SDoug Rabson u_char *p; 156c19800e8SDoug Rabson u_char *seq; 157c19800e8SDoug Rabson uint32_t seq_number; 158c19800e8SDoug Rabson OM_uint32 ret; 159c19800e8SDoug Rabson krb5_crypto crypto; 160c19800e8SDoug Rabson krb5_data seq_data; 161c19800e8SDoug Rabson int cmp, docompat; 162c19800e8SDoug Rabson Checksum csum; 163c19800e8SDoug Rabson char *tmp; 164c19800e8SDoug Rabson char ivec[8]; 165c19800e8SDoug Rabson 166c19800e8SDoug Rabson p = token_buffer->value; 167c19800e8SDoug Rabson ret = _gsskrb5_verify_header (&p, 168c19800e8SDoug Rabson token_buffer->length, 169c19800e8SDoug Rabson type, 170c19800e8SDoug Rabson GSS_KRB5_MECHANISM); 171c19800e8SDoug Rabson if (ret) 172c19800e8SDoug Rabson return ret; 173c19800e8SDoug Rabson 174c19800e8SDoug Rabson if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ 175c19800e8SDoug Rabson return GSS_S_BAD_SIG; 176c19800e8SDoug Rabson p += 2; 177c19800e8SDoug Rabson if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 178c19800e8SDoug Rabson return GSS_S_BAD_MIC; 179c19800e8SDoug Rabson p += 4; 180c19800e8SDoug Rabson 181c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 182c19800e8SDoug Rabson ETYPE_DES3_CBC_NONE, &crypto); 183c19800e8SDoug Rabson if (ret){ 184c19800e8SDoug Rabson *minor_status = ret; 185c19800e8SDoug Rabson return GSS_S_FAILURE; 186c19800e8SDoug Rabson } 187c19800e8SDoug Rabson 188c19800e8SDoug Rabson /* verify sequence number */ 189c19800e8SDoug Rabson docompat = 0; 190c19800e8SDoug Rabson retry: 191c19800e8SDoug Rabson if (docompat) 192c19800e8SDoug Rabson memset(ivec, 0, 8); 193c19800e8SDoug Rabson else 194c19800e8SDoug Rabson memcpy(ivec, p + 8, 8); 195c19800e8SDoug Rabson 196c19800e8SDoug Rabson ret = krb5_decrypt_ivec (context, 197c19800e8SDoug Rabson crypto, 198c19800e8SDoug Rabson KRB5_KU_USAGE_SEQ, 199c19800e8SDoug Rabson p, 8, &seq_data, ivec); 200c19800e8SDoug Rabson if (ret) { 201c19800e8SDoug Rabson if (docompat++) { 202c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 203c19800e8SDoug Rabson *minor_status = ret; 204c19800e8SDoug Rabson return GSS_S_FAILURE; 205c19800e8SDoug Rabson } else 206c19800e8SDoug Rabson goto retry; 207c19800e8SDoug Rabson } 208c19800e8SDoug Rabson 209c19800e8SDoug Rabson if (seq_data.length != 8) { 210c19800e8SDoug Rabson krb5_data_free (&seq_data); 211c19800e8SDoug Rabson if (docompat++) { 212c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 213c19800e8SDoug Rabson return GSS_S_BAD_MIC; 214c19800e8SDoug Rabson } else 215c19800e8SDoug Rabson goto retry; 216c19800e8SDoug Rabson } 217c19800e8SDoug Rabson 218c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 219c19800e8SDoug Rabson 220c19800e8SDoug Rabson seq = seq_data.data; 221c19800e8SDoug Rabson _gsskrb5_decode_om_uint32(seq, &seq_number); 222c19800e8SDoug Rabson 223c19800e8SDoug Rabson if (context_handle->more_flags & LOCAL) 224ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 225c19800e8SDoug Rabson else 226ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 227c19800e8SDoug Rabson 228c19800e8SDoug Rabson krb5_data_free (&seq_data); 229c19800e8SDoug Rabson if (cmp != 0) { 230c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 231c19800e8SDoug Rabson *minor_status = 0; 232c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 233c19800e8SDoug Rabson return GSS_S_BAD_MIC; 234c19800e8SDoug Rabson } 235c19800e8SDoug Rabson 236c19800e8SDoug Rabson ret = _gssapi_msg_order_check(context_handle->order, seq_number); 237c19800e8SDoug Rabson if (ret) { 238c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 239c19800e8SDoug Rabson *minor_status = 0; 240c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 241c19800e8SDoug Rabson return ret; 242c19800e8SDoug Rabson } 243c19800e8SDoug Rabson 244c19800e8SDoug Rabson /* verify checksum */ 245c19800e8SDoug Rabson 246c19800e8SDoug Rabson tmp = malloc (message_buffer->length + 8); 247c19800e8SDoug Rabson if (tmp == NULL) { 248c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 249c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 250c19800e8SDoug Rabson *minor_status = ENOMEM; 251c19800e8SDoug Rabson return GSS_S_FAILURE; 252c19800e8SDoug Rabson } 253c19800e8SDoug Rabson 254c19800e8SDoug Rabson memcpy (tmp, p - 8, 8); 255c19800e8SDoug Rabson memcpy (tmp + 8, message_buffer->value, message_buffer->length); 256c19800e8SDoug Rabson 257c19800e8SDoug Rabson csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 258c19800e8SDoug Rabson csum.checksum.length = 20; 259c19800e8SDoug Rabson csum.checksum.data = p + 8; 260c19800e8SDoug Rabson 261cf771f22SStanislav Sedov krb5_crypto_destroy (context, crypto); 262cf771f22SStanislav Sedov ret = krb5_crypto_init(context, key, 263cf771f22SStanislav Sedov ETYPE_DES3_CBC_SHA1, &crypto); 264cf771f22SStanislav Sedov if (ret){ 265cf771f22SStanislav Sedov *minor_status = ret; 266cf771f22SStanislav Sedov return GSS_S_FAILURE; 267cf771f22SStanislav Sedov } 268cf771f22SStanislav Sedov 269c19800e8SDoug Rabson ret = krb5_verify_checksum (context, crypto, 270c19800e8SDoug Rabson KRB5_KU_USAGE_SIGN, 271c19800e8SDoug Rabson tmp, message_buffer->length + 8, 272c19800e8SDoug Rabson &csum); 273c19800e8SDoug Rabson free (tmp); 274c19800e8SDoug Rabson if (ret) { 275c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 276c19800e8SDoug Rabson *minor_status = ret; 277c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 278c19800e8SDoug Rabson return GSS_S_BAD_MIC; 279c19800e8SDoug Rabson } 280c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 281c19800e8SDoug Rabson 282c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 283c19800e8SDoug Rabson return GSS_S_COMPLETE; 284c19800e8SDoug Rabson } 285c19800e8SDoug Rabson 286c19800e8SDoug Rabson OM_uint32 287c19800e8SDoug Rabson _gsskrb5_verify_mic_internal 288c19800e8SDoug Rabson (OM_uint32 * minor_status, 289ae771770SStanislav Sedov const gsskrb5_ctx ctx, 290c19800e8SDoug Rabson krb5_context context, 291c19800e8SDoug Rabson const gss_buffer_t message_buffer, 292c19800e8SDoug Rabson const gss_buffer_t token_buffer, 293c19800e8SDoug Rabson gss_qop_t * qop_state, 294ae771770SStanislav Sedov const char * type 295c19800e8SDoug Rabson ) 296c19800e8SDoug Rabson { 297c19800e8SDoug Rabson krb5_keyblock *key; 298c19800e8SDoug Rabson OM_uint32 ret; 299c19800e8SDoug Rabson krb5_keytype keytype; 300c19800e8SDoug Rabson 301ae771770SStanislav Sedov if (ctx->more_flags & IS_CFX) 302ae771770SStanislav Sedov return _gssapi_verify_mic_cfx (minor_status, ctx, 303ae771770SStanislav Sedov context, message_buffer, token_buffer, 304ae771770SStanislav Sedov qop_state); 305ae771770SStanislav Sedov 306ae771770SStanislav Sedov HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 307ae771770SStanislav Sedov ret = _gsskrb5i_get_token_key(ctx, context, &key); 308ae771770SStanislav Sedov HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 309c19800e8SDoug Rabson if (ret) { 310c19800e8SDoug Rabson *minor_status = ret; 311c19800e8SDoug Rabson return GSS_S_FAILURE; 312c19800e8SDoug Rabson } 313c19800e8SDoug Rabson *minor_status = 0; 314c19800e8SDoug Rabson krb5_enctype_to_keytype (context, key->keytype, &keytype); 315c19800e8SDoug Rabson switch (keytype) { 316c19800e8SDoug Rabson case KEYTYPE_DES : 317ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO 318ae771770SStanislav Sedov ret = verify_mic_des (minor_status, ctx, context, 319c19800e8SDoug Rabson message_buffer, token_buffer, qop_state, key, 320c19800e8SDoug Rabson type); 321ae771770SStanislav Sedov #else 322ae771770SStanislav Sedov ret = GSS_S_FAILURE; 323ae771770SStanislav Sedov #endif 324c19800e8SDoug Rabson break; 325c19800e8SDoug Rabson case KEYTYPE_DES3 : 326ae771770SStanislav Sedov ret = verify_mic_des3 (minor_status, ctx, context, 327c19800e8SDoug Rabson message_buffer, token_buffer, qop_state, key, 328c19800e8SDoug Rabson type); 329c19800e8SDoug Rabson break; 330c19800e8SDoug Rabson case KEYTYPE_ARCFOUR : 331c19800e8SDoug Rabson case KEYTYPE_ARCFOUR_56 : 332ae771770SStanislav Sedov ret = _gssapi_verify_mic_arcfour (minor_status, ctx, 333c19800e8SDoug Rabson context, 334c19800e8SDoug Rabson message_buffer, token_buffer, 335c19800e8SDoug Rabson qop_state, key, type); 336c19800e8SDoug Rabson break; 337c19800e8SDoug Rabson default : 338ae771770SStanislav Sedov abort(); 339c19800e8SDoug Rabson } 340c19800e8SDoug Rabson krb5_free_keyblock (context, key); 341c19800e8SDoug Rabson 342c19800e8SDoug Rabson return ret; 343c19800e8SDoug Rabson } 344c19800e8SDoug Rabson 345ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 346c19800e8SDoug Rabson _gsskrb5_verify_mic 347c19800e8SDoug Rabson (OM_uint32 * minor_status, 348c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 349c19800e8SDoug Rabson const gss_buffer_t message_buffer, 350c19800e8SDoug Rabson const gss_buffer_t token_buffer, 351c19800e8SDoug Rabson gss_qop_t * qop_state 352c19800e8SDoug Rabson ) 353c19800e8SDoug Rabson { 354c19800e8SDoug Rabson krb5_context context; 355c19800e8SDoug Rabson OM_uint32 ret; 356c19800e8SDoug Rabson 357c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context); 358c19800e8SDoug Rabson 359c19800e8SDoug Rabson if (qop_state != NULL) 360c19800e8SDoug Rabson *qop_state = GSS_C_QOP_DEFAULT; 361c19800e8SDoug Rabson 362c19800e8SDoug Rabson ret = _gsskrb5_verify_mic_internal(minor_status, 363c19800e8SDoug Rabson (gsskrb5_ctx)context_handle, 364c19800e8SDoug Rabson context, 365c19800e8SDoug Rabson message_buffer, token_buffer, 366ae771770SStanislav Sedov qop_state, (void *)(intptr_t)"\x01\x01"); 367c19800e8SDoug Rabson 368c19800e8SDoug Rabson return ret; 369c19800e8SDoug Rabson } 370