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: verify_mic.c 19031 2006-11-13 18:02:57Z lha $"); 37 38 static OM_uint32 39 verify_mic_des 40 (OM_uint32 * minor_status, 41 const gsskrb5_ctx context_handle, 42 krb5_context context, 43 const gss_buffer_t message_buffer, 44 const gss_buffer_t token_buffer, 45 gss_qop_t * qop_state, 46 krb5_keyblock *key, 47 char *type 48 ) 49 { 50 u_char *p; 51 MD5_CTX md5; 52 u_char hash[16], *seq; 53 DES_key_schedule schedule; 54 DES_cblock zero; 55 DES_cblock deskey; 56 uint32_t seq_number; 57 OM_uint32 ret; 58 int cmp; 59 60 p = token_buffer->value; 61 ret = _gsskrb5_verify_header (&p, 62 token_buffer->length, 63 type, 64 GSS_KRB5_MECHANISM); 65 if (ret) 66 return ret; 67 68 if (memcmp(p, "\x00\x00", 2) != 0) 69 return GSS_S_BAD_SIG; 70 p += 2; 71 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 72 return GSS_S_BAD_MIC; 73 p += 4; 74 p += 16; 75 76 /* verify checksum */ 77 MD5_Init (&md5); 78 MD5_Update (&md5, p - 24, 8); 79 MD5_Update (&md5, message_buffer->value, 80 message_buffer->length); 81 MD5_Final (hash, &md5); 82 83 memset (&zero, 0, sizeof(zero)); 84 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 85 86 DES_set_key (&deskey, &schedule); 87 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 88 &schedule, &zero); 89 if (memcmp (p - 8, hash, 8) != 0) { 90 memset (deskey, 0, sizeof(deskey)); 91 memset (&schedule, 0, sizeof(schedule)); 92 return GSS_S_BAD_MIC; 93 } 94 95 /* verify sequence number */ 96 97 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 98 99 p -= 16; 100 DES_set_key (&deskey, &schedule); 101 DES_cbc_encrypt ((void *)p, (void *)p, 8, 102 &schedule, (DES_cblock *)hash, DES_DECRYPT); 103 104 memset (deskey, 0, sizeof(deskey)); 105 memset (&schedule, 0, sizeof(schedule)); 106 107 seq = p; 108 _gsskrb5_decode_om_uint32(seq, &seq_number); 109 110 if (context_handle->more_flags & LOCAL) 111 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); 112 else 113 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); 114 115 if (cmp != 0) { 116 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 117 return GSS_S_BAD_MIC; 118 } 119 120 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 121 if (ret) { 122 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 123 return ret; 124 } 125 126 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 127 128 return GSS_S_COMPLETE; 129 } 130 131 static OM_uint32 132 verify_mic_des3 133 (OM_uint32 * minor_status, 134 const gsskrb5_ctx context_handle, 135 krb5_context context, 136 const gss_buffer_t message_buffer, 137 const gss_buffer_t token_buffer, 138 gss_qop_t * qop_state, 139 krb5_keyblock *key, 140 char *type 141 ) 142 { 143 u_char *p; 144 u_char *seq; 145 uint32_t seq_number; 146 OM_uint32 ret; 147 krb5_crypto crypto; 148 krb5_data seq_data; 149 int cmp, docompat; 150 Checksum csum; 151 char *tmp; 152 char ivec[8]; 153 154 p = token_buffer->value; 155 ret = _gsskrb5_verify_header (&p, 156 token_buffer->length, 157 type, 158 GSS_KRB5_MECHANISM); 159 if (ret) 160 return ret; 161 162 if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ 163 return GSS_S_BAD_SIG; 164 p += 2; 165 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) 166 return GSS_S_BAD_MIC; 167 p += 4; 168 169 ret = krb5_crypto_init(context, key, 170 ETYPE_DES3_CBC_NONE, &crypto); 171 if (ret){ 172 *minor_status = ret; 173 return GSS_S_FAILURE; 174 } 175 176 /* verify sequence number */ 177 docompat = 0; 178 retry: 179 if (docompat) 180 memset(ivec, 0, 8); 181 else 182 memcpy(ivec, p + 8, 8); 183 184 ret = krb5_decrypt_ivec (context, 185 crypto, 186 KRB5_KU_USAGE_SEQ, 187 p, 8, &seq_data, ivec); 188 if (ret) { 189 if (docompat++) { 190 krb5_crypto_destroy (context, crypto); 191 *minor_status = ret; 192 return GSS_S_FAILURE; 193 } else 194 goto retry; 195 } 196 197 if (seq_data.length != 8) { 198 krb5_data_free (&seq_data); 199 if (docompat++) { 200 krb5_crypto_destroy (context, crypto); 201 return GSS_S_BAD_MIC; 202 } else 203 goto retry; 204 } 205 206 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 207 208 seq = seq_data.data; 209 _gsskrb5_decode_om_uint32(seq, &seq_number); 210 211 if (context_handle->more_flags & LOCAL) 212 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); 213 else 214 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); 215 216 krb5_data_free (&seq_data); 217 if (cmp != 0) { 218 krb5_crypto_destroy (context, crypto); 219 *minor_status = 0; 220 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 221 return GSS_S_BAD_MIC; 222 } 223 224 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 225 if (ret) { 226 krb5_crypto_destroy (context, crypto); 227 *minor_status = 0; 228 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 229 return ret; 230 } 231 232 /* verify checksum */ 233 234 tmp = malloc (message_buffer->length + 8); 235 if (tmp == NULL) { 236 krb5_crypto_destroy (context, crypto); 237 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 238 *minor_status = ENOMEM; 239 return GSS_S_FAILURE; 240 } 241 242 memcpy (tmp, p - 8, 8); 243 memcpy (tmp + 8, message_buffer->value, message_buffer->length); 244 245 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 246 csum.checksum.length = 20; 247 csum.checksum.data = p + 8; 248 249 ret = krb5_verify_checksum (context, crypto, 250 KRB5_KU_USAGE_SIGN, 251 tmp, message_buffer->length + 8, 252 &csum); 253 free (tmp); 254 if (ret) { 255 krb5_crypto_destroy (context, crypto); 256 *minor_status = ret; 257 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 258 return GSS_S_BAD_MIC; 259 } 260 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 261 262 krb5_crypto_destroy (context, crypto); 263 return GSS_S_COMPLETE; 264 } 265 266 OM_uint32 267 _gsskrb5_verify_mic_internal 268 (OM_uint32 * minor_status, 269 const gsskrb5_ctx context_handle, 270 krb5_context context, 271 const gss_buffer_t message_buffer, 272 const gss_buffer_t token_buffer, 273 gss_qop_t * qop_state, 274 char * type 275 ) 276 { 277 krb5_keyblock *key; 278 OM_uint32 ret; 279 krb5_keytype keytype; 280 281 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 282 ret = _gsskrb5i_get_token_key(context_handle, context, &key); 283 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 284 if (ret) { 285 *minor_status = ret; 286 return GSS_S_FAILURE; 287 } 288 *minor_status = 0; 289 krb5_enctype_to_keytype (context, key->keytype, &keytype); 290 switch (keytype) { 291 case KEYTYPE_DES : 292 ret = verify_mic_des (minor_status, context_handle, context, 293 message_buffer, token_buffer, qop_state, key, 294 type); 295 break; 296 case KEYTYPE_DES3 : 297 ret = verify_mic_des3 (minor_status, context_handle, context, 298 message_buffer, token_buffer, qop_state, key, 299 type); 300 break; 301 case KEYTYPE_ARCFOUR : 302 case KEYTYPE_ARCFOUR_56 : 303 ret = _gssapi_verify_mic_arcfour (minor_status, context_handle, 304 context, 305 message_buffer, token_buffer, 306 qop_state, key, type); 307 break; 308 default : 309 ret = _gssapi_verify_mic_cfx (minor_status, context_handle, 310 context, 311 message_buffer, token_buffer, qop_state, 312 key); 313 break; 314 } 315 krb5_free_keyblock (context, key); 316 317 return ret; 318 } 319 320 OM_uint32 321 _gsskrb5_verify_mic 322 (OM_uint32 * minor_status, 323 const gss_ctx_id_t context_handle, 324 const gss_buffer_t message_buffer, 325 const gss_buffer_t token_buffer, 326 gss_qop_t * qop_state 327 ) 328 { 329 krb5_context context; 330 OM_uint32 ret; 331 332 GSSAPI_KRB5_INIT (&context); 333 334 if (qop_state != NULL) 335 *qop_state = GSS_C_QOP_DEFAULT; 336 337 ret = _gsskrb5_verify_mic_internal(minor_status, 338 (gsskrb5_ctx)context_handle, 339 context, 340 message_buffer, token_buffer, 341 qop_state, "\x01\x01"); 342 343 return ret; 344 } 345