curl_ntlm_core.c (18865B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #if defined(USE_CURL_NTLM_CORE) 28 29 /* 30 * NTLM details: 31 * 32 * https://davenport.sourceforge.net/ntlm.html 33 * https://www.innovation.ch/java/ntlm.html 34 */ 35 36 /* Please keep the SSL backend-specific #if branches in this order: 37 38 1. USE_OPENSSL 39 2. USE_WOLFSSL 40 3. USE_GNUTLS 41 4. - 42 5. USE_MBEDTLS 43 6. USE_OS400CRYPTO 44 7. USE_WIN32_CRYPTO 45 46 This ensures that: 47 - the same SSL branch gets activated throughout this source 48 file even if multiple backends are enabled at the same time. 49 - OpenSSL has higher priority than Windows Crypt, due 50 to issues with the latter supporting NTLM2Session responses 51 in NTLM type-3 messages. 52 */ 53 54 #if defined(USE_OPENSSL) 55 #include <openssl/opensslconf.h> 56 #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0) 57 #define USE_OPENSSL_DES 58 #endif 59 #elif defined(USE_WOLFSSL) 60 #include <wolfssl/options.h> 61 #if !defined(NO_DES3) 62 #define USE_OPENSSL_DES 63 #endif 64 #endif 65 66 #if defined(USE_OPENSSL_DES) 67 68 #if defined(USE_OPENSSL) 69 # include <openssl/des.h> 70 # include <openssl/md5.h> 71 # include <openssl/ssl.h> 72 # include <openssl/rand.h> 73 # if defined(OPENSSL_IS_AWSLC) 74 # define DES_set_key_unchecked (void)DES_set_key 75 # define DESKEYARG(x) *x 76 # define DESKEY(x) &x 77 # else 78 # define DESKEYARG(x) *x 79 # define DESKEY(x) &x 80 # endif 81 #else 82 # include <wolfssl/openssl/des.h> 83 # include <wolfssl/openssl/md5.h> 84 # include <wolfssl/openssl/ssl.h> 85 # include <wolfssl/openssl/rand.h> 86 # if defined(OPENSSL_COEXIST) 87 # define DES_key_schedule WOLFSSL_DES_key_schedule 88 # define DES_cblock WOLFSSL_DES_cblock 89 # define DES_set_odd_parity wolfSSL_DES_set_odd_parity 90 # define DES_set_key wolfSSL_DES_set_key 91 # define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked 92 # define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt 93 # define DESKEY(x) ((WOLFSSL_DES_key_schedule *)(x)) 94 # define DESKEYARG(x) *x 95 # else 96 # define DESKEYARG(x) *x 97 # define DESKEY(x) &x 98 # endif 99 #endif 100 101 #elif defined(USE_GNUTLS) 102 103 # include <nettle/des.h> 104 105 #elif defined(USE_MBEDTLS) 106 107 # include <mbedtls/des.h> 108 109 #elif defined(USE_OS400CRYPTO) 110 # include "cipher.mih" /* mih/cipher */ 111 #elif defined(USE_WIN32_CRYPTO) 112 # include <wincrypt.h> 113 #else 114 # error "cannot compile NTLM support without a crypto library with DES." 115 # define CURL_NTLM_NOT_SUPPORTED 116 #endif 117 118 #include "urldata.h" 119 #include "strcase.h" 120 #include "curl_ntlm_core.h" 121 #include "curl_md5.h" 122 #include "curl_hmac.h" 123 #include "curlx/warnless.h" 124 #include "curl_endian.h" 125 #include "curl_des.h" 126 #include "curl_md4.h" 127 /* The last 3 #include files should be in this order */ 128 #include "curl_printf.h" 129 #include "curl_memory.h" 130 #include "memdebug.h" 131 132 #if !defined(CURL_NTLM_NOT_SUPPORTED) 133 /* 134 * Turns a 56-bit key into being 64-bit wide. 135 */ 136 static void extend_key_56_to_64(const unsigned char *key_56, char *key) 137 { 138 key[0] = (char)key_56[0]; 139 key[1] = (char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); 140 key[2] = (char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); 141 key[3] = (char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); 142 key[4] = (char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); 143 key[5] = (char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); 144 key[6] = (char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); 145 key[7] = (char) ((key_56[6] << 1) & 0xFF); 146 } 147 #endif 148 149 #if defined(USE_OPENSSL_DES) 150 /* 151 * Turns a 56-bit key into a 64-bit, odd parity key and sets the key. The 152 * key schedule ks is also set. 153 */ 154 static void setup_des_key(const unsigned char *key_56, 155 DES_key_schedule DESKEYARG(ks)) 156 { 157 DES_cblock key; 158 159 /* Expand the 56-bit key to 64 bits */ 160 extend_key_56_to_64(key_56, (char *) &key); 161 162 /* Set the key parity to odd */ 163 DES_set_odd_parity(&key); 164 165 /* Set the key */ 166 DES_set_key_unchecked(&key, ks); 167 } 168 169 #elif defined(USE_GNUTLS) 170 171 static void setup_des_key(const unsigned char *key_56, 172 struct des_ctx *des) 173 { 174 char key[8]; 175 176 /* Expand the 56-bit key to 64 bits */ 177 extend_key_56_to_64(key_56, key); 178 179 /* Set the key parity to odd */ 180 Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); 181 182 /* Set the key */ 183 des_set_key(des, (const uint8_t *) key); 184 } 185 186 #elif defined(USE_MBEDTLS) 187 188 static bool encrypt_des(const unsigned char *in, unsigned char *out, 189 const unsigned char *key_56) 190 { 191 mbedtls_des_context ctx; 192 char key[8]; 193 194 /* Expand the 56-bit key to 64 bits */ 195 extend_key_56_to_64(key_56, key); 196 197 /* Set the key parity to odd */ 198 mbedtls_des_key_set_parity((unsigned char *) key); 199 200 /* Perform the encryption */ 201 mbedtls_des_init(&ctx); 202 mbedtls_des_setkey_enc(&ctx, (unsigned char *) key); 203 return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; 204 } 205 206 #elif defined(USE_OS400CRYPTO) 207 208 static bool encrypt_des(const unsigned char *in, unsigned char *out, 209 const unsigned char *key_56) 210 { 211 char key[8]; 212 _CIPHER_Control_T ctl; 213 214 /* Setup the cipher control structure */ 215 ctl.Func_ID = ENCRYPT_ONLY; 216 ctl.Data_Len = sizeof(key); 217 218 /* Expand the 56-bit key to 64 bits */ 219 extend_key_56_to_64(key_56, ctl.Crypto_Key); 220 221 /* Set the key parity to odd */ 222 Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); 223 224 /* Perform the encryption */ 225 _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); 226 227 return TRUE; 228 } 229 230 #elif defined(USE_WIN32_CRYPTO) 231 232 static bool encrypt_des(const unsigned char *in, unsigned char *out, 233 const unsigned char *key_56) 234 { 235 HCRYPTPROV hprov; 236 HCRYPTKEY hkey; 237 struct { 238 BLOBHEADER hdr; 239 unsigned int len; 240 char key[8]; 241 } blob; 242 DWORD len = 8; 243 244 /* Acquire the crypto provider */ 245 if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, 246 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) 247 return FALSE; 248 249 /* Setup the key blob structure */ 250 memset(&blob, 0, sizeof(blob)); 251 blob.hdr.bType = PLAINTEXTKEYBLOB; 252 blob.hdr.bVersion = 2; 253 blob.hdr.aiKeyAlg = CALG_DES; 254 blob.len = sizeof(blob.key); 255 256 /* Expand the 56-bit key to 64 bits */ 257 extend_key_56_to_64(key_56, blob.key); 258 259 /* Set the key parity to odd */ 260 Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); 261 262 /* Import the key */ 263 if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { 264 CryptReleaseContext(hprov, 0); 265 266 return FALSE; 267 } 268 269 memcpy(out, in, 8); 270 271 /* Perform the encryption */ 272 CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len); 273 274 CryptDestroyKey(hkey); 275 CryptReleaseContext(hprov, 0); 276 277 return TRUE; 278 } 279 280 #endif /* defined(USE_WIN32_CRYPTO) */ 281 282 /* 283 * takes a 21 byte array and treats it as 3 56-bit DES keys. The 284 * 8 byte plaintext is encrypted with each key and the resulting 24 285 * bytes are stored in the results array. 286 */ 287 void Curl_ntlm_core_lm_resp(const unsigned char *keys, 288 const unsigned char *plaintext, 289 unsigned char *results) 290 { 291 #if defined(USE_OPENSSL_DES) 292 DES_key_schedule ks; 293 294 setup_des_key(keys, DESKEY(ks)); 295 DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), 296 (DES_cblock*)results, DESKEY(ks), DES_ENCRYPT); 297 298 setup_des_key(keys + 7, DESKEY(ks)); 299 DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), 300 (DES_cblock*)(results + 8), DESKEY(ks), DES_ENCRYPT); 301 302 setup_des_key(keys + 14, DESKEY(ks)); 303 DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), 304 (DES_cblock*)(results + 16), DESKEY(ks), DES_ENCRYPT); 305 #elif defined(USE_GNUTLS) 306 struct des_ctx des; 307 setup_des_key(keys, &des); 308 des_encrypt(&des, 8, results, plaintext); 309 setup_des_key(keys + 7, &des); 310 des_encrypt(&des, 8, results + 8, plaintext); 311 setup_des_key(keys + 14, &des); 312 des_encrypt(&des, 8, results + 16, plaintext); 313 #elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \ 314 defined(USE_WIN32_CRYPTO) 315 encrypt_des(plaintext, results, keys); 316 encrypt_des(plaintext, results + 8, keys + 7); 317 encrypt_des(plaintext, results + 16, keys + 14); 318 #else 319 (void)keys; 320 (void)plaintext; 321 (void)results; 322 #endif 323 } 324 325 /* 326 * Set up lanmanager hashed password 327 */ 328 CURLcode Curl_ntlm_core_mk_lm_hash(const char *password, 329 unsigned char *lmbuffer /* 21 bytes */) 330 { 331 unsigned char pw[14]; 332 #if !defined(CURL_NTLM_NOT_SUPPORTED) 333 static const unsigned char magic[] = { 334 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ 335 }; 336 #endif 337 size_t len = CURLMIN(strlen(password), 14); 338 339 Curl_strntoupper((char *)pw, password, len); 340 memset(&pw[len], 0, 14 - len); 341 342 { 343 /* Create LanManager hashed password. */ 344 345 #if defined(USE_OPENSSL_DES) 346 DES_key_schedule ks; 347 348 setup_des_key(pw, DESKEY(ks)); 349 DES_ecb_encrypt((DES_cblock *)CURL_UNCONST(magic), 350 (DES_cblock *)lmbuffer, DESKEY(ks), DES_ENCRYPT); 351 352 setup_des_key(pw + 7, DESKEY(ks)); 353 DES_ecb_encrypt((DES_cblock *)CURL_UNCONST(magic), 354 (DES_cblock *)(lmbuffer + 8), DESKEY(ks), DES_ENCRYPT); 355 #elif defined(USE_GNUTLS) 356 struct des_ctx des; 357 setup_des_key(pw, &des); 358 des_encrypt(&des, 8, lmbuffer, magic); 359 setup_des_key(pw + 7, &des); 360 des_encrypt(&des, 8, lmbuffer + 8, magic); 361 #elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \ 362 defined(USE_WIN32_CRYPTO) 363 encrypt_des(magic, lmbuffer, pw); 364 encrypt_des(magic, lmbuffer + 8, pw + 7); 365 #endif 366 367 memset(lmbuffer + 16, 0, 21 - 16); 368 } 369 370 return CURLE_OK; 371 } 372 373 static void ascii_to_unicode_le(unsigned char *dest, const char *src, 374 size_t srclen) 375 { 376 size_t i; 377 for(i = 0; i < srclen; i++) { 378 dest[2 * i] = (unsigned char)src[i]; 379 dest[2 * i + 1] = '\0'; 380 } 381 } 382 383 #if !defined(USE_WINDOWS_SSPI) 384 385 static void ascii_uppercase_to_unicode_le(unsigned char *dest, 386 const char *src, size_t srclen) 387 { 388 size_t i; 389 for(i = 0; i < srclen; i++) { 390 dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i])); 391 dest[2 * i + 1] = '\0'; 392 } 393 } 394 395 #endif /* !USE_WINDOWS_SSPI */ 396 397 /* 398 * Set up nt hashed passwords 399 * @unittest: 1600 400 */ 401 CURLcode Curl_ntlm_core_mk_nt_hash(const char *password, 402 unsigned char *ntbuffer /* 21 bytes */) 403 { 404 size_t len = strlen(password); 405 unsigned char *pw; 406 CURLcode result; 407 if(len > SIZE_T_MAX/2) /* avoid integer overflow */ 408 return CURLE_OUT_OF_MEMORY; 409 pw = len ? malloc(len * 2) : (unsigned char *)strdup(""); 410 if(!pw) 411 return CURLE_OUT_OF_MEMORY; 412 413 ascii_to_unicode_le(pw, password, len); 414 415 /* Create NT hashed password. */ 416 result = Curl_md4it(ntbuffer, pw, 2 * len); 417 if(!result) 418 memset(ntbuffer + 16, 0, 21 - 16); 419 420 free(pw); 421 422 return result; 423 } 424 425 #if !defined(USE_WINDOWS_SSPI) 426 427 #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" 428 #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) 429 430 /* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */ 431 struct ms_filetime { 432 unsigned int dwLowDateTime; 433 unsigned int dwHighDateTime; 434 }; 435 436 /* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */ 437 static void time2filetime(struct ms_filetime *ft, time_t t) 438 { 439 #if SIZEOF_TIME_T > 4 440 t = (t + (curl_off_t)11644473600) * 10000000; 441 ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF); 442 ft->dwHighDateTime = (unsigned int) (t >> 32); 443 #else 444 unsigned int r, s; 445 unsigned int i; 446 447 ft->dwLowDateTime = (unsigned int)t & 0xFFFFFFFF; 448 ft->dwHighDateTime = 0; 449 450 # ifndef HAVE_TIME_T_UNSIGNED 451 /* Extend sign if needed. */ 452 if(ft->dwLowDateTime & 0x80000000) 453 ft->dwHighDateTime = ~(unsigned int)0; 454 # endif 455 456 /* Bias seconds to Jan 1, 1601. 457 134774 days = 11644473600 seconds = 0x2B6109100 */ 458 r = ft->dwLowDateTime; 459 ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF; 460 ft->dwHighDateTime += ft->dwLowDateTime < r ? 0x03 : 0x02; 461 462 /* Convert to tenths of microseconds. */ 463 ft->dwHighDateTime *= 10000000; 464 i = 32; 465 do { 466 i -= 8; 467 s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1); 468 r = (s << i) & 0xFFFFFFFF; 469 s >>= 1; /* Split shift to avoid width overflow. */ 470 s >>= 31 - i; 471 ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF; 472 if(ft->dwLowDateTime < r) 473 s++; 474 ft->dwHighDateTime += s; 475 } while(i); 476 ft->dwHighDateTime &= 0xFFFFFFFF; 477 #endif 478 } 479 480 /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode 481 * (uppercase UserName + Domain) as the data 482 */ 483 CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, 484 const char *domain, size_t domlen, 485 unsigned char *ntlmhash, 486 unsigned char *ntlmv2hash) 487 { 488 /* Unicode representation */ 489 size_t identity_len; 490 unsigned char *identity; 491 CURLcode result = CURLE_OK; 492 493 if((userlen > CURL_MAX_INPUT_LENGTH) || (domlen > CURL_MAX_INPUT_LENGTH)) 494 return CURLE_OUT_OF_MEMORY; 495 496 identity_len = (userlen + domlen) * 2; 497 identity = malloc(identity_len + 1); 498 499 if(!identity) 500 return CURLE_OUT_OF_MEMORY; 501 502 ascii_uppercase_to_unicode_le(identity, user, userlen); 503 ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); 504 505 result = Curl_hmacit(&Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len, 506 ntlmv2hash); 507 free(identity); 508 509 return result; 510 } 511 512 /* 513 * Curl_ntlm_core_mk_ntlmv2_resp() 514 * 515 * This creates the NTLMv2 response as set in the NTLM type-3 message. 516 * 517 * Parameters: 518 * 519 * ntlmv2hash [in] - The NTLMv2 hash (16 bytes) 520 * challenge_client [in] - The client nonce (8 bytes) 521 * ntlm [in] - The NTLM data struct being used to read TargetInfo 522 and Server challenge received in the type-2 message 523 * ntresp [out] - The address where a pointer to newly allocated 524 * memory holding the NTLMv2 response. 525 * ntresp_len [out] - The length of the output message. 526 * 527 * Returns CURLE_OK on success. 528 */ 529 CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, 530 unsigned char *challenge_client, 531 struct ntlmdata *ntlm, 532 unsigned char **ntresp, 533 unsigned int *ntresp_len) 534 { 535 /* NTLMv2 response structure : 536 ------------------------------------------------------------------------------ 537 0 HMAC MD5 16 bytes 538 ------BLOB-------------------------------------------------------------------- 539 16 Signature 0x01010000 540 20 Reserved long (0x00000000) 541 24 Timestamp LE, 64-bit signed value representing the number of 542 tenths of a microsecond since January 1, 1601. 543 32 Client Nonce 8 bytes 544 40 Unknown 4 bytes 545 44 Target Info N bytes (from the type-2 message) 546 44+N Unknown 4 bytes 547 ------------------------------------------------------------------------------ 548 */ 549 550 unsigned int len = 0; 551 unsigned char *ptr = NULL; 552 unsigned char hmac_output[HMAC_MD5_LENGTH]; 553 struct ms_filetime tw; 554 555 CURLcode result = CURLE_OK; 556 557 /* Calculate the timestamp */ 558 #ifdef DEBUGBUILD 559 char *force_timestamp = getenv("CURL_FORCETIME"); 560 if(force_timestamp) 561 time2filetime(&tw, (time_t) 0); 562 else 563 #endif 564 time2filetime(&tw, time(NULL)); 565 566 /* Calculate the response len */ 567 len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN; 568 569 /* Allocate the response */ 570 ptr = calloc(1, len); 571 if(!ptr) 572 return CURLE_OUT_OF_MEMORY; 573 574 /* Create the BLOB structure */ 575 msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN, 576 "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ 577 "%c%c%c%c" /* Reserved = 0 */ 578 "%c%c%c%c%c%c%c%c", /* Timestamp */ 579 NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], 580 NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], 581 0, 0, 0, 0, 582 LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime)); 583 584 memcpy(ptr + 32, challenge_client, 8); 585 if(ntlm->target_info_len) 586 memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); 587 588 /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ 589 memcpy(ptr + 8, &ntlm->nonce[0], 8); 590 result = Curl_hmacit(&Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8, 591 NTLMv2_BLOB_LEN + 8, hmac_output); 592 if(result) { 593 free(ptr); 594 return result; 595 } 596 597 /* Concatenate the HMAC MD5 output with the BLOB */ 598 memcpy(ptr, hmac_output, HMAC_MD5_LENGTH); 599 600 /* Return the response */ 601 *ntresp = ptr; 602 *ntresp_len = len; 603 604 return result; 605 } 606 607 /* 608 * Curl_ntlm_core_mk_lmv2_resp() 609 * 610 * This creates the LMv2 response as used in the NTLM type-3 message. 611 * 612 * Parameters: 613 * 614 * ntlmv2hash [in] - The NTLMv2 hash (16 bytes) 615 * challenge_client [in] - The client nonce (8 bytes) 616 * challenge_client [in] - The server challenge (8 bytes) 617 * lmresp [out] - The LMv2 response (24 bytes) 618 * 619 * Returns CURLE_OK on success. 620 */ 621 CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, 622 unsigned char *challenge_client, 623 unsigned char *challenge_server, 624 unsigned char *lmresp) 625 { 626 unsigned char data[16]; 627 unsigned char hmac_output[16]; 628 CURLcode result = CURLE_OK; 629 630 memcpy(&data[0], challenge_server, 8); 631 memcpy(&data[8], challenge_client, 8); 632 633 result = Curl_hmacit(&Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16, 634 hmac_output); 635 if(result) 636 return result; 637 638 /* Concatenate the HMAC MD5 output with the client nonce */ 639 memcpy(lmresp, hmac_output, 16); 640 memcpy(lmresp + 16, challenge_client, 8); 641 642 return result; 643 } 644 645 #endif /* !USE_WINDOWS_SSPI */ 646 647 #endif /* USE_CURL_NTLM_CORE */