1178825Sdfr/* 2233294Sstas * Copyright (c) 1997 - 2003 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "gsskrb5_locl.h" 35178825Sdfr 36178825Sdfr/* 37178825Sdfr * Return initiator subkey, or if that doesn't exists, the subkey. 38178825Sdfr */ 39178825Sdfr 40178825Sdfrkrb5_error_code 41178825Sdfr_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, 42178825Sdfr krb5_context context, 43178825Sdfr krb5_keyblock **key) 44178825Sdfr{ 45178825Sdfr krb5_error_code ret; 46178825Sdfr *key = NULL; 47178825Sdfr 48178825Sdfr if (ctx->more_flags & LOCAL) { 49178825Sdfr ret = krb5_auth_con_getlocalsubkey(context, 50233294Sstas ctx->auth_context, 51178825Sdfr key); 52178825Sdfr } else { 53178825Sdfr ret = krb5_auth_con_getremotesubkey(context, 54233294Sstas ctx->auth_context, 55178825Sdfr key); 56178825Sdfr } 57178825Sdfr if (ret == 0 && *key == NULL) 58178825Sdfr ret = krb5_auth_con_getkey(context, 59233294Sstas ctx->auth_context, 60178825Sdfr key); 61178825Sdfr if (ret == 0 && *key == NULL) { 62233294Sstas krb5_set_error_message(context, 0, "No initiator subkey available"); 63178825Sdfr return GSS_KRB5_S_KG_NO_SUBKEY; 64178825Sdfr } 65178825Sdfr return ret; 66178825Sdfr} 67178825Sdfr 68178825Sdfrkrb5_error_code 69178825Sdfr_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, 70178825Sdfr krb5_context context, 71178825Sdfr krb5_keyblock **key) 72178825Sdfr{ 73178825Sdfr krb5_error_code ret; 74178825Sdfr *key = NULL; 75178825Sdfr 76178825Sdfr if (ctx->more_flags & LOCAL) { 77178825Sdfr ret = krb5_auth_con_getremotesubkey(context, 78233294Sstas ctx->auth_context, 79178825Sdfr key); 80178825Sdfr } else { 81178825Sdfr ret = krb5_auth_con_getlocalsubkey(context, 82233294Sstas ctx->auth_context, 83178825Sdfr key); 84178825Sdfr } 85178825Sdfr if (ret == 0 && *key == NULL) { 86233294Sstas krb5_set_error_message(context, 0, "No acceptor subkey available"); 87178825Sdfr return GSS_KRB5_S_KG_NO_SUBKEY; 88178825Sdfr } 89178825Sdfr return ret; 90178825Sdfr} 91178825Sdfr 92178825SdfrOM_uint32 93178825Sdfr_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, 94178825Sdfr krb5_context context, 95178825Sdfr krb5_keyblock **key) 96178825Sdfr{ 97178825Sdfr _gsskrb5i_get_acceptor_subkey(ctx, context, key); 98178825Sdfr if(*key == NULL) { 99178825Sdfr /* 100178825Sdfr * Only use the initiator subkey or ticket session key if an 101178825Sdfr * acceptor subkey was not required. 102178825Sdfr */ 103178825Sdfr if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) 104178825Sdfr _gsskrb5i_get_initiator_subkey(ctx, context, key); 105178825Sdfr } 106178825Sdfr if (*key == NULL) { 107233294Sstas krb5_set_error_message(context, 0, "No token key available"); 108178825Sdfr return GSS_KRB5_S_KG_NO_SUBKEY; 109178825Sdfr } 110178825Sdfr return 0; 111178825Sdfr} 112178825Sdfr 113178825Sdfrstatic OM_uint32 114178825Sdfrsub_wrap_size ( 115178825Sdfr OM_uint32 req_output_size, 116178825Sdfr OM_uint32 * max_input_size, 117178825Sdfr int blocksize, 118178825Sdfr int extrasize 119178825Sdfr ) 120178825Sdfr{ 121233294Sstas size_t len, total_len; 122178825Sdfr 123178825Sdfr len = 8 + req_output_size + blocksize + extrasize; 124178825Sdfr 125178825Sdfr _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 126178825Sdfr 127178825Sdfr total_len -= req_output_size; /* token length */ 128178825Sdfr if (total_len < req_output_size) { 129178825Sdfr *max_input_size = (req_output_size - total_len); 130178825Sdfr (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); 131178825Sdfr } else { 132178825Sdfr *max_input_size = 0; 133178825Sdfr } 134178825Sdfr return GSS_S_COMPLETE; 135178825Sdfr} 136178825Sdfr 137233294SstasOM_uint32 GSSAPI_CALLCONV 138178825Sdfr_gsskrb5_wrap_size_limit ( 139178825Sdfr OM_uint32 * minor_status, 140178825Sdfr const gss_ctx_id_t context_handle, 141178825Sdfr int conf_req_flag, 142178825Sdfr gss_qop_t qop_req, 143178825Sdfr OM_uint32 req_output_size, 144178825Sdfr OM_uint32 * max_input_size 145178825Sdfr ) 146178825Sdfr{ 147178825Sdfr krb5_context context; 148178825Sdfr krb5_keyblock *key; 149178825Sdfr OM_uint32 ret; 150178825Sdfr krb5_keytype keytype; 151178825Sdfr const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 152178825Sdfr 153178825Sdfr GSSAPI_KRB5_INIT (&context); 154178825Sdfr 155233294Sstas if (ctx->more_flags & IS_CFX) 156233294Sstas return _gssapi_wrap_size_cfx(minor_status, ctx, context, 157233294Sstas conf_req_flag, qop_req, 158233294Sstas req_output_size, max_input_size); 159233294Sstas 160178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 161178825Sdfr ret = _gsskrb5i_get_token_key(ctx, context, &key); 162178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 163178825Sdfr if (ret) { 164178825Sdfr *minor_status = ret; 165178825Sdfr return GSS_S_FAILURE; 166178825Sdfr } 167178825Sdfr krb5_enctype_to_keytype (context, key->keytype, &keytype); 168178825Sdfr 169178825Sdfr switch (keytype) { 170178825Sdfr case KEYTYPE_DES : 171233294Sstas#ifdef HEIM_WEAK_CRYPTO 172178825Sdfr ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); 173233294Sstas#else 174233294Sstas ret = GSS_S_FAILURE; 175233294Sstas#endif 176178825Sdfr break; 177233294Sstas case ENCTYPE_ARCFOUR_HMAC_MD5: 178233294Sstas case ENCTYPE_ARCFOUR_HMAC_MD5_56: 179178825Sdfr ret = _gssapi_wrap_size_arcfour(minor_status, ctx, context, 180233294Sstas conf_req_flag, qop_req, 181178825Sdfr req_output_size, max_input_size, key); 182178825Sdfr break; 183178825Sdfr case KEYTYPE_DES3 : 184178825Sdfr ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); 185178825Sdfr break; 186178825Sdfr default : 187233294Sstas abort(); 188178825Sdfr break; 189178825Sdfr } 190178825Sdfr krb5_free_keyblock (context, key); 191178825Sdfr *minor_status = 0; 192178825Sdfr return ret; 193178825Sdfr} 194178825Sdfr 195233294Sstas#ifdef HEIM_WEAK_CRYPTO 196233294Sstas 197178825Sdfrstatic OM_uint32 198178825Sdfrwrap_des 199178825Sdfr (OM_uint32 * minor_status, 200178825Sdfr const gsskrb5_ctx ctx, 201178825Sdfr krb5_context context, 202178825Sdfr int conf_req_flag, 203178825Sdfr gss_qop_t qop_req, 204178825Sdfr const gss_buffer_t input_message_buffer, 205178825Sdfr int * conf_state, 206178825Sdfr gss_buffer_t output_message_buffer, 207178825Sdfr krb5_keyblock *key 208178825Sdfr ) 209178825Sdfr{ 210178825Sdfr u_char *p; 211233294Sstas EVP_MD_CTX *md5; 212178825Sdfr u_char hash[16]; 213178825Sdfr DES_key_schedule schedule; 214233294Sstas EVP_CIPHER_CTX des_ctx; 215178825Sdfr DES_cblock deskey; 216178825Sdfr DES_cblock zero; 217233294Sstas size_t i; 218178825Sdfr int32_t seq_number; 219178825Sdfr size_t len, total_len, padlength, datalen; 220178825Sdfr 221233294Sstas if (IS_DCE_STYLE(ctx)) { 222233294Sstas padlength = 0; 223233294Sstas datalen = input_message_buffer->length; 224233294Sstas len = 22 + 8; 225233294Sstas _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 226233294Sstas total_len += datalen; 227233294Sstas datalen += 8; 228233294Sstas } else { 229233294Sstas padlength = 8 - (input_message_buffer->length % 8); 230233294Sstas datalen = input_message_buffer->length + padlength + 8; 231233294Sstas len = datalen + 22; 232233294Sstas _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 233233294Sstas } 234178825Sdfr 235178825Sdfr output_message_buffer->length = total_len; 236178825Sdfr output_message_buffer->value = malloc (total_len); 237178825Sdfr if (output_message_buffer->value == NULL) { 238178825Sdfr output_message_buffer->length = 0; 239178825Sdfr *minor_status = ENOMEM; 240178825Sdfr return GSS_S_FAILURE; 241178825Sdfr } 242178825Sdfr 243178825Sdfr p = _gsskrb5_make_header(output_message_buffer->value, 244178825Sdfr len, 245178825Sdfr "\x02\x01", /* TOK_ID */ 246178825Sdfr GSS_KRB5_MECHANISM); 247178825Sdfr 248178825Sdfr /* SGN_ALG */ 249178825Sdfr memcpy (p, "\x00\x00", 2); 250178825Sdfr p += 2; 251178825Sdfr /* SEAL_ALG */ 252178825Sdfr if(conf_req_flag) 253178825Sdfr memcpy (p, "\x00\x00", 2); 254178825Sdfr else 255178825Sdfr memcpy (p, "\xff\xff", 2); 256178825Sdfr p += 2; 257178825Sdfr /* Filler */ 258178825Sdfr memcpy (p, "\xff\xff", 2); 259178825Sdfr p += 2; 260178825Sdfr 261178825Sdfr /* fill in later */ 262178825Sdfr memset (p, 0, 16); 263178825Sdfr p += 16; 264178825Sdfr 265178825Sdfr /* confounder + data + pad */ 266178825Sdfr krb5_generate_random_block(p, 8); 267178825Sdfr memcpy (p + 8, input_message_buffer->value, 268178825Sdfr input_message_buffer->length); 269178825Sdfr memset (p + 8 + input_message_buffer->length, padlength, padlength); 270178825Sdfr 271178825Sdfr /* checksum */ 272233294Sstas md5 = EVP_MD_CTX_create(); 273233294Sstas EVP_DigestInit_ex(md5, EVP_md5(), NULL); 274233294Sstas EVP_DigestUpdate(md5, p - 24, 8); 275233294Sstas EVP_DigestUpdate(md5, p, datalen); 276233294Sstas EVP_DigestFinal_ex(md5, hash, NULL); 277233294Sstas EVP_MD_CTX_destroy(md5); 278178825Sdfr 279178825Sdfr memset (&zero, 0, sizeof(zero)); 280178825Sdfr memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 281233294Sstas DES_set_key_unchecked (&deskey, &schedule); 282178825Sdfr DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 283178825Sdfr &schedule, &zero); 284178825Sdfr memcpy (p - 8, hash, 8); 285178825Sdfr 286178825Sdfr /* sequence number */ 287178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 288178825Sdfr krb5_auth_con_getlocalseqnumber (context, 289178825Sdfr ctx->auth_context, 290178825Sdfr &seq_number); 291178825Sdfr 292178825Sdfr p -= 16; 293178825Sdfr p[0] = (seq_number >> 0) & 0xFF; 294178825Sdfr p[1] = (seq_number >> 8) & 0xFF; 295178825Sdfr p[2] = (seq_number >> 16) & 0xFF; 296178825Sdfr p[3] = (seq_number >> 24) & 0xFF; 297178825Sdfr memset (p + 4, 298178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 299178825Sdfr 4); 300178825Sdfr 301233294Sstas EVP_CIPHER_CTX_init(&des_ctx); 302233294Sstas EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); 303233294Sstas EVP_Cipher(&des_ctx, p, p, 8); 304233294Sstas EVP_CIPHER_CTX_cleanup(&des_ctx); 305178825Sdfr 306178825Sdfr krb5_auth_con_setlocalseqnumber (context, 307178825Sdfr ctx->auth_context, 308178825Sdfr ++seq_number); 309178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 310178825Sdfr 311178825Sdfr /* encrypt the data */ 312178825Sdfr p += 16; 313178825Sdfr 314178825Sdfr if(conf_req_flag) { 315178825Sdfr memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 316178825Sdfr 317178825Sdfr for (i = 0; i < sizeof(deskey); ++i) 318178825Sdfr deskey[i] ^= 0xf0; 319233294Sstas 320233294Sstas EVP_CIPHER_CTX_init(&des_ctx); 321233294Sstas EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 1); 322233294Sstas EVP_Cipher(&des_ctx, p, p, datalen); 323233294Sstas EVP_CIPHER_CTX_cleanup(&des_ctx); 324178825Sdfr } 325178825Sdfr memset (deskey, 0, sizeof(deskey)); 326178825Sdfr memset (&schedule, 0, sizeof(schedule)); 327178825Sdfr 328178825Sdfr if(conf_state != NULL) 329178825Sdfr *conf_state = conf_req_flag; 330178825Sdfr *minor_status = 0; 331178825Sdfr return GSS_S_COMPLETE; 332178825Sdfr} 333178825Sdfr 334233294Sstas#endif 335233294Sstas 336178825Sdfrstatic OM_uint32 337178825Sdfrwrap_des3 338178825Sdfr (OM_uint32 * minor_status, 339178825Sdfr const gsskrb5_ctx ctx, 340178825Sdfr krb5_context context, 341178825Sdfr int conf_req_flag, 342178825Sdfr gss_qop_t qop_req, 343178825Sdfr const gss_buffer_t input_message_buffer, 344178825Sdfr int * conf_state, 345178825Sdfr gss_buffer_t output_message_buffer, 346178825Sdfr krb5_keyblock *key 347178825Sdfr ) 348178825Sdfr{ 349178825Sdfr u_char *p; 350178825Sdfr u_char seq[8]; 351178825Sdfr int32_t seq_number; 352178825Sdfr size_t len, total_len, padlength, datalen; 353178825Sdfr uint32_t ret; 354178825Sdfr krb5_crypto crypto; 355178825Sdfr Checksum cksum; 356178825Sdfr krb5_data encdata; 357178825Sdfr 358233294Sstas if (IS_DCE_STYLE(ctx)) { 359233294Sstas padlength = 0; 360233294Sstas datalen = input_message_buffer->length; 361233294Sstas len = 34 + 8; 362233294Sstas _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 363233294Sstas total_len += datalen; 364233294Sstas datalen += 8; 365233294Sstas } else { 366233294Sstas padlength = 8 - (input_message_buffer->length % 8); 367233294Sstas datalen = input_message_buffer->length + padlength + 8; 368233294Sstas len = datalen + 34; 369233294Sstas _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 370233294Sstas } 371178825Sdfr 372178825Sdfr output_message_buffer->length = total_len; 373178825Sdfr output_message_buffer->value = malloc (total_len); 374178825Sdfr if (output_message_buffer->value == NULL) { 375178825Sdfr output_message_buffer->length = 0; 376178825Sdfr *minor_status = ENOMEM; 377178825Sdfr return GSS_S_FAILURE; 378178825Sdfr } 379178825Sdfr 380178825Sdfr p = _gsskrb5_make_header(output_message_buffer->value, 381178825Sdfr len, 382178825Sdfr "\x02\x01", /* TOK_ID */ 383233294Sstas GSS_KRB5_MECHANISM); 384178825Sdfr 385178825Sdfr /* SGN_ALG */ 386178825Sdfr memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */ 387178825Sdfr p += 2; 388178825Sdfr /* SEAL_ALG */ 389178825Sdfr if(conf_req_flag) 390178825Sdfr memcpy (p, "\x02\x00", 2); /* DES3-KD */ 391178825Sdfr else 392178825Sdfr memcpy (p, "\xff\xff", 2); 393178825Sdfr p += 2; 394178825Sdfr /* Filler */ 395178825Sdfr memcpy (p, "\xff\xff", 2); 396178825Sdfr p += 2; 397178825Sdfr 398178825Sdfr /* calculate checksum (the above + confounder + data + pad) */ 399178825Sdfr 400178825Sdfr memcpy (p + 20, p - 8, 8); 401178825Sdfr krb5_generate_random_block(p + 28, 8); 402178825Sdfr memcpy (p + 28 + 8, input_message_buffer->value, 403178825Sdfr input_message_buffer->length); 404178825Sdfr memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); 405178825Sdfr 406178825Sdfr ret = krb5_crypto_init(context, key, 0, &crypto); 407178825Sdfr if (ret) { 408178825Sdfr free (output_message_buffer->value); 409178825Sdfr output_message_buffer->length = 0; 410178825Sdfr output_message_buffer->value = NULL; 411178825Sdfr *minor_status = ret; 412178825Sdfr return GSS_S_FAILURE; 413178825Sdfr } 414178825Sdfr 415178825Sdfr ret = krb5_create_checksum (context, 416178825Sdfr crypto, 417178825Sdfr KRB5_KU_USAGE_SIGN, 418178825Sdfr 0, 419178825Sdfr p + 20, 420178825Sdfr datalen + 8, 421178825Sdfr &cksum); 422178825Sdfr krb5_crypto_destroy (context, crypto); 423178825Sdfr if (ret) { 424178825Sdfr free (output_message_buffer->value); 425178825Sdfr output_message_buffer->length = 0; 426178825Sdfr output_message_buffer->value = NULL; 427178825Sdfr *minor_status = ret; 428178825Sdfr return GSS_S_FAILURE; 429178825Sdfr } 430178825Sdfr 431178825Sdfr /* zero out SND_SEQ + SGN_CKSUM in case */ 432178825Sdfr memset (p, 0, 28); 433178825Sdfr 434178825Sdfr memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 435178825Sdfr free_Checksum (&cksum); 436178825Sdfr 437178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 438178825Sdfr /* sequence number */ 439178825Sdfr krb5_auth_con_getlocalseqnumber (context, 440178825Sdfr ctx->auth_context, 441178825Sdfr &seq_number); 442178825Sdfr 443178825Sdfr seq[0] = (seq_number >> 0) & 0xFF; 444178825Sdfr seq[1] = (seq_number >> 8) & 0xFF; 445178825Sdfr seq[2] = (seq_number >> 16) & 0xFF; 446178825Sdfr seq[3] = (seq_number >> 24) & 0xFF; 447178825Sdfr memset (seq + 4, 448178825Sdfr (ctx->more_flags & LOCAL) ? 0 : 0xFF, 449178825Sdfr 4); 450178825Sdfr 451178825Sdfr 452178825Sdfr ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, 453178825Sdfr &crypto); 454178825Sdfr if (ret) { 455178825Sdfr free (output_message_buffer->value); 456178825Sdfr output_message_buffer->length = 0; 457178825Sdfr output_message_buffer->value = NULL; 458178825Sdfr *minor_status = ret; 459178825Sdfr return GSS_S_FAILURE; 460178825Sdfr } 461178825Sdfr 462178825Sdfr { 463178825Sdfr DES_cblock ivec; 464178825Sdfr 465178825Sdfr memcpy (&ivec, p + 8, 8); 466178825Sdfr ret = krb5_encrypt_ivec (context, 467178825Sdfr crypto, 468178825Sdfr KRB5_KU_USAGE_SEQ, 469178825Sdfr seq, 8, &encdata, 470178825Sdfr &ivec); 471178825Sdfr } 472178825Sdfr krb5_crypto_destroy (context, crypto); 473178825Sdfr if (ret) { 474178825Sdfr free (output_message_buffer->value); 475178825Sdfr output_message_buffer->length = 0; 476178825Sdfr output_message_buffer->value = NULL; 477178825Sdfr *minor_status = ret; 478178825Sdfr return GSS_S_FAILURE; 479178825Sdfr } 480233294Sstas 481178825Sdfr assert (encdata.length == 8); 482178825Sdfr 483178825Sdfr memcpy (p, encdata.data, encdata.length); 484178825Sdfr krb5_data_free (&encdata); 485178825Sdfr 486178825Sdfr krb5_auth_con_setlocalseqnumber (context, 487178825Sdfr ctx->auth_context, 488178825Sdfr ++seq_number); 489178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 490178825Sdfr 491178825Sdfr /* encrypt the data */ 492178825Sdfr p += 28; 493178825Sdfr 494178825Sdfr if(conf_req_flag) { 495178825Sdfr krb5_data tmp; 496178825Sdfr 497178825Sdfr ret = krb5_crypto_init(context, key, 498178825Sdfr ETYPE_DES3_CBC_NONE, &crypto); 499178825Sdfr if (ret) { 500178825Sdfr free (output_message_buffer->value); 501178825Sdfr output_message_buffer->length = 0; 502178825Sdfr output_message_buffer->value = NULL; 503178825Sdfr *minor_status = ret; 504178825Sdfr return GSS_S_FAILURE; 505178825Sdfr } 506178825Sdfr ret = krb5_encrypt(context, crypto, KRB5_KU_USAGE_SEAL, 507178825Sdfr p, datalen, &tmp); 508178825Sdfr krb5_crypto_destroy(context, crypto); 509178825Sdfr if (ret) { 510178825Sdfr free (output_message_buffer->value); 511178825Sdfr output_message_buffer->length = 0; 512178825Sdfr output_message_buffer->value = NULL; 513178825Sdfr *minor_status = ret; 514178825Sdfr return GSS_S_FAILURE; 515178825Sdfr } 516178825Sdfr assert (tmp.length == datalen); 517178825Sdfr 518178825Sdfr memcpy (p, tmp.data, datalen); 519178825Sdfr krb5_data_free(&tmp); 520178825Sdfr } 521178825Sdfr if(conf_state != NULL) 522178825Sdfr *conf_state = conf_req_flag; 523178825Sdfr *minor_status = 0; 524178825Sdfr return GSS_S_COMPLETE; 525178825Sdfr} 526178825Sdfr 527233294SstasOM_uint32 GSSAPI_CALLCONV 528233294Sstas_gsskrb5_wrap 529178825Sdfr (OM_uint32 * minor_status, 530178825Sdfr const gss_ctx_id_t context_handle, 531178825Sdfr int conf_req_flag, 532178825Sdfr gss_qop_t qop_req, 533178825Sdfr const gss_buffer_t input_message_buffer, 534178825Sdfr int * conf_state, 535178825Sdfr gss_buffer_t output_message_buffer 536178825Sdfr ) 537178825Sdfr{ 538178825Sdfr krb5_context context; 539178825Sdfr krb5_keyblock *key; 540178825Sdfr OM_uint32 ret; 541178825Sdfr krb5_keytype keytype; 542178825Sdfr const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 543178825Sdfr 544233294Sstas output_message_buffer->value = NULL; 545233294Sstas output_message_buffer->length = 0; 546233294Sstas 547178825Sdfr GSSAPI_KRB5_INIT (&context); 548178825Sdfr 549233294Sstas if (ctx->more_flags & IS_CFX) 550233294Sstas return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag, 551233294Sstas input_message_buffer, conf_state, 552233294Sstas output_message_buffer); 553233294Sstas 554178825Sdfr HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 555178825Sdfr ret = _gsskrb5i_get_token_key(ctx, context, &key); 556178825Sdfr HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 557178825Sdfr if (ret) { 558178825Sdfr *minor_status = ret; 559178825Sdfr return GSS_S_FAILURE; 560178825Sdfr } 561178825Sdfr krb5_enctype_to_keytype (context, key->keytype, &keytype); 562178825Sdfr 563178825Sdfr switch (keytype) { 564178825Sdfr case KEYTYPE_DES : 565233294Sstas#ifdef HEIM_WEAK_CRYPTO 566178825Sdfr ret = wrap_des (minor_status, ctx, context, conf_req_flag, 567178825Sdfr qop_req, input_message_buffer, conf_state, 568178825Sdfr output_message_buffer, key); 569233294Sstas#else 570233294Sstas ret = GSS_S_FAILURE; 571233294Sstas#endif 572178825Sdfr break; 573178825Sdfr case KEYTYPE_DES3 : 574178825Sdfr ret = wrap_des3 (minor_status, ctx, context, conf_req_flag, 575178825Sdfr qop_req, input_message_buffer, conf_state, 576178825Sdfr output_message_buffer, key); 577178825Sdfr break; 578178825Sdfr case KEYTYPE_ARCFOUR: 579178825Sdfr case KEYTYPE_ARCFOUR_56: 580178825Sdfr ret = _gssapi_wrap_arcfour (minor_status, ctx, context, conf_req_flag, 581178825Sdfr qop_req, input_message_buffer, conf_state, 582178825Sdfr output_message_buffer, key); 583178825Sdfr break; 584178825Sdfr default : 585233294Sstas abort(); 586178825Sdfr break; 587178825Sdfr } 588178825Sdfr krb5_free_keyblock (context, key); 589178825Sdfr return ret; 590178825Sdfr} 591