1 /* 2 * Copyright (c) 2006 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 "ntlm/ntlm.h" 35 36 RCSID("$Id: crypto.c 19535 2006-12-28 14:49:01Z lha $"); 37 38 uint32_t 39 _krb5_crc_update (const char *p, size_t len, uint32_t res); 40 void 41 _krb5_crc_init_table(void); 42 43 /* 44 * 45 */ 46 47 static void 48 encode_le_uint32(uint32_t n, unsigned char *p) 49 { 50 p[0] = (n >> 0) & 0xFF; 51 p[1] = (n >> 8) & 0xFF; 52 p[2] = (n >> 16) & 0xFF; 53 p[3] = (n >> 24) & 0xFF; 54 } 55 56 57 static void 58 decode_le_uint32(const void *ptr, uint32_t *n) 59 { 60 const unsigned char *p = ptr; 61 *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 62 } 63 64 /* 65 * 66 */ 67 68 const char a2i_signmagic[] = 69 "session key to server-to-client signing key magic constant"; 70 const char a2i_sealmagic[] = 71 "session key to server-to-client sealing key magic constant"; 72 const char i2a_signmagic[] = 73 "session key to client-to-server signing key magic constant"; 74 const char i2a_sealmagic[] = 75 "session key to client-to-server sealing key magic constant"; 76 77 78 void 79 _gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 80 unsigned char *data, size_t len) 81 { 82 unsigned char out[16]; 83 MD5_CTX ctx; 84 const char *signmagic; 85 const char *sealmagic; 86 87 if (acceptor) { 88 signmagic = a2i_signmagic; 89 sealmagic = a2i_sealmagic; 90 } else { 91 signmagic = i2a_signmagic; 92 sealmagic = i2a_sealmagic; 93 } 94 95 key->seq = 0; 96 97 MD5_Init(&ctx); 98 MD5_Update(&ctx, data, len); 99 MD5_Update(&ctx, signmagic, strlen(signmagic) + 1); 100 MD5_Final(key->signkey, &ctx); 101 102 MD5_Init(&ctx); 103 MD5_Update(&ctx, data, len); 104 MD5_Update(&ctx, sealmagic, strlen(sealmagic) + 1); 105 MD5_Final(out, &ctx); 106 107 RC4_set_key(&key->sealkey, 16, out); 108 if (sealsign) 109 key->signsealkey = &key->sealkey; 110 } 111 112 /* 113 * 114 */ 115 116 static OM_uint32 117 v1_sign_message(gss_buffer_t in, 118 RC4_KEY *signkey, 119 uint32_t seq, 120 unsigned char out[16]) 121 { 122 unsigned char sigature[12]; 123 uint32_t crc; 124 125 _krb5_crc_init_table(); 126 crc = _krb5_crc_update(in->value, in->length, 0); 127 128 encode_le_uint32(0, &sigature[0]); 129 encode_le_uint32(crc, &sigature[4]); 130 encode_le_uint32(seq, &sigature[8]); 131 132 encode_le_uint32(1, out); /* version */ 133 RC4(signkey, sizeof(sigature), sigature, out + 4); 134 135 if (RAND_bytes(out + 4, 4) != 1) 136 return GSS_S_UNAVAILABLE; 137 138 return 0; 139 } 140 141 142 static OM_uint32 143 v2_sign_message(gss_buffer_t in, 144 unsigned char signkey[16], 145 RC4_KEY *sealkey, 146 uint32_t seq, 147 unsigned char out[16]) 148 { 149 unsigned char hmac[16]; 150 unsigned int hmaclen; 151 HMAC_CTX c; 152 153 HMAC_CTX_init(&c); 154 HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL); 155 156 encode_le_uint32(seq, hmac); 157 HMAC_Update(&c, hmac, 4); 158 HMAC_Update(&c, in->value, in->length); 159 HMAC_Final(&c, hmac, &hmaclen); 160 HMAC_CTX_cleanup(&c); 161 162 encode_le_uint32(1, &out[0]); 163 if (sealkey) 164 RC4(sealkey, 8, hmac, &out[4]); 165 else 166 memcpy(&out[4], hmac, 8); 167 168 memset(&out[12], 0, 4); 169 170 return GSS_S_COMPLETE; 171 } 172 173 static OM_uint32 174 v2_verify_message(gss_buffer_t in, 175 unsigned char signkey[16], 176 RC4_KEY *sealkey, 177 uint32_t seq, 178 const unsigned char checksum[16]) 179 { 180 OM_uint32 ret; 181 unsigned char out[16]; 182 183 ret = v2_sign_message(in, signkey, sealkey, seq, out); 184 if (ret) 185 return ret; 186 187 if (memcmp(checksum, out, 16) != 0) 188 return GSS_S_BAD_MIC; 189 190 return GSS_S_COMPLETE; 191 } 192 193 static OM_uint32 194 v2_seal_message(const gss_buffer_t in, 195 unsigned char signkey[16], 196 uint32_t seq, 197 RC4_KEY *sealkey, 198 gss_buffer_t out) 199 { 200 unsigned char *p; 201 OM_uint32 ret; 202 203 if (in->length + 16 < in->length) 204 return EINVAL; 205 206 p = malloc(in->length + 16); 207 if (p == NULL) 208 return ENOMEM; 209 210 RC4(sealkey, in->length, in->value, p); 211 212 ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 213 if (ret) { 214 free(p); 215 return ret; 216 } 217 218 out->value = p; 219 out->length = in->length + 16; 220 221 return 0; 222 } 223 224 static OM_uint32 225 v2_unseal_message(gss_buffer_t in, 226 unsigned char signkey[16], 227 uint32_t seq, 228 RC4_KEY *sealkey, 229 gss_buffer_t out) 230 { 231 OM_uint32 ret; 232 233 if (in->length < 16) 234 return GSS_S_BAD_MIC; 235 236 out->length = in->length - 16; 237 out->value = malloc(out->length); 238 if (out->value == NULL) 239 return GSS_S_BAD_MIC; 240 241 RC4(sealkey, out->length, in->value, out->value); 242 243 ret = v2_verify_message(out, signkey, sealkey, seq, 244 ((const unsigned char *)in->value) + out->length); 245 if (ret) { 246 OM_uint32 junk; 247 gss_release_buffer(&junk, out); 248 } 249 return ret; 250 } 251 252 /* 253 * 254 */ 255 256 #define CTX_FLAGS_ISSET(_ctx,_flags) \ 257 (((_ctx)->flags & (_flags)) == (_flags)) 258 259 /* 260 * 261 */ 262 263 OM_uint32 _gss_ntlm_get_mic 264 (OM_uint32 * minor_status, 265 const gss_ctx_id_t context_handle, 266 gss_qop_t qop_req, 267 const gss_buffer_t message_buffer, 268 gss_buffer_t message_token 269 ) 270 { 271 ntlm_ctx ctx = (ntlm_ctx)context_handle; 272 OM_uint32 junk; 273 274 if (minor_status) 275 *minor_status = 0; 276 if (message_token) { 277 message_token->length = 0; 278 message_token->value = NULL; 279 } 280 281 message_token->value = malloc(16); 282 message_token->length = 16; 283 if (message_token->value == NULL) { 284 *minor_status = ENOMEM; 285 return GSS_S_FAILURE; 286 } 287 288 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 289 OM_uint32 ret; 290 291 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 292 gss_release_buffer(&junk, message_token); 293 return GSS_S_UNAVAILABLE; 294 } 295 296 ret = v2_sign_message(message_buffer, 297 ctx->u.v2.send.signkey, 298 ctx->u.v2.send.signsealkey, 299 ctx->u.v2.send.seq++, 300 message_token->value); 301 if (ret) 302 gss_release_buffer(&junk, message_token); 303 return ret; 304 305 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 306 OM_uint32 ret; 307 308 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 309 gss_release_buffer(&junk, message_token); 310 return GSS_S_UNAVAILABLE; 311 } 312 313 ret = v1_sign_message(message_buffer, 314 &ctx->u.v1.crypto_send.key, 315 ctx->u.v1.crypto_send.seq++, 316 message_token->value); 317 if (ret) 318 gss_release_buffer(&junk, message_token); 319 return ret; 320 321 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 322 unsigned char *sigature; 323 324 sigature = message_token->value; 325 326 encode_le_uint32(1, &sigature[0]); /* version */ 327 encode_le_uint32(0, &sigature[4]); 328 encode_le_uint32(0, &sigature[8]); 329 encode_le_uint32(0, &sigature[12]); 330 331 return GSS_S_COMPLETE; 332 } 333 gss_release_buffer(&junk, message_token); 334 335 return GSS_S_UNAVAILABLE; 336 } 337 338 /* 339 * 340 */ 341 342 OM_uint32 343 _gss_ntlm_verify_mic 344 (OM_uint32 * minor_status, 345 const gss_ctx_id_t context_handle, 346 const gss_buffer_t message_buffer, 347 const gss_buffer_t token_buffer, 348 gss_qop_t * qop_state 349 ) 350 { 351 ntlm_ctx ctx = (ntlm_ctx)context_handle; 352 353 if (qop_state != NULL) 354 *qop_state = GSS_C_QOP_DEFAULT; 355 *minor_status = 0; 356 357 if (token_buffer->length != 16) 358 return GSS_S_BAD_MIC; 359 360 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 361 OM_uint32 ret; 362 363 if ((ctx->status & STATUS_SESSIONKEY) == 0) 364 return GSS_S_UNAVAILABLE; 365 366 ret = v2_verify_message(message_buffer, 367 ctx->u.v2.recv.signkey, 368 ctx->u.v2.recv.signsealkey, 369 ctx->u.v2.recv.seq++, 370 token_buffer->value); 371 if (ret) 372 return ret; 373 374 return GSS_S_COMPLETE; 375 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 376 377 unsigned char sigature[12]; 378 uint32_t crc, num; 379 380 if ((ctx->status & STATUS_SESSIONKEY) == 0) 381 return GSS_S_UNAVAILABLE; 382 383 decode_le_uint32(token_buffer->value, &num); 384 if (num != 1) 385 return GSS_S_BAD_MIC; 386 387 RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 388 ((unsigned char *)token_buffer->value) + 4, sigature); 389 390 _krb5_crc_init_table(); 391 crc = _krb5_crc_update(message_buffer->value, 392 message_buffer->length, 0); 393 /* skip first 4 bytes in the encrypted checksum */ 394 decode_le_uint32(&sigature[4], &num); 395 if (num != crc) 396 return GSS_S_BAD_MIC; 397 decode_le_uint32(&sigature[8], &num); 398 if (ctx->u.v1.crypto_recv.seq != num) 399 return GSS_S_BAD_MIC; 400 ctx->u.v1.crypto_recv.seq++; 401 402 return GSS_S_COMPLETE; 403 } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 404 uint32_t num; 405 unsigned char *p; 406 407 p = (unsigned char*)(token_buffer->value); 408 409 decode_le_uint32(&p[0], &num); /* version */ 410 if (num != 1) return GSS_S_BAD_MIC; 411 decode_le_uint32(&p[4], &num); 412 if (num != 0) return GSS_S_BAD_MIC; 413 decode_le_uint32(&p[8], &num); 414 if (num != 0) return GSS_S_BAD_MIC; 415 decode_le_uint32(&p[12], &num); 416 if (num != 0) return GSS_S_BAD_MIC; 417 418 return GSS_S_COMPLETE; 419 } 420 421 return GSS_S_UNAVAILABLE; 422 } 423 424 /* 425 * 426 */ 427 428 OM_uint32 429 _gss_ntlm_wrap_size_limit ( 430 OM_uint32 * minor_status, 431 const gss_ctx_id_t context_handle, 432 int conf_req_flag, 433 gss_qop_t qop_req, 434 OM_uint32 req_output_size, 435 OM_uint32 * max_input_size 436 ) 437 { 438 ntlm_ctx ctx = (ntlm_ctx)context_handle; 439 440 *minor_status = 0; 441 442 if(ctx->flags & NTLM_NEG_SEAL) { 443 444 if (req_output_size < 16) 445 *max_input_size = 0; 446 else 447 *max_input_size = req_output_size - 16; 448 449 return GSS_S_COMPLETE; 450 } 451 452 return GSS_S_UNAVAILABLE; 453 } 454 455 /* 456 * 457 */ 458 459 OM_uint32 _gss_ntlm_wrap 460 (OM_uint32 * minor_status, 461 const gss_ctx_id_t context_handle, 462 int conf_req_flag, 463 gss_qop_t qop_req, 464 const gss_buffer_t input_message_buffer, 465 int * conf_state, 466 gss_buffer_t output_message_buffer 467 ) 468 { 469 ntlm_ctx ctx = (ntlm_ctx)context_handle; 470 OM_uint32 ret; 471 472 if (minor_status) 473 *minor_status = 0; 474 if (conf_state) 475 *conf_state = 0; 476 if (output_message_buffer == GSS_C_NO_BUFFER) 477 return GSS_S_FAILURE; 478 479 480 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 481 482 return v2_seal_message(input_message_buffer, 483 ctx->u.v2.send.signkey, 484 ctx->u.v2.send.seq++, 485 &ctx->u.v2.send.sealkey, 486 output_message_buffer); 487 488 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 489 gss_buffer_desc trailer; 490 OM_uint32 junk; 491 492 output_message_buffer->length = input_message_buffer->length + 16; 493 output_message_buffer->value = malloc(output_message_buffer->length); 494 if (output_message_buffer->value == NULL) { 495 output_message_buffer->length = 0; 496 return GSS_S_FAILURE; 497 } 498 499 500 RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 501 input_message_buffer->value, output_message_buffer->value); 502 503 ret = _gss_ntlm_get_mic(minor_status, context_handle, 504 0, input_message_buffer, 505 &trailer); 506 if (ret) { 507 gss_release_buffer(&junk, output_message_buffer); 508 return ret; 509 } 510 if (trailer.length != 16) { 511 gss_release_buffer(&junk, output_message_buffer); 512 gss_release_buffer(&junk, &trailer); 513 return GSS_S_FAILURE; 514 } 515 memcpy(((unsigned char *)output_message_buffer->value) + 516 input_message_buffer->length, 517 trailer.value, trailer.length); 518 gss_release_buffer(&junk, &trailer); 519 520 return GSS_S_COMPLETE; 521 } 522 523 return GSS_S_UNAVAILABLE; 524 } 525 526 /* 527 * 528 */ 529 530 OM_uint32 _gss_ntlm_unwrap 531 (OM_uint32 * minor_status, 532 const gss_ctx_id_t context_handle, 533 const gss_buffer_t input_message_buffer, 534 gss_buffer_t output_message_buffer, 535 int * conf_state, 536 gss_qop_t * qop_state 537 ) 538 { 539 ntlm_ctx ctx = (ntlm_ctx)context_handle; 540 OM_uint32 ret; 541 542 if (minor_status) 543 *minor_status = 0; 544 if (output_message_buffer) { 545 output_message_buffer->value = NULL; 546 output_message_buffer->length = 0; 547 } 548 if (conf_state) 549 *conf_state = 0; 550 if (qop_state) 551 *qop_state = 0; 552 553 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 554 555 return v2_unseal_message(input_message_buffer, 556 ctx->u.v2.recv.signkey, 557 ctx->u.v2.recv.seq++, 558 &ctx->u.v2.recv.sealkey, 559 output_message_buffer); 560 561 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 562 563 gss_buffer_desc trailer; 564 OM_uint32 junk; 565 566 if (input_message_buffer->length < 16) 567 return GSS_S_BAD_MIC; 568 569 output_message_buffer->length = input_message_buffer->length - 16; 570 output_message_buffer->value = malloc(output_message_buffer->length); 571 if (output_message_buffer->value == NULL) { 572 output_message_buffer->length = 0; 573 return GSS_S_FAILURE; 574 } 575 576 RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 577 input_message_buffer->value, output_message_buffer->value); 578 579 trailer.value = ((unsigned char *)input_message_buffer->value) + 580 output_message_buffer->length; 581 trailer.length = 16; 582 583 ret = _gss_ntlm_verify_mic(minor_status, context_handle, 584 output_message_buffer, 585 &trailer, NULL); 586 if (ret) { 587 gss_release_buffer(&junk, output_message_buffer); 588 return ret; 589 } 590 591 return GSS_S_COMPLETE; 592 } 593 594 return GSS_S_UNAVAILABLE; 595 } 596