11771SN/A/* 21771SN/A * Copyright (c) 1997 - 2004 Kungliga Tekniska H��gskolan 31771SN/A * (Royal Institute of Technology, Stockholm, Sweden). 41771SN/A * All rights reserved. 51771SN/A * 62362SN/A * Redistribution and use in source and binary forms, with or without 71771SN/A * modification, are permitted provided that the following conditions 82362SN/A * are met: 91771SN/A * 101771SN/A * 1. Redistributions of source code must retain the above copyright 111771SN/A * notice, this list of conditions and the following disclaimer. 121771SN/A * 131771SN/A * 2. Redistributions in binary form must reproduce the above copyright 141771SN/A * notice, this list of conditions and the following disclaimer in the 151771SN/A * documentation and/or other materials provided with the distribution. 161771SN/A * 171771SN/A * 3. Neither the name of the Institute nor the names of its contributors 181771SN/A * may be used to endorse or promote products derived from this software 191771SN/A * without specific prior written permission. 202362SN/A * 212362SN/A * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 222362SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231771SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241771SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 251771SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261771SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271771SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281771SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291771SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301771SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311771SN/A * SUCH DAMAGE. 321771SN/A */ 333984SN/A 341771SN/A#include "gsskrb5_locl.h" 351771SN/A 361771SN/A#ifdef HEIM_WEAK_CRYPTO 371771SN/A 381771SN/Astatic OM_uint32 391771SN/Aunwrap_des 401771SN/A (OM_uint32 * minor_status, 411771SN/A const gsskrb5_ctx context_handle, 421771SN/A const gss_buffer_t input_message_buffer, 4312876Sdl gss_buffer_t output_message_buffer, 441771SN/A int * conf_state, 451771SN/A gss_qop_t * qop_state, 461771SN/A krb5_keyblock *key 4712876Sdl ) 481771SN/A{ 497646SN/A u_char *p, *seq; 501771SN/A size_t len; 511771SN/A EVP_MD_CTX *md5; 521771SN/A u_char hash[16]; 531771SN/A EVP_CIPHER_CTX des_ctx; 541771SN/A DES_key_schedule schedule; 551771SN/A DES_cblock deskey; 561771SN/A DES_cblock zero; 571771SN/A size_t i; 581771SN/A uint32_t seq_number; 591771SN/A size_t padlength; 601771SN/A OM_uint32 ret; 611771SN/A int cstate; 621771SN/A int cmp; 631771SN/A int token_len; 641771SN/A 651771SN/A if (IS_DCE_STYLE(context_handle)) { 661771SN/A token_len = 22 + 8 + 15; /* 45 */ 671771SN/A } else { 681771SN/A token_len = input_message_buffer->length; 691771SN/A } 701771SN/A 711771SN/A p = input_message_buffer->value; 721771SN/A ret = _gsskrb5_verify_header (&p, 731771SN/A token_len, 741771SN/A "\x02\x01", 751771SN/A GSS_KRB5_MECHANISM); 761771SN/A if (ret) 771771SN/A return ret; 787646SN/A 791771SN/A if (memcmp (p, "\x00\x00", 2) != 0) 801771SN/A return GSS_S_BAD_SIG; 811771SN/A p += 2; 821771SN/A if (memcmp (p, "\x00\x00", 2) == 0) { 831771SN/A cstate = 1; 841771SN/A } else if (memcmp (p, "\xFF\xFF", 2) == 0) { 851771SN/A cstate = 0; 861771SN/A } else 871771SN/A return GSS_S_BAD_MIC; 881771SN/A p += 2; 891771SN/A if(conf_state != NULL) 901771SN/A *conf_state = cstate; 911771SN/A if (memcmp (p, "\xff\xff", 2) != 0) 921771SN/A return GSS_S_DEFECTIVE_TOKEN; 931771SN/A p += 2; 941771SN/A p += 16; 951771SN/A 961771SN/A len = p - (u_char *)input_message_buffer->value; 971771SN/A 981771SN/A 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 EVP_CIPHER_CTX_init(&des_ctx); 108 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0); 109 EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len); 110 EVP_CIPHER_CTX_cleanup(&des_ctx); 111 112 memset (&schedule, 0, sizeof(schedule)); 113 } 114 115 if (IS_DCE_STYLE(context_handle)) { 116 padlength = 0; 117 } else { 118 /* check pad */ 119 ret = _gssapi_verify_pad(input_message_buffer, 120 input_message_buffer->length - len, 121 &padlength); 122 if (ret) 123 return ret; 124 } 125 126 md5 = EVP_MD_CTX_create(); 127 EVP_DigestInit_ex(md5, EVP_md5(), NULL); 128 EVP_DigestUpdate(md5, p - 24, 8); 129 EVP_DigestUpdate(md5, p, input_message_buffer->length - len); 130 EVP_DigestFinal_ex(md5, hash, NULL); 131 EVP_MD_CTX_destroy(md5); 132 133 memset (&zero, 0, sizeof(zero)); 134 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 135 DES_set_key_unchecked (&deskey, &schedule); 136 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 137 &schedule, &zero); 138 if (ct_memcmp (p - 8, hash, 8) != 0) 139 return GSS_S_BAD_MIC; 140 141 /* verify sequence number */ 142 143 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 144 145 p -= 16; 146 147 EVP_CIPHER_CTX_init(&des_ctx); 148 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); 149 EVP_Cipher(&des_ctx, p, p, 8); 150 EVP_CIPHER_CTX_cleanup(&des_ctx); 151 152 memset (deskey, 0, sizeof(deskey)); 153 memset (&schedule, 0, sizeof(schedule)); 154 155 seq = p; 156 _gsskrb5_decode_om_uint32(seq, &seq_number); 157 158 if (context_handle->more_flags & LOCAL) 159 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 160 else 161 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 162 163 if (cmp != 0) { 164 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 165 return GSS_S_BAD_MIC; 166 } 167 168 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 169 if (ret) { 170 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 171 return ret; 172 } 173 174 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 175 176 /* copy out data */ 177 178 output_message_buffer->length = input_message_buffer->length 179 - len - padlength - 8; 180 output_message_buffer->value = malloc(output_message_buffer->length); 181 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 182 return GSS_S_FAILURE; 183 memcpy (output_message_buffer->value, 184 p + 24, 185 output_message_buffer->length); 186 return GSS_S_COMPLETE; 187} 188#endif 189 190static OM_uint32 191unwrap_des3 192 (OM_uint32 * minor_status, 193 const gsskrb5_ctx context_handle, 194 krb5_context context, 195 const gss_buffer_t input_message_buffer, 196 gss_buffer_t output_message_buffer, 197 int * conf_state, 198 gss_qop_t * qop_state, 199 krb5_keyblock *key 200 ) 201{ 202 u_char *p; 203 size_t len; 204 u_char *seq; 205 krb5_data seq_data; 206 u_char cksum[20]; 207 uint32_t seq_number; 208 size_t padlength; 209 OM_uint32 ret; 210 int cstate; 211 krb5_crypto crypto; 212 Checksum csum; 213 int cmp; 214 int token_len; 215 216 if (IS_DCE_STYLE(context_handle)) { 217 token_len = 34 + 8 + 15; /* 57 */ 218 } else { 219 token_len = input_message_buffer->length; 220 } 221 222 p = input_message_buffer->value; 223 ret = _gsskrb5_verify_header (&p, 224 token_len, 225 "\x02\x01", 226 GSS_KRB5_MECHANISM); 227 if (ret) 228 return ret; 229 230 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ 231 return GSS_S_BAD_SIG; 232 p += 2; 233 if (ct_memcmp (p, "\x02\x00", 2) == 0) { 234 cstate = 1; 235 } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { 236 cstate = 0; 237 } else 238 return GSS_S_BAD_MIC; 239 p += 2; 240 if(conf_state != NULL) 241 *conf_state = cstate; 242 if (ct_memcmp (p, "\xff\xff", 2) != 0) 243 return GSS_S_DEFECTIVE_TOKEN; 244 p += 2; 245 p += 28; 246 247 len = p - (u_char *)input_message_buffer->value; 248 249 if(cstate) { 250 /* decrypt data */ 251 krb5_data tmp; 252 253 ret = krb5_crypto_init(context, key, 254 ETYPE_DES3_CBC_NONE, &crypto); 255 if (ret) { 256 *minor_status = ret; 257 return GSS_S_FAILURE; 258 } 259 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, 260 p, input_message_buffer->length - len, &tmp); 261 krb5_crypto_destroy(context, crypto); 262 if (ret) { 263 *minor_status = ret; 264 return GSS_S_FAILURE; 265 } 266 assert (tmp.length == input_message_buffer->length - len); 267 268 memcpy (p, tmp.data, tmp.length); 269 krb5_data_free(&tmp); 270 } 271 272 if (IS_DCE_STYLE(context_handle)) { 273 padlength = 0; 274 } else { 275 /* check pad */ 276 ret = _gssapi_verify_pad(input_message_buffer, 277 input_message_buffer->length - len, 278 &padlength); 279 if (ret) 280 return ret; 281 } 282 283 /* verify sequence number */ 284 285 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 286 287 p -= 28; 288 289 ret = krb5_crypto_init(context, key, 290 ETYPE_DES3_CBC_NONE, &crypto); 291 if (ret) { 292 *minor_status = ret; 293 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 294 return GSS_S_FAILURE; 295 } 296 { 297 DES_cblock ivec; 298 299 memcpy(&ivec, p + 8, 8); 300 ret = krb5_decrypt_ivec (context, 301 crypto, 302 KRB5_KU_USAGE_SEQ, 303 p, 8, &seq_data, 304 &ivec); 305 } 306 krb5_crypto_destroy (context, crypto); 307 if (ret) { 308 *minor_status = ret; 309 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 310 return GSS_S_FAILURE; 311 } 312 if (seq_data.length != 8) { 313 krb5_data_free (&seq_data); 314 *minor_status = 0; 315 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 316 return GSS_S_BAD_MIC; 317 } 318 319 seq = seq_data.data; 320 _gsskrb5_decode_om_uint32(seq, &seq_number); 321 322 if (context_handle->more_flags & LOCAL) 323 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 324 else 325 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 326 327 krb5_data_free (&seq_data); 328 if (cmp != 0) { 329 *minor_status = 0; 330 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 331 return GSS_S_BAD_MIC; 332 } 333 334 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 335 if (ret) { 336 *minor_status = 0; 337 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 338 return ret; 339 } 340 341 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 342 343 /* verify checksum */ 344 345 memcpy (cksum, p + 8, 20); 346 347 memcpy (p + 20, p - 8, 8); 348 349 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 350 csum.checksum.length = 20; 351 csum.checksum.data = cksum; 352 353 ret = krb5_crypto_init(context, key, 0, &crypto); 354 if (ret) { 355 *minor_status = ret; 356 return GSS_S_FAILURE; 357 } 358 359 ret = krb5_verify_checksum (context, crypto, 360 KRB5_KU_USAGE_SIGN, 361 p + 20, 362 input_message_buffer->length - len + 8, 363 &csum); 364 krb5_crypto_destroy (context, crypto); 365 if (ret) { 366 *minor_status = ret; 367 return GSS_S_FAILURE; 368 } 369 370 /* copy out data */ 371 372 output_message_buffer->length = input_message_buffer->length 373 - len - padlength - 8; 374 output_message_buffer->value = malloc(output_message_buffer->length); 375 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 376 return GSS_S_FAILURE; 377 memcpy (output_message_buffer->value, 378 p + 36, 379 output_message_buffer->length); 380 return GSS_S_COMPLETE; 381} 382 383OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap 384 (OM_uint32 * minor_status, 385 const gss_ctx_id_t context_handle, 386 const gss_buffer_t input_message_buffer, 387 gss_buffer_t output_message_buffer, 388 int * conf_state, 389 gss_qop_t * qop_state 390 ) 391{ 392 krb5_keyblock *key; 393 krb5_context context; 394 OM_uint32 ret; 395 krb5_keytype keytype; 396 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; 397 398 output_message_buffer->value = NULL; 399 output_message_buffer->length = 0; 400 if (qop_state != NULL) 401 *qop_state = GSS_C_QOP_DEFAULT; 402 403 GSSAPI_KRB5_INIT (&context); 404 405 if (ctx->more_flags & IS_CFX) 406 return _gssapi_unwrap_cfx (minor_status, ctx, context, 407 input_message_buffer, output_message_buffer, 408 conf_state, qop_state); 409 410 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 411 ret = _gsskrb5i_get_token_key(ctx, context, &key); 412 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 413 if (ret) { 414 *minor_status = ret; 415 return GSS_S_FAILURE; 416 } 417 krb5_enctype_to_keytype (context, key->keytype, &keytype); 418 419 *minor_status = 0; 420 421 switch (keytype) { 422 case KEYTYPE_DES : 423#ifdef HEIM_WEAK_CRYPTO 424 ret = unwrap_des (minor_status, ctx, 425 input_message_buffer, output_message_buffer, 426 conf_state, qop_state, key); 427#else 428 ret = GSS_S_FAILURE; 429#endif 430 break; 431 case KEYTYPE_DES3 : 432 ret = unwrap_des3 (minor_status, ctx, context, 433 input_message_buffer, output_message_buffer, 434 conf_state, qop_state, key); 435 break; 436 case KEYTYPE_ARCFOUR: 437 case KEYTYPE_ARCFOUR_56: 438 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, 439 input_message_buffer, output_message_buffer, 440 conf_state, qop_state, key); 441 break; 442 default : 443 abort(); 444 break; 445 } 446 krb5_free_keyblock (context, key); 447 return ret; 448} 449