1 /* $NetBSD: crypto.c,v 1.3 2018/02/05 16:00:52 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "ntlm.h" 37 struct hx509_certs_data; 38 struct krb5_pk_identity; 39 struct krb5_pk_cert; 40 struct ContentInfo; 41 struct AlgorithmIdentifier; 42 struct _krb5_krb_auth_data; 43 struct krb5_dh_moduli; 44 struct _krb5_key_data; 45 struct _krb5_encryption_type; 46 struct _krb5_key_type; 47 #include "krb5_locl.h" 48 49 /* 50 * 51 */ 52 53 static void 54 encode_le_uint32(uint32_t n, unsigned char *p) 55 { 56 p[0] = (n >> 0) & 0xFF; 57 p[1] = (n >> 8) & 0xFF; 58 p[2] = (n >> 16) & 0xFF; 59 p[3] = (n >> 24) & 0xFF; 60 } 61 62 63 static void 64 decode_le_uint32(const void *ptr, uint32_t *n) 65 { 66 const unsigned char *p = ptr; 67 *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 68 } 69 70 /* 71 * 72 */ 73 74 const char a2i_signmagic[] = 75 "session key to server-to-client signing key magic constant"; 76 const char a2i_sealmagic[] = 77 "session key to server-to-client sealing key magic constant"; 78 const char i2a_signmagic[] = 79 "session key to client-to-server signing key magic constant"; 80 const char i2a_sealmagic[] = 81 "session key to client-to-server sealing key magic constant"; 82 83 84 void 85 _gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 86 unsigned char *data, size_t len) 87 { 88 unsigned char out[16]; 89 EVP_MD_CTX *ctx; 90 const char *signmagic; 91 const char *sealmagic; 92 93 if (acceptor) { 94 signmagic = a2i_signmagic; 95 sealmagic = a2i_sealmagic; 96 } else { 97 signmagic = i2a_signmagic; 98 sealmagic = i2a_sealmagic; 99 } 100 101 key->seq = 0; 102 103 ctx = EVP_MD_CTX_create(); 104 EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 105 EVP_DigestUpdate(ctx, data, len); 106 EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); 107 EVP_DigestFinal_ex(ctx, key->signkey, NULL); 108 109 EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 110 EVP_DigestUpdate(ctx, data, len); 111 EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); 112 EVP_DigestFinal_ex(ctx, out, NULL); 113 EVP_MD_CTX_destroy(ctx); 114 115 RC4_set_key(&key->sealkey, 16, out); 116 if (sealsign) 117 key->signsealkey = &key->sealkey; 118 } 119 120 /* 121 * 122 */ 123 124 static OM_uint32 125 v1_sign_message(gss_buffer_t in, 126 RC4_KEY *signkey, 127 uint32_t seq, 128 unsigned char out[16]) 129 { 130 unsigned char sigature[12]; 131 uint32_t crc; 132 133 _krb5_crc_init_table(); 134 crc = _krb5_crc_update(in->value, in->length, 0); 135 136 encode_le_uint32(0, &sigature[0]); 137 encode_le_uint32(crc, &sigature[4]); 138 encode_le_uint32(seq, &sigature[8]); 139 140 encode_le_uint32(1, out); /* version */ 141 RC4(signkey, sizeof(sigature), sigature, out + 4); 142 143 if (RAND_bytes(out + 4, 4) != 1) 144 return GSS_S_UNAVAILABLE; 145 146 return 0; 147 } 148 149 150 static OM_uint32 151 v2_sign_message(gss_buffer_t in, 152 unsigned char signkey[16], 153 RC4_KEY *sealkey, 154 uint32_t seq, 155 unsigned char out[16]) 156 { 157 unsigned char hmac[16]; 158 unsigned int hmaclen; 159 HMAC_CTX *c; 160 161 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 162 HMAC_CTX cs; 163 c = &cs; 164 HMAC_CTX_init(c); 165 #else 166 c = HMAC_CTX_new(); 167 #endif 168 HMAC_Init_ex(c, signkey, 16, EVP_md5(), NULL); 169 170 encode_le_uint32(seq, hmac); 171 HMAC_Update(c, hmac, 4); 172 HMAC_Update(c, in->value, in->length); 173 HMAC_Final(c, hmac, &hmaclen); 174 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 175 HMAC_CTX_cleanup(c); 176 #else 177 HMAC_CTX_free(c); 178 #endif 179 180 encode_le_uint32(1, &out[0]); 181 if (sealkey) 182 RC4(sealkey, 8, hmac, &out[4]); 183 else 184 memcpy(&out[4], hmac, 8); 185 186 memset(&out[12], 0, 4); 187 188 return GSS_S_COMPLETE; 189 } 190 191 static OM_uint32 192 v2_verify_message(gss_buffer_t in, 193 unsigned char signkey[16], 194 RC4_KEY *sealkey, 195 uint32_t seq, 196 const unsigned char checksum[16]) 197 { 198 OM_uint32 ret; 199 unsigned char out[16]; 200 201 ret = v2_sign_message(in, signkey, sealkey, seq, out); 202 if (ret) 203 return ret; 204 205 if (memcmp(checksum, out, 16) != 0) 206 return GSS_S_BAD_MIC; 207 208 return GSS_S_COMPLETE; 209 } 210 211 static OM_uint32 212 v2_seal_message(const gss_buffer_t in, 213 unsigned char signkey[16], 214 uint32_t seq, 215 RC4_KEY *sealkey, 216 gss_buffer_t out) 217 { 218 unsigned char *p; 219 OM_uint32 ret; 220 221 if (in->length + 16 < in->length) 222 return EINVAL; 223 224 p = malloc(in->length + 16); 225 if (p == NULL) 226 return ENOMEM; 227 228 RC4(sealkey, in->length, in->value, p); 229 230 ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 231 if (ret) { 232 free(p); 233 return ret; 234 } 235 236 out->value = p; 237 out->length = in->length + 16; 238 239 return 0; 240 } 241 242 static OM_uint32 243 v2_unseal_message(gss_buffer_t in, 244 unsigned char signkey[16], 245 uint32_t seq, 246 RC4_KEY *sealkey, 247 gss_buffer_t out) 248 { 249 OM_uint32 ret; 250 251 if (in->length < 16) 252 return GSS_S_BAD_MIC; 253 254 out->length = in->length - 16; 255 out->value = malloc(out->length); 256 if (out->value == NULL) 257 return GSS_S_BAD_MIC; 258 259 RC4(sealkey, out->length, in->value, out->value); 260 261 ret = v2_verify_message(out, signkey, sealkey, seq, 262 ((const unsigned char *)in->value) + out->length); 263 if (ret) { 264 OM_uint32 junk; 265 gss_release_buffer(&junk, out); 266 } 267 return ret; 268 } 269 270 /* 271 * 272 */ 273 274 #define CTX_FLAGS_ISSET(_ctx,_flags) \ 275 (((_ctx)->flags & (_flags)) == (_flags)) 276 277 /* 278 * 279 */ 280 281 OM_uint32 GSSAPI_CALLCONV 282 _gss_ntlm_get_mic 283 (OM_uint32 * minor_status, 284 gss_const_ctx_id_t context_handle, 285 gss_qop_t qop_req, 286 const gss_buffer_t message_buffer, 287 gss_buffer_t message_token 288 ) 289 { 290 ntlm_ctx ctx = (ntlm_ctx)context_handle; 291 OM_uint32 junk; 292 293 *minor_status = 0; 294 295 message_token->value = malloc(16); 296 message_token->length = 16; 297 if (message_token->value == NULL) { 298 *minor_status = ENOMEM; 299 return GSS_S_FAILURE; 300 } 301 302 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 303 OM_uint32 ret; 304 305 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 306 gss_release_buffer(&junk, message_token); 307 return GSS_S_UNAVAILABLE; 308 } 309 310 ret = v2_sign_message(message_buffer, 311 ctx->u.v2.send.signkey, 312 ctx->u.v2.send.signsealkey, 313 ctx->u.v2.send.seq++, 314 message_token->value); 315 if (ret) 316 gss_release_buffer(&junk, message_token); 317 return ret; 318 319 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 320 OM_uint32 ret; 321 322 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 323 gss_release_buffer(&junk, message_token); 324 return GSS_S_UNAVAILABLE; 325 } 326 327 ret = v1_sign_message(message_buffer, 328 &ctx->u.v1.crypto_send.key, 329 ctx->u.v1.crypto_send.seq++, 330 message_token->value); 331 if (ret) 332 gss_release_buffer(&junk, message_token); 333 return ret; 334 335 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 336 unsigned char *sigature; 337 338 sigature = message_token->value; 339 340 encode_le_uint32(1, &sigature[0]); /* version */ 341 encode_le_uint32(0, &sigature[4]); 342 encode_le_uint32(0, &sigature[8]); 343 encode_le_uint32(0, &sigature[12]); 344 345 return GSS_S_COMPLETE; 346 } 347 gss_release_buffer(&junk, message_token); 348 349 return GSS_S_UNAVAILABLE; 350 } 351 352 /* 353 * 354 */ 355 356 OM_uint32 GSSAPI_CALLCONV 357 _gss_ntlm_verify_mic 358 (OM_uint32 * minor_status, 359 gss_const_ctx_id_t context_handle, 360 const gss_buffer_t message_buffer, 361 const gss_buffer_t token_buffer, 362 gss_qop_t * qop_state 363 ) 364 { 365 ntlm_ctx ctx = (ntlm_ctx)context_handle; 366 367 if (qop_state != NULL) 368 *qop_state = GSS_C_QOP_DEFAULT; 369 *minor_status = 0; 370 371 if (token_buffer->length != 16) 372 return GSS_S_BAD_MIC; 373 374 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 375 OM_uint32 ret; 376 377 if ((ctx->status & STATUS_SESSIONKEY) == 0) 378 return GSS_S_UNAVAILABLE; 379 380 ret = v2_verify_message(message_buffer, 381 ctx->u.v2.recv.signkey, 382 ctx->u.v2.recv.signsealkey, 383 ctx->u.v2.recv.seq++, 384 token_buffer->value); 385 if (ret) 386 return ret; 387 388 return GSS_S_COMPLETE; 389 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 390 391 unsigned char sigature[12]; 392 uint32_t crc, num; 393 394 if ((ctx->status & STATUS_SESSIONKEY) == 0) 395 return GSS_S_UNAVAILABLE; 396 397 decode_le_uint32(token_buffer->value, &num); 398 if (num != 1) 399 return GSS_S_BAD_MIC; 400 401 RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 402 ((unsigned char *)token_buffer->value) + 4, sigature); 403 404 _krb5_crc_init_table(); 405 crc = _krb5_crc_update(message_buffer->value, 406 message_buffer->length, 0); 407 /* skip first 4 bytes in the encrypted checksum */ 408 decode_le_uint32(&sigature[4], &num); 409 if (num != crc) 410 return GSS_S_BAD_MIC; 411 decode_le_uint32(&sigature[8], &num); 412 if (ctx->u.v1.crypto_recv.seq != num) 413 return GSS_S_BAD_MIC; 414 ctx->u.v1.crypto_recv.seq++; 415 416 return GSS_S_COMPLETE; 417 } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 418 uint32_t num; 419 unsigned char *p; 420 421 p = (unsigned char*)(token_buffer->value); 422 423 decode_le_uint32(&p[0], &num); /* version */ 424 if (num != 1) return GSS_S_BAD_MIC; 425 decode_le_uint32(&p[4], &num); 426 if (num != 0) return GSS_S_BAD_MIC; 427 decode_le_uint32(&p[8], &num); 428 if (num != 0) return GSS_S_BAD_MIC; 429 decode_le_uint32(&p[12], &num); 430 if (num != 0) return GSS_S_BAD_MIC; 431 432 return GSS_S_COMPLETE; 433 } 434 435 return GSS_S_UNAVAILABLE; 436 } 437 438 /* 439 * 440 */ 441 442 OM_uint32 GSSAPI_CALLCONV 443 _gss_ntlm_wrap_size_limit ( 444 OM_uint32 * minor_status, 445 gss_const_ctx_id_t context_handle, 446 int conf_req_flag, 447 gss_qop_t qop_req, 448 OM_uint32 req_output_size, 449 OM_uint32 * max_input_size 450 ) 451 { 452 ntlm_ctx ctx = (ntlm_ctx)context_handle; 453 454 *minor_status = 0; 455 456 if(ctx->flags & NTLM_NEG_SEAL) { 457 458 if (req_output_size < 16) 459 *max_input_size = 0; 460 else 461 *max_input_size = req_output_size - 16; 462 463 return GSS_S_COMPLETE; 464 } 465 466 return GSS_S_UNAVAILABLE; 467 } 468 469 /* 470 * 471 */ 472 473 OM_uint32 GSSAPI_CALLCONV 474 _gss_ntlm_wrap 475 (OM_uint32 * minor_status, 476 gss_const_ctx_id_t context_handle, 477 int conf_req_flag, 478 gss_qop_t qop_req, 479 const gss_buffer_t input_message_buffer, 480 int * conf_state, 481 gss_buffer_t output_message_buffer 482 ) 483 { 484 ntlm_ctx ctx = (ntlm_ctx)context_handle; 485 OM_uint32 ret; 486 487 *minor_status = 0; 488 if (conf_state) 489 *conf_state = 0; 490 if (output_message_buffer == GSS_C_NO_BUFFER) 491 return GSS_S_FAILURE; 492 493 494 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 495 496 return v2_seal_message(input_message_buffer, 497 ctx->u.v2.send.signkey, 498 ctx->u.v2.send.seq++, 499 &ctx->u.v2.send.sealkey, 500 output_message_buffer); 501 502 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 503 gss_buffer_desc trailer; 504 OM_uint32 junk; 505 506 output_message_buffer->length = input_message_buffer->length + 16; 507 output_message_buffer->value = malloc(output_message_buffer->length); 508 if (output_message_buffer->value == NULL) { 509 output_message_buffer->length = 0; 510 return GSS_S_FAILURE; 511 } 512 513 514 RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 515 input_message_buffer->value, output_message_buffer->value); 516 517 ret = _gss_ntlm_get_mic(minor_status, context_handle, 518 0, input_message_buffer, 519 &trailer); 520 if (ret) { 521 gss_release_buffer(&junk, output_message_buffer); 522 return ret; 523 } 524 if (trailer.length != 16) { 525 gss_release_buffer(&junk, output_message_buffer); 526 gss_release_buffer(&junk, &trailer); 527 return GSS_S_FAILURE; 528 } 529 memcpy(((unsigned char *)output_message_buffer->value) + 530 input_message_buffer->length, 531 trailer.value, trailer.length); 532 gss_release_buffer(&junk, &trailer); 533 534 return GSS_S_COMPLETE; 535 } 536 537 return GSS_S_UNAVAILABLE; 538 } 539 540 /* 541 * 542 */ 543 544 OM_uint32 GSSAPI_CALLCONV 545 _gss_ntlm_unwrap 546 (OM_uint32 * minor_status, 547 gss_const_ctx_id_t context_handle, 548 const gss_buffer_t input_message_buffer, 549 gss_buffer_t output_message_buffer, 550 int * conf_state, 551 gss_qop_t * qop_state 552 ) 553 { 554 ntlm_ctx ctx = (ntlm_ctx)context_handle; 555 OM_uint32 ret; 556 557 *minor_status = 0; 558 output_message_buffer->value = NULL; 559 output_message_buffer->length = 0; 560 561 if (conf_state) 562 *conf_state = 0; 563 if (qop_state) 564 *qop_state = 0; 565 566 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 567 568 return v2_unseal_message(input_message_buffer, 569 ctx->u.v2.recv.signkey, 570 ctx->u.v2.recv.seq++, 571 &ctx->u.v2.recv.sealkey, 572 output_message_buffer); 573 574 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 575 576 gss_buffer_desc trailer; 577 OM_uint32 junk; 578 579 if (input_message_buffer->length < 16) 580 return GSS_S_BAD_MIC; 581 582 output_message_buffer->length = input_message_buffer->length - 16; 583 output_message_buffer->value = malloc(output_message_buffer->length); 584 if (output_message_buffer->value == NULL) { 585 output_message_buffer->length = 0; 586 return GSS_S_FAILURE; 587 } 588 589 RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 590 input_message_buffer->value, output_message_buffer->value); 591 592 trailer.value = ((unsigned char *)input_message_buffer->value) + 593 output_message_buffer->length; 594 trailer.length = 16; 595 596 ret = _gss_ntlm_verify_mic(minor_status, context_handle, 597 output_message_buffer, 598 &trailer, NULL); 599 if (ret) { 600 gss_release_buffer(&junk, output_message_buffer); 601 return ret; 602 } 603 604 return GSS_S_COMPLETE; 605 } 606 607 return GSS_S_UNAVAILABLE; 608 } 609