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