xref: /aosp_15_r20/external/cronet/net/ntlm/ntlm_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 // Tests on exact results from cryptographic operations are based on test data
6*6777b538SAndroid Build Coastguard Worker // provided in [MS-NLMP] Version 28.0 [1] Section 4.2.
7*6777b538SAndroid Build Coastguard Worker //
8*6777b538SAndroid Build Coastguard Worker // Additional sanity checks on the low level hashing operations test for
9*6777b538SAndroid Build Coastguard Worker // properties of the outputs, such as whether the hashes change, whether they
10*6777b538SAndroid Build Coastguard Worker // should be zeroed out, or whether they should be the same or different.
11*6777b538SAndroid Build Coastguard Worker //
12*6777b538SAndroid Build Coastguard Worker // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include <iterator>
17*6777b538SAndroid Build Coastguard Worker #include <string>
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_test_data.h"
22*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace net::ntlm {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker namespace {
27*6777b538SAndroid Build Coastguard Worker 
MakeDomainAvPair()28*6777b538SAndroid Build Coastguard Worker AvPair MakeDomainAvPair() {
29*6777b538SAndroid Build Coastguard Worker   return AvPair(TargetInfoAvId::kDomainName,
30*6777b538SAndroid Build Coastguard Worker                 std::vector<uint8_t>{std::begin(test::kNtlmDomainRaw),
31*6777b538SAndroid Build Coastguard Worker                                      std::end(test::kNtlmDomainRaw)});
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker 
MakeServerAvPair()34*6777b538SAndroid Build Coastguard Worker AvPair MakeServerAvPair() {
35*6777b538SAndroid Build Coastguard Worker   return AvPair(TargetInfoAvId::kServerName,
36*6777b538SAndroid Build Coastguard Worker                 std::vector<uint8_t>{std::begin(test::kServerRaw),
37*6777b538SAndroid Build Coastguard Worker                                      std::end(test::kServerRaw)});
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker // Clear the least significant bit in each byte.
ClearLsb(base::span<uint8_t> data)41*6777b538SAndroid Build Coastguard Worker void ClearLsb(base::span<uint8_t> data) {
42*6777b538SAndroid Build Coastguard Worker   for (uint8_t& byte : data) {
43*6777b538SAndroid Build Coastguard Worker     byte &= ~1;
44*6777b538SAndroid Build Coastguard Worker   }
45*6777b538SAndroid Build Coastguard Worker }
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker }  // namespace
48*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,MapHashToDesKeysAllOnes)49*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, MapHashToDesKeysAllOnes) {
50*6777b538SAndroid Build Coastguard Worker   // Test mapping an NTLM hash with all 1 bits.
51*6777b538SAndroid Build Coastguard Worker   const uint8_t hash[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
52*6777b538SAndroid Build Coastguard Worker                             0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
53*6777b538SAndroid Build Coastguard Worker   const uint8_t expected[24] = {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
54*6777b538SAndroid Build Coastguard Worker                                 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
55*6777b538SAndroid Build Coastguard Worker                                 0xfe, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00};
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   uint8_t result[24];
58*6777b538SAndroid Build Coastguard Worker   Create3DesKeysFromNtlmHash(hash, result);
59*6777b538SAndroid Build Coastguard Worker   // The least significant bit in result from |Create3DesKeysFromNtlmHash|
60*6777b538SAndroid Build Coastguard Worker   // is undefined, so clear it to do memcmp.
61*6777b538SAndroid Build Coastguard Worker   ClearLsb(result);
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ranges::equal(expected, result));
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,MapHashToDesKeysAllZeros)66*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, MapHashToDesKeysAllZeros) {
67*6777b538SAndroid Build Coastguard Worker   // Test mapping an NTLM hash with all 0 bits.
68*6777b538SAndroid Build Coastguard Worker   const uint8_t hash[16] = {0x00};
69*6777b538SAndroid Build Coastguard Worker   const uint8_t expected[24] = {0x00};
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker   uint8_t result[24];
72*6777b538SAndroid Build Coastguard Worker   Create3DesKeysFromNtlmHash(hash, result);
73*6777b538SAndroid Build Coastguard Worker   // The least significant bit in result from |Create3DesKeysFromNtlmHash|
74*6777b538SAndroid Build Coastguard Worker   // is undefined, so clear it to do memcmp.
75*6777b538SAndroid Build Coastguard Worker   ClearLsb(result);
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ranges::equal(expected, result));
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,MapHashToDesKeysAlternatingBits)80*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, MapHashToDesKeysAlternatingBits) {
81*6777b538SAndroid Build Coastguard Worker   // Test mapping an NTLM hash with alternating 0 and 1 bits.
82*6777b538SAndroid Build Coastguard Worker   const uint8_t hash[16] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
83*6777b538SAndroid Build Coastguard Worker                             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
84*6777b538SAndroid Build Coastguard Worker   const uint8_t expected[24] = {0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54,
85*6777b538SAndroid Build Coastguard Worker                                 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54,
86*6777b538SAndroid Build Coastguard Worker                                 0xaa, 0x54, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00};
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   uint8_t result[24];
89*6777b538SAndroid Build Coastguard Worker   Create3DesKeysFromNtlmHash(hash, result);
90*6777b538SAndroid Build Coastguard Worker   // The least significant bit in result from |Create3DesKeysFromNtlmHash|
91*6777b538SAndroid Build Coastguard Worker   // is undefined, so clear it to do memcmp.
92*6777b538SAndroid Build Coastguard Worker   ClearLsb(result);
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ranges::equal(expected, result));
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmHashV1PasswordSpecTests)97*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmHashV1PasswordSpecTests) {
98*6777b538SAndroid Build Coastguard Worker   uint8_t hash[kNtlmHashLen];
99*6777b538SAndroid Build Coastguard Worker   GenerateNtlmHashV1(test::kPassword, hash);
100*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(hash, test::kExpectedNtlmHashV1, kNtlmHashLen));
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmHashV1PasswordChangesHash)103*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmHashV1PasswordChangesHash) {
104*6777b538SAndroid Build Coastguard Worker   std::u16string password1 = u"pwd01";
105*6777b538SAndroid Build Coastguard Worker   std::u16string password2 = u"pwd02";
106*6777b538SAndroid Build Coastguard Worker   uint8_t hash1[kNtlmHashLen];
107*6777b538SAndroid Build Coastguard Worker   uint8_t hash2[kNtlmHashLen];
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   GenerateNtlmHashV1(password1, hash1);
110*6777b538SAndroid Build Coastguard Worker   GenerateNtlmHashV1(password2, hash2);
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   // Verify that the hash is different with a different password.
113*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(hash1, hash2, kNtlmHashLen));
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateResponsesV1SpecTests)116*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateResponsesV1SpecTests) {
117*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response[kResponseLenV1];
118*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response[kResponseLenV1];
119*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1(test::kPassword, test::kServerChallenge, lm_response,
120*6777b538SAndroid Build Coastguard Worker                       ntlm_response);
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(
123*6777b538SAndroid Build Coastguard Worker       0, memcmp(test::kExpectedNtlmResponseV1, ntlm_response, kResponseLenV1));
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // This implementation never sends an LMv1 response (spec equivalent of the
126*6777b538SAndroid Build Coastguard Worker   // client variable NoLMResponseNTLMv1 being false) so the LM response is
127*6777b538SAndroid Build Coastguard Worker   // equal to the NTLM response when
128*6777b538SAndroid Build Coastguard Worker   // NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY is not negotiated. See
129*6777b538SAndroid Build Coastguard Worker   // [MS-NLMP] Section 3.3.1.
130*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0,
131*6777b538SAndroid Build Coastguard Worker             memcmp(test::kExpectedNtlmResponseV1, lm_response, kResponseLenV1));
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateResponsesV1WithSessionSecuritySpecTests)134*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateResponsesV1WithSessionSecuritySpecTests) {
135*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response[kResponseLenV1];
136*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response[kResponseLenV1];
137*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1WithSessionSecurity(
138*6777b538SAndroid Build Coastguard Worker       test::kPassword, test::kServerChallenge, test::kClientChallenge,
139*6777b538SAndroid Build Coastguard Worker       lm_response, ntlm_response);
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedLmResponseWithV1SS, lm_response,
142*6777b538SAndroid Build Coastguard Worker                       kResponseLenV1));
143*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedNtlmResponseWithV1SS, ntlm_response,
144*6777b538SAndroid Build Coastguard Worker                       kResponseLenV1));
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateResponsesV1WithSessionSecurityClientChallengeUsed)147*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateResponsesV1WithSessionSecurityClientChallengeUsed) {
148*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response1[kResponseLenV1];
149*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response2[kResponseLenV1];
150*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response1[kResponseLenV1];
151*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response2[kResponseLenV1];
152*6777b538SAndroid Build Coastguard Worker   uint8_t client_challenge1[kChallengeLen];
153*6777b538SAndroid Build Coastguard Worker   uint8_t client_challenge2[kChallengeLen];
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   memset(client_challenge1, 0x01, kChallengeLen);
156*6777b538SAndroid Build Coastguard Worker   memset(client_challenge2, 0x02, kChallengeLen);
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1WithSessionSecurity(
159*6777b538SAndroid Build Coastguard Worker       test::kPassword, test::kServerChallenge, client_challenge1, lm_response1,
160*6777b538SAndroid Build Coastguard Worker       ntlm_response1);
161*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1WithSessionSecurity(
162*6777b538SAndroid Build Coastguard Worker       test::kPassword, test::kServerChallenge, client_challenge2, lm_response2,
163*6777b538SAndroid Build Coastguard Worker       ntlm_response2);
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   // The point of session security is that the client can introduce some
166*6777b538SAndroid Build Coastguard Worker   // randomness, so verify different client_challenge gives a different result.
167*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(lm_response1, lm_response2, kResponseLenV1));
168*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(ntlm_response1, ntlm_response2, kResponseLenV1));
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker   // With session security the lm and ntlm hash should be different.
171*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(lm_response1, ntlm_response1, kResponseLenV1));
172*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(lm_response2, ntlm_response2, kResponseLenV1));
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateResponsesV1WithSessionSecurityVerifySSUsed)175*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateResponsesV1WithSessionSecurityVerifySSUsed) {
176*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response1[kResponseLenV1];
177*6777b538SAndroid Build Coastguard Worker   uint8_t lm_response2[kResponseLenV1];
178*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response1[kResponseLenV1];
179*6777b538SAndroid Build Coastguard Worker   uint8_t ntlm_response2[kResponseLenV1];
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1WithSessionSecurity(
182*6777b538SAndroid Build Coastguard Worker       test::kPassword, test::kServerChallenge, test::kClientChallenge,
183*6777b538SAndroid Build Coastguard Worker       lm_response1, ntlm_response1);
184*6777b538SAndroid Build Coastguard Worker   GenerateResponsesV1(test::kPassword, test::kServerChallenge, lm_response2,
185*6777b538SAndroid Build Coastguard Worker                       ntlm_response2);
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker   // Verify that the responses with session security are not the
188*6777b538SAndroid Build Coastguard Worker   // same as without it.
189*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(lm_response1, lm_response2, kResponseLenV1));
190*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(0, memcmp(ntlm_response1, ntlm_response2, kResponseLenV1));
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker // ------------------------------------------------
194*6777b538SAndroid Build Coastguard Worker // NTLM V2 specific tests.
195*6777b538SAndroid Build Coastguard Worker // ------------------------------------------------
196*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmHashV2SpecTests)197*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmHashV2SpecTests) {
198*6777b538SAndroid Build Coastguard Worker   uint8_t hash[kNtlmHashLen];
199*6777b538SAndroid Build Coastguard Worker   GenerateNtlmHashV2(test::kNtlmDomain, test::kUser, test::kPassword, hash);
200*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(hash, test::kExpectedNtlmHashV2, kNtlmHashLen));
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateProofInputV2SpecTests)203*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateProofInputV2SpecTests) {
204*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> proof_input;
205*6777b538SAndroid Build Coastguard Worker   proof_input =
206*6777b538SAndroid Build Coastguard Worker       GenerateProofInputV2(test::kServerTimestamp, test::kClientChallenge);
207*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(kProofInputLenV2, proof_input.size());
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker   // |GenerateProofInputV2| generates the first |kProofInputLenV2| bytes of
210*6777b538SAndroid Build Coastguard Worker   // what [MS-NLMP] calls "temp".
211*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedTempFromSpecV2, proof_input.data(),
212*6777b538SAndroid Build Coastguard Worker                       proof_input.size()));
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmProofV2SpecTests)215*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmProofV2SpecTests) {
216*6777b538SAndroid Build Coastguard Worker   // Only the first |kProofInputLenV2| bytes of |test::kExpectedTempFromSpecV2|
217*6777b538SAndroid Build Coastguard Worker   // are read and this is equivalent to the output of |GenerateProofInputV2|.
218*6777b538SAndroid Build Coastguard Worker   // See |GenerateProofInputV2SpecTests| for validation.
219*6777b538SAndroid Build Coastguard Worker   uint8_t v2_proof[kNtlmProofLenV2];
220*6777b538SAndroid Build Coastguard Worker   GenerateNtlmProofV2(test::kExpectedNtlmHashV2, test::kServerChallenge,
221*6777b538SAndroid Build Coastguard Worker                       base::make_span(test::kExpectedTempFromSpecV2)
222*6777b538SAndroid Build Coastguard Worker                           .subspan<0, kProofInputLenV2>(),
223*6777b538SAndroid Build Coastguard Worker                       test::kExpectedTargetInfoFromSpecV2, v2_proof);
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0,
226*6777b538SAndroid Build Coastguard Worker             memcmp(test::kExpectedProofFromSpecV2, v2_proof, kNtlmProofLenV2));
227*6777b538SAndroid Build Coastguard Worker }
228*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateSessionBaseKeyV2SpecTests)229*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateSessionBaseKeyV2SpecTests) {
230*6777b538SAndroid Build Coastguard Worker   // Generate the session base key.
231*6777b538SAndroid Build Coastguard Worker   uint8_t session_base_key[kSessionKeyLenV2];
232*6777b538SAndroid Build Coastguard Worker   GenerateSessionBaseKeyV2(test::kExpectedNtlmHashV2,
233*6777b538SAndroid Build Coastguard Worker                            test::kExpectedProofFromSpecV2, session_base_key);
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker   // Verify the session base key.
236*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedSessionBaseKeyFromSpecV2, session_base_key,
237*6777b538SAndroid Build Coastguard Worker                       kSessionKeyLenV2));
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateSessionBaseKeyWithClientTimestampV2SpecTests)240*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateSessionBaseKeyWithClientTimestampV2SpecTests) {
241*6777b538SAndroid Build Coastguard Worker   // Generate the session base key.
242*6777b538SAndroid Build Coastguard Worker   uint8_t session_base_key[kSessionKeyLenV2];
243*6777b538SAndroid Build Coastguard Worker   GenerateSessionBaseKeyV2(
244*6777b538SAndroid Build Coastguard Worker       test::kExpectedNtlmHashV2,
245*6777b538SAndroid Build Coastguard Worker       test::kExpectedProofSpecResponseWithClientTimestampV2, session_base_key);
246*6777b538SAndroid Build Coastguard Worker 
247*6777b538SAndroid Build Coastguard Worker   // Verify the session base key.
248*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedSessionBaseKeyWithClientTimestampV2,
249*6777b538SAndroid Build Coastguard Worker                       session_base_key, kSessionKeyLenV2));
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateChannelBindingHashV2SpecTests)252*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateChannelBindingHashV2SpecTests) {
253*6777b538SAndroid Build Coastguard Worker   uint8_t v2_channel_binding_hash[kChannelBindingsHashLen];
254*6777b538SAndroid Build Coastguard Worker   GenerateChannelBindingHashV2(
255*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(test::kChannelBindings),
256*6777b538SAndroid Build Coastguard Worker       v2_channel_binding_hash);
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedChannelBindingHashV2,
259*6777b538SAndroid Build Coastguard Worker                       v2_channel_binding_hash, kChannelBindingsHashLen));
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateMicV2Simple)262*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateMicV2Simple) {
263*6777b538SAndroid Build Coastguard Worker   // The MIC is defined as HMAC_MD5(session_base_key, CONCAT(a, b, c)) where
264*6777b538SAndroid Build Coastguard Worker   // a, b, c are the negotiate, challenge and authenticate messages
265*6777b538SAndroid Build Coastguard Worker   // respectively.
266*6777b538SAndroid Build Coastguard Worker   //
267*6777b538SAndroid Build Coastguard Worker   // This compares a simple set of inputs to a precalculated result.
268*6777b538SAndroid Build Coastguard Worker   const std::vector<uint8_t> a{0x44, 0x44, 0x44, 0x44};
269*6777b538SAndroid Build Coastguard Worker   const std::vector<uint8_t> b{0x66, 0x66, 0x66, 0x66, 0x66, 0x66};
270*6777b538SAndroid Build Coastguard Worker   const std::vector<uint8_t> c{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker   // expected_mic = HMAC_MD5(
273*6777b538SAndroid Build Coastguard Worker   //          key=8de40ccadbc14a82f15cb0ad0de95ca3,
274*6777b538SAndroid Build Coastguard Worker   //          input=444444446666666666668888888888888888)
275*6777b538SAndroid Build Coastguard Worker   uint8_t expected_mic[kMicLenV2] = {0x71, 0xfe, 0xef, 0xd7, 0x76, 0xd4,
276*6777b538SAndroid Build Coastguard Worker                                      0x42, 0xa8, 0x5f, 0x6e, 0x18, 0x0a,
277*6777b538SAndroid Build Coastguard Worker                                      0x6b, 0x02, 0x47, 0x20};
278*6777b538SAndroid Build Coastguard Worker 
279*6777b538SAndroid Build Coastguard Worker   uint8_t mic[kMicLenV2];
280*6777b538SAndroid Build Coastguard Worker   GenerateMicV2(test::kExpectedSessionBaseKeyFromSpecV2, a, b, c, mic);
281*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(expected_mic, mic, kMicLenV2));
282*6777b538SAndroid Build Coastguard Worker }
283*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateMicSpecResponseV2)284*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateMicSpecResponseV2) {
285*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> authenticate_msg(
286*6777b538SAndroid Build Coastguard Worker       std::begin(test::kExpectedAuthenticateMsgSpecResponseV2),
287*6777b538SAndroid Build Coastguard Worker       std::end(test::kExpectedAuthenticateMsgSpecResponseV2));
288*6777b538SAndroid Build Coastguard Worker   memset(&authenticate_msg[kMicOffsetV2], 0x00, kMicLenV2);
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   uint8_t mic[kMicLenV2];
291*6777b538SAndroid Build Coastguard Worker   GenerateMicV2(test::kExpectedSessionBaseKeyWithClientTimestampV2,
292*6777b538SAndroid Build Coastguard Worker                 test::kExpectedNegotiateMsg, test::kChallengeMsgFromSpecV2,
293*6777b538SAndroid Build Coastguard Worker                 authenticate_msg, mic);
294*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedMicV2, mic, kMicLenV2));
295*6777b538SAndroid Build Coastguard Worker }
296*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateUpdatedTargetInfo)297*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateUpdatedTargetInfo) {
298*6777b538SAndroid Build Coastguard Worker   // This constructs a std::vector<AvPair> that corresponds to the test input
299*6777b538SAndroid Build Coastguard Worker   // values in [MS-NLMP] Section 4.2.4.
300*6777b538SAndroid Build Coastguard Worker   std::vector<AvPair> server_av_pairs;
301*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeDomainAvPair());
302*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeServerAvPair());
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker   uint64_t server_timestamp = UINT64_MAX;
305*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
306*6777b538SAndroid Build Coastguard Worker       true, true, reinterpret_cast<const char*>(test::kChannelBindings),
307*6777b538SAndroid Build Coastguard Worker       test::kNtlmSpn, server_av_pairs, &server_timestamp);
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker   // With MIC and EPA enabled 3 additional AvPairs will be added.
310*6777b538SAndroid Build Coastguard Worker   // 1) A flags AVPair with the MIC_PRESENT bit set.
311*6777b538SAndroid Build Coastguard Worker   // 2) A channel bindings AVPair containing the channel bindings hash.
312*6777b538SAndroid Build Coastguard Worker   // 3) A target name AVPair containing the SPN of the server.
313*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(std::size(test::kExpectedTargetInfoSpecResponseV2),
314*6777b538SAndroid Build Coastguard Worker             updated_target_info.size());
315*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoSpecResponseV2,
316*6777b538SAndroid Build Coastguard Worker                       updated_target_info.data(), updated_target_info.size()));
317*6777b538SAndroid Build Coastguard Worker }
318*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateUpdatedTargetInfoNoEpaOrMic)319*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateUpdatedTargetInfoNoEpaOrMic) {
320*6777b538SAndroid Build Coastguard Worker   // This constructs a std::vector<AvPair> that corresponds to the test input
321*6777b538SAndroid Build Coastguard Worker   // values in [MS-NLMP] Section 4.2.4.
322*6777b538SAndroid Build Coastguard Worker   std::vector<AvPair> server_av_pairs;
323*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeDomainAvPair());
324*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeServerAvPair());
325*6777b538SAndroid Build Coastguard Worker 
326*6777b538SAndroid Build Coastguard Worker   uint64_t server_timestamp = UINT64_MAX;
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker   // When both EPA and MIC are false the target info does not get modified by
329*6777b538SAndroid Build Coastguard Worker   // the client.
330*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
331*6777b538SAndroid Build Coastguard Worker       false, false, reinterpret_cast<const char*>(test::kChannelBindings),
332*6777b538SAndroid Build Coastguard Worker       test::kNtlmSpn, server_av_pairs, &server_timestamp);
333*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(std::size(test::kExpectedTargetInfoFromSpecV2),
334*6777b538SAndroid Build Coastguard Worker             updated_target_info.size());
335*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoFromSpecV2,
336*6777b538SAndroid Build Coastguard Worker                       updated_target_info.data(), updated_target_info.size()));
337*6777b538SAndroid Build Coastguard Worker }
338*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateUpdatedTargetInfoWithServerTimestamp)339*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateUpdatedTargetInfoWithServerTimestamp) {
340*6777b538SAndroid Build Coastguard Worker   // This constructs a std::vector<AvPair> that corresponds to the test input
341*6777b538SAndroid Build Coastguard Worker   // values in [MS-NLMP] Section 4.2.4 with an additional server timestamp.
342*6777b538SAndroid Build Coastguard Worker   std::vector<AvPair> server_av_pairs;
343*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeDomainAvPair());
344*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(MakeServerAvPair());
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker   // Set the timestamp to |test::kServerTimestamp| and the buffer to all zeros.
347*6777b538SAndroid Build Coastguard Worker   AvPair pair(TargetInfoAvId::kTimestamp,
348*6777b538SAndroid Build Coastguard Worker               std::vector<uint8_t>(sizeof(uint64_t), 0));
349*6777b538SAndroid Build Coastguard Worker   pair.timestamp = test::kServerTimestamp;
350*6777b538SAndroid Build Coastguard Worker   server_av_pairs.push_back(std::move(pair));
351*6777b538SAndroid Build Coastguard Worker 
352*6777b538SAndroid Build Coastguard Worker   uint64_t server_timestamp = UINT64_MAX;
353*6777b538SAndroid Build Coastguard Worker   // When both EPA and MIC are false the target info does not get modified by
354*6777b538SAndroid Build Coastguard Worker   // the client.
355*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
356*6777b538SAndroid Build Coastguard Worker       false, false, reinterpret_cast<const char*>(test::kChannelBindings),
357*6777b538SAndroid Build Coastguard Worker       test::kNtlmSpn, server_av_pairs, &server_timestamp);
358*6777b538SAndroid Build Coastguard Worker   // Verify that the server timestamp was read from the target info.
359*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(test::kServerTimestamp, server_timestamp);
360*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(std::size(test::kExpectedTargetInfoFromSpecPlusServerTimestampV2),
361*6777b538SAndroid Build Coastguard Worker             updated_target_info.size());
362*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoFromSpecPlusServerTimestampV2,
363*6777b538SAndroid Build Coastguard Worker                       updated_target_info.data(), updated_target_info.size()));
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateUpdatedTargetInfoWhenServerSendsNoTargetInfo)366*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateUpdatedTargetInfoWhenServerSendsNoTargetInfo) {
367*6777b538SAndroid Build Coastguard Worker   // In some older implementations the server supports NTLMv2 but does not
368*6777b538SAndroid Build Coastguard Worker   // send target info. This manifests as an empty list of AvPairs.
369*6777b538SAndroid Build Coastguard Worker   std::vector<AvPair> server_av_pairs;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker   uint64_t server_timestamp = UINT64_MAX;
372*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
373*6777b538SAndroid Build Coastguard Worker       true, true, reinterpret_cast<const char*>(test::kChannelBindings),
374*6777b538SAndroid Build Coastguard Worker       test::kNtlmSpn, server_av_pairs, &server_timestamp);
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker   // With MIC and EPA enabled 3 additional AvPairs will be added.
377*6777b538SAndroid Build Coastguard Worker   // 1) A flags AVPair with the MIC_PRESENT bit set.
378*6777b538SAndroid Build Coastguard Worker   // 2) A channel bindings AVPair containing the channel bindings hash.
379*6777b538SAndroid Build Coastguard Worker   // 3) A target name AVPair containing the SPN of the server.
380*6777b538SAndroid Build Coastguard Worker   //
381*6777b538SAndroid Build Coastguard Worker   // Compared to the spec example in |GenerateUpdatedTargetInfo| the result
382*6777b538SAndroid Build Coastguard Worker   // is the same but with the first 32 bytes (which were the Domain and
383*6777b538SAndroid Build Coastguard Worker   // Server pairs) not present.
384*6777b538SAndroid Build Coastguard Worker   const size_t kMissingServerPairsLength = 32;
385*6777b538SAndroid Build Coastguard Worker 
386*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(std::size(test::kExpectedTargetInfoSpecResponseV2) -
387*6777b538SAndroid Build Coastguard Worker                 kMissingServerPairsLength,
388*6777b538SAndroid Build Coastguard Worker             updated_target_info.size());
389*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoSpecResponseV2 +
390*6777b538SAndroid Build Coastguard Worker                           kMissingServerPairsLength,
391*6777b538SAndroid Build Coastguard Worker                       updated_target_info.data(), updated_target_info.size()));
392*6777b538SAndroid Build Coastguard Worker }
393*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmProofV2)394*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmProofV2) {
395*6777b538SAndroid Build Coastguard Worker   uint8_t proof[kNtlmProofLenV2];
396*6777b538SAndroid Build Coastguard Worker 
397*6777b538SAndroid Build Coastguard Worker   GenerateNtlmProofV2(test::kExpectedNtlmHashV2, test::kServerChallenge,
398*6777b538SAndroid Build Coastguard Worker                       base::make_span(test::kExpectedTempFromSpecV2)
399*6777b538SAndroid Build Coastguard Worker                           .subspan<0, kProofInputLenV2>(),
400*6777b538SAndroid Build Coastguard Worker                       test::kExpectedTargetInfoSpecResponseV2, proof);
401*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0,
402*6777b538SAndroid Build Coastguard Worker             memcmp(test::kExpectedProofSpecResponseV2, proof, kNtlmProofLenV2));
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker 
TEST(NtlmTest,GenerateNtlmProofWithClientTimestampV2)405*6777b538SAndroid Build Coastguard Worker TEST(NtlmTest, GenerateNtlmProofWithClientTimestampV2) {
406*6777b538SAndroid Build Coastguard Worker   uint8_t proof[kNtlmProofLenV2];
407*6777b538SAndroid Build Coastguard Worker 
408*6777b538SAndroid Build Coastguard Worker   // Since the test data for "temp" in the spec does not include the client
409*6777b538SAndroid Build Coastguard Worker   // timestamp, a separate proof test value must be validated for use in full
410*6777b538SAndroid Build Coastguard Worker   // message validation.
411*6777b538SAndroid Build Coastguard Worker   GenerateNtlmProofV2(test::kExpectedNtlmHashV2, test::kServerChallenge,
412*6777b538SAndroid Build Coastguard Worker                       base::make_span(test::kExpectedTempWithClientTimestampV2)
413*6777b538SAndroid Build Coastguard Worker                           .subspan<0, kProofInputLenV2>(),
414*6777b538SAndroid Build Coastguard Worker                       test::kExpectedTargetInfoSpecResponseV2, proof);
415*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(0, memcmp(test::kExpectedProofSpecResponseWithClientTimestampV2,
416*6777b538SAndroid Build Coastguard Worker                       proof, kNtlmProofLenV2));
417*6777b538SAndroid Build Coastguard Worker }
418*6777b538SAndroid Build Coastguard Worker 
419*6777b538SAndroid Build Coastguard Worker }  // namespace net::ntlm
420