1 /* $NetBSD: arcfour.c,v 1.1.1.1 2011/04/13 18:14:44 elric Exp $ */ 2 3 /* 4 * Copyright (c) 2003 - 2006 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 /* 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 EVP_CIPHER_CTX 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 EVP_CIPHER_CTX_init(&rc4_key); 241 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 242 EVP_Cipher(&rc4_key, p, p, 8); 243 EVP_CIPHER_CTX_cleanup(&rc4_key); 244 245 memset(k6_data, 0, sizeof(k6_data)); 246 247 *minor_status = 0; 248 return GSS_S_COMPLETE; 249 } 250 251 252 OM_uint32 253 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, 254 const gsskrb5_ctx context_handle, 255 krb5_context context, 256 const gss_buffer_t message_buffer, 257 const gss_buffer_t token_buffer, 258 gss_qop_t * qop_state, 259 krb5_keyblock *key, 260 char *type) 261 { 262 krb5_error_code ret; 263 uint32_t seq_number; 264 OM_uint32 omret; 265 u_char SND_SEQ[8], cksum_data[8], *p; 266 char k6_data[16]; 267 int cmp; 268 269 if (qop_state) 270 *qop_state = 0; 271 272 p = token_buffer->value; 273 omret = _gsskrb5_verify_header (&p, 274 token_buffer->length, 275 (u_char *)type, 276 GSS_KRB5_MECHANISM); 277 if (omret) 278 return omret; 279 280 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ 281 return GSS_S_BAD_SIG; 282 p += 2; 283 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 284 return GSS_S_BAD_MIC; 285 p += 4; 286 287 ret = arcfour_mic_cksum(context, 288 key, KRB5_KU_USAGE_SIGN, 289 cksum_data, sizeof(cksum_data), 290 p - 8, 8, 291 message_buffer->value, message_buffer->length, 292 NULL, 0); 293 if (ret) { 294 *minor_status = ret; 295 return GSS_S_FAILURE; 296 } 297 298 ret = arcfour_mic_key(context, key, 299 cksum_data, sizeof(cksum_data), 300 k6_data, sizeof(k6_data)); 301 if (ret) { 302 *minor_status = ret; 303 return GSS_S_FAILURE; 304 } 305 306 cmp = ct_memcmp(cksum_data, p + 8, 8); 307 if (cmp) { 308 *minor_status = 0; 309 return GSS_S_BAD_MIC; 310 } 311 312 { 313 EVP_CIPHER_CTX rc4_key; 314 315 EVP_CIPHER_CTX_init(&rc4_key); 316 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0); 317 EVP_Cipher(&rc4_key, SND_SEQ, p, 8); 318 EVP_CIPHER_CTX_cleanup(&rc4_key); 319 320 memset(k6_data, 0, sizeof(k6_data)); 321 } 322 323 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); 324 325 if (context_handle->more_flags & LOCAL) 326 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); 327 else 328 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); 329 330 memset(SND_SEQ, 0, sizeof(SND_SEQ)); 331 if (cmp != 0) { 332 *minor_status = 0; 333 return GSS_S_BAD_MIC; 334 } 335 336 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 337 omret = _gssapi_msg_order_check(context_handle->order, seq_number); 338 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 339 if (omret) 340 return omret; 341 342 *minor_status = 0; 343 return GSS_S_COMPLETE; 344 } 345 346 OM_uint32 347 _gssapi_wrap_arcfour(OM_uint32 * minor_status, 348 const gsskrb5_ctx context_handle, 349 krb5_context context, 350 int conf_req_flag, 351 gss_qop_t qop_req, 352 const gss_buffer_t input_message_buffer, 353 int * conf_state, 354 gss_buffer_t output_message_buffer, 355 krb5_keyblock *key) 356 { 357 u_char Klocaldata[16], k6_data[16], *p, *p0; 358 size_t len, total_len, datalen; 359 krb5_keyblock Klocal; 360 krb5_error_code ret; 361 int32_t seq_number; 362 363 if (conf_state) 364 *conf_state = 0; 365 366 datalen = input_message_buffer->length; 367 368 if (IS_DCE_STYLE(context_handle)) { 369 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 370 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 371 total_len += datalen; 372 } else { 373 datalen += 1; /* padding */ 374 len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; 375 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 376 } 377 378 output_message_buffer->length = total_len; 379 output_message_buffer->value = malloc (total_len); 380 if (output_message_buffer->value == NULL) { 381 *minor_status = ENOMEM; 382 return GSS_S_FAILURE; 383 } 384 385 p0 = _gssapi_make_mech_header(output_message_buffer->value, 386 len, 387 GSS_KRB5_MECHANISM); 388 p = p0; 389 390 *p++ = 0x02; /* TOK_ID */ 391 *p++ = 0x01; 392 *p++ = 0x11; /* SGN_ALG */ 393 *p++ = 0x00; 394 if (conf_req_flag) { 395 *p++ = 0x10; /* SEAL_ALG */ 396 *p++ = 0x00; 397 } else { 398 *p++ = 0xff; /* SEAL_ALG */ 399 *p++ = 0xff; 400 } 401 *p++ = 0xff; /* Filler */ 402 *p++ = 0xff; 403 404 p = NULL; 405 406 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 407 krb5_auth_con_getlocalseqnumber (context, 408 context_handle->auth_context, 409 &seq_number); 410 411 _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); 412 413 krb5_auth_con_setlocalseqnumber (context, 414 context_handle->auth_context, 415 ++seq_number); 416 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 417 418 memset (p0 + 8 + 4, 419 (context_handle->more_flags & LOCAL) ? 0 : 0xff, 420 4); 421 422 krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ 423 424 /* p points to data */ 425 p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; 426 memcpy(p, input_message_buffer->value, input_message_buffer->length); 427 428 if (!IS_DCE_STYLE(context_handle)) 429 p[input_message_buffer->length] = 1; /* padding */ 430 431 ret = arcfour_mic_cksum(context, 432 key, KRB5_KU_USAGE_SEAL, 433 p0 + 16, 8, /* SGN_CKSUM */ 434 p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ 435 p0 + 24, 8, /* Confounder */ 436 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, 437 datalen); 438 if (ret) { 439 *minor_status = ret; 440 _gsskrb5_release_buffer(minor_status, output_message_buffer); 441 return GSS_S_FAILURE; 442 } 443 444 { 445 int i; 446 447 Klocal.keytype = key->keytype; 448 Klocal.keyvalue.data = Klocaldata; 449 Klocal.keyvalue.length = sizeof(Klocaldata); 450 451 for (i = 0; i < 16; i++) 452 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; 453 } 454 ret = arcfour_mic_key(context, &Klocal, 455 p0 + 8, 4, /* SND_SEQ */ 456 k6_data, sizeof(k6_data)); 457 memset(Klocaldata, 0, sizeof(Klocaldata)); 458 if (ret) { 459 _gsskrb5_release_buffer(minor_status, output_message_buffer); 460 *minor_status = ret; 461 return GSS_S_FAILURE; 462 } 463 464 465 if(conf_req_flag) { 466 EVP_CIPHER_CTX rc4_key; 467 468 EVP_CIPHER_CTX_init(&rc4_key); 469 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 470 EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen); 471 EVP_CIPHER_CTX_cleanup(&rc4_key); 472 } 473 memset(k6_data, 0, sizeof(k6_data)); 474 475 ret = arcfour_mic_key(context, key, 476 p0 + 16, 8, /* SGN_CKSUM */ 477 k6_data, sizeof(k6_data)); 478 if (ret) { 479 _gsskrb5_release_buffer(minor_status, output_message_buffer); 480 *minor_status = ret; 481 return GSS_S_FAILURE; 482 } 483 484 { 485 EVP_CIPHER_CTX rc4_key; 486 487 EVP_CIPHER_CTX_init(&rc4_key); 488 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 489 EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8); 490 EVP_CIPHER_CTX_cleanup(&rc4_key); 491 memset(k6_data, 0, sizeof(k6_data)); 492 } 493 494 if (conf_state) 495 *conf_state = conf_req_flag; 496 497 *minor_status = 0; 498 return GSS_S_COMPLETE; 499 } 500 501 OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, 502 const gsskrb5_ctx context_handle, 503 krb5_context context, 504 const gss_buffer_t input_message_buffer, 505 gss_buffer_t output_message_buffer, 506 int *conf_state, 507 gss_qop_t *qop_state, 508 krb5_keyblock *key) 509 { 510 u_char Klocaldata[16]; 511 krb5_keyblock Klocal; 512 krb5_error_code ret; 513 uint32_t seq_number; 514 size_t datalen; 515 OM_uint32 omret; 516 u_char k6_data[16], SND_SEQ[8], Confounder[8]; 517 u_char cksum_data[8]; 518 u_char *p, *p0; 519 int cmp; 520 int conf_flag; 521 size_t padlen = 0, len; 522 523 if (conf_state) 524 *conf_state = 0; 525 if (qop_state) 526 *qop_state = 0; 527 528 p0 = input_message_buffer->value; 529 530 if (IS_DCE_STYLE(context_handle)) { 531 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + 532 GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; 533 if (input_message_buffer->length < len) 534 return GSS_S_BAD_MECH; 535 } else { 536 len = input_message_buffer->length; 537 } 538 539 omret = _gssapi_verify_mech_header(&p0, 540 len, 541 GSS_KRB5_MECHANISM); 542 if (omret) 543 return omret; 544 545 /* length of mech header */ 546 len = (p0 - (u_char *)input_message_buffer->value) + 547 GSS_ARCFOUR_WRAP_TOKEN_SIZE; 548 549 if (len > input_message_buffer->length) 550 return GSS_S_BAD_MECH; 551 552 /* length of data */ 553 datalen = input_message_buffer->length - len; 554 555 p = p0; 556 557 if (memcmp(p, "\x02\x01", 2) != 0) 558 return GSS_S_BAD_SIG; 559 p += 2; 560 if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ 561 return GSS_S_BAD_SIG; 562 p += 2; 563 564 if (memcmp (p, "\x10\x00", 2) == 0) 565 conf_flag = 1; 566 else if (memcmp (p, "\xff\xff", 2) == 0) 567 conf_flag = 0; 568 else 569 return GSS_S_BAD_SIG; 570 571 p += 2; 572 if (memcmp (p, "\xff\xff", 2) != 0) 573 return GSS_S_BAD_MIC; 574 p = NULL; 575 576 ret = arcfour_mic_key(context, key, 577 p0 + 16, 8, /* SGN_CKSUM */ 578 k6_data, sizeof(k6_data)); 579 if (ret) { 580 *minor_status = ret; 581 return GSS_S_FAILURE; 582 } 583 584 { 585 EVP_CIPHER_CTX rc4_key; 586 587 EVP_CIPHER_CTX_init(&rc4_key); 588 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 589 EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8); 590 EVP_CIPHER_CTX_cleanup(&rc4_key); 591 memset(k6_data, 0, sizeof(k6_data)); 592 } 593 594 _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); 595 596 if (context_handle->more_flags & LOCAL) 597 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); 598 else 599 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); 600 601 if (cmp != 0) { 602 *minor_status = 0; 603 return GSS_S_BAD_MIC; 604 } 605 606 { 607 int i; 608 609 Klocal.keytype = key->keytype; 610 Klocal.keyvalue.data = Klocaldata; 611 Klocal.keyvalue.length = sizeof(Klocaldata); 612 613 for (i = 0; i < 16; i++) 614 Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; 615 } 616 ret = arcfour_mic_key(context, &Klocal, 617 SND_SEQ, 4, 618 k6_data, sizeof(k6_data)); 619 memset(Klocaldata, 0, sizeof(Klocaldata)); 620 if (ret) { 621 *minor_status = ret; 622 return GSS_S_FAILURE; 623 } 624 625 output_message_buffer->value = malloc(datalen); 626 if (output_message_buffer->value == NULL) { 627 *minor_status = ENOMEM; 628 return GSS_S_FAILURE; 629 } 630 output_message_buffer->length = datalen; 631 632 if(conf_flag) { 633 EVP_CIPHER_CTX rc4_key; 634 635 EVP_CIPHER_CTX_init(&rc4_key); 636 EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); 637 EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); 638 EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); 639 EVP_CIPHER_CTX_cleanup(&rc4_key); 640 } else { 641 memcpy(Confounder, p0 + 24, 8); /* Confounder */ 642 memcpy(output_message_buffer->value, 643 p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, 644 datalen); 645 } 646 memset(k6_data, 0, sizeof(k6_data)); 647 648 if (!IS_DCE_STYLE(context_handle)) { 649 ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); 650 if (ret) { 651 _gsskrb5_release_buffer(minor_status, output_message_buffer); 652 *minor_status = 0; 653 return ret; 654 } 655 output_message_buffer->length -= padlen; 656 } 657 658 ret = arcfour_mic_cksum(context, 659 key, KRB5_KU_USAGE_SEAL, 660 cksum_data, sizeof(cksum_data), 661 p0, 8, 662 Confounder, sizeof(Confounder), 663 output_message_buffer->value, 664 output_message_buffer->length + padlen); 665 if (ret) { 666 _gsskrb5_release_buffer(minor_status, output_message_buffer); 667 *minor_status = ret; 668 return GSS_S_FAILURE; 669 } 670 671 cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ 672 if (cmp) { 673 _gsskrb5_release_buffer(minor_status, output_message_buffer); 674 *minor_status = 0; 675 return GSS_S_BAD_MIC; 676 } 677 678 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 679 omret = _gssapi_msg_order_check(context_handle->order, seq_number); 680 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 681 if (omret) 682 return omret; 683 684 if (conf_state) 685 *conf_state = conf_flag; 686 687 *minor_status = 0; 688 return GSS_S_COMPLETE; 689 } 690 691 static OM_uint32 692 max_wrap_length_arcfour(const gsskrb5_ctx ctx, 693 krb5_crypto crypto, 694 size_t input_length, 695 OM_uint32 *max_input_size) 696 { 697 /* 698 * if GSS_C_DCE_STYLE is in use: 699 * - we only need to encapsulate the WRAP token 700 * However, since this is a fixed since, we just 701 */ 702 if (IS_DCE_STYLE(ctx)) { 703 size_t len, total_len; 704 705 len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 706 _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 707 708 if (input_length < len) 709 *max_input_size = 0; 710 else 711 *max_input_size = input_length - len; 712 713 } else { 714 size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; 715 size_t blocksize = 8; 716 size_t len, total_len; 717 718 len = 8 + input_length + blocksize + extrasize; 719 720 _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 721 722 total_len -= input_length; /* token length */ 723 if (total_len < input_length) { 724 *max_input_size = (input_length - total_len); 725 (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); 726 } else { 727 *max_input_size = 0; 728 } 729 } 730 731 return GSS_S_COMPLETE; 732 } 733 734 OM_uint32 735 _gssapi_wrap_size_arcfour(OM_uint32 *minor_status, 736 const gsskrb5_ctx ctx, 737 krb5_context context, 738 int conf_req_flag, 739 gss_qop_t qop_req, 740 OM_uint32 req_output_size, 741 OM_uint32 *max_input_size, 742 krb5_keyblock *key) 743 { 744 krb5_error_code ret; 745 krb5_crypto crypto; 746 747 ret = krb5_crypto_init(context, key, 0, &crypto); 748 if (ret != 0) { 749 *minor_status = ret; 750 return GSS_S_FAILURE; 751 } 752 753 ret = max_wrap_length_arcfour(ctx, crypto, 754 req_output_size, max_input_size); 755 if (ret != 0) { 756 *minor_status = ret; 757 krb5_crypto_destroy(context, crypto); 758 return GSS_S_FAILURE; 759 } 760 761 krb5_crypto_destroy(context, crypto); 762 763 return GSS_S_COMPLETE; 764 } 765