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