1 /* 2 * Copyright (c) 1997 - 2004 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 unwrap_des 40 (OM_uint32 * minor_status, 41 const gsskrb5_ctx context_handle, 42 const gss_buffer_t input_message_buffer, 43 gss_buffer_t output_message_buffer, 44 int * conf_state, 45 gss_qop_t * qop_state, 46 krb5_keyblock *key 47 ) 48 { 49 u_char *p, *seq; 50 size_t len; 51 EVP_MD_CTX *md5; 52 u_char hash[16]; 53 EVP_CIPHER_CTX *des_ctx; 54 DES_key_schedule schedule; 55 DES_cblock deskey; 56 DES_cblock zero; 57 size_t i; 58 uint32_t seq_number; 59 size_t padlength; 60 OM_uint32 ret; 61 int cstate; 62 int cmp; 63 int token_len; 64 65 if (IS_DCE_STYLE(context_handle)) { 66 token_len = 22 + 8 + 15; /* 45 */ 67 if (input_message_buffer->length < token_len) 68 return GSS_S_BAD_MECH; 69 } else { 70 token_len = input_message_buffer->length; 71 } 72 73 p = input_message_buffer->value; 74 ret = _gsskrb5_verify_header (&p, 75 token_len, 76 "\x02\x01", 77 GSS_KRB5_MECHANISM); 78 if (ret) 79 return ret; 80 81 len = (p - (u_char *)input_message_buffer->value) 82 + 22 + 8; 83 if (input_message_buffer->length < len) 84 return GSS_S_BAD_MECH; 85 86 if (memcmp (p, "\x00\x00", 2) != 0) 87 return GSS_S_BAD_SIG; 88 p += 2; 89 if (memcmp (p, "\x00\x00", 2) == 0) { 90 cstate = 1; 91 } else if (memcmp (p, "\xFF\xFF", 2) == 0) { 92 cstate = 0; 93 } else 94 return GSS_S_BAD_MIC; 95 p += 2; 96 if(conf_state != NULL) 97 *conf_state = cstate; 98 if (memcmp (p, "\xff\xff", 2) != 0) 99 return GSS_S_DEFECTIVE_TOKEN; 100 p += 2; 101 p += 16; 102 103 len = p - (u_char *)input_message_buffer->value; 104 105 if(cstate) { 106 /* decrypt data */ 107 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 108 memset (&zero, 0, sizeof(zero)); 109 110 for (i = 0; i < sizeof(deskey); ++i) 111 deskey[i] ^= 0xf0; 112 113 114 des_ctx = EVP_CIPHER_CTX_new(); 115 if (des_ctx == NULL) { 116 memset (deskey, 0, sizeof(deskey)); 117 *minor_status = ENOMEM; 118 return GSS_S_FAILURE; 119 } 120 EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0); 121 EVP_Cipher(des_ctx, p, p, input_message_buffer->length - len); 122 EVP_CIPHER_CTX_free(des_ctx); 123 124 memset (deskey, 0, sizeof(deskey)); 125 } 126 127 if (IS_DCE_STYLE(context_handle)) { 128 padlength = 0; 129 } else { 130 /* check pad */ 131 ret = _gssapi_verify_pad(input_message_buffer, 132 input_message_buffer->length - len - 8, 133 &padlength); 134 if (ret) 135 return ret; 136 } 137 138 md5 = EVP_MD_CTX_create(); 139 EVP_DigestInit_ex(md5, EVP_md5(), NULL); 140 EVP_DigestUpdate(md5, p - 24, 8); 141 EVP_DigestUpdate(md5, p, input_message_buffer->length - len); 142 EVP_DigestFinal_ex(md5, hash, NULL); 143 EVP_MD_CTX_destroy(md5); 144 145 memset (&zero, 0, sizeof(zero)); 146 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 147 DES_set_key_unchecked (&deskey, &schedule); 148 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 149 &schedule, &zero); 150 if (ct_memcmp (p - 8, hash, 8) != 0) { 151 memset (deskey, 0, sizeof(deskey)); 152 memset (&schedule, 0, sizeof(schedule)); 153 return GSS_S_BAD_MIC; 154 } 155 156 /* verify sequence number */ 157 158 des_ctx = EVP_CIPHER_CTX_new(); 159 if (des_ctx == NULL) { 160 memset (deskey, 0, sizeof(deskey)); 161 memset (&schedule, 0, sizeof(schedule)); 162 *minor_status = ENOMEM; 163 return GSS_S_FAILURE; 164 } 165 166 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 167 168 p -= 16; 169 170 EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); 171 EVP_Cipher(des_ctx, p, p, 8); 172 EVP_CIPHER_CTX_free(des_ctx); 173 174 memset (deskey, 0, sizeof(deskey)); 175 memset (&schedule, 0, sizeof(schedule)); 176 177 seq = p; 178 _gsskrb5_decode_om_uint32(seq, &seq_number); 179 180 if (context_handle->more_flags & LOCAL) 181 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 182 else 183 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 184 185 if (cmp != 0) { 186 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 187 return GSS_S_BAD_MIC; 188 } 189 190 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 191 if (ret) { 192 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 193 return ret; 194 } 195 196 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 197 198 /* copy out data */ 199 200 output_message_buffer->length = input_message_buffer->length 201 - len - padlength - 8; 202 output_message_buffer->value = malloc(output_message_buffer->length); 203 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 204 return GSS_S_FAILURE; 205 if (output_message_buffer->value != NULL) 206 memcpy (output_message_buffer->value, 207 p + 24, 208 output_message_buffer->length); 209 return GSS_S_COMPLETE; 210 } 211 #endif 212 213 static OM_uint32 214 unwrap_des3 215 (OM_uint32 * minor_status, 216 const gsskrb5_ctx context_handle, 217 krb5_context context, 218 const gss_buffer_t input_message_buffer, 219 gss_buffer_t output_message_buffer, 220 int * conf_state, 221 gss_qop_t * qop_state, 222 krb5_keyblock *key 223 ) 224 { 225 u_char *p; 226 size_t len; 227 u_char *seq; 228 krb5_data seq_data; 229 u_char cksum[20]; 230 uint32_t seq_number; 231 size_t padlength; 232 OM_uint32 ret; 233 int cstate; 234 krb5_crypto crypto; 235 Checksum csum; 236 int cmp; 237 int token_len; 238 239 if (IS_DCE_STYLE(context_handle)) { 240 token_len = 34 + 8 + 15; /* 57 */ 241 if (input_message_buffer->length < token_len) 242 return GSS_S_BAD_MECH; 243 } else { 244 token_len = input_message_buffer->length; 245 } 246 247 p = input_message_buffer->value; 248 ret = _gsskrb5_verify_header (&p, 249 token_len, 250 "\x02\x01", 251 GSS_KRB5_MECHANISM); 252 if (ret) 253 return ret; 254 255 len = (p - (u_char *)input_message_buffer->value) 256 + 34 + 8; 257 if (input_message_buffer->length < len) 258 return GSS_S_BAD_MECH; 259 260 if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ 261 return GSS_S_BAD_SIG; 262 p += 2; 263 if (ct_memcmp (p, "\x02\x00", 2) == 0) { 264 cstate = 1; 265 } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { 266 cstate = 0; 267 } else 268 return GSS_S_BAD_MIC; 269 p += 2; 270 if(conf_state != NULL) 271 *conf_state = cstate; 272 if (ct_memcmp (p, "\xff\xff", 2) != 0) 273 return GSS_S_DEFECTIVE_TOKEN; 274 p += 2; 275 p += 28; 276 277 len = p - (u_char *)input_message_buffer->value; 278 279 if(cstate) { 280 /* decrypt data */ 281 krb5_data tmp; 282 283 ret = krb5_crypto_init(context, key, 284 ETYPE_DES3_CBC_NONE, &crypto); 285 if (ret) { 286 *minor_status = ret; 287 return GSS_S_FAILURE; 288 } 289 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, 290 p, input_message_buffer->length - len, &tmp); 291 krb5_crypto_destroy(context, crypto); 292 if (ret) { 293 *minor_status = ret; 294 return GSS_S_FAILURE; 295 } 296 assert (tmp.length == input_message_buffer->length - len); 297 298 memcpy (p, tmp.data, tmp.length); 299 krb5_data_free(&tmp); 300 } 301 302 if (IS_DCE_STYLE(context_handle)) { 303 padlength = 0; 304 } else { 305 /* check pad */ 306 ret = _gssapi_verify_pad(input_message_buffer, 307 input_message_buffer->length - len - 8, 308 &padlength); 309 if (ret) 310 return ret; 311 } 312 313 /* verify sequence number */ 314 315 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 316 317 p -= 28; 318 319 ret = krb5_crypto_init(context, key, 320 ETYPE_DES3_CBC_NONE, &crypto); 321 if (ret) { 322 *minor_status = ret; 323 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 324 return GSS_S_FAILURE; 325 } 326 { 327 DES_cblock ivec; 328 329 memcpy(&ivec, p + 8, 8); 330 ret = krb5_decrypt_ivec (context, 331 crypto, 332 KRB5_KU_USAGE_SEQ, 333 p, 8, &seq_data, 334 &ivec); 335 } 336 krb5_crypto_destroy (context, crypto); 337 if (ret) { 338 *minor_status = ret; 339 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 340 return GSS_S_FAILURE; 341 } 342 if (seq_data.length != 8) { 343 krb5_data_free (&seq_data); 344 *minor_status = 0; 345 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 346 return GSS_S_BAD_MIC; 347 } 348 349 seq = seq_data.data; 350 _gsskrb5_decode_om_uint32(seq, &seq_number); 351 352 if (context_handle->more_flags & LOCAL) 353 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 354 else 355 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 356 357 krb5_data_free (&seq_data); 358 if (cmp != 0) { 359 *minor_status = 0; 360 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 361 return GSS_S_BAD_MIC; 362 } 363 364 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 365 if (ret) { 366 *minor_status = 0; 367 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 368 return ret; 369 } 370 371 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 372 373 /* verify checksum */ 374 375 memcpy (cksum, p + 8, 20); 376 377 memcpy (p + 20, p - 8, 8); 378 379 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 380 csum.checksum.length = 20; 381 csum.checksum.data = cksum; 382 383 ret = krb5_crypto_init(context, key, 0, &crypto); 384 if (ret) { 385 *minor_status = ret; 386 return GSS_S_FAILURE; 387 } 388 389 ret = krb5_verify_checksum (context, crypto, 390 KRB5_KU_USAGE_SIGN, 391 p + 20, 392 input_message_buffer->length - len + 8, 393 &csum); 394 krb5_crypto_destroy (context, crypto); 395 if (ret) { 396 *minor_status = ret; 397 return GSS_S_FAILURE; 398 } 399 400 /* copy out data */ 401 402 output_message_buffer->length = input_message_buffer->length 403 - len - padlength - 8; 404 output_message_buffer->value = malloc(output_message_buffer->length); 405 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 406 return GSS_S_FAILURE; 407 if (output_message_buffer->value != NULL) 408 memcpy (output_message_buffer->value, 409 p + 36, 410 output_message_buffer->length); 411 return GSS_S_COMPLETE; 412 } 413 414 OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap 415 (OM_uint32 * minor_status, 416 const gss_ctx_id_t context_handle, 417 const gss_buffer_t input_message_buffer, 418 gss_buffer_t output_message_buffer, 419 int * conf_state, 420 gss_qop_t * qop_state 421 ) 422 { 423 krb5_keyblock *key; 424 krb5_context context; 425 OM_uint32 ret; 426 krb5_keytype keytype; 427 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; 428 429 output_message_buffer->value = NULL; 430 output_message_buffer->length = 0; 431 if (qop_state != NULL) 432 *qop_state = GSS_C_QOP_DEFAULT; 433 434 GSSAPI_KRB5_INIT (&context); 435 436 if (ctx->more_flags & IS_CFX) 437 return _gssapi_unwrap_cfx (minor_status, ctx, context, 438 input_message_buffer, output_message_buffer, 439 conf_state, qop_state); 440 441 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 442 ret = _gsskrb5i_get_token_key(ctx, context, &key); 443 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 444 if (ret) { 445 *minor_status = ret; 446 return GSS_S_FAILURE; 447 } 448 krb5_enctype_to_keytype (context, key->keytype, &keytype); 449 450 *minor_status = 0; 451 452 switch (keytype) { 453 case KEYTYPE_DES : 454 #ifdef HEIM_WEAK_CRYPTO 455 ret = unwrap_des (minor_status, ctx, 456 input_message_buffer, output_message_buffer, 457 conf_state, qop_state, key); 458 #else 459 ret = GSS_S_FAILURE; 460 #endif 461 break; 462 case KEYTYPE_DES3 : 463 ret = unwrap_des3 (minor_status, ctx, context, 464 input_message_buffer, output_message_buffer, 465 conf_state, qop_state, key); 466 break; 467 case KEYTYPE_ARCFOUR: 468 case KEYTYPE_ARCFOUR_56: 469 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, 470 input_message_buffer, output_message_buffer, 471 conf_state, qop_state, key); 472 break; 473 default : 474 abort(); 475 break; 476 } 477 krb5_free_keyblock (context, key); 478 return ret; 479 } 480