1 /* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $ 33 */ 34 35 /* 36 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 /* 40 * NTLM support functions 41 * 42 * Some code from the driver: smb_smb.c, smb_crypt.c 43 */ 44 45 #include <sys/errno.h> 46 #include <sys/types.h> 47 #include <sys/md4.h> 48 #include <sys/md5.h> 49 50 #include <ctype.h> 51 #include <stdlib.h> 52 #include <strings.h> 53 54 #include <netsmb/smb_lib.h> 55 56 #include "private.h" 57 #include "charsets.h" 58 #include "smb_crypt.h" 59 #include "ntlm.h" 60 61 62 /* 63 * ntlm_compute_lm_hash 64 * 65 * Compute an LM hash given a password 66 * 67 * Output: 68 * hash: 16-byte "LanMan" (LM) hash. 69 * Inputs: 70 * ucpw: User's password, upper-case UTF-8 string. 71 * 72 * Source: Implementing CIFS (Chris Hertel) 73 * 74 * P14 = UCPW padded to 14-bytes, or truncated (as needed) 75 * result = Encrypt(Key=P14, Data=MagicString) 76 */ 77 int 78 ntlm_compute_lm_hash(uchar_t *hash, const char *pass) 79 { 80 static const uchar_t M8[8] = "KGS!@#$%"; 81 uchar_t P14[14 + 1]; 82 int err; 83 char *ucpw; 84 85 /* First, convert the p/w to upper case. */ 86 ucpw = utf8_str_toupper(pass); 87 if (ucpw == NULL) 88 return (ENOMEM); 89 90 /* Pad or truncate the upper-case P/W as needed. */ 91 bzero(P14, sizeof (P14)); 92 (void) strncpy((char *)P14, ucpw, 14); 93 94 /* Compute the hash. */ 95 err = smb_encrypt_DES(hash, NTLM_HASH_SZ, 96 P14, 14, M8, 8); 97 98 free(ucpw); 99 return (err); 100 } 101 102 /* 103 * ntlm_compute_nt_hash 104 * 105 * Compute an NT hash given a password in UTF-8. 106 * 107 * Output: 108 * hash: 16-byte "NT" hash. 109 * Inputs: 110 * upw: User's password, mixed-case UCS-2LE. 111 * pwlen: Size (in bytes) of upw 112 */ 113 int 114 ntlm_compute_nt_hash(uchar_t *hash, const char *pass) 115 { 116 MD4_CTX ctx; 117 uint16_t *unipw = NULL; 118 int pwsz; 119 120 /* First, convert the password to unicode. */ 121 unipw = convert_utf8_to_leunicode(pass); 122 if (unipw == NULL) 123 return (ENOMEM); 124 pwsz = unicode_strlen(unipw) << 1; 125 126 /* Compute the hash. */ 127 MD4Init(&ctx); 128 MD4Update(&ctx, unipw, pwsz); 129 MD4Final(hash, &ctx); 130 131 free(unipw); 132 return (0); 133 } 134 135 /* 136 * ntlm_v1_response 137 * 138 * Create an LM response from the given LM hash and challenge, 139 * or an NTLM repsonse from a given NTLM hash and challenge. 140 * Both response types are 24 bytes (NTLM_V1_RESP_SZ) 141 */ 142 static int 143 ntlm_v1_response(uchar_t *resp, 144 const uchar_t *hash, 145 const uchar_t *chal, int clen) 146 { 147 uchar_t S21[21]; 148 int err; 149 150 /* 151 * 14-byte LM Hash should be padded with 5 nul bytes to create 152 * a 21-byte string to be used in producing LM response 153 */ 154 bzero(&S21, sizeof (S21)); 155 bcopy(hash, S21, NTLM_HASH_SZ); 156 157 /* padded LM Hash -> LM Response */ 158 err = smb_encrypt_DES(resp, NTLM_V1_RESP_SZ, 159 S21, 21, chal, clen); 160 return (err); 161 } 162 163 /* 164 * Calculate an NTLMv1 session key (16 bytes). 165 */ 166 static void 167 ntlm_v1_session_key(uchar_t *ssn_key, const uchar_t *nt_hash) 168 { 169 MD4_CTX md4; 170 171 MD4Init(&md4); 172 MD4Update(&md4, nt_hash, NTLM_HASH_SZ); 173 MD4Final(ssn_key, &md4); 174 } 175 176 /* 177 * Compute both the LM(v1) response and the NTLM(v1) response, 178 * and put them in the mbdata chains passed. This allocates 179 * mbuf chains in the output args, which the caller frees. 180 */ 181 int 182 ntlm_put_v1_responses(struct smb_ctx *ctx, 183 struct mbdata *lm_mbp, struct mbdata *nt_mbp) 184 { 185 uchar_t *lmresp, *ntresp; 186 int err; 187 188 /* Get mbuf chain for the LM response. */ 189 if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0) 190 return (err); 191 192 /* Get mbuf chain for the NT response. */ 193 if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0) 194 return (err); 195 196 /* 197 * Compute the LM response, derived 198 * from the challenge and the ASCII 199 * password (if authflags allow). 200 */ 201 err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp); 202 if (err) 203 return (err); 204 bzero(lmresp, NTLM_V1_RESP_SZ); 205 if (ctx->ct_authflags & SMB_AT_LM1) { 206 /* They asked to send the LM hash too. */ 207 err = ntlm_v1_response(lmresp, ctx->ct_lmhash, 208 ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 209 if (err) 210 return (err); 211 } 212 213 /* 214 * Compute the NTLM response, derived from 215 * the challenge and the NT hash. 216 */ 217 err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp); 218 if (err) 219 return (err); 220 bzero(ntresp, NTLM_V1_RESP_SZ); 221 err = ntlm_v1_response(ntresp, ctx->ct_nthash, 222 ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 223 224 /* 225 * Compute the session key 226 */ 227 ntlm_v1_session_key(ctx->ct_ssn_key, ctx->ct_nthash); 228 229 return (err); 230 } 231 232 /* 233 * A variation on HMAC-MD5 known as HMACT64 is used by Windows systems. 234 * The HMACT64() function is the same as the HMAC-MD5() except that 235 * it truncates the input key to 64 bytes rather than hashing it down 236 * to 16 bytes using the MD5() function. 237 * 238 * Output: digest (16-bytes) 239 */ 240 static void 241 HMACT64(uchar_t *digest, 242 const uchar_t *key, size_t key_len, 243 const uchar_t *data, size_t data_len) 244 { 245 MD5_CTX context; 246 uchar_t k_ipad[64]; /* inner padding - key XORd with ipad */ 247 uchar_t k_opad[64]; /* outer padding - key XORd with opad */ 248 int i; 249 250 /* if key is longer than 64 bytes use only the first 64 bytes */ 251 if (key_len > 64) 252 key_len = 64; 253 254 /* 255 * The HMAC-MD5 (and HMACT64) transform looks like: 256 * 257 * MD5(K XOR opad, MD5(K XOR ipad, data)) 258 * 259 * where K is an n byte key 260 * ipad is the byte 0x36 repeated 64 times 261 * opad is the byte 0x5c repeated 64 times 262 * and data is the data being protected. 263 */ 264 265 /* start out by storing key in pads */ 266 bzero(k_ipad, sizeof (k_ipad)); 267 bzero(k_opad, sizeof (k_opad)); 268 bcopy(key, k_ipad, key_len); 269 bcopy(key, k_opad, key_len); 270 271 /* XOR key with ipad and opad values */ 272 for (i = 0; i < 64; i++) { 273 k_ipad[i] ^= 0x36; 274 k_opad[i] ^= 0x5c; 275 } 276 277 /* 278 * perform inner MD5 279 */ 280 MD5Init(&context); /* init context for 1st pass */ 281 MD5Update(&context, k_ipad, 64); /* start with inner pad */ 282 MD5Update(&context, data, data_len); /* then data of datagram */ 283 MD5Final(digest, &context); /* finish up 1st pass */ 284 285 /* 286 * perform outer MD5 287 */ 288 MD5Init(&context); /* init context for 2nd pass */ 289 MD5Update(&context, k_opad, 64); /* start with outer pad */ 290 MD5Update(&context, digest, 16); /* then results of 1st hash */ 291 MD5Final(digest, &context); /* finish up 2nd pass */ 292 } 293 294 295 /* 296 * Compute an NTLMv2 hash given the NTLMv1 hash, the user name, 297 * and the destination (machine or domain name). 298 * 299 * Output: 300 * v2hash: 16-byte NTLMv2 hash. 301 * Inputs: 302 * v1hash: 16-byte NTLMv1 hash. 303 * user: User name, UPPER-case UTF-8 string. 304 * destination: Domain or server, MIXED-case UTF-8 string. 305 */ 306 static int 307 ntlm_v2_hash(uchar_t *v2hash, const uchar_t *v1hash, 308 const char *user, const char *destination) 309 { 310 int ulen, dlen; 311 size_t ucs2len; 312 uint16_t *ucs2data = NULL; 313 char *utf8data = NULL; 314 int err = ENOMEM; 315 316 /* 317 * v2hash = HMACT64(v1hash, 16, concat(upcase(user), dest)) 318 * where "dest" is the domain or server name ("target name") 319 * Note: user name is converted to upper-case by the caller. 320 */ 321 322 /* utf8data = concat(user, dest) */ 323 ulen = strlen(user); 324 dlen = strlen(destination); 325 utf8data = malloc(ulen + dlen + 1); 326 if (utf8data == NULL) 327 goto out; 328 bcopy(user, utf8data, ulen); 329 bcopy(destination, utf8data + ulen, dlen + 1); 330 331 /* Convert to UCS-2LE */ 332 ucs2data = convert_utf8_to_leunicode(utf8data); 333 if (ucs2data == NULL) 334 goto out; 335 ucs2len = 2 * unicode_strlen(ucs2data); 336 337 HMACT64(v2hash, v1hash, NTLM_HASH_SZ, 338 (uchar_t *)ucs2data, ucs2len); 339 err = 0; 340 out: 341 if (ucs2data) 342 free(ucs2data); 343 if (utf8data) 344 free(utf8data); 345 return (err); 346 } 347 348 /* 349 * Compute a partial LMv2 or NTLMv2 response (first 16-bytes). 350 * The full response is composed by the caller by 351 * appending the client_data to the returned hash. 352 * 353 * Output: 354 * rhash: _partial_ LMv2/NTLMv2 response (first 16-bytes) 355 * Inputs: 356 * v2hash: 16-byte NTLMv2 hash. 357 * C8: Challenge from server (8 bytes) 358 * client_data: client nonce (for LMv2) or the 359 * "blob" from ntlm_build_target_info (NTLMv2) 360 */ 361 static int 362 ntlm_v2_resp_hash(uchar_t *rhash, 363 const uchar_t *v2hash, const uchar_t *C8, 364 const uchar_t *client_data, size_t cdlen) 365 { 366 size_t dlen; 367 uchar_t *data = NULL; 368 369 /* data = concat(C8, client_data) */ 370 dlen = 8 + cdlen; 371 data = malloc(dlen); 372 if (data == NULL) 373 return (ENOMEM); 374 bcopy(C8, data, 8); 375 bcopy(client_data, data + 8, cdlen); 376 377 HMACT64(rhash, v2hash, NTLM_HASH_SZ, data, dlen); 378 379 free(data); 380 return (0); 381 } 382 383 /* 384 * Calculate an NTLMv2 session key (16 bytes). 385 */ 386 static void 387 ntlm_v2_session_key(uchar_t *ssn_key, 388 const uchar_t *v2hash, 389 const uchar_t *ntresp) 390 { 391 392 /* session key uses only 1st 16 bytes of ntresp */ 393 HMACT64(ssn_key, v2hash, NTLM_HASH_SZ, ntresp, NTLM_HASH_SZ); 394 } 395 396 397 /* 398 * Compute both the LMv2 response and the NTLMv2 response, 399 * and put them in the mbdata chains passed. This allocates 400 * mbuf chains in the output args, which the caller frees. 401 * Also computes the session key. 402 */ 403 int 404 ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp, 405 struct mbdata *lm_mbp, struct mbdata *nt_mbp) 406 { 407 uchar_t *lmresp, *ntresp; 408 int err; 409 char *ucuser = NULL; /* upper-case user name */ 410 uchar_t v2hash[NTLM_HASH_SZ]; 411 struct mbuf *tim = ti_mbp->mb_top; 412 413 if ((err = mb_init(lm_mbp)) != 0) 414 return (err); 415 if ((err = mb_init(nt_mbp)) != 0) 416 return (err); 417 418 /* 419 * Convert the user name to upper-case, as 420 * that's what's used when computing LMv2 421 * and NTLMv2 responses. Note that the 422 * domain name is NOT upper-cased! 423 */ 424 ucuser = utf8_str_toupper(ctx->ct_user); 425 if (ucuser == NULL) { 426 err = ENOMEM; 427 goto out; 428 } 429 430 /* 431 * Compute the NTLMv2 hash 432 */ 433 err = ntlm_v2_hash(v2hash, ctx->ct_nthash, 434 ucuser, ctx->ct_domain); 435 if (err) 436 goto out; 437 438 /* 439 * Compute the LMv2 response, derived from 440 * the v2hash, the server challenge, and 441 * the client nonce (random bits). 442 * 443 * We compose it from two parts: 444 * 1: 16-byte response hash 445 * 2: Client nonce 446 */ 447 lmresp = (uchar_t *)lm_mbp->mb_pos; 448 mb_put_mem(lm_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM); 449 err = ntlm_v2_resp_hash(lmresp, 450 v2hash, ctx->ct_ntlm_chal, 451 ctx->ct_clnonce, NTLM_CHAL_SZ); 452 if (err) 453 goto out; 454 mb_put_mem(lm_mbp, ctx->ct_clnonce, NTLM_CHAL_SZ, MB_MSYSTEM); 455 456 /* 457 * Compute the NTLMv2 response, derived 458 * from the server challenge and the 459 * "target info." blob passed in. 460 * 461 * Again composed from two parts: 462 * 1: 16-byte response hash 463 * 2: "target info." blob 464 */ 465 ntresp = (uchar_t *)nt_mbp->mb_pos; 466 mb_put_mem(nt_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM); 467 err = ntlm_v2_resp_hash(ntresp, 468 v2hash, ctx->ct_ntlm_chal, 469 (uchar_t *)tim->m_data, tim->m_len); 470 if (err) 471 goto out; 472 mb_put_mem(nt_mbp, tim->m_data, tim->m_len, MB_MSYSTEM); 473 474 /* 475 * Compute the session key 476 */ 477 ntlm_v2_session_key(ctx->ct_ssn_key, v2hash, ntresp); 478 479 out: 480 if (err) { 481 mb_done(lm_mbp); 482 mb_done(nt_mbp); 483 } 484 free(ucuser); 485 486 return (err); 487 } 488 489 /* 490 * Helper for ntlm_build_target_info below. 491 * Put a name in the NTLMv2 "target info." blob. 492 */ 493 static void 494 smb_put_blob_name(struct mbdata *mbp, char *name, int type) 495 { 496 uint16_t *ucs = NULL; 497 int nlen; 498 499 if (name) 500 ucs = convert_utf8_to_leunicode(name); 501 if (ucs) 502 nlen = unicode_strlen(ucs); 503 else 504 nlen = 0; 505 506 nlen <<= 1; /* length in bytes, without null. */ 507 508 mb_put_uint16le(mbp, type); 509 mb_put_uint16le(mbp, nlen); 510 mb_put_mem(mbp, (char *)ucs, nlen, MB_MSYSTEM); 511 512 if (ucs) 513 free(ucs); 514 } 515 516 /* 517 * Build an NTLMv2 "target info." blob. When called from NTLMSSP, 518 * the list of names comes from the Type 2 message. Otherwise, 519 * we create the name list here. 520 */ 521 int 522 ntlm_build_target_info(struct smb_ctx *ctx, struct mbuf *names, 523 struct mbdata *mbp) 524 { 525 struct timeval now; 526 uint64_t nt_time; 527 528 char *ucdom = NULL; /* user's domain */ 529 int err; 530 531 /* Get mbuf chain for the "target info". */ 532 if ((err = mb_init(mbp)) != 0) 533 return (err); 534 535 /* 536 * Construct the client nonce by getting 537 * some random data from /dev/urandom 538 */ 539 err = smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ); 540 if (err) 541 goto out; 542 543 /* 544 * Get the "NT time" for the target info header. 545 */ 546 (void) gettimeofday(&now, 0); 547 smb_time_local2NT(&now, 0, &nt_time); 548 549 /* 550 * Build the "target info." block. 551 * 552 * Based on information at: 553 * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response 554 * 555 * First the fixed-size part. 556 */ 557 mb_put_uint32le(mbp, 0x101); /* Blob signature */ 558 mb_put_uint32le(mbp, 0); /* reserved */ 559 mb_put_uint64le(mbp, nt_time); /* NT time stamp */ 560 mb_put_mem(mbp, ctx->ct_clnonce, NTLM_CHAL_SZ, MB_MSYSTEM); 561 mb_put_uint32le(mbp, 0); /* unknown */ 562 563 /* 564 * Now put the list of names, either from the 565 * NTLMSSP Type 2 message or composed here. 566 */ 567 if (names) { 568 err = mb_put_mem(mbp, names->m_data, names->m_len, MB_MSYSTEM); 569 } else { 570 /* Get upper-case names. */ 571 ucdom = utf8_str_toupper(ctx->ct_domain); 572 if (ucdom == NULL) { 573 err = ENOMEM; 574 goto out; 575 } 576 smb_put_blob_name(mbp, ucdom, NAMETYPE_DOMAIN_NB); 577 smb_put_blob_name(mbp, NULL, NAMETYPE_EOL); 578 /* OK, that's the whole "target info." blob! */ 579 } 580 err = 0; 581 582 out: 583 free(ucdom); 584 return (err); 585 } 586