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