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