1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/base/net_string_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_buffer_writer.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_constants.h"
16*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/des.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/hmac.h"
18*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/md4.h"
19*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/md5.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net::ntlm {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace {
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker // Takes the parsed target info in |av_pairs| and performs the following
26*6777b538SAndroid Build Coastguard Worker // actions.
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // 1) If a |TargetInfoAvId::kTimestamp| AvPair exists, |server_timestamp|
29*6777b538SAndroid Build Coastguard Worker // is set to the payload.
30*6777b538SAndroid Build Coastguard Worker // 2) If |is_mic_enabled| is true, the existing |TargetInfoAvId::kFlags| AvPair
31*6777b538SAndroid Build Coastguard Worker // will have the |TargetInfoAvFlags::kMicPresent| bit set. If an existing
32*6777b538SAndroid Build Coastguard Worker // flags AvPair does not already exist, a new one is added with the value of
33*6777b538SAndroid Build Coastguard Worker // |TargetInfoAvFlags::kMicPresent|.
34*6777b538SAndroid Build Coastguard Worker // 3) If |is_epa_enabled| is true, two new AvPair entries will be added to
35*6777b538SAndroid Build Coastguard Worker // |av_pairs|. The first will be of type |TargetInfoAvId::kChannelBindings|
36*6777b538SAndroid Build Coastguard Worker // and contains MD5(|channel_bindings|) as the payload. The second will be
37*6777b538SAndroid Build Coastguard Worker // of type |TargetInfoAvId::kTargetName| and contains |spn| as a little
38*6777b538SAndroid Build Coastguard Worker // endian UTF16 string.
39*6777b538SAndroid Build Coastguard Worker // 4) Sets |target_info_len| to the size of |av_pairs| when serialized into
40*6777b538SAndroid Build Coastguard Worker // a payload.
UpdateTargetInfoAvPairs(bool is_mic_enabled,bool is_epa_enabled,const std::string & channel_bindings,const std::string & spn,std::vector<AvPair> * av_pairs,uint64_t * server_timestamp,size_t * target_info_len)41*6777b538SAndroid Build Coastguard Worker void UpdateTargetInfoAvPairs(bool is_mic_enabled,
42*6777b538SAndroid Build Coastguard Worker bool is_epa_enabled,
43*6777b538SAndroid Build Coastguard Worker const std::string& channel_bindings,
44*6777b538SAndroid Build Coastguard Worker const std::string& spn,
45*6777b538SAndroid Build Coastguard Worker std::vector<AvPair>* av_pairs,
46*6777b538SAndroid Build Coastguard Worker uint64_t* server_timestamp,
47*6777b538SAndroid Build Coastguard Worker size_t* target_info_len) {
48*6777b538SAndroid Build Coastguard Worker // Do a pass to update flags and calculate current length and
49*6777b538SAndroid Build Coastguard Worker // pull out the server timestamp if it is there.
50*6777b538SAndroid Build Coastguard Worker *server_timestamp = UINT64_MAX;
51*6777b538SAndroid Build Coastguard Worker *target_info_len = 0;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker bool need_flags_added = is_mic_enabled;
54*6777b538SAndroid Build Coastguard Worker for (AvPair& pair : *av_pairs) {
55*6777b538SAndroid Build Coastguard Worker *target_info_len += pair.avlen + kAvPairHeaderLen;
56*6777b538SAndroid Build Coastguard Worker switch (pair.avid) {
57*6777b538SAndroid Build Coastguard Worker case TargetInfoAvId::kFlags:
58*6777b538SAndroid Build Coastguard Worker // The parsing phase already set the payload to the |flags| field.
59*6777b538SAndroid Build Coastguard Worker if (is_mic_enabled) {
60*6777b538SAndroid Build Coastguard Worker pair.flags = pair.flags | TargetInfoAvFlags::kMicPresent;
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker need_flags_added = false;
64*6777b538SAndroid Build Coastguard Worker break;
65*6777b538SAndroid Build Coastguard Worker case TargetInfoAvId::kTimestamp:
66*6777b538SAndroid Build Coastguard Worker // The parsing phase already set the payload to the |timestamp| field.
67*6777b538SAndroid Build Coastguard Worker *server_timestamp = pair.timestamp;
68*6777b538SAndroid Build Coastguard Worker break;
69*6777b538SAndroid Build Coastguard Worker case TargetInfoAvId::kEol:
70*6777b538SAndroid Build Coastguard Worker case TargetInfoAvId::kChannelBindings:
71*6777b538SAndroid Build Coastguard Worker case TargetInfoAvId::kTargetName:
72*6777b538SAndroid Build Coastguard Worker // The terminator, |kEol|, should already have been removed from the
73*6777b538SAndroid Build Coastguard Worker // end of the list and would have been rejected if it has been inside
74*6777b538SAndroid Build Coastguard Worker // the list. Additionally |kChannelBindings| and |kTargetName| pairs
75*6777b538SAndroid Build Coastguard Worker // would have been rejected during the initial parsing. See
76*6777b538SAndroid Build Coastguard Worker // |NtlmBufferReader::ReadTargetInfo|.
77*6777b538SAndroid Build Coastguard Worker NOTREACHED();
78*6777b538SAndroid Build Coastguard Worker break;
79*6777b538SAndroid Build Coastguard Worker default:
80*6777b538SAndroid Build Coastguard Worker // Ignore entries we don't care about.
81*6777b538SAndroid Build Coastguard Worker break;
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Worker if (need_flags_added) {
86*6777b538SAndroid Build Coastguard Worker DCHECK(is_mic_enabled);
87*6777b538SAndroid Build Coastguard Worker AvPair flags_pair(TargetInfoAvId::kFlags, sizeof(uint32_t));
88*6777b538SAndroid Build Coastguard Worker flags_pair.flags = TargetInfoAvFlags::kMicPresent;
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker av_pairs->push_back(flags_pair);
91*6777b538SAndroid Build Coastguard Worker *target_info_len += kAvPairHeaderLen + flags_pair.avlen;
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker if (is_epa_enabled) {
95*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> channel_bindings_hash(kChannelBindingsHashLen, 0);
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker // Hash the channel bindings if they exist otherwise they remain zeros.
98*6777b538SAndroid Build Coastguard Worker if (!channel_bindings.empty()) {
99*6777b538SAndroid Build Coastguard Worker GenerateChannelBindingHashV2(
100*6777b538SAndroid Build Coastguard Worker channel_bindings,
101*6777b538SAndroid Build Coastguard Worker base::make_span<kChannelBindingsHashLen>(channel_bindings_hash));
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker av_pairs->emplace_back(TargetInfoAvId::kChannelBindings,
105*6777b538SAndroid Build Coastguard Worker std::move(channel_bindings_hash));
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker // Convert the SPN to little endian unicode.
108*6777b538SAndroid Build Coastguard Worker std::u16string spn16 = base::UTF8ToUTF16(spn);
109*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter spn_writer(spn16.length() * 2);
110*6777b538SAndroid Build Coastguard Worker bool spn_writer_result =
111*6777b538SAndroid Build Coastguard Worker spn_writer.WriteUtf16String(spn16) && spn_writer.IsEndOfBuffer();
112*6777b538SAndroid Build Coastguard Worker DCHECK(spn_writer_result);
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker av_pairs->emplace_back(TargetInfoAvId::kTargetName, spn_writer.Pass());
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker // Add the length of the two new AV Pairs to the total length.
117*6777b538SAndroid Build Coastguard Worker *target_info_len +=
118*6777b538SAndroid Build Coastguard Worker (2 * kAvPairHeaderLen) + kChannelBindingsHashLen + (spn16.length() * 2);
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker // Add extra space for the terminator at the end.
122*6777b538SAndroid Build Coastguard Worker *target_info_len += kAvPairHeaderLen;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
WriteUpdatedTargetInfo(const std::vector<AvPair> & av_pairs,size_t updated_target_info_len)125*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> WriteUpdatedTargetInfo(const std::vector<AvPair>& av_pairs,
126*6777b538SAndroid Build Coastguard Worker size_t updated_target_info_len) {
127*6777b538SAndroid Build Coastguard Worker bool result = true;
128*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter writer(updated_target_info_len);
129*6777b538SAndroid Build Coastguard Worker for (const AvPair& pair : av_pairs) {
130*6777b538SAndroid Build Coastguard Worker result = writer.WriteAvPair(pair);
131*6777b538SAndroid Build Coastguard Worker DCHECK(result);
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker result = writer.WriteAvPairTerminator() && writer.IsEndOfBuffer();
135*6777b538SAndroid Build Coastguard Worker DCHECK(result);
136*6777b538SAndroid Build Coastguard Worker return writer.Pass();
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker // Reads 7 bytes (56 bits) from |key_56| and writes them into 8 bytes of
140*6777b538SAndroid Build Coastguard Worker // |key_64| with 7 bits in every byte. The least significant bits are
141*6777b538SAndroid Build Coastguard Worker // undefined and a subsequent operation will set those bits with a parity bit.
142*6777b538SAndroid Build Coastguard Worker // |key_56| must contain 7 bytes.
143*6777b538SAndroid Build Coastguard Worker // |key_64| must contain 8 bytes.
Splay56To64(base::span<const uint8_t,7> key_56,base::span<uint8_t,8> key_64)144*6777b538SAndroid Build Coastguard Worker void Splay56To64(base::span<const uint8_t, 7> key_56,
145*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, 8> key_64) {
146*6777b538SAndroid Build Coastguard Worker key_64[0] = key_56[0];
147*6777b538SAndroid Build Coastguard Worker key_64[1] = key_56[0] << 7 | key_56[1] >> 1;
148*6777b538SAndroid Build Coastguard Worker key_64[2] = key_56[1] << 6 | key_56[2] >> 2;
149*6777b538SAndroid Build Coastguard Worker key_64[3] = key_56[2] << 5 | key_56[3] >> 3;
150*6777b538SAndroid Build Coastguard Worker key_64[4] = key_56[3] << 4 | key_56[4] >> 4;
151*6777b538SAndroid Build Coastguard Worker key_64[5] = key_56[4] << 3 | key_56[5] >> 5;
152*6777b538SAndroid Build Coastguard Worker key_64[6] = key_56[5] << 2 | key_56[6] >> 6;
153*6777b538SAndroid Build Coastguard Worker key_64[7] = key_56[6] << 1;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker } // namespace
157*6777b538SAndroid Build Coastguard Worker
Create3DesKeysFromNtlmHash(base::span<const uint8_t,kNtlmHashLen> ntlm_hash,base::span<uint8_t,24> keys)158*6777b538SAndroid Build Coastguard Worker void Create3DesKeysFromNtlmHash(
159*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kNtlmHashLen> ntlm_hash,
160*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, 24> keys) {
161*6777b538SAndroid Build Coastguard Worker // Put the first 112 bits from |ntlm_hash| into the first 16 bytes of
162*6777b538SAndroid Build Coastguard Worker // |keys|.
163*6777b538SAndroid Build Coastguard Worker Splay56To64(ntlm_hash.first<7>(), keys.first<8>());
164*6777b538SAndroid Build Coastguard Worker Splay56To64(ntlm_hash.subspan<7, 7>(), keys.subspan<8, 8>());
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker // Put the next 2x 7 bits in bytes 16 and 17 of |keys|, then
167*6777b538SAndroid Build Coastguard Worker // the last 2 bits in byte 18, then zero pad the rest of the final key.
168*6777b538SAndroid Build Coastguard Worker keys[16] = ntlm_hash[14];
169*6777b538SAndroid Build Coastguard Worker keys[17] = ntlm_hash[14] << 7 | ntlm_hash[15] >> 1;
170*6777b538SAndroid Build Coastguard Worker keys[18] = ntlm_hash[15] << 6;
171*6777b538SAndroid Build Coastguard Worker memset(keys.data() + 19, 0, 5);
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
GenerateNtlmHashV1(const std::u16string & password,base::span<uint8_t,kNtlmHashLen> hash)174*6777b538SAndroid Build Coastguard Worker void GenerateNtlmHashV1(const std::u16string& password,
175*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kNtlmHashLen> hash) {
176*6777b538SAndroid Build Coastguard Worker size_t length = password.length() * 2;
177*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter writer(length);
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker // The writer will handle the big endian case if necessary.
180*6777b538SAndroid Build Coastguard Worker bool result = writer.WriteUtf16String(password) && writer.IsEndOfBuffer();
181*6777b538SAndroid Build Coastguard Worker DCHECK(result);
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker MD4(writer.GetBuffer().data(), writer.GetLength(), hash.data());
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
GenerateResponseDesl(base::span<const uint8_t,kNtlmHashLen> hash,base::span<const uint8_t,kChallengeLen> challenge,base::span<uint8_t,kResponseLenV1> response)186*6777b538SAndroid Build Coastguard Worker void GenerateResponseDesl(base::span<const uint8_t, kNtlmHashLen> hash,
187*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> challenge,
188*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> response) {
189*6777b538SAndroid Build Coastguard Worker constexpr size_t block_count = 3;
190*6777b538SAndroid Build Coastguard Worker constexpr size_t block_size = sizeof(DES_cblock);
191*6777b538SAndroid Build Coastguard Worker static_assert(kChallengeLen == block_size,
192*6777b538SAndroid Build Coastguard Worker "kChallengeLen must equal block_size");
193*6777b538SAndroid Build Coastguard Worker static_assert(kResponseLenV1 == block_count * block_size,
194*6777b538SAndroid Build Coastguard Worker "kResponseLenV1 must equal block_count * block_size");
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker const DES_cblock* challenge_block =
197*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const DES_cblock*>(challenge.data());
198*6777b538SAndroid Build Coastguard Worker uint8_t keys[block_count * block_size];
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker // Map the NTLM hash to three 8 byte DES keys, with 7 bits of the key in each
201*6777b538SAndroid Build Coastguard Worker // byte and the least significant bit set with odd parity. Then encrypt the
202*6777b538SAndroid Build Coastguard Worker // 8 byte challenge with each of the three keys. This produces three 8 byte
203*6777b538SAndroid Build Coastguard Worker // encrypted blocks into |response|.
204*6777b538SAndroid Build Coastguard Worker Create3DesKeysFromNtlmHash(hash, keys);
205*6777b538SAndroid Build Coastguard Worker for (size_t ix = 0; ix < block_count * block_size; ix += block_size) {
206*6777b538SAndroid Build Coastguard Worker DES_cblock* key_block = reinterpret_cast<DES_cblock*>(keys + ix);
207*6777b538SAndroid Build Coastguard Worker DES_cblock* response_block =
208*6777b538SAndroid Build Coastguard Worker reinterpret_cast<DES_cblock*>(response.data() + ix);
209*6777b538SAndroid Build Coastguard Worker
210*6777b538SAndroid Build Coastguard Worker DES_key_schedule key_schedule;
211*6777b538SAndroid Build Coastguard Worker DES_set_odd_parity(key_block);
212*6777b538SAndroid Build Coastguard Worker DES_set_key(key_block, &key_schedule);
213*6777b538SAndroid Build Coastguard Worker DES_ecb_encrypt(challenge_block, response_block, &key_schedule,
214*6777b538SAndroid Build Coastguard Worker DES_ENCRYPT);
215*6777b538SAndroid Build Coastguard Worker }
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
GenerateNtlmResponseV1(const std::u16string & password,base::span<const uint8_t,kChallengeLen> server_challenge,base::span<uint8_t,kResponseLenV1> ntlm_response)218*6777b538SAndroid Build Coastguard Worker void GenerateNtlmResponseV1(
219*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
220*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
221*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> ntlm_response) {
222*6777b538SAndroid Build Coastguard Worker uint8_t ntlm_hash[kNtlmHashLen];
223*6777b538SAndroid Build Coastguard Worker GenerateNtlmHashV1(password, ntlm_hash);
224*6777b538SAndroid Build Coastguard Worker GenerateResponseDesl(ntlm_hash, server_challenge, ntlm_response);
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker
GenerateResponsesV1(const std::u16string & password,base::span<const uint8_t,kChallengeLen> server_challenge,base::span<uint8_t,kResponseLenV1> lm_response,base::span<uint8_t,kResponseLenV1> ntlm_response)227*6777b538SAndroid Build Coastguard Worker void GenerateResponsesV1(
228*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
229*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
230*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> lm_response,
231*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> ntlm_response) {
232*6777b538SAndroid Build Coastguard Worker GenerateNtlmResponseV1(password, server_challenge, ntlm_response);
233*6777b538SAndroid Build Coastguard Worker
234*6777b538SAndroid Build Coastguard Worker // In NTLM v1 (with LMv1 disabled), the lm_response and ntlm_response are the
235*6777b538SAndroid Build Coastguard Worker // same. So just copy the ntlm_response into the lm_response.
236*6777b538SAndroid Build Coastguard Worker memcpy(lm_response.data(), ntlm_response.data(), kResponseLenV1);
237*6777b538SAndroid Build Coastguard Worker }
238*6777b538SAndroid Build Coastguard Worker
GenerateLMResponseV1WithSessionSecurity(base::span<const uint8_t,kChallengeLen> client_challenge,base::span<uint8_t,kResponseLenV1> lm_response)239*6777b538SAndroid Build Coastguard Worker void GenerateLMResponseV1WithSessionSecurity(
240*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge,
241*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> lm_response) {
242*6777b538SAndroid Build Coastguard Worker // In NTLM v1 with Session Security (aka NTLM2) the lm_response is 8 bytes of
243*6777b538SAndroid Build Coastguard Worker // client challenge and 16 bytes of zeros. (See 3.3.1)
244*6777b538SAndroid Build Coastguard Worker memcpy(lm_response.data(), client_challenge.data(), kChallengeLen);
245*6777b538SAndroid Build Coastguard Worker memset(lm_response.data() + kChallengeLen, 0, kResponseLenV1 - kChallengeLen);
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker
GenerateSessionHashV1WithSessionSecurity(base::span<const uint8_t,kChallengeLen> server_challenge,base::span<const uint8_t,kChallengeLen> client_challenge,base::span<uint8_t,kNtlmHashLen> session_hash)248*6777b538SAndroid Build Coastguard Worker void GenerateSessionHashV1WithSessionSecurity(
249*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
250*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge,
251*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kNtlmHashLen> session_hash) {
252*6777b538SAndroid Build Coastguard Worker MD5_CTX ctx;
253*6777b538SAndroid Build Coastguard Worker MD5_Init(&ctx);
254*6777b538SAndroid Build Coastguard Worker MD5_Update(&ctx, server_challenge.data(), kChallengeLen);
255*6777b538SAndroid Build Coastguard Worker MD5_Update(&ctx, client_challenge.data(), kChallengeLen);
256*6777b538SAndroid Build Coastguard Worker MD5_Final(session_hash.data(), &ctx);
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker
GenerateNtlmResponseV1WithSessionSecurity(const std::u16string & password,base::span<const uint8_t,kChallengeLen> server_challenge,base::span<const uint8_t,kChallengeLen> client_challenge,base::span<uint8_t,kResponseLenV1> ntlm_response)259*6777b538SAndroid Build Coastguard Worker void GenerateNtlmResponseV1WithSessionSecurity(
260*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
261*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
262*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge,
263*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> ntlm_response) {
264*6777b538SAndroid Build Coastguard Worker // Generate the NTLMv1 Hash.
265*6777b538SAndroid Build Coastguard Worker uint8_t ntlm_hash[kNtlmHashLen];
266*6777b538SAndroid Build Coastguard Worker GenerateNtlmHashV1(password, ntlm_hash);
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker // Generate the NTLMv1 Session Hash.
269*6777b538SAndroid Build Coastguard Worker uint8_t session_hash[kNtlmHashLen];
270*6777b538SAndroid Build Coastguard Worker GenerateSessionHashV1WithSessionSecurity(server_challenge, client_challenge,
271*6777b538SAndroid Build Coastguard Worker session_hash);
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker GenerateResponseDesl(
274*6777b538SAndroid Build Coastguard Worker ntlm_hash, base::make_span(session_hash).subspan<0, kChallengeLen>(),
275*6777b538SAndroid Build Coastguard Worker ntlm_response);
276*6777b538SAndroid Build Coastguard Worker }
277*6777b538SAndroid Build Coastguard Worker
GenerateResponsesV1WithSessionSecurity(const std::u16string & password,base::span<const uint8_t,kChallengeLen> server_challenge,base::span<const uint8_t,kChallengeLen> client_challenge,base::span<uint8_t,kResponseLenV1> lm_response,base::span<uint8_t,kResponseLenV1> ntlm_response)278*6777b538SAndroid Build Coastguard Worker void GenerateResponsesV1WithSessionSecurity(
279*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
280*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
281*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge,
282*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> lm_response,
283*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kResponseLenV1> ntlm_response) {
284*6777b538SAndroid Build Coastguard Worker GenerateLMResponseV1WithSessionSecurity(client_challenge, lm_response);
285*6777b538SAndroid Build Coastguard Worker GenerateNtlmResponseV1WithSessionSecurity(password, server_challenge,
286*6777b538SAndroid Build Coastguard Worker client_challenge, ntlm_response);
287*6777b538SAndroid Build Coastguard Worker }
288*6777b538SAndroid Build Coastguard Worker
GenerateNtlmHashV2(const std::u16string & domain,const std::u16string & username,const std::u16string & password,base::span<uint8_t,kNtlmHashLen> v2_hash)289*6777b538SAndroid Build Coastguard Worker void GenerateNtlmHashV2(const std::u16string& domain,
290*6777b538SAndroid Build Coastguard Worker const std::u16string& username,
291*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
292*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kNtlmHashLen> v2_hash) {
293*6777b538SAndroid Build Coastguard Worker // NOTE: According to [MS-NLMP] Section 3.3.2 only the username and not the
294*6777b538SAndroid Build Coastguard Worker // domain is uppercased.
295*6777b538SAndroid Build Coastguard Worker
296*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1051924): Using a locale-sensitive upper casing
297*6777b538SAndroid Build Coastguard Worker // algorithm is problematic. A more predictable approach would be to only
298*6777b538SAndroid Build Coastguard Worker // uppercase ASCII characters, so the hash does not change depending on the
299*6777b538SAndroid Build Coastguard Worker // user's locale.
300*6777b538SAndroid Build Coastguard Worker std::u16string upper_username;
301*6777b538SAndroid Build Coastguard Worker bool result = ToUpper(username, &upper_username);
302*6777b538SAndroid Build Coastguard Worker DCHECK(result);
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker uint8_t v1_hash[kNtlmHashLen];
305*6777b538SAndroid Build Coastguard Worker GenerateNtlmHashV1(password, v1_hash);
306*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter input_writer((upper_username.length() + domain.length()) *
307*6777b538SAndroid Build Coastguard Worker 2);
308*6777b538SAndroid Build Coastguard Worker bool writer_result = input_writer.WriteUtf16String(upper_username) &&
309*6777b538SAndroid Build Coastguard Worker input_writer.WriteUtf16String(domain) &&
310*6777b538SAndroid Build Coastguard Worker input_writer.IsEndOfBuffer();
311*6777b538SAndroid Build Coastguard Worker DCHECK(writer_result);
312*6777b538SAndroid Build Coastguard Worker
313*6777b538SAndroid Build Coastguard Worker unsigned int outlen = kNtlmHashLen;
314*6777b538SAndroid Build Coastguard Worker uint8_t* out_hash =
315*6777b538SAndroid Build Coastguard Worker HMAC(EVP_md5(), v1_hash, sizeof(v1_hash), input_writer.GetBuffer().data(),
316*6777b538SAndroid Build Coastguard Worker input_writer.GetLength(), v2_hash.data(), &outlen);
317*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(v2_hash.data(), out_hash);
318*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(sizeof(v1_hash), outlen);
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker
GenerateProofInputV2(uint64_t timestamp,base::span<const uint8_t,kChallengeLen> client_challenge)321*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> GenerateProofInputV2(
322*6777b538SAndroid Build Coastguard Worker uint64_t timestamp,
323*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge) {
324*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter writer(kProofInputLenV2);
325*6777b538SAndroid Build Coastguard Worker bool result = writer.WriteUInt16(kProofInputVersionV2) &&
326*6777b538SAndroid Build Coastguard Worker writer.WriteZeros(6) && writer.WriteUInt64(timestamp) &&
327*6777b538SAndroid Build Coastguard Worker writer.WriteBytes(client_challenge) && writer.WriteZeros(4) &&
328*6777b538SAndroid Build Coastguard Worker writer.IsEndOfBuffer();
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker DCHECK(result);
331*6777b538SAndroid Build Coastguard Worker return writer.Pass();
332*6777b538SAndroid Build Coastguard Worker }
333*6777b538SAndroid Build Coastguard Worker
GenerateNtlmProofV2(base::span<const uint8_t,kNtlmHashLen> v2_hash,base::span<const uint8_t,kChallengeLen> server_challenge,base::span<const uint8_t,kProofInputLenV2> v2_input,base::span<const uint8_t> target_info,base::span<uint8_t,kNtlmProofLenV2> v2_proof)334*6777b538SAndroid Build Coastguard Worker void GenerateNtlmProofV2(
335*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kNtlmHashLen> v2_hash,
336*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> server_challenge,
337*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kProofInputLenV2> v2_input,
338*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> target_info,
339*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kNtlmProofLenV2> v2_proof) {
340*6777b538SAndroid Build Coastguard Worker bssl::ScopedHMAC_CTX ctx;
341*6777b538SAndroid Build Coastguard Worker HMAC_Init_ex(ctx.get(), v2_hash.data(), kNtlmHashLen, EVP_md5(), nullptr);
342*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kNtlmProofLenV2, HMAC_size(ctx.get()));
343*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), server_challenge.data(), kChallengeLen);
344*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), v2_input.data(), kProofInputLenV2);
345*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), target_info.data(), target_info.size());
346*6777b538SAndroid Build Coastguard Worker const uint32_t zero = 0;
347*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), reinterpret_cast<const uint8_t*>(&zero),
348*6777b538SAndroid Build Coastguard Worker sizeof(uint32_t));
349*6777b538SAndroid Build Coastguard Worker HMAC_Final(ctx.get(), v2_proof.data(), nullptr);
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker
GenerateSessionBaseKeyV2(base::span<const uint8_t,kNtlmHashLen> v2_hash,base::span<const uint8_t,kNtlmProofLenV2> v2_proof,base::span<uint8_t,kSessionKeyLenV2> session_key)352*6777b538SAndroid Build Coastguard Worker void GenerateSessionBaseKeyV2(
353*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kNtlmHashLen> v2_hash,
354*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kNtlmProofLenV2> v2_proof,
355*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kSessionKeyLenV2> session_key) {
356*6777b538SAndroid Build Coastguard Worker unsigned int outlen = kSessionKeyLenV2;
357*6777b538SAndroid Build Coastguard Worker uint8_t* result =
358*6777b538SAndroid Build Coastguard Worker HMAC(EVP_md5(), v2_hash.data(), kNtlmHashLen, v2_proof.data(),
359*6777b538SAndroid Build Coastguard Worker kNtlmProofLenV2, session_key.data(), &outlen);
360*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(session_key.data(), result);
361*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kSessionKeyLenV2, outlen);
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker
GenerateChannelBindingHashV2(const std::string & channel_bindings,base::span<uint8_t,kNtlmHashLen> channel_bindings_hash)364*6777b538SAndroid Build Coastguard Worker void GenerateChannelBindingHashV2(
365*6777b538SAndroid Build Coastguard Worker const std::string& channel_bindings,
366*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kNtlmHashLen> channel_bindings_hash) {
367*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter writer(kEpaUnhashedStructHeaderLen);
368*6777b538SAndroid Build Coastguard Worker bool result = writer.WriteZeros(16) &&
369*6777b538SAndroid Build Coastguard Worker writer.WriteUInt32(channel_bindings.length()) &&
370*6777b538SAndroid Build Coastguard Worker writer.IsEndOfBuffer();
371*6777b538SAndroid Build Coastguard Worker DCHECK(result);
372*6777b538SAndroid Build Coastguard Worker
373*6777b538SAndroid Build Coastguard Worker MD5_CTX ctx;
374*6777b538SAndroid Build Coastguard Worker MD5_Init(&ctx);
375*6777b538SAndroid Build Coastguard Worker MD5_Update(&ctx, writer.GetBuffer().data(), writer.GetBuffer().size());
376*6777b538SAndroid Build Coastguard Worker MD5_Update(&ctx, channel_bindings.data(), channel_bindings.size());
377*6777b538SAndroid Build Coastguard Worker MD5_Final(channel_bindings_hash.data(), &ctx);
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker
GenerateMicV2(base::span<const uint8_t,kSessionKeyLenV2> session_key,base::span<const uint8_t> negotiate_msg,base::span<const uint8_t> challenge_msg,base::span<const uint8_t> authenticate_msg,base::span<uint8_t,kMicLenV2> mic)380*6777b538SAndroid Build Coastguard Worker void GenerateMicV2(base::span<const uint8_t, kSessionKeyLenV2> session_key,
381*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> negotiate_msg,
382*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> challenge_msg,
383*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> authenticate_msg,
384*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kMicLenV2> mic) {
385*6777b538SAndroid Build Coastguard Worker bssl::ScopedHMAC_CTX ctx;
386*6777b538SAndroid Build Coastguard Worker HMAC_Init_ex(ctx.get(), session_key.data(), kSessionKeyLenV2, EVP_md5(),
387*6777b538SAndroid Build Coastguard Worker nullptr);
388*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kMicLenV2, HMAC_size(ctx.get()));
389*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), negotiate_msg.data(), negotiate_msg.size());
390*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), challenge_msg.data(), challenge_msg.size());
391*6777b538SAndroid Build Coastguard Worker HMAC_Update(ctx.get(), authenticate_msg.data(), authenticate_msg.size());
392*6777b538SAndroid Build Coastguard Worker HMAC_Final(ctx.get(), mic.data(), nullptr);
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker
GenerateUpdatedTargetInfo(bool is_mic_enabled,bool is_epa_enabled,const std::string & channel_bindings,const std::string & spn,const std::vector<AvPair> & av_pairs,uint64_t * server_timestamp)395*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::vector<uint8_t> GenerateUpdatedTargetInfo(
396*6777b538SAndroid Build Coastguard Worker bool is_mic_enabled,
397*6777b538SAndroid Build Coastguard Worker bool is_epa_enabled,
398*6777b538SAndroid Build Coastguard Worker const std::string& channel_bindings,
399*6777b538SAndroid Build Coastguard Worker const std::string& spn,
400*6777b538SAndroid Build Coastguard Worker const std::vector<AvPair>& av_pairs,
401*6777b538SAndroid Build Coastguard Worker uint64_t* server_timestamp) {
402*6777b538SAndroid Build Coastguard Worker size_t updated_target_info_len = 0;
403*6777b538SAndroid Build Coastguard Worker std::vector<AvPair> updated_av_pairs(av_pairs);
404*6777b538SAndroid Build Coastguard Worker UpdateTargetInfoAvPairs(is_mic_enabled, is_epa_enabled, channel_bindings, spn,
405*6777b538SAndroid Build Coastguard Worker &updated_av_pairs, server_timestamp,
406*6777b538SAndroid Build Coastguard Worker &updated_target_info_len);
407*6777b538SAndroid Build Coastguard Worker return WriteUpdatedTargetInfo(updated_av_pairs, updated_target_info_len);
408*6777b538SAndroid Build Coastguard Worker }
409*6777b538SAndroid Build Coastguard Worker
410*6777b538SAndroid Build Coastguard Worker } // namespace net::ntlm
411