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