1/* 2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "gsskrb5_locl.h" 35 36#ifdef HEIM_KRB5_DES 37 38static OM_uint32 39mic_des 40 (OM_uint32 * minor_status, 41 const gsskrb5_ctx ctx, 42 krb5_context context, 43 gss_qop_t qop_req, 44 const gss_buffer_t message_buffer, 45 gss_buffer_t message_token, 46 krb5_keyblock *key 47 ) 48{ 49 u_char *p; 50 CCDigestRef md5; 51 u_char hash[16]; 52 DES_key_schedule schedule; 53 EVP_CIPHER_CTX des_ctx; 54 DES_cblock deskey; 55 DES_cblock zero; 56 int32_t seq_number; 57 size_t len, total_len; 58 59 _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); 60 61 message_token->length = total_len; 62 message_token->value = malloc (total_len); 63 if (message_token->value == NULL) { 64 message_token->length = 0; 65 *minor_status = ENOMEM; 66 return GSS_S_FAILURE; 67 } 68 69 p = _gsskrb5_make_header(message_token->value, 70 len, 71 "\x01\x01", /* TOK_ID */ 72 GSS_KRB5_MECHANISM); 73 74 memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ 75 p += 2; 76 77 memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ 78 p += 4; 79 80 /* Fill in later (SND-SEQ) */ 81 memset (p, 0, 16); 82 p += 16; 83 84 /* checksum */ 85 md5 = CCDigestCreate(kCCDigestMD5); 86 CCDigestUpdate(md5, p - 24, 8); 87 CCDigestUpdate(md5, message_buffer->value, message_buffer->length); 88 CCDigestFinal(md5, hash); 89 CCDigestDestroy(md5); 90 91 memset (&zero, 0, sizeof(zero)); 92 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 93#ifndef __APPLE_PRIVATE__ 94 DES_set_key_unchecked (&deskey, &schedule); 95 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 96 &schedule, &zero); 97#else 98 CCDesCBCCksum(hash, hash, sizeof(hash), deskey, sizeof(deskey), &zero); 99#endif 100 memcpy (p - 8, hash, 8); /* SGN_CKSUM */ 101 102 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 103 /* sequence number */ 104 krb5_auth_con_getlocalseqnumber (context, 105 ctx->auth_context, 106 &seq_number); 107 108 p -= 16; /* SND_SEQ */ 109 p[0] = (seq_number >> 0) & 0xFF; 110 p[1] = (seq_number >> 8) & 0xFF; 111 p[2] = (seq_number >> 16) & 0xFF; 112 p[3] = (seq_number >> 24) & 0xFF; 113 memset (p + 4, 114 (ctx->more_flags & LOCAL) ? 0 : 0xFF, 115 4); 116 117 EVP_CIPHER_CTX_init(&des_ctx); 118 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); 119 EVP_Cipher(&des_ctx, p, p, 8); 120 EVP_CIPHER_CTX_cleanup(&des_ctx); 121 122 krb5_auth_con_setlocalseqnumber (context, 123 ctx->auth_context, 124 ++seq_number); 125 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 126 127 memset (deskey, 0, sizeof(deskey)); 128 memset (&schedule, 0, sizeof(schedule)); 129 130 *minor_status = 0; 131 return GSS_S_COMPLETE; 132} 133#endif 134 135#ifdef HEIM_KRB5_DES3 136static OM_uint32 137mic_des3 138 (OM_uint32 * minor_status, 139 const gsskrb5_ctx ctx, 140 krb5_context context, 141 gss_qop_t qop_req, 142 const gss_buffer_t message_buffer, 143 gss_buffer_t message_token, 144 krb5_keyblock *key 145 ) 146{ 147 u_char *p; 148 Checksum cksum; 149 u_char seq[8]; 150 151 int32_t seq_number; 152 size_t len, total_len; 153 154 krb5_crypto crypto; 155 krb5_error_code kret; 156 krb5_data encdata; 157 char *tmp; 158 char ivec[8]; 159 160 _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); 161 162 message_token->length = total_len; 163 message_token->value = malloc (total_len); 164 if (message_token->value == NULL) { 165 message_token->length = 0; 166 *minor_status = ENOMEM; 167 return GSS_S_FAILURE; 168 } 169 170 p = _gsskrb5_make_header(message_token->value, 171 len, 172 "\x01\x01", /* TOK-ID */ 173 GSS_KRB5_MECHANISM); 174 175 memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ 176 p += 2; 177 178 memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ 179 p += 4; 180 181 /* this should be done in parts */ 182 183 tmp = malloc (message_buffer->length + 8); 184 if (tmp == NULL) { 185 free (message_token->value); 186 message_token->value = NULL; 187 message_token->length = 0; 188 *minor_status = ENOMEM; 189 return GSS_S_FAILURE; 190 } 191 memcpy (tmp, p - 8, 8); 192 memcpy (tmp + 8, message_buffer->value, message_buffer->length); 193 194 kret = krb5_crypto_init(context, key, 0, &crypto); 195 if (kret) { 196 free (message_token->value); 197 message_token->value = NULL; 198 message_token->length = 0; 199 free (tmp); 200 *minor_status = kret; 201 return GSS_S_FAILURE; 202 } 203 204 kret = krb5_create_checksum (context, 205 crypto, 206 KRB5_KU_USAGE_SIGN, 207 0, 208 tmp, 209 message_buffer->length + 8, 210 &cksum); 211 free (tmp); 212 krb5_crypto_destroy (context, crypto); 213 if (kret) { 214 free (message_token->value); 215 message_token->value = NULL; 216 message_token->length = 0; 217 *minor_status = kret; 218 return GSS_S_FAILURE; 219 } 220 221 memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 222 223 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 224 /* sequence number */ 225 krb5_auth_con_getlocalseqnumber (context, 226 ctx->auth_context, 227 &seq_number); 228 229 seq[0] = (seq_number >> 0) & 0xFF; 230 seq[1] = (seq_number >> 8) & 0xFF; 231 seq[2] = (seq_number >> 16) & 0xFF; 232 seq[3] = (seq_number >> 24) & 0xFF; 233 memset (seq + 4, 234 (ctx->more_flags & LOCAL) ? 0 : 0xFF, 235 4); 236 237 kret = krb5_crypto_init(context, key, 238 ETYPE_DES3_CBC_NONE, &crypto); 239 if (kret) { 240 free (message_token->value); 241 message_token->value = NULL; 242 message_token->length = 0; 243 *minor_status = kret; 244 return GSS_S_FAILURE; 245 } 246 247 if (ctx->more_flags & COMPAT_OLD_DES3) 248 memset(ivec, 0, 8); 249 else 250 memcpy(ivec, p + 8, 8); 251 252 kret = krb5_encrypt_ivec (context, 253 crypto, 254 KRB5_KU_USAGE_SEQ, 255 seq, 8, &encdata, ivec); 256 krb5_crypto_destroy (context, crypto); 257 if (kret) { 258 free (message_token->value); 259 message_token->value = NULL; 260 message_token->length = 0; 261 *minor_status = kret; 262 return GSS_S_FAILURE; 263 } 264 265 assert (encdata.length == 8); 266 267 memcpy (p, encdata.data, encdata.length); 268 krb5_data_free (&encdata); 269 270 krb5_auth_con_setlocalseqnumber (context, 271 ctx->auth_context, 272 ++seq_number); 273 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 274 275 free_Checksum (&cksum); 276 *minor_status = 0; 277 return GSS_S_COMPLETE; 278} 279#endif 280 281OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic 282 (OM_uint32 * minor_status, 283 const gss_ctx_id_t context_handle, 284 gss_qop_t qop_req, 285 const gss_buffer_t message_buffer, 286 gss_buffer_t message_token 287 ) 288{ 289 krb5_context context; 290 const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 291 krb5_keyblock *key; 292 OM_uint32 ret; 293 294 GSSAPI_KRB5_INIT (&context); 295 296 if (ctx->more_flags & IS_CFX) 297 return _gssapi_mic_cfx (minor_status, &ctx->gk5c, context, qop_req, 298 message_buffer, message_token); 299 300 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 301 ret = _gsskrb5i_get_token_key(ctx, context, &key); 302 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 303 if (ret) { 304 *minor_status = ret; 305 return GSS_S_FAILURE; 306 } 307 308 switch (key->keytype) { 309#ifdef HEIM_KRB5_DES 310 case KRB5_ENCTYPE_DES_CBC_CRC : 311 case KRB5_ENCTYPE_DES_CBC_MD4 : 312 case KRB5_ENCTYPE_DES_CBC_MD5 : 313 ret = mic_des (minor_status, ctx, context, qop_req, 314 message_buffer, message_token, key); 315 break; 316#endif 317#ifdef HEIM_KRB5_DES3 318 case KRB5_ENCTYPE_DES3_CBC_MD5 : 319 case KRB5_ENCTYPE_DES3_CBC_SHA1 : 320 ret = mic_des3 (minor_status, ctx, context, qop_req, 321 message_buffer, message_token, key); 322 break; 323#endif 324#ifdef HEIM_KRB5_ARCFOUR 325 case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: 326 case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: 327 ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, 328 message_buffer, message_token, key); 329 break; 330#endif 331 default : 332 ret = GSS_S_FAILURE; 333 break; 334 } 335 krb5_free_keyblock (context, key); 336 return ret; 337} 338