1 /* 2 * Copyright (c) 2003 - 2006 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 /* 37 * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt 38 * 39 * The arcfour message have the following formats: 40 * 41 * MIC token 42 * TOK_ID[2] = 01 01 43 * SGN_ALG[2] = 11 00 44 * Filler[4] 45 * SND_SEQ[8] 46 * SGN_CKSUM[8] 47 * 48 * WRAP token 49 * TOK_ID[2] = 02 01 50 * SGN_ALG[2]; 51 * SEAL_ALG[2] 52 * Filler[2] 53 * SND_SEQ[2] 54 * SGN_CKSUM[8] 55 * Confounder[8] 56 */ 57 58 /* 59 * WRAP in DCE-style have a fixed size header, the oid and length over 60 * the WRAP header is a total of 61 * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE + 62 * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead, 63 * remember the 2 bytes from APPL [0] SEQ). 64 */ 65 66 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 67 #define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13 68 69 70 static krb5_error_code 71 arcfour_mic_key(krb5_context context, krb5_keyblock *key, 72 void *cksum_data, size_t cksum_size, 73 void *key6_data, size_t key6_size) 74 { 75 krb5_error_code ret; 76 77 Checksum cksum_k5; 78 krb5_keyblock key5; 79 char k5_data[16]; 80 81 Checksum cksum_k6; 82 83 char T[4]; 84 85 memset(T, 0, 4); 86 cksum_k5.checksum.data = k5_data; 87 cksum_k5.checksum.length = sizeof(k5_data); 88 89 if (key->keytype == ENCTYPE_ARCFOUR_HMAC_MD5_56) { 90 char L40[14] = "fortybits"; 91 92 memcpy(L40 + 10, T, sizeof(T)); 93 ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, 94 L40, 14, 0, key, &cksum_k5); 95 memset(&k5_data[7], 0xAB, 9); 96 } else { 97 ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, 98 T, 4, 0, key, &cksum_k5); 99 } 100 if (ret) 101 return ret; 102 103 key5.keytype = ENCTYPE_ARCFOUR_HMAC_MD5; 104 key5.keyvalue = cksum_k5.checksum; 105 106 cksum_k6.checksum.data = key6_data; 107 cksum_k6.checksum.length = key6_size; 108 109 return krb5_hmac(context, CKSUMTYPE_RSA_MD5, 110 cksum_data, cksum_size, 0, &key5, &cksum_k6); 111 } 112 113 114 static krb5_error_code 115 arcfour_mic_cksum(krb5_context context, 116 krb5_keyblock *key, unsigned usage, 117 u_char *sgn_cksum, size_t sgn_cksum_sz, 118 const u_char *v1, size_t l1, 119 const void *v2, size_t l2, 120 const void *v3, size_t l3) 121 { 122 Checksum CKSUM; 123 u_char *ptr; 124 size_t len; 125 krb5_crypto crypto; 126 krb5_error_code ret; 127 128 assert(sgn_cksum_sz == 8); 129 130 len = l1 + l2 + l3; 131 132 ptr = malloc(len); 133 if (ptr == NULL) 134 return ENOMEM; 135 136 memcpy(ptr, v1, l1); 137 memcpy(ptr + l1, v2, l2); 138 memcpy(ptr + l1 + l2, v3, l3); 139 140 ret = krb5_crypto_init(context, key, 0, &crypto); 141 if (ret) { 142 free(ptr); 143 return ret; 144 } 145 146 ret = krb5_create_checksum(context, 147 crypto, 148 usage, 149 0, 150 ptr, len, 151 &CKSUM); 152 free(ptr); 153 if (ret == 0) { 154 memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz); 155 free_Checksum(&CKSUM); 156 } 157 krb5_crypto_destroy(context, crypto); 158 159 return ret; 160 } 161 162 163 OM_uint32 164 _gssapi_get_mic_arcfour(OM_uint32 * minor_status, 165 const gsskrb5_ctx context_handle, 166 krb5_context context, 167 gss_qop_t qop_req, 168 const gss_buffer_t message_buffer, 169 gss_buffer_t message_token, 170 krb5_keyblock *key) 171 { 172 krb5_error_code ret; 173 int32_t seq_number; 174 size_t len, total_len; 175 u_char k6_data[16], *p0, *p; 176 EVP_CIPHER_CTX rc4_key; 177 178 _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); 179 180 message_token->length = total_len; 181 message_token->value = malloc (total_len); 182 if (message_token->value == NULL) { 183 *minor_status = ENOMEM; 184 return GSS_S_FAILURE; 185 } 186 187 p0 = _gssapi_make_mech_header(message_token->value, 188 len, 189 GSS_KRB5_MECHANISM); 190 p = p0; 191 192 *p++ = 0x01; /* TOK_ID */ 193 *p++ = 0x01; 194 *p++ = 0x11; /* SGN_ALG */ 195 *p++ = 0x00; 196 *p++ = 0xff; /* Filler */ 197 *p++ = 0xff; 198 *p++ = 0xff; 199 *p++ = 0xff; 200 201 p = NULL; 202 203 ret = arcfour_mic_cksum(context, 204 key, KRB5_KU_USAGE_SIGN, 205 p0 + 16, 8, /* SGN_CKSUM */ 206 p0, 8, /* TOK_ID, SGN_ALG, Filer */ 207 message_buffer->value, message_buffer->length, 208 NULL, 0); 209 if (ret) { 210 _gsskrb5_release_buffer(minor_status, message_token); 211 *minor_status = ret; 212 return GSS_S_FAILURE; 213 } 214 215 ret = arcfour_mic_key(context, key, 216 p0 + 16, 8, /* SGN_CKSUM */ 217 k6_data, sizeof(k6_data)); 218 if (ret) { 219 _gsskrb5_release_buffer(minor_status, message_token); 220 *minor_status = ret; 221 return GSS_S_FAILURE; 222 } 223 224 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 225 krb5_auth_con_getlocalseqnumber (context, 226 context_handle->auth_context, 227 &seq_number); 228 p = p0 + 8; /* SND_SEQ */ 229 _gsskrb5_encode_be_om_uint32(seq_number, p); 230 231 krb5_auth_con_setlocalseqnumber (context, 232 context_handle->auth_context, 233 ++seq_number); 234 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 235 236 memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); 237 238 EVP_CIPHER_CTX_init(&rc4_key); 239 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 240 EVP_Cipher(&rc4_key, p, p, 8); 241 EVP_CIPHER_CTX_cleanup(&rc4_key); 242 243 memset(k6_data, 0, sizeof(k6_data)); 244 245 *minor_status = 0; 246 return GSS_S_COMPLETE; 247 } 248 249 250 OM_uint32 251 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, 252 const gsskrb5_ctx context_handle, 253 krb5_context context, 254 const gss_buffer_t message_buffer, 255 const gss_buffer_t token_buffer, 256 gss_qop_t * qop_state, 257 krb5_keyblock *key, 258 const char *type) 259 { 260 krb5_error_code ret; 261 uint32_t seq_number; 262 OM_uint32 omret; 263 u_char SND_SEQ[8], cksum_data[8], *p; 264 char k6_data[16]; 265 int cmp; 266 267 if (qop_state) 268 *qop_state = 0; 269 270 p = token_buffer->value; 271 omret = _gsskrb5_verify_header (&p, 272 token_buffer->length, 273 type, 274 GSS_KRB5_MECHANISM); 275 if (omret) 276 return omret; 277 278 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ 279 return GSS_S_BAD_SIG; 280 p += 2; 281 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 282 return GSS_S_BAD_MIC; 283 p += 4; 284 285 ret = arcfour_mic_cksum(context, 286 key, KRB5_KU_USAGE_SIGN, 287 cksum_data, sizeof(cksum_data), 288 p - 8, 8, 289 message_buffer->value, message_buffer->length, 290 NULL, 0); 291 if (ret) { 292 *minor_status = ret; 293 return GSS_S_FAILURE; 294 } 295 296 ret = arcfour_mic_key(context, key, 297 cksum_data, sizeof(cksum_data), 298 k6_data, sizeof(k6_data)); 299 if (ret) { 300 *minor_status = ret; 301 return GSS_S_FAILURE; 302 } 303 304 cmp = ct_memcmp(cksum_data, p + 8, 8); 305 if (cmp) { 306 *minor_status = 0; 307 return GSS_S_BAD_MIC; 308 } 309 310 { 311 EVP_CIPHER_CTX rc4_key; 312 313 EVP_CIPHER_CTX_init(&rc4_key); 314 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0); 315 EVP_Cipher(&rc4_key, SND_SEQ, p, 8); 316 EVP_CIPHER_CTX_cleanup(&rc4_key); 317 318 memset(k6_data, 0, sizeof(k6_data)); 319 } 320 321 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); 322 323 if (context_handle->more_flags & LOCAL) 324 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); 325 else 326 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); 327 328 memset(SND_SEQ, 0, sizeof(SND_SEQ)); 329 if (cmp != 0) { 330 *minor_status = 0; 331 return GSS_S_BAD_MIC; 332 } 333 334 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 335 omret = _gssapi_msg_order_check(context_handle->order, seq_number); 336 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 337 if (omret) 338 return omret; 339 340 *minor_status = 0; 341 return GSS_S_COMPLETE; 342 } 343 344 OM_uint32 345 _gssapi_wrap_arcfour(OM_uint32 * minor_status, 346 const gsskrb5_ctx context_handle, 347 krb5_context context, 348 int conf_req_flag, 349 gss_qop_t qop_req, 350 const gss_buffer_t input_message_buffer, 351 int * conf_state, 352 gss_buffer_t output_message_buffer, 353 krb5_keyblock *key) 354 { 355 u_char Klocaldata[16], k6_data[16], *p, *p0; 356 size_t len, total_len, datalen; 357 krb5_keyblock Klocal; 358 krb5_error_code ret; 359 int32_t seq_number; 360 361 if (conf_state) 362 *conf_state = 0; 363 364 datalen = input_message_buffer->length; 365 366 if (IS_DCE_STYLE(context_handle)) { 367 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 368 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 369 total_len += datalen; 370 } else { 371 datalen += 1; /* padding */ 372 len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; 373 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 374 } 375 376 output_message_buffer->length = total_len; 377 output_message_buffer->value = malloc (total_len); 378 if (output_message_buffer->value == NULL) { 379 *minor_status = ENOMEM; 380 return GSS_S_FAILURE; 381 } 382 383 p0 = _gssapi_make_mech_header(output_message_buffer->value, 384 len, 385 GSS_KRB5_MECHANISM); 386 p = p0; 387 388 *p++ = 0x02; /* TOK_ID */ 389 *p++ = 0x01; 390 *p++ = 0x11; /* SGN_ALG */ 391 *p++ = 0x00; 392 if (conf_req_flag) { 393 *p++ = 0x10; /* SEAL_ALG */ 394 *p++ = 0x00; 395 } else { 396 *p++ = 0xff; /* SEAL_ALG */ 397 *p++ = 0xff; 398 } 399 *p++ = 0xff; /* Filler */ 400 *p++ = 0xff; 401 402 p = NULL; 403 404 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 405 krb5_auth_con_getlocalseqnumber (context, 406 context_handle->auth_context, 407 &seq_number); 408 409 _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); 410 411 krb5_auth_con_setlocalseqnumber (context, 412 context_handle->auth_context, 413 ++seq_number); 414 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 415 416 memset (p0 + 8 + 4, 417 (context_handle->more_flags & LOCAL) ? 0 : 0xff, 418 4); 419 420 krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ 421 422 /* p points to data */ 423 p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; 424 memcpy(p, input_message_buffer->value, input_message_buffer->length); 425 426 if (!IS_DCE_STYLE(context_handle)) 427 p[input_message_buffer->length] = 1; /* padding */ 428 429 ret = arcfour_mic_cksum(context, 430 key, KRB5_KU_USAGE_SEAL, 431 p0 + 16, 8, /* SGN_CKSUM */ 432 p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ 433 p0 + 24, 8, /* Confounder */ 434 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, 435 datalen); 436 if (ret) { 437 *minor_status = ret; 438 _gsskrb5_release_buffer(minor_status, output_message_buffer); 439 return GSS_S_FAILURE; 440 } 441 442 { 443 int i; 444 445 Klocal.keytype = key->keytype; 446 Klocal.keyvalue.data = Klocaldata; 447 Klocal.keyvalue.length = sizeof(Klocaldata); 448 449 for (i = 0; i < 16; i++) 450 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; 451 } 452 ret = arcfour_mic_key(context, &Klocal, 453 p0 + 8, 4, /* SND_SEQ */ 454 k6_data, sizeof(k6_data)); 455 memset(Klocaldata, 0, sizeof(Klocaldata)); 456 if (ret) { 457 _gsskrb5_release_buffer(minor_status, output_message_buffer); 458 *minor_status = ret; 459 return GSS_S_FAILURE; 460 } 461 462 463 if(conf_req_flag) { 464 EVP_CIPHER_CTX rc4_key; 465 466 EVP_CIPHER_CTX_init(&rc4_key); 467 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 468 EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen); 469 EVP_CIPHER_CTX_cleanup(&rc4_key); 470 } 471 memset(k6_data, 0, sizeof(k6_data)); 472 473 ret = arcfour_mic_key(context, key, 474 p0 + 16, 8, /* SGN_CKSUM */ 475 k6_data, sizeof(k6_data)); 476 if (ret) { 477 _gsskrb5_release_buffer(minor_status, output_message_buffer); 478 *minor_status = ret; 479 return GSS_S_FAILURE; 480 } 481 482 { 483 EVP_CIPHER_CTX rc4_key; 484 485 EVP_CIPHER_CTX_init(&rc4_key); 486 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 487 EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8); 488 EVP_CIPHER_CTX_cleanup(&rc4_key); 489 memset(k6_data, 0, sizeof(k6_data)); 490 } 491 492 if (conf_state) 493 *conf_state = conf_req_flag; 494 495 *minor_status = 0; 496 return GSS_S_COMPLETE; 497 } 498 499 OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, 500 const gsskrb5_ctx context_handle, 501 krb5_context context, 502 const gss_buffer_t input_message_buffer, 503 gss_buffer_t output_message_buffer, 504 int *conf_state, 505 gss_qop_t *qop_state, 506 krb5_keyblock *key) 507 { 508 u_char Klocaldata[16]; 509 krb5_keyblock Klocal; 510 krb5_error_code ret; 511 uint32_t seq_number; 512 size_t datalen; 513 OM_uint32 omret; 514 u_char k6_data[16], SND_SEQ[8], Confounder[8]; 515 u_char cksum_data[8]; 516 u_char *p, *p0; 517 int cmp; 518 int conf_flag; 519 size_t padlen = 0, len; 520 521 if (conf_state) 522 *conf_state = 0; 523 if (qop_state) 524 *qop_state = 0; 525 526 p0 = input_message_buffer->value; 527 528 if (IS_DCE_STYLE(context_handle)) { 529 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + 530 GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; 531 if (input_message_buffer->length < len) 532 return GSS_S_BAD_MECH; 533 } else { 534 len = input_message_buffer->length; 535 } 536 537 omret = _gssapi_verify_mech_header(&p0, 538 len, 539 GSS_KRB5_MECHANISM); 540 if (omret) 541 return omret; 542 543 /* length of mech header */ 544 len = (p0 - (u_char *)input_message_buffer->value) + 545 GSS_ARCFOUR_WRAP_TOKEN_SIZE; 546 547 if (len > input_message_buffer->length) 548 return GSS_S_BAD_MECH; 549 550 /* length of data */ 551 datalen = input_message_buffer->length - len; 552 553 p = p0; 554 555 if (memcmp(p, "\x02\x01", 2) != 0) 556 return GSS_S_BAD_SIG; 557 p += 2; 558 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ 559 return GSS_S_BAD_SIG; 560 p += 2; 561 562 if (memcmp (p, "\x10\x00", 2) == 0) 563 conf_flag = 1; 564 else if (memcmp (p, "\xff\xff", 2) == 0) 565 conf_flag = 0; 566 else 567 return GSS_S_BAD_SIG; 568 569 p += 2; 570 if (memcmp (p, "\xff\xff", 2) != 0) 571 return GSS_S_BAD_MIC; 572 p = NULL; 573 574 ret = arcfour_mic_key(context, key, 575 p0 + 16, 8, /* SGN_CKSUM */ 576 k6_data, sizeof(k6_data)); 577 if (ret) { 578 *minor_status = ret; 579 return GSS_S_FAILURE; 580 } 581 582 { 583 EVP_CIPHER_CTX rc4_key; 584 585 EVP_CIPHER_CTX_init(&rc4_key); 586 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 587 EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8); 588 EVP_CIPHER_CTX_cleanup(&rc4_key); 589 memset(k6_data, 0, sizeof(k6_data)); 590 } 591 592 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); 593 594 if (context_handle->more_flags & LOCAL) 595 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); 596 else 597 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); 598 599 if (cmp != 0) { 600 *minor_status = 0; 601 return GSS_S_BAD_MIC; 602 } 603 604 { 605 int i; 606 607 Klocal.keytype = key->keytype; 608 Klocal.keyvalue.data = Klocaldata; 609 Klocal.keyvalue.length = sizeof(Klocaldata); 610 611 for (i = 0; i < 16; i++) 612 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; 613 } 614 ret = arcfour_mic_key(context, &Klocal, 615 SND_SEQ, 4, 616 k6_data, sizeof(k6_data)); 617 memset(Klocaldata, 0, sizeof(Klocaldata)); 618 if (ret) { 619 *minor_status = ret; 620 return GSS_S_FAILURE; 621 } 622 623 output_message_buffer->value = malloc(datalen); 624 if (output_message_buffer->value == NULL) { 625 *minor_status = ENOMEM; 626 return GSS_S_FAILURE; 627 } 628 output_message_buffer->length = datalen; 629 630 if(conf_flag) { 631 EVP_CIPHER_CTX rc4_key; 632 633 EVP_CIPHER_CTX_init(&rc4_key); 634 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 635 EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); 636 EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); 637 EVP_CIPHER_CTX_cleanup(&rc4_key); 638 } else { 639 memcpy(Confounder, p0 + 24, 8); /* Confounder */ 640 memcpy(output_message_buffer->value, 641 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, 642 datalen); 643 } 644 memset(k6_data, 0, sizeof(k6_data)); 645 646 if (!IS_DCE_STYLE(context_handle)) { 647 ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); 648 if (ret) { 649 _gsskrb5_release_buffer(minor_status, output_message_buffer); 650 *minor_status = 0; 651 return ret; 652 } 653 output_message_buffer->length -= padlen; 654 } 655 656 ret = arcfour_mic_cksum(context, 657 key, KRB5_KU_USAGE_SEAL, 658 cksum_data, sizeof(cksum_data), 659 p0, 8, 660 Confounder, sizeof(Confounder), 661 output_message_buffer->value, 662 output_message_buffer->length + padlen); 663 if (ret) { 664 _gsskrb5_release_buffer(minor_status, output_message_buffer); 665 *minor_status = ret; 666 return GSS_S_FAILURE; 667 } 668 669 cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ 670 if (cmp) { 671 _gsskrb5_release_buffer(minor_status, output_message_buffer); 672 *minor_status = 0; 673 return GSS_S_BAD_MIC; 674 } 675 676 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 677 omret = _gssapi_msg_order_check(context_handle->order, seq_number); 678 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 679 if (omret) 680 return omret; 681 682 if (conf_state) 683 *conf_state = conf_flag; 684 685 *minor_status = 0; 686 return GSS_S_COMPLETE; 687 } 688 689 static OM_uint32 690 max_wrap_length_arcfour(const gsskrb5_ctx ctx, 691 krb5_crypto crypto, 692 size_t input_length, 693 OM_uint32 *max_input_size) 694 { 695 /* 696 * if GSS_C_DCE_STYLE is in use: 697 * - we only need to encapsulate the WRAP token 698 * However, since this is a fixed since, we just 699 */ 700 if (IS_DCE_STYLE(ctx)) { 701 size_t len, total_len; 702 703 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 704 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 705 706 if (input_length < len) 707 *max_input_size = 0; 708 else 709 *max_input_size = input_length - len; 710 711 } else { 712 size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 713 size_t blocksize = 8; 714 size_t len, total_len; 715 716 len = 8 + input_length + blocksize + extrasize; 717 718 _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 719 720 total_len -= input_length; /* token length */ 721 if (total_len < input_length) { 722 *max_input_size = (input_length - total_len); 723 (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); 724 } else { 725 *max_input_size = 0; 726 } 727 } 728 729 return GSS_S_COMPLETE; 730 } 731 732 OM_uint32 733 _gssapi_wrap_size_arcfour(OM_uint32 *minor_status, 734 const gsskrb5_ctx ctx, 735 krb5_context context, 736 int conf_req_flag, 737 gss_qop_t qop_req, 738 OM_uint32 req_output_size, 739 OM_uint32 *max_input_size, 740 krb5_keyblock *key) 741 { 742 krb5_error_code ret; 743 krb5_crypto crypto; 744 745 ret = krb5_crypto_init(context, key, 0, &crypto); 746 if (ret != 0) { 747 *minor_status = ret; 748 return GSS_S_FAILURE; 749 } 750 751 ret = max_wrap_length_arcfour(ctx, crypto, 752 req_output_size, max_input_size); 753 if (ret != 0) { 754 *minor_status = ret; 755 krb5_crypto_destroy(context, crypto); 756 return GSS_S_FAILURE; 757 } 758 759 krb5_crypto_destroy(context, crypto); 760 761 return GSS_S_COMPLETE; 762 } 763