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