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