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 "krb5/gsskrb5_locl.h" 35 36 RCSID("$Id: get_mic.c 19031 2006-11-13 18:02:57Z lha $"); 37 38 static OM_uint32 39 mic_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 MD5_CTX md5; 51 u_char hash[16]; 52 DES_key_schedule schedule; 53 DES_cblock deskey; 54 DES_cblock zero; 55 int32_t seq_number; 56 size_t len, total_len; 57 58 _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); 59 60 message_token->length = total_len; 61 message_token->value = malloc (total_len); 62 if (message_token->value == NULL) { 63 message_token->length = 0; 64 *minor_status = ENOMEM; 65 return GSS_S_FAILURE; 66 } 67 68 p = _gsskrb5_make_header(message_token->value, 69 len, 70 "\x01\x01", /* TOK_ID */ 71 GSS_KRB5_MECHANISM); 72 73 memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ 74 p += 2; 75 76 memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ 77 p += 4; 78 79 /* Fill in later (SND-SEQ) */ 80 memset (p, 0, 16); 81 p += 16; 82 83 /* checksum */ 84 MD5_Init (&md5); 85 MD5_Update (&md5, p - 24, 8); 86 MD5_Update (&md5, message_buffer->value, message_buffer->length); 87 MD5_Final (hash, &md5); 88 89 memset (&zero, 0, sizeof(zero)); 90 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 91 DES_set_key (&deskey, &schedule); 92 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 93 &schedule, &zero); 94 memcpy (p - 8, hash, 8); /* SGN_CKSUM */ 95 96 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 97 /* sequence number */ 98 krb5_auth_con_getlocalseqnumber (context, 99 ctx->auth_context, 100 &seq_number); 101 102 p -= 16; /* SND_SEQ */ 103 p[0] = (seq_number >> 0) & 0xFF; 104 p[1] = (seq_number >> 8) & 0xFF; 105 p[2] = (seq_number >> 16) & 0xFF; 106 p[3] = (seq_number >> 24) & 0xFF; 107 memset (p + 4, 108 (ctx->more_flags & LOCAL) ? 0 : 0xFF, 109 4); 110 111 DES_set_key (&deskey, &schedule); 112 DES_cbc_encrypt ((void *)p, (void *)p, 8, 113 &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); 114 115 krb5_auth_con_setlocalseqnumber (context, 116 ctx->auth_context, 117 ++seq_number); 118 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 119 120 memset (deskey, 0, sizeof(deskey)); 121 memset (&schedule, 0, sizeof(schedule)); 122 123 *minor_status = 0; 124 return GSS_S_COMPLETE; 125 } 126 127 static OM_uint32 128 mic_des3 129 (OM_uint32 * minor_status, 130 const gsskrb5_ctx ctx, 131 krb5_context context, 132 gss_qop_t qop_req, 133 const gss_buffer_t message_buffer, 134 gss_buffer_t message_token, 135 krb5_keyblock *key 136 ) 137 { 138 u_char *p; 139 Checksum cksum; 140 u_char seq[8]; 141 142 int32_t seq_number; 143 size_t len, total_len; 144 145 krb5_crypto crypto; 146 krb5_error_code kret; 147 krb5_data encdata; 148 char *tmp; 149 char ivec[8]; 150 151 _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); 152 153 message_token->length = total_len; 154 message_token->value = malloc (total_len); 155 if (message_token->value == NULL) { 156 message_token->length = 0; 157 *minor_status = ENOMEM; 158 return GSS_S_FAILURE; 159 } 160 161 p = _gsskrb5_make_header(message_token->value, 162 len, 163 "\x01\x01", /* TOK-ID */ 164 GSS_KRB5_MECHANISM); 165 166 memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ 167 p += 2; 168 169 memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ 170 p += 4; 171 172 /* this should be done in parts */ 173 174 tmp = malloc (message_buffer->length + 8); 175 if (tmp == NULL) { 176 free (message_token->value); 177 message_token->value = NULL; 178 message_token->length = 0; 179 *minor_status = ENOMEM; 180 return GSS_S_FAILURE; 181 } 182 memcpy (tmp, p - 8, 8); 183 memcpy (tmp + 8, message_buffer->value, message_buffer->length); 184 185 kret = krb5_crypto_init(context, key, 0, &crypto); 186 if (kret) { 187 free (message_token->value); 188 message_token->value = NULL; 189 message_token->length = 0; 190 free (tmp); 191 *minor_status = kret; 192 return GSS_S_FAILURE; 193 } 194 195 kret = krb5_create_checksum (context, 196 crypto, 197 KRB5_KU_USAGE_SIGN, 198 0, 199 tmp, 200 message_buffer->length + 8, 201 &cksum); 202 free (tmp); 203 krb5_crypto_destroy (context, crypto); 204 if (kret) { 205 free (message_token->value); 206 message_token->value = NULL; 207 message_token->length = 0; 208 *minor_status = kret; 209 return GSS_S_FAILURE; 210 } 211 212 memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); 213 214 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 215 /* sequence number */ 216 krb5_auth_con_getlocalseqnumber (context, 217 ctx->auth_context, 218 &seq_number); 219 220 seq[0] = (seq_number >> 0) & 0xFF; 221 seq[1] = (seq_number >> 8) & 0xFF; 222 seq[2] = (seq_number >> 16) & 0xFF; 223 seq[3] = (seq_number >> 24) & 0xFF; 224 memset (seq + 4, 225 (ctx->more_flags & LOCAL) ? 0 : 0xFF, 226 4); 227 228 kret = krb5_crypto_init(context, key, 229 ETYPE_DES3_CBC_NONE, &crypto); 230 if (kret) { 231 free (message_token->value); 232 message_token->value = NULL; 233 message_token->length = 0; 234 *minor_status = kret; 235 return GSS_S_FAILURE; 236 } 237 238 if (ctx->more_flags & COMPAT_OLD_DES3) 239 memset(ivec, 0, 8); 240 else 241 memcpy(ivec, p + 8, 8); 242 243 kret = krb5_encrypt_ivec (context, 244 crypto, 245 KRB5_KU_USAGE_SEQ, 246 seq, 8, &encdata, ivec); 247 krb5_crypto_destroy (context, crypto); 248 if (kret) { 249 free (message_token->value); 250 message_token->value = NULL; 251 message_token->length = 0; 252 *minor_status = kret; 253 return GSS_S_FAILURE; 254 } 255 256 assert (encdata.length == 8); 257 258 memcpy (p, encdata.data, encdata.length); 259 krb5_data_free (&encdata); 260 261 krb5_auth_con_setlocalseqnumber (context, 262 ctx->auth_context, 263 ++seq_number); 264 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 265 266 free_Checksum (&cksum); 267 *minor_status = 0; 268 return GSS_S_COMPLETE; 269 } 270 271 OM_uint32 _gsskrb5_get_mic 272 (OM_uint32 * minor_status, 273 const gss_ctx_id_t context_handle, 274 gss_qop_t qop_req, 275 const gss_buffer_t message_buffer, 276 gss_buffer_t message_token 277 ) 278 { 279 krb5_context context; 280 const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; 281 krb5_keyblock *key; 282 OM_uint32 ret; 283 krb5_keytype keytype; 284 285 GSSAPI_KRB5_INIT (&context); 286 287 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 288 ret = _gsskrb5i_get_token_key(ctx, context, &key); 289 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 290 if (ret) { 291 *minor_status = ret; 292 return GSS_S_FAILURE; 293 } 294 krb5_enctype_to_keytype (context, key->keytype, &keytype); 295 296 switch (keytype) { 297 case KEYTYPE_DES : 298 ret = mic_des (minor_status, ctx, context, qop_req, 299 message_buffer, message_token, key); 300 break; 301 case KEYTYPE_DES3 : 302 ret = mic_des3 (minor_status, ctx, context, qop_req, 303 message_buffer, message_token, key); 304 break; 305 case KEYTYPE_ARCFOUR: 306 case KEYTYPE_ARCFOUR_56: 307 ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, 308 message_buffer, message_token, key); 309 break; 310 default : 311 ret = _gssapi_mic_cfx (minor_status, ctx, context, qop_req, 312 message_buffer, message_token, key); 313 break; 314 } 315 krb5_free_keyblock (context, key); 316 return ret; 317 } 318