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 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 190 static OM_uint32 191 unwrap_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 383 OM_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