1 /* 2 * Copyright (c) 1997 - 2004 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: unwrap.c 19031 2006-11-13 18:02:57Z lha $"); 37 38 static OM_uint32 39 unwrap_des 40 (OM_uint32 * minor_status, 41 const gsskrb5_ctx context_handle, 42 const gss_buffer_t input_message_buffer, 43 gss_buffer_t output_message_buffer, 44 int * conf_state, 45 gss_qop_t * qop_state, 46 krb5_keyblock *key 47 ) 48 { 49 u_char *p, *seq; 50 size_t len; 51 MD5_CTX md5; 52 u_char hash[16]; 53 DES_key_schedule schedule; 54 DES_cblock deskey; 55 DES_cblock zero; 56 int i; 57 uint32_t seq_number; 58 size_t padlength; 59 OM_uint32 ret; 60 int cstate; 61 int cmp; 62 63 p = input_message_buffer->value; 64 ret = _gsskrb5_verify_header (&p, 65 input_message_buffer->length, 66 "\x02\x01", 67 GSS_KRB5_MECHANISM); 68 if (ret) 69 return ret; 70 71 if (memcmp (p, "\x00\x00", 2) != 0) 72 return GSS_S_BAD_SIG; 73 p += 2; 74 if (memcmp (p, "\x00\x00", 2) == 0) { 75 cstate = 1; 76 } else if (memcmp (p, "\xFF\xFF", 2) == 0) { 77 cstate = 0; 78 } else 79 return GSS_S_BAD_MIC; 80 p += 2; 81 if(conf_state != NULL) 82 *conf_state = cstate; 83 if (memcmp (p, "\xff\xff", 2) != 0) 84 return GSS_S_DEFECTIVE_TOKEN; 85 p += 2; 86 p += 16; 87 88 len = p - (u_char *)input_message_buffer->value; 89 90 if(cstate) { 91 /* decrypt data */ 92 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 93 94 for (i = 0; i < sizeof(deskey); ++i) 95 deskey[i] ^= 0xf0; 96 DES_set_key (&deskey, &schedule); 97 memset (&zero, 0, sizeof(zero)); 98 DES_cbc_encrypt ((void *)p, 99 (void *)p, 100 input_message_buffer->length - len, 101 &schedule, 102 &zero, 103 DES_DECRYPT); 104 105 memset (deskey, 0, sizeof(deskey)); 106 memset (&schedule, 0, sizeof(schedule)); 107 } 108 /* check pad */ 109 ret = _gssapi_verify_pad(input_message_buffer, 110 input_message_buffer->length - len, 111 &padlength); 112 if (ret) 113 return ret; 114 115 MD5_Init (&md5); 116 MD5_Update (&md5, p - 24, 8); 117 MD5_Update (&md5, p, input_message_buffer->length - len); 118 MD5_Final (hash, &md5); 119 120 memset (&zero, 0, sizeof(zero)); 121 memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); 122 DES_set_key (&deskey, &schedule); 123 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), 124 &schedule, &zero); 125 if (memcmp (p - 8, hash, 8) != 0) 126 return GSS_S_BAD_MIC; 127 128 /* verify sequence number */ 129 130 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 131 132 p -= 16; 133 DES_set_key (&deskey, &schedule); 134 DES_cbc_encrypt ((void *)p, (void *)p, 8, 135 &schedule, (DES_cblock *)hash, DES_DECRYPT); 136 137 memset (deskey, 0, sizeof(deskey)); 138 memset (&schedule, 0, sizeof(schedule)); 139 140 seq = p; 141 _gsskrb5_decode_om_uint32(seq, &seq_number); 142 143 if (context_handle->more_flags & LOCAL) 144 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); 145 else 146 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); 147 148 if (cmp != 0) { 149 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 150 return GSS_S_BAD_MIC; 151 } 152 153 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 154 if (ret) { 155 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 156 return ret; 157 } 158 159 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 160 161 /* copy out data */ 162 163 output_message_buffer->length = input_message_buffer->length 164 - len - padlength - 8; 165 output_message_buffer->value = malloc(output_message_buffer->length); 166 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 167 return GSS_S_FAILURE; 168 memcpy (output_message_buffer->value, 169 p + 24, 170 output_message_buffer->length); 171 return GSS_S_COMPLETE; 172 } 173 174 static OM_uint32 175 unwrap_des3 176 (OM_uint32 * minor_status, 177 const gsskrb5_ctx context_handle, 178 krb5_context context, 179 const gss_buffer_t input_message_buffer, 180 gss_buffer_t output_message_buffer, 181 int * conf_state, 182 gss_qop_t * qop_state, 183 krb5_keyblock *key 184 ) 185 { 186 u_char *p; 187 size_t len; 188 u_char *seq; 189 krb5_data seq_data; 190 u_char cksum[20]; 191 uint32_t seq_number; 192 size_t padlength; 193 OM_uint32 ret; 194 int cstate; 195 krb5_crypto crypto; 196 Checksum csum; 197 int cmp; 198 199 p = input_message_buffer->value; 200 ret = _gsskrb5_verify_header (&p, 201 input_message_buffer->length, 202 "\x02\x01", 203 GSS_KRB5_MECHANISM); 204 if (ret) 205 return ret; 206 207 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ 208 return GSS_S_BAD_SIG; 209 p += 2; 210 if (memcmp (p, "\x02\x00", 2) == 0) { 211 cstate = 1; 212 } else if (memcmp (p, "\xff\xff", 2) == 0) { 213 cstate = 0; 214 } else 215 return GSS_S_BAD_MIC; 216 p += 2; 217 if(conf_state != NULL) 218 *conf_state = cstate; 219 if (memcmp (p, "\xff\xff", 2) != 0) 220 return GSS_S_DEFECTIVE_TOKEN; 221 p += 2; 222 p += 28; 223 224 len = p - (u_char *)input_message_buffer->value; 225 226 if(cstate) { 227 /* decrypt data */ 228 krb5_data tmp; 229 230 ret = krb5_crypto_init(context, key, 231 ETYPE_DES3_CBC_NONE, &crypto); 232 if (ret) { 233 *minor_status = ret; 234 return GSS_S_FAILURE; 235 } 236 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, 237 p, input_message_buffer->length - len, &tmp); 238 krb5_crypto_destroy(context, crypto); 239 if (ret) { 240 *minor_status = ret; 241 return GSS_S_FAILURE; 242 } 243 assert (tmp.length == input_message_buffer->length - len); 244 245 memcpy (p, tmp.data, tmp.length); 246 krb5_data_free(&tmp); 247 } 248 /* check pad */ 249 ret = _gssapi_verify_pad(input_message_buffer, 250 input_message_buffer->length - len, 251 &padlength); 252 if (ret) 253 return ret; 254 255 /* verify sequence number */ 256 257 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); 258 259 p -= 28; 260 261 ret = krb5_crypto_init(context, key, 262 ETYPE_DES3_CBC_NONE, &crypto); 263 if (ret) { 264 *minor_status = ret; 265 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 266 return GSS_S_FAILURE; 267 } 268 { 269 DES_cblock ivec; 270 271 memcpy(&ivec, p + 8, 8); 272 ret = krb5_decrypt_ivec (context, 273 crypto, 274 KRB5_KU_USAGE_SEQ, 275 p, 8, &seq_data, 276 &ivec); 277 } 278 krb5_crypto_destroy (context, crypto); 279 if (ret) { 280 *minor_status = ret; 281 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 282 return GSS_S_FAILURE; 283 } 284 if (seq_data.length != 8) { 285 krb5_data_free (&seq_data); 286 *minor_status = 0; 287 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 288 return GSS_S_BAD_MIC; 289 } 290 291 seq = seq_data.data; 292 _gsskrb5_decode_om_uint32(seq, &seq_number); 293 294 if (context_handle->more_flags & LOCAL) 295 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); 296 else 297 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); 298 299 krb5_data_free (&seq_data); 300 if (cmp != 0) { 301 *minor_status = 0; 302 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 303 return GSS_S_BAD_MIC; 304 } 305 306 ret = _gssapi_msg_order_check(context_handle->order, seq_number); 307 if (ret) { 308 *minor_status = 0; 309 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 310 return ret; 311 } 312 313 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); 314 315 /* verify checksum */ 316 317 memcpy (cksum, p + 8, 20); 318 319 memcpy (p + 20, p - 8, 8); 320 321 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; 322 csum.checksum.length = 20; 323 csum.checksum.data = cksum; 324 325 ret = krb5_crypto_init(context, key, 0, &crypto); 326 if (ret) { 327 *minor_status = ret; 328 return GSS_S_FAILURE; 329 } 330 331 ret = krb5_verify_checksum (context, crypto, 332 KRB5_KU_USAGE_SIGN, 333 p + 20, 334 input_message_buffer->length - len + 8, 335 &csum); 336 krb5_crypto_destroy (context, crypto); 337 if (ret) { 338 *minor_status = ret; 339 return GSS_S_FAILURE; 340 } 341 342 /* copy out data */ 343 344 output_message_buffer->length = input_message_buffer->length 345 - len - padlength - 8; 346 output_message_buffer->value = malloc(output_message_buffer->length); 347 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) 348 return GSS_S_FAILURE; 349 memcpy (output_message_buffer->value, 350 p + 36, 351 output_message_buffer->length); 352 return GSS_S_COMPLETE; 353 } 354 355 OM_uint32 _gsskrb5_unwrap 356 (OM_uint32 * minor_status, 357 const gss_ctx_id_t context_handle, 358 const gss_buffer_t input_message_buffer, 359 gss_buffer_t output_message_buffer, 360 int * conf_state, 361 gss_qop_t * qop_state 362 ) 363 { 364 krb5_keyblock *key; 365 krb5_context context; 366 OM_uint32 ret; 367 krb5_keytype keytype; 368 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; 369 370 output_message_buffer->value = NULL; 371 output_message_buffer->length = 0; 372 373 GSSAPI_KRB5_INIT (&context); 374 375 if (qop_state != NULL) 376 *qop_state = GSS_C_QOP_DEFAULT; 377 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 378 ret = _gsskrb5i_get_token_key(ctx, context, &key); 379 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 380 if (ret) { 381 *minor_status = ret; 382 return GSS_S_FAILURE; 383 } 384 krb5_enctype_to_keytype (context, key->keytype, &keytype); 385 386 *minor_status = 0; 387 388 switch (keytype) { 389 case KEYTYPE_DES : 390 ret = unwrap_des (minor_status, ctx, 391 input_message_buffer, output_message_buffer, 392 conf_state, qop_state, key); 393 break; 394 case KEYTYPE_DES3 : 395 ret = unwrap_des3 (minor_status, ctx, context, 396 input_message_buffer, output_message_buffer, 397 conf_state, qop_state, key); 398 break; 399 case KEYTYPE_ARCFOUR: 400 case KEYTYPE_ARCFOUR_56: 401 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, 402 input_message_buffer, output_message_buffer, 403 conf_state, qop_state, key); 404 break; 405 default : 406 ret = _gssapi_unwrap_cfx (minor_status, ctx, context, 407 input_message_buffer, output_message_buffer, 408 conf_state, qop_state, key); 409 break; 410 } 411 krb5_free_keyblock (context, key); 412 return ret; 413 } 414