16void ntlm_nt_hash(
const char *password, uint8_t nt_hash[16])
20 for (
const char *p = password; *p; p++)
22 uint8_t pair[2] = {(uint8_t)*p, 0};
23 md4_update(&c, pair, 2);
25 md4_final(&c, nt_hash);
28bool ntlm_ntowfv2(
const uint8_t nt_hash[16],
const char *user,
const char *domain, uint8_t owf[16])
32 for (
const char *p = user; *p; p++)
35 if (up >=
'a' && up <=
'z')
37 if (n + 2 >
sizeof(buf))
39 buf[n++] = (uint8_t)up;
42 for (
const char *p = domain; *p; p++)
44 if (n + 2 >
sizeof(buf))
46 buf[n++] = (uint8_t)*p;
49 hmac_md5(nt_hash, 16, buf, n, owf);
55static void hmac_md5_2(
const uint8_t key[16],
const uint8_t *m1,
size_t l1,
const uint8_t *m2,
size_t l2,
60 for (
int i = 0; i < 64; i++)
62 uint8_t k = (i < 16) ? key[i] : 0;
63 ipad[i] = (uint8_t)(k ^ 0x36);
64 opad[i] = (uint8_t)(k ^ 0x5c);
69 md5_update(&c, ipad, 64);
70 md5_update(&c, m1, l1);
72 md5_update(&c, m2, l2);
75 md5_update(&c, opad, 64);
76 md5_update(&c, inner, 16);
80size_t ntlm_v2_response(
const uint8_t owf[16],
const uint8_t server_challenge[8],
const uint8_t client_challenge[8],
81 const uint8_t timestamp[8],
const uint8_t *target_info,
size_t ti_len, uint8_t *out,
82 size_t out_cap, uint8_t session_key[16])
84 const size_t temp_len = 2 + 6 + 8 + 8 + 4 + ti_len + 4;
85 const size_t resp_len = 16 + temp_len;
86 if (!out || resp_len > out_cap)
90 uint8_t *temp = out + 16;
94 memset(temp + k, 0, 6);
96 memcpy(temp + k, timestamp, 8);
98 memcpy(temp + k, client_challenge, 8);
100 memset(temp + k, 0, 4);
102 memcpy(temp + k, target_info, ti_len);
104 memset(temp + k, 0, 4);
107 hmac_md5_2(owf, server_challenge, 8, temp, temp_len, ntproof);
108 memcpy(out, ntproof, 16);
110 hmac_md5(owf, 16, ntproof, 16, session_key);
NTLMv2 response computation (MS-NLMP §3.3.2) for the SMB2 client (DETWS_ENABLE_SMB).
MD4 (RFC 1320), MD5 (RFC 1321), and HMAC-MD5 (RFC 2104) - the legacy digests NTLM needs,...