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