1 /* $NetBSD: unwrap.c,v 1.2 2017/01/28 21:31:46 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "gsskrb5_locl.h" 37 38 #ifdef HEIM_WEAK_CRYPTO 39 40 static OM_uint32 41 unwrap_des 42 (OM_uint32 * minor_status, 43 const gsskrb5_ctx context_handle, 44 const gss_buffer_t input_message_buffer, 45 gss_buffer_t output_message_buffer, 46 int * conf_state, 47 gss_qop_t * qop_state, 48 krb5_keyblock *key 49 ) 50 { 51 u_char *p, *seq; 52 size_t len; 53 EVP_MD_CTX *md5; 54 u_char hash[16]; 55 EVP_CIPHER_CTX des_ctx; 56 DES_key_schedule schedule; 57 DES_cblock deskey; 58 DES_cblock zero; 59 size_t i; 60 uint32_t seq_number; 61 size_t padlength; 62 OM_uint32 ret; 63 int cstate; 64 int cmp; 65 int token_len; 66 67 if (IS_DCE_STYLE(context_handle)) { 68 token_len = 22 + 8 + 15; /* 45 */ 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 if (memcmp (p, "\x00\x00", 2) != 0) 82 return GSS_S_BAD_SIG; 83 p += 2; 84 if (memcmp (p, "\x00\x00", 2) == 0) { 85 cstate = 1; 86 } else if (memcmp (p, "\xFF\xFF", 2) == 0) { 87 cstate = 0; 88 } else 89 return GSS_S_BAD_MIC; 90 p += 2; 91 if(conf_state != NULL) 92 *conf_state = cstate; 93 if (memcmp (p, "\xff\xff", 2) != 0) 94 return GSS_S_DEFECTIVE_TOKEN; 95 p += 2; 96 p += 16; 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 = EVP_MD_CTX_create(); 129 EVP_DigestInit_ex(md5, EVP_md5(), NULL); 130 EVP_DigestUpdate(md5, p - 24, 8); 131 EVP_DigestUpdate(md5, p, input_message_buffer->length - len); 132 EVP_DigestFinal_ex(md5, hash, NULL); 133 EVP_MD_CTX_destroy(md5); 134 135 memset (&zero, 0, sizeof(zero)); 136 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 137 DES_set_key_unchecked (&deskey, &schedule); 138 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 139 &schedule, &zero); 140 if (ct_memcmp (p - 8, hash, 8) != 0) 141 return GSS_S_BAD_MIC; 142 143 /* verify sequence number */ 144 145 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 146 147 p -= 16; 148 149 EVP_CIPHER_CTX_init(&des_ctx); 150 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); 151 EVP_Cipher(&des_ctx, p, p, 8); 152 EVP_CIPHER_CTX_cleanup(&des_ctx); 153 154 memset (deskey, 0, sizeof(deskey)); 155 memset (&schedule, 0, sizeof(schedule)); 156 157 seq = p; 158 _gsskrb5_decode_om_uint32(seq, &seq_number); 159 160 if (context_handle->more_flags & LOCAL) 161 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 162 else 163 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 164 165 if (cmp != 0) { 166 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 167 return GSS_S_BAD_MIC; 168 } 169 170 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 171 if (ret) { 172 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 173 return ret; 174 } 175 176 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 177 178 /* copy out data */ 179 180 output_message_buffer->length = input_message_buffer->length 181 - len - padlength - 8; 182 output_message_buffer->value = malloc(output_message_buffer->length); 183 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 184 return GSS_S_FAILURE; 185 memcpy (output_message_buffer->value, 186 p + 24, 187 output_message_buffer->length); 188 return GSS_S_COMPLETE; 189 } 190 #endif 191 192 static OM_uint32 193 unwrap_des3 194 (OM_uint32 * minor_status, 195 const gsskrb5_ctx context_handle, 196 krb5_context context, 197 const gss_buffer_t input_message_buffer, 198 gss_buffer_t output_message_buffer, 199 int * conf_state, 200 gss_qop_t * qop_state, 201 krb5_keyblock *key 202 ) 203 { 204 u_char *p; 205 size_t len; 206 u_char *seq; 207 krb5_data seq_data; 208 u_char cksum[20]; 209 uint32_t seq_number; 210 size_t padlength; 211 OM_uint32 ret; 212 int cstate; 213 krb5_crypto crypto; 214 Checksum csum; 215 int cmp; 216 int token_len; 217 218 if (IS_DCE_STYLE(context_handle)) { 219 token_len = 34 + 8 + 15; /* 57 */ 220 } else { 221 token_len = input_message_buffer->length; 222 } 223 224 p = input_message_buffer->value; 225 ret = _gsskrb5_verify_header (&p, 226 token_len, 227 "\x02\x01", 228 GSS_KRB5_MECHANISM); 229 if (ret) 230 return ret; 231 232 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ 233 return GSS_S_BAD_SIG; 234 p += 2; 235 if (ct_memcmp (p, "\x02\x00", 2) == 0) { 236 cstate = 1; 237 } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { 238 cstate = 0; 239 } else 240 return GSS_S_BAD_MIC; 241 p += 2; 242 if(conf_state != NULL) 243 *conf_state = cstate; 244 if (ct_memcmp (p, "\xff\xff", 2) != 0) 245 return GSS_S_DEFECTIVE_TOKEN; 246 p += 2; 247 p += 28; 248 249 len = p - (u_char *)input_message_buffer->value; 250 251 if(cstate) { 252 /* decrypt data */ 253 krb5_data tmp; 254 255 ret = krb5_crypto_init(context, key, 256 ETYPE_DES3_CBC_NONE, &crypto); 257 if (ret) { 258 *minor_status = ret; 259 return GSS_S_FAILURE; 260 } 261 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, 262 p, input_message_buffer->length - len, &tmp); 263 krb5_crypto_destroy(context, crypto); 264 if (ret) { 265 *minor_status = ret; 266 return GSS_S_FAILURE; 267 } 268 assert (tmp.length == input_message_buffer->length - len); 269 270 memcpy (p, tmp.data, tmp.length); 271 krb5_data_free(&tmp); 272 } 273 274 if (IS_DCE_STYLE(context_handle)) { 275 padlength = 0; 276 } else { 277 /* check pad */ 278 ret = _gssapi_verify_pad(input_message_buffer, 279 input_message_buffer->length - len, 280 &padlength); 281 if (ret) 282 return ret; 283 } 284 285 /* verify sequence number */ 286 287 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 288 289 p -= 28; 290 291 ret = krb5_crypto_init(context, key, 292 ETYPE_DES3_CBC_NONE, &crypto); 293 if (ret) { 294 *minor_status = ret; 295 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 296 return GSS_S_FAILURE; 297 } 298 { 299 DES_cblock ivec; 300 301 memcpy(&ivec, p + 8, 8); 302 ret = krb5_decrypt_ivec (context, 303 crypto, 304 KRB5_KU_USAGE_SEQ, 305 p, 8, &seq_data, 306 &ivec); 307 } 308 krb5_crypto_destroy (context, crypto); 309 if (ret) { 310 *minor_status = ret; 311 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 312 return GSS_S_FAILURE; 313 } 314 if (seq_data.length != 8) { 315 krb5_data_free (&seq_data); 316 *minor_status = 0; 317 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 318 return GSS_S_BAD_MIC; 319 } 320 321 seq = seq_data.data; 322 _gsskrb5_decode_om_uint32(seq, &seq_number); 323 324 if (context_handle->more_flags & LOCAL) 325 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); 326 else 327 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); 328 329 krb5_data_free (&seq_data); 330 if (cmp != 0) { 331 *minor_status = 0; 332 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 333 return GSS_S_BAD_MIC; 334 } 335 336 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 337 if (ret) { 338 *minor_status = 0; 339 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 340 return ret; 341 } 342 343 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 344 345 /* verify checksum */ 346 347 memcpy (cksum, p + 8, 20); 348 349 memcpy (p + 20, p - 8, 8); 350 351 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 352 csum.checksum.length = 20; 353 csum.checksum.data = cksum; 354 355 ret = krb5_crypto_init(context, key, 0, &crypto); 356 if (ret) { 357 *minor_status = ret; 358 return GSS_S_FAILURE; 359 } 360 361 ret = krb5_verify_checksum (context, crypto, 362 KRB5_KU_USAGE_SIGN, 363 p + 20, 364 input_message_buffer->length - len + 8, 365 &csum); 366 krb5_crypto_destroy (context, crypto); 367 if (ret) { 368 *minor_status = ret; 369 return GSS_S_FAILURE; 370 } 371 372 /* copy out data */ 373 374 output_message_buffer->length = input_message_buffer->length 375 - len - padlength - 8; 376 output_message_buffer->value = malloc(output_message_buffer->length); 377 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 378 return GSS_S_FAILURE; 379 memcpy (output_message_buffer->value, 380 p + 36, 381 output_message_buffer->length); 382 return GSS_S_COMPLETE; 383 } 384 385 OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap 386 (OM_uint32 * minor_status, 387 gss_const_ctx_id_t context_handle, 388 const gss_buffer_t input_message_buffer, 389 gss_buffer_t output_message_buffer, 390 int * conf_state, 391 gss_qop_t * qop_state 392 ) 393 { 394 krb5_keyblock *key; 395 krb5_context context; 396 OM_uint32 ret; 397 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; 398 399 output_message_buffer->value = NULL; 400 output_message_buffer->length = 0; 401 if (qop_state != NULL) 402 *qop_state = GSS_C_QOP_DEFAULT; 403 404 GSSAPI_KRB5_INIT (&context); 405 406 if (ctx->more_flags & IS_CFX) 407 return _gssapi_unwrap_cfx (minor_status, ctx, context, 408 input_message_buffer, output_message_buffer, 409 conf_state, qop_state); 410 411 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 412 ret = _gsskrb5i_get_token_key(ctx, context, &key); 413 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 414 if (ret) { 415 *minor_status = ret; 416 return GSS_S_FAILURE; 417 } 418 419 *minor_status = 0; 420 421 switch (key->keytype) { 422 case KRB5_ENCTYPE_DES_CBC_CRC : 423 case KRB5_ENCTYPE_DES_CBC_MD4 : 424 case KRB5_ENCTYPE_DES_CBC_MD5 : 425 #ifdef HEIM_WEAK_CRYPTO 426 ret = unwrap_des (minor_status, ctx, 427 input_message_buffer, output_message_buffer, 428 conf_state, qop_state, key); 429 #else 430 ret = GSS_S_FAILURE; 431 #endif 432 break; 433 case KRB5_ENCTYPE_DES3_CBC_MD5 : 434 case KRB5_ENCTYPE_DES3_CBC_SHA1 : 435 ret = unwrap_des3 (minor_status, ctx, context, 436 input_message_buffer, output_message_buffer, 437 conf_state, qop_state, key); 438 break; 439 case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: 440 case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: 441 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, 442 input_message_buffer, output_message_buffer, 443 conf_state, qop_state, key); 444 break; 445 default : 446 abort(); 447 break; 448 } 449 krb5_free_keyblock (context, key); 450 return ret; 451 } 452