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