1c19800e8SDoug Rabson /* 2ae771770SStanislav Sedov * Copyright (c) 1997 - 2003 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 * Return initiator subkey, or if that doesn't exists, the subkey. 38c19800e8SDoug Rabson */ 39c19800e8SDoug Rabson 40c19800e8SDoug Rabson krb5_error_code 41c19800e8SDoug Rabson _gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, 42c19800e8SDoug Rabson krb5_context context, 43c19800e8SDoug Rabson krb5_keyblock **key) 44c19800e8SDoug Rabson { 45c19800e8SDoug Rabson krb5_error_code ret; 46c19800e8SDoug Rabson *key = NULL; 47c19800e8SDoug Rabson 48c19800e8SDoug Rabson if (ctx->more_flags & LOCAL) { 49c19800e8SDoug Rabson ret = krb5_auth_con_getlocalsubkey(context, 50c19800e8SDoug Rabson ctx->auth_context, 51c19800e8SDoug Rabson key); 52c19800e8SDoug Rabson } else { 53c19800e8SDoug Rabson ret = krb5_auth_con_getremotesubkey(context, 54c19800e8SDoug Rabson ctx->auth_context, 55c19800e8SDoug Rabson key); 56c19800e8SDoug Rabson } 57c19800e8SDoug Rabson if (ret == 0 && *key == NULL) 58c19800e8SDoug Rabson ret = krb5_auth_con_getkey(context, 59c19800e8SDoug Rabson ctx->auth_context, 60c19800e8SDoug Rabson key); 61c19800e8SDoug Rabson if (ret == 0 && *key == NULL) { 62ae771770SStanislav Sedov krb5_set_error_message(context, 0, "No initiator subkey available"); 63c19800e8SDoug Rabson return GSS_KRB5_S_KG_NO_SUBKEY; 64c19800e8SDoug Rabson } 65c19800e8SDoug Rabson return ret; 66c19800e8SDoug Rabson } 67c19800e8SDoug Rabson 68c19800e8SDoug Rabson krb5_error_code 69c19800e8SDoug Rabson _gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, 70c19800e8SDoug Rabson krb5_context context, 71c19800e8SDoug Rabson krb5_keyblock **key) 72c19800e8SDoug Rabson { 73c19800e8SDoug Rabson krb5_error_code ret; 74c19800e8SDoug Rabson *key = NULL; 75c19800e8SDoug Rabson 76c19800e8SDoug Rabson if (ctx->more_flags & LOCAL) { 77c19800e8SDoug Rabson ret = krb5_auth_con_getremotesubkey(context, 78c19800e8SDoug Rabson ctx->auth_context, 79c19800e8SDoug Rabson key); 80c19800e8SDoug Rabson } else { 81c19800e8SDoug Rabson ret = krb5_auth_con_getlocalsubkey(context, 82c19800e8SDoug Rabson ctx->auth_context, 83c19800e8SDoug Rabson key); 84c19800e8SDoug Rabson } 85c19800e8SDoug Rabson if (ret == 0 && *key == NULL) { 86ae771770SStanislav Sedov krb5_set_error_message(context, 0, "No acceptor subkey available"); 87c19800e8SDoug Rabson return GSS_KRB5_S_KG_NO_SUBKEY; 88c19800e8SDoug Rabson } 89c19800e8SDoug Rabson return ret; 90c19800e8SDoug Rabson } 91c19800e8SDoug Rabson 92c19800e8SDoug Rabson OM_uint32 93c19800e8SDoug Rabson _gsskrb5i_get_token_key(const gsskrb5_ctx ctx, 94c19800e8SDoug Rabson krb5_context context, 95c19800e8SDoug Rabson krb5_keyblock **key) 96c19800e8SDoug Rabson { 97c19800e8SDoug Rabson _gsskrb5i_get_acceptor_subkey(ctx, context, key); 98c19800e8SDoug Rabson if(*key == NULL) { 99c19800e8SDoug Rabson /* 100c19800e8SDoug Rabson * Only use the initiator subkey or ticket session key if an 101c19800e8SDoug Rabson * acceptor subkey was not required. 102c19800e8SDoug Rabson */ 103c19800e8SDoug Rabson if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) 104c19800e8SDoug Rabson _gsskrb5i_get_initiator_subkey(ctx, context, key); 105c19800e8SDoug Rabson } 106c19800e8SDoug Rabson if (*key == NULL) { 107ae771770SStanislav Sedov krb5_set_error_message(context, 0, "No token key available"); 108c19800e8SDoug Rabson return GSS_KRB5_S_KG_NO_SUBKEY; 109c19800e8SDoug Rabson } 110c19800e8SDoug Rabson return 0; 111c19800e8SDoug Rabson } 112c19800e8SDoug Rabson 113c19800e8SDoug Rabson static OM_uint32 114c19800e8SDoug Rabson sub_wrap_size ( 115c19800e8SDoug Rabson OM_uint32 req_output_size, 116c19800e8SDoug Rabson OM_uint32 * max_input_size, 117c19800e8SDoug Rabson int blocksize, 118c19800e8SDoug Rabson int extrasize 119c19800e8SDoug Rabson ) 120c19800e8SDoug Rabson { 121c19800e8SDoug Rabson size_t len, total_len; 122c19800e8SDoug Rabson 123c19800e8SDoug Rabson len = 8 + req_output_size + blocksize + extrasize; 124c19800e8SDoug Rabson 125c19800e8SDoug Rabson _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); 126c19800e8SDoug Rabson 127c19800e8SDoug Rabson total_len -= req_output_size; /* token length */ 128c19800e8SDoug Rabson if (total_len < req_output_size) { 129c19800e8SDoug Rabson *max_input_size = (req_output_size - total_len); 130c19800e8SDoug Rabson (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); 131c19800e8SDoug Rabson } else { 132c19800e8SDoug Rabson *max_input_size = 0; 133c19800e8SDoug Rabson } 134c19800e8SDoug Rabson return GSS_S_COMPLETE; 135c19800e8SDoug Rabson } 136c19800e8SDoug Rabson 137ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 138c19800e8SDoug Rabson _gsskrb5_wrap_size_limit ( 139c19800e8SDoug Rabson OM_uint32 * minor_status, 140c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 141c19800e8SDoug Rabson int conf_req_flag, 142c19800e8SDoug Rabson gss_qop_t qop_req, 143c19800e8SDoug Rabson OM_uint32 req_output_size, 144c19800e8SDoug Rabson OM_uint32 * max_input_size 145c19800e8SDoug Rabson ) 146c19800e8SDoug Rabson { 147c19800e8SDoug Rabson krb5_context context; 148c19800e8SDoug Rabson krb5_keyblock *key; 149c19800e8SDoug Rabson OM_uint32 ret; 150c19800e8SDoug Rabson krb5_keytype keytype; 151c19800e8SDoug Rabson const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 152c19800e8SDoug Rabson 153c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context); 154c19800e8SDoug Rabson 155ae771770SStanislav Sedov if (ctx->more_flags & IS_CFX) 156ae771770SStanislav Sedov return _gssapi_wrap_size_cfx(minor_status, ctx, context, 157ae771770SStanislav Sedov conf_req_flag, qop_req, 158ae771770SStanislav Sedov req_output_size, max_input_size); 159ae771770SStanislav Sedov 160c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 161c19800e8SDoug Rabson ret = _gsskrb5i_get_token_key(ctx, context, &key); 162c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 163c19800e8SDoug Rabson if (ret) { 164c19800e8SDoug Rabson *minor_status = ret; 165c19800e8SDoug Rabson return GSS_S_FAILURE; 166c19800e8SDoug Rabson } 167c19800e8SDoug Rabson krb5_enctype_to_keytype (context, key->keytype, &keytype); 168c19800e8SDoug Rabson 169c19800e8SDoug Rabson switch (keytype) { 170c19800e8SDoug Rabson case KEYTYPE_DES : 171ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO 172c19800e8SDoug Rabson ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); 173ae771770SStanislav Sedov #else 174ae771770SStanislav Sedov ret = GSS_S_FAILURE; 175ae771770SStanislav Sedov #endif 176c19800e8SDoug Rabson break; 177ae771770SStanislav Sedov case ENCTYPE_ARCFOUR_HMAC_MD5: 178ae771770SStanislav Sedov case ENCTYPE_ARCFOUR_HMAC_MD5_56: 179c19800e8SDoug Rabson ret = _gssapi_wrap_size_arcfour(minor_status, ctx, context, 180c19800e8SDoug Rabson conf_req_flag, qop_req, 181c19800e8SDoug Rabson req_output_size, max_input_size, key); 182c19800e8SDoug Rabson break; 183c19800e8SDoug Rabson case KEYTYPE_DES3 : 184c19800e8SDoug Rabson ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); 185c19800e8SDoug Rabson break; 186c19800e8SDoug Rabson default : 187ae771770SStanislav Sedov abort(); 188c19800e8SDoug Rabson break; 189c19800e8SDoug Rabson } 190c19800e8SDoug Rabson krb5_free_keyblock (context, key); 191c19800e8SDoug Rabson *minor_status = 0; 192c19800e8SDoug Rabson return ret; 193c19800e8SDoug Rabson } 194c19800e8SDoug Rabson 195ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO 196ae771770SStanislav Sedov 197c19800e8SDoug Rabson static OM_uint32 198c19800e8SDoug Rabson wrap_des 199c19800e8SDoug Rabson (OM_uint32 * minor_status, 200c19800e8SDoug Rabson const gsskrb5_ctx ctx, 201c19800e8SDoug Rabson krb5_context context, 202c19800e8SDoug Rabson int conf_req_flag, 203c19800e8SDoug Rabson gss_qop_t qop_req, 204c19800e8SDoug Rabson const gss_buffer_t input_message_buffer, 205c19800e8SDoug Rabson int * conf_state, 206c19800e8SDoug Rabson gss_buffer_t output_message_buffer, 207c19800e8SDoug Rabson krb5_keyblock *key 208c19800e8SDoug Rabson ) 209c19800e8SDoug Rabson { 210c19800e8SDoug Rabson u_char *p; 211ae771770SStanislav Sedov EVP_MD_CTX *md5; 212c19800e8SDoug Rabson u_char hash[16]; 213c19800e8SDoug Rabson DES_key_schedule schedule; 214*e4456411SJohn Baldwin EVP_CIPHER_CTX *des_ctx; 215c19800e8SDoug Rabson DES_cblock deskey; 216c19800e8SDoug Rabson DES_cblock zero; 217ae771770SStanislav Sedov size_t i; 218c19800e8SDoug Rabson int32_t seq_number; 219c19800e8SDoug Rabson size_t len, total_len, padlength, datalen; 220c19800e8SDoug Rabson 221ae771770SStanislav Sedov if (IS_DCE_STYLE(ctx)) { 222ae771770SStanislav Sedov padlength = 0; 223ae771770SStanislav Sedov datalen = input_message_buffer->length; 224ae771770SStanislav Sedov len = 22 + 8; 225ae771770SStanislav Sedov _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 226ae771770SStanislav Sedov total_len += datalen; 227ae771770SStanislav Sedov datalen += 8; 228ae771770SStanislav Sedov } else { 229c19800e8SDoug Rabson padlength = 8 - (input_message_buffer->length % 8); 230c19800e8SDoug Rabson datalen = input_message_buffer->length + padlength + 8; 231c19800e8SDoug Rabson len = datalen + 22; 232c19800e8SDoug Rabson _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 233ae771770SStanislav Sedov } 234c19800e8SDoug Rabson 235c19800e8SDoug Rabson output_message_buffer->length = total_len; 236c19800e8SDoug Rabson output_message_buffer->value = malloc (total_len); 237c19800e8SDoug Rabson if (output_message_buffer->value == NULL) { 238c19800e8SDoug Rabson output_message_buffer->length = 0; 239c19800e8SDoug Rabson *minor_status = ENOMEM; 240c19800e8SDoug Rabson return GSS_S_FAILURE; 241c19800e8SDoug Rabson } 242c19800e8SDoug Rabson 243c19800e8SDoug Rabson p = _gsskrb5_make_header(output_message_buffer->value, 244c19800e8SDoug Rabson len, 245c19800e8SDoug Rabson "\x02\x01", /* TOK_ID */ 246c19800e8SDoug Rabson GSS_KRB5_MECHANISM); 247c19800e8SDoug Rabson 248c19800e8SDoug Rabson /* SGN_ALG */ 249c19800e8SDoug Rabson memcpy (p, "\x00\x00", 2); 250c19800e8SDoug Rabson p += 2; 251c19800e8SDoug Rabson /* SEAL_ALG */ 252c19800e8SDoug Rabson if(conf_req_flag) 253c19800e8SDoug Rabson memcpy (p, "\x00\x00", 2); 254c19800e8SDoug Rabson else 255c19800e8SDoug Rabson memcpy (p, "\xff\xff", 2); 256c19800e8SDoug Rabson p += 2; 257c19800e8SDoug Rabson /* Filler */ 258c19800e8SDoug Rabson memcpy (p, "\xff\xff", 2); 259c19800e8SDoug Rabson p += 2; 260c19800e8SDoug Rabson 261c19800e8SDoug Rabson /* fill in later */ 262c19800e8SDoug Rabson memset (p, 0, 16); 263c19800e8SDoug Rabson p += 16; 264c19800e8SDoug Rabson 265c19800e8SDoug Rabson /* confounder + data + pad */ 266c19800e8SDoug Rabson krb5_generate_random_block(p, 8); 267c19800e8SDoug Rabson memcpy (p + 8, input_message_buffer->value, 268c19800e8SDoug Rabson input_message_buffer->length); 269c19800e8SDoug Rabson memset (p + 8 + input_message_buffer->length, padlength, padlength); 270c19800e8SDoug Rabson 271c19800e8SDoug Rabson /* checksum */ 272ae771770SStanislav Sedov md5 = EVP_MD_CTX_create(); 273ae771770SStanislav Sedov EVP_DigestInit_ex(md5, EVP_md5(), NULL); 274ae771770SStanislav Sedov EVP_DigestUpdate(md5, p - 24, 8); 275ae771770SStanislav Sedov EVP_DigestUpdate(md5, p, datalen); 276ae771770SStanislav Sedov EVP_DigestFinal_ex(md5, hash, NULL); 277ae771770SStanislav Sedov EVP_MD_CTX_destroy(md5); 278c19800e8SDoug Rabson 279c19800e8SDoug Rabson memset (&zero, 0, sizeof(zero)); 280c19800e8SDoug Rabson memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 281ae771770SStanislav Sedov DES_set_key_unchecked (&deskey, &schedule); 282c19800e8SDoug Rabson DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 283c19800e8SDoug Rabson &schedule, &zero); 284c19800e8SDoug Rabson memcpy (p - 8, hash, 8); 285c19800e8SDoug Rabson 286*e4456411SJohn Baldwin des_ctx = EVP_CIPHER_CTX_new(); 287*e4456411SJohn Baldwin if (des_ctx == NULL) { 288*e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey)); 289*e4456411SJohn Baldwin memset (&schedule, 0, sizeof(schedule)); 290*e4456411SJohn Baldwin free(output_message_buffer->value); 291*e4456411SJohn Baldwin output_message_buffer->value = NULL; 292*e4456411SJohn Baldwin output_message_buffer->length = 0; 293*e4456411SJohn Baldwin *minor_status = ENOMEM; 294*e4456411SJohn Baldwin return GSS_S_FAILURE; 295*e4456411SJohn Baldwin } 296*e4456411SJohn Baldwin 297c19800e8SDoug Rabson /* sequence number */ 298c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 299c19800e8SDoug Rabson krb5_auth_con_getlocalseqnumber (context, 300c19800e8SDoug Rabson ctx->auth_context, 301c19800e8SDoug Rabson &seq_number); 302c19800e8SDoug Rabson 303c19800e8SDoug Rabson p -= 16; 304c19800e8SDoug Rabson p[0] = (seq_number >> 0) & 0xFF; 305c19800e8SDoug Rabson p[1] = (seq_number >> 8) & 0xFF; 306c19800e8SDoug Rabson p[2] = (seq_number >> 16) & 0xFF; 307c19800e8SDoug Rabson p[3] = (seq_number >> 24) & 0xFF; 308c19800e8SDoug Rabson memset (p + 4, 309c19800e8SDoug Rabson (ctx->more_flags & LOCAL) ? 0 : 0xFF, 310c19800e8SDoug Rabson 4); 311c19800e8SDoug Rabson 312*e4456411SJohn Baldwin EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); 313*e4456411SJohn Baldwin EVP_Cipher(des_ctx, p, p, 8); 314c19800e8SDoug Rabson 315c19800e8SDoug Rabson krb5_auth_con_setlocalseqnumber (context, 316c19800e8SDoug Rabson ctx->auth_context, 317c19800e8SDoug Rabson ++seq_number); 318c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 319c19800e8SDoug Rabson 320c19800e8SDoug Rabson /* encrypt the data */ 321c19800e8SDoug Rabson p += 16; 322c19800e8SDoug Rabson 323c19800e8SDoug Rabson if(conf_req_flag) { 324c19800e8SDoug Rabson memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 325c19800e8SDoug Rabson 326c19800e8SDoug Rabson for (i = 0; i < sizeof(deskey); ++i) 327c19800e8SDoug Rabson deskey[i] ^= 0xf0; 328ae771770SStanislav Sedov 329*e4456411SJohn Baldwin EVP_CIPHER_CTX_reset(des_ctx); 330*e4456411SJohn Baldwin EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, deskey, zero, 1); 331*e4456411SJohn Baldwin EVP_Cipher(des_ctx, p, p, datalen); 332c19800e8SDoug Rabson } 333*e4456411SJohn Baldwin EVP_CIPHER_CTX_free(des_ctx); 334c19800e8SDoug Rabson memset (deskey, 0, sizeof(deskey)); 335c19800e8SDoug Rabson memset (&schedule, 0, sizeof(schedule)); 336c19800e8SDoug Rabson 337c19800e8SDoug Rabson if(conf_state != NULL) 338c19800e8SDoug Rabson *conf_state = conf_req_flag; 339c19800e8SDoug Rabson *minor_status = 0; 340c19800e8SDoug Rabson return GSS_S_COMPLETE; 341c19800e8SDoug Rabson } 342c19800e8SDoug Rabson 343ae771770SStanislav Sedov #endif 344ae771770SStanislav Sedov 345c19800e8SDoug Rabson static OM_uint32 346c19800e8SDoug Rabson wrap_des3 347c19800e8SDoug Rabson (OM_uint32 * minor_status, 348c19800e8SDoug Rabson const gsskrb5_ctx ctx, 349c19800e8SDoug Rabson krb5_context context, 350c19800e8SDoug Rabson int conf_req_flag, 351c19800e8SDoug Rabson gss_qop_t qop_req, 352c19800e8SDoug Rabson const gss_buffer_t input_message_buffer, 353c19800e8SDoug Rabson int * conf_state, 354c19800e8SDoug Rabson gss_buffer_t output_message_buffer, 355c19800e8SDoug Rabson krb5_keyblock *key 356c19800e8SDoug Rabson ) 357c19800e8SDoug Rabson { 358c19800e8SDoug Rabson u_char *p; 359c19800e8SDoug Rabson u_char seq[8]; 360c19800e8SDoug Rabson int32_t seq_number; 361c19800e8SDoug Rabson size_t len, total_len, padlength, datalen; 362c19800e8SDoug Rabson uint32_t ret; 363c19800e8SDoug Rabson krb5_crypto crypto; 364c19800e8SDoug Rabson Checksum cksum; 365c19800e8SDoug Rabson krb5_data encdata; 366c19800e8SDoug Rabson 367ae771770SStanislav Sedov if (IS_DCE_STYLE(ctx)) { 368ae771770SStanislav Sedov padlength = 0; 369ae771770SStanislav Sedov datalen = input_message_buffer->length; 370ae771770SStanislav Sedov len = 34 + 8; 371ae771770SStanislav Sedov _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 372ae771770SStanislav Sedov total_len += datalen; 373ae771770SStanislav Sedov datalen += 8; 374ae771770SStanislav Sedov } else { 375c19800e8SDoug Rabson padlength = 8 - (input_message_buffer->length % 8); 376c19800e8SDoug Rabson datalen = input_message_buffer->length + padlength + 8; 377c19800e8SDoug Rabson len = datalen + 34; 378c19800e8SDoug Rabson _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); 379ae771770SStanislav Sedov } 380c19800e8SDoug Rabson 381c19800e8SDoug Rabson output_message_buffer->length = total_len; 382c19800e8SDoug Rabson output_message_buffer->value = malloc (total_len); 383c19800e8SDoug Rabson if (output_message_buffer->value == NULL) { 384c19800e8SDoug Rabson output_message_buffer->length = 0; 385c19800e8SDoug Rabson *minor_status = ENOMEM; 386c19800e8SDoug Rabson return GSS_S_FAILURE; 387c19800e8SDoug Rabson } 388c19800e8SDoug Rabson 389c19800e8SDoug Rabson p = _gsskrb5_make_header(output_message_buffer->value, 390c19800e8SDoug Rabson len, 391c19800e8SDoug Rabson "\x02\x01", /* TOK_ID */ 392c19800e8SDoug Rabson GSS_KRB5_MECHANISM); 393c19800e8SDoug Rabson 394c19800e8SDoug Rabson /* SGN_ALG */ 395c19800e8SDoug Rabson memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */ 396c19800e8SDoug Rabson p += 2; 397c19800e8SDoug Rabson /* SEAL_ALG */ 398c19800e8SDoug Rabson if(conf_req_flag) 399c19800e8SDoug Rabson memcpy (p, "\x02\x00", 2); /* DES3-KD */ 400c19800e8SDoug Rabson else 401c19800e8SDoug Rabson memcpy (p, "\xff\xff", 2); 402c19800e8SDoug Rabson p += 2; 403c19800e8SDoug Rabson /* Filler */ 404c19800e8SDoug Rabson memcpy (p, "\xff\xff", 2); 405c19800e8SDoug Rabson p += 2; 406c19800e8SDoug Rabson 407c19800e8SDoug Rabson /* calculate checksum (the above + confounder + data + pad) */ 408c19800e8SDoug Rabson 409c19800e8SDoug Rabson memcpy (p + 20, p - 8, 8); 410c19800e8SDoug Rabson krb5_generate_random_block(p + 28, 8); 411c19800e8SDoug Rabson memcpy (p + 28 + 8, input_message_buffer->value, 412c19800e8SDoug Rabson input_message_buffer->length); 413c19800e8SDoug Rabson memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); 414c19800e8SDoug Rabson 415c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 0, &crypto); 416c19800e8SDoug Rabson if (ret) { 417c19800e8SDoug Rabson free (output_message_buffer->value); 418c19800e8SDoug Rabson output_message_buffer->length = 0; 419c19800e8SDoug Rabson output_message_buffer->value = NULL; 420c19800e8SDoug Rabson *minor_status = ret; 421c19800e8SDoug Rabson return GSS_S_FAILURE; 422c19800e8SDoug Rabson } 423c19800e8SDoug Rabson 424c19800e8SDoug Rabson ret = krb5_create_checksum (context, 425c19800e8SDoug Rabson crypto, 426c19800e8SDoug Rabson KRB5_KU_USAGE_SIGN, 427c19800e8SDoug Rabson 0, 428c19800e8SDoug Rabson p + 20, 429c19800e8SDoug Rabson datalen + 8, 430c19800e8SDoug Rabson &cksum); 431c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 432c19800e8SDoug Rabson if (ret) { 433c19800e8SDoug Rabson free (output_message_buffer->value); 434c19800e8SDoug Rabson output_message_buffer->length = 0; 435c19800e8SDoug Rabson output_message_buffer->value = NULL; 436c19800e8SDoug Rabson *minor_status = ret; 437c19800e8SDoug Rabson return GSS_S_FAILURE; 438c19800e8SDoug Rabson } 439c19800e8SDoug Rabson 440c19800e8SDoug Rabson /* zero out SND_SEQ + SGN_CKSUM in case */ 441c19800e8SDoug Rabson memset (p, 0, 28); 442c19800e8SDoug Rabson 443c19800e8SDoug Rabson memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 444c19800e8SDoug Rabson free_Checksum (&cksum); 445c19800e8SDoug Rabson 446c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 447c19800e8SDoug Rabson /* sequence number */ 448c19800e8SDoug Rabson krb5_auth_con_getlocalseqnumber (context, 449c19800e8SDoug Rabson ctx->auth_context, 450c19800e8SDoug Rabson &seq_number); 451c19800e8SDoug Rabson 452c19800e8SDoug Rabson seq[0] = (seq_number >> 0) & 0xFF; 453c19800e8SDoug Rabson seq[1] = (seq_number >> 8) & 0xFF; 454c19800e8SDoug Rabson seq[2] = (seq_number >> 16) & 0xFF; 455c19800e8SDoug Rabson seq[3] = (seq_number >> 24) & 0xFF; 456c19800e8SDoug Rabson memset (seq + 4, 457c19800e8SDoug Rabson (ctx->more_flags & LOCAL) ? 0 : 0xFF, 458c19800e8SDoug Rabson 4); 459c19800e8SDoug Rabson 460c19800e8SDoug Rabson 461c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, 462c19800e8SDoug Rabson &crypto); 463c19800e8SDoug Rabson if (ret) { 464c19800e8SDoug Rabson free (output_message_buffer->value); 465c19800e8SDoug Rabson output_message_buffer->length = 0; 466c19800e8SDoug Rabson output_message_buffer->value = NULL; 467c19800e8SDoug Rabson *minor_status = ret; 468c19800e8SDoug Rabson return GSS_S_FAILURE; 469c19800e8SDoug Rabson } 470c19800e8SDoug Rabson 471c19800e8SDoug Rabson { 472c19800e8SDoug Rabson DES_cblock ivec; 473c19800e8SDoug Rabson 474c19800e8SDoug Rabson memcpy (&ivec, p + 8, 8); 475c19800e8SDoug Rabson ret = krb5_encrypt_ivec (context, 476c19800e8SDoug Rabson crypto, 477c19800e8SDoug Rabson KRB5_KU_USAGE_SEQ, 478c19800e8SDoug Rabson seq, 8, &encdata, 479c19800e8SDoug Rabson &ivec); 480c19800e8SDoug Rabson } 481c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto); 482c19800e8SDoug Rabson if (ret) { 483c19800e8SDoug Rabson free (output_message_buffer->value); 484c19800e8SDoug Rabson output_message_buffer->length = 0; 485c19800e8SDoug Rabson output_message_buffer->value = NULL; 486c19800e8SDoug Rabson *minor_status = ret; 487c19800e8SDoug Rabson return GSS_S_FAILURE; 488c19800e8SDoug Rabson } 489c19800e8SDoug Rabson 490c19800e8SDoug Rabson assert (encdata.length == 8); 491c19800e8SDoug Rabson 492c19800e8SDoug Rabson memcpy (p, encdata.data, encdata.length); 493c19800e8SDoug Rabson krb5_data_free (&encdata); 494c19800e8SDoug Rabson 495c19800e8SDoug Rabson krb5_auth_con_setlocalseqnumber (context, 496c19800e8SDoug Rabson ctx->auth_context, 497c19800e8SDoug Rabson ++seq_number); 498c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 499c19800e8SDoug Rabson 500c19800e8SDoug Rabson /* encrypt the data */ 501c19800e8SDoug Rabson p += 28; 502c19800e8SDoug Rabson 503c19800e8SDoug Rabson if(conf_req_flag) { 504c19800e8SDoug Rabson krb5_data tmp; 505c19800e8SDoug Rabson 506c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 507c19800e8SDoug Rabson ETYPE_DES3_CBC_NONE, &crypto); 508c19800e8SDoug Rabson if (ret) { 509c19800e8SDoug Rabson free (output_message_buffer->value); 510c19800e8SDoug Rabson output_message_buffer->length = 0; 511c19800e8SDoug Rabson output_message_buffer->value = NULL; 512c19800e8SDoug Rabson *minor_status = ret; 513c19800e8SDoug Rabson return GSS_S_FAILURE; 514c19800e8SDoug Rabson } 515c19800e8SDoug Rabson ret = krb5_encrypt(context, crypto, KRB5_KU_USAGE_SEAL, 516c19800e8SDoug Rabson p, datalen, &tmp); 517c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 518c19800e8SDoug Rabson if (ret) { 519c19800e8SDoug Rabson free (output_message_buffer->value); 520c19800e8SDoug Rabson output_message_buffer->length = 0; 521c19800e8SDoug Rabson output_message_buffer->value = NULL; 522c19800e8SDoug Rabson *minor_status = ret; 523c19800e8SDoug Rabson return GSS_S_FAILURE; 524c19800e8SDoug Rabson } 525c19800e8SDoug Rabson assert (tmp.length == datalen); 526c19800e8SDoug Rabson 527c19800e8SDoug Rabson memcpy (p, tmp.data, datalen); 528c19800e8SDoug Rabson krb5_data_free(&tmp); 529c19800e8SDoug Rabson } 530c19800e8SDoug Rabson if(conf_state != NULL) 531c19800e8SDoug Rabson *conf_state = conf_req_flag; 532c19800e8SDoug Rabson *minor_status = 0; 533c19800e8SDoug Rabson return GSS_S_COMPLETE; 534c19800e8SDoug Rabson } 535c19800e8SDoug Rabson 536ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 537ae771770SStanislav Sedov _gsskrb5_wrap 538c19800e8SDoug Rabson (OM_uint32 * minor_status, 539c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 540c19800e8SDoug Rabson int conf_req_flag, 541c19800e8SDoug Rabson gss_qop_t qop_req, 542c19800e8SDoug Rabson const gss_buffer_t input_message_buffer, 543c19800e8SDoug Rabson int * conf_state, 544c19800e8SDoug Rabson gss_buffer_t output_message_buffer 545c19800e8SDoug Rabson ) 546c19800e8SDoug Rabson { 547c19800e8SDoug Rabson krb5_context context; 548c19800e8SDoug Rabson krb5_keyblock *key; 549c19800e8SDoug Rabson OM_uint32 ret; 550c19800e8SDoug Rabson krb5_keytype keytype; 551c19800e8SDoug Rabson const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 552c19800e8SDoug Rabson 553ae771770SStanislav Sedov output_message_buffer->value = NULL; 554ae771770SStanislav Sedov output_message_buffer->length = 0; 555ae771770SStanislav Sedov 556c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context); 557c19800e8SDoug Rabson 558ae771770SStanislav Sedov if (ctx->more_flags & IS_CFX) 559ae771770SStanislav Sedov return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag, 560ae771770SStanislav Sedov input_message_buffer, conf_state, 561ae771770SStanislav Sedov output_message_buffer); 562ae771770SStanislav Sedov 563c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 564c19800e8SDoug Rabson ret = _gsskrb5i_get_token_key(ctx, context, &key); 565c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 566c19800e8SDoug Rabson if (ret) { 567c19800e8SDoug Rabson *minor_status = ret; 568c19800e8SDoug Rabson return GSS_S_FAILURE; 569c19800e8SDoug Rabson } 570c19800e8SDoug Rabson krb5_enctype_to_keytype (context, key->keytype, &keytype); 571c19800e8SDoug Rabson 572c19800e8SDoug Rabson switch (keytype) { 573c19800e8SDoug Rabson case KEYTYPE_DES : 574ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO 575c19800e8SDoug Rabson ret = wrap_des (minor_status, ctx, context, conf_req_flag, 576c19800e8SDoug Rabson qop_req, input_message_buffer, conf_state, 577c19800e8SDoug Rabson output_message_buffer, key); 578ae771770SStanislav Sedov #else 579ae771770SStanislav Sedov ret = GSS_S_FAILURE; 580ae771770SStanislav Sedov #endif 581c19800e8SDoug Rabson break; 582c19800e8SDoug Rabson case KEYTYPE_DES3 : 583c19800e8SDoug Rabson ret = wrap_des3 (minor_status, ctx, context, conf_req_flag, 584c19800e8SDoug Rabson qop_req, input_message_buffer, conf_state, 585c19800e8SDoug Rabson output_message_buffer, key); 586c19800e8SDoug Rabson break; 587c19800e8SDoug Rabson case KEYTYPE_ARCFOUR: 588c19800e8SDoug Rabson case KEYTYPE_ARCFOUR_56: 589c19800e8SDoug Rabson ret = _gssapi_wrap_arcfour (minor_status, ctx, context, conf_req_flag, 590c19800e8SDoug Rabson qop_req, input_message_buffer, conf_state, 591c19800e8SDoug Rabson output_message_buffer, key); 592c19800e8SDoug Rabson break; 593c19800e8SDoug Rabson default : 594ae771770SStanislav Sedov abort(); 595c19800e8SDoug Rabson break; 596c19800e8SDoug Rabson } 597c19800e8SDoug Rabson krb5_free_keyblock (context, key); 598c19800e8SDoug Rabson return ret; 599c19800e8SDoug Rabson } 600