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