OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/http/ntlm_client.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/md5.h" | |
11 #include "net/base/zap.h" | |
12 #include "net/http/des.h" | |
13 #include "net/http/md4.h" | |
14 #include "net/http/ntlm_buffer_writer.h" | |
15 | |
16 namespace net { | |
17 | |
18 namespace ntlm { | |
19 | |
20 void GenerateNtlmHashV1(const base::string16& password, uint8_t* hash) { | |
21 size_t length = password.length() * 2; | |
22 // hash param must have at least 16 bytes of space. | |
23 NtlmBufferWriter writer(length); | |
24 | |
25 // The writer will handle the big endian case if necessary. | |
26 writer.WriteUnicodeString(password); | |
27 | |
28 std::unique_ptr<uint8_t[]> buffer(writer.ReleaseBufferPtr()); | |
29 | |
30 weak_crypto::MD4Sum(buffer.get(), length, hash); | |
31 ZapBuf(buffer.get(), length); | |
Ryan Sleevi
2017/06/08 18:47:43
https://codereview.chromium.org/2926333002/ :)
zentaro
2017/06/12 23:16:54
Done.
| |
32 } | |
33 | |
34 void GenerateResponseDesl(const uint8_t* hash, | |
35 const uint8_t* challenge, | |
36 uint8_t* response) { | |
37 // hash param must be 16 bytes. | |
38 // challenge param must be 8 bytes. | |
39 // response param must be at least 24 bytes. | |
40 | |
41 // See DESL(K, D) function in Section 6 Appendix A of NTLMSSP specification. | |
42 uint8_t key1[8]; | |
Ryan Sleevi
2017/06/08 18:47:43
Should we = {0}; these to ensure they're all zero-
zentaro
2017/06/12 23:16:54
I assumed it wasn't necessary since we do (should)
| |
43 uint8_t key2[8]; | |
44 uint8_t key3[8]; | |
45 | |
46 // The last 2 bytes of the hash are zero padded (5 zeros) as the | |
47 // input to generate key3. | |
48 uint8_t padded_hash[7]; | |
49 padded_hash[0] = hash[14]; | |
50 padded_hash[1] = hash[15]; | |
51 memset(padded_hash + 2, 0, 5); | |
52 | |
53 DESMakeKey(hash, key1); | |
54 DESMakeKey(hash + 7, key2); | |
55 DESMakeKey(padded_hash, key3); | |
56 | |
57 DESEncrypt(key1, challenge, response); | |
58 DESEncrypt(key2, challenge, response + 8); | |
59 DESEncrypt(key3, challenge, response + 16); | |
60 } | |
61 | |
62 void GenerateNtlmResponseV1(const base::string16& password, | |
63 const uint8_t* challenge, | |
64 uint8_t* ntlm_response) { | |
65 uint8_t ntlm_hash[ntlm::NTLM_HASH_LEN]; | |
66 GenerateNtlmHashV1(password, ntlm_hash); | |
67 GenerateResponseDesl(ntlm_hash, challenge, ntlm_response); | |
68 } | |
69 | |
70 void GenerateResponsesV1(const base::string16& password, | |
71 const uint8_t* server_challenge, | |
72 uint8_t* lm_response, | |
73 uint8_t* ntlm_response) { | |
74 GenerateNtlmResponseV1(password, server_challenge, ntlm_response); | |
75 | |
76 // In NTLM v1 (with LMv1 disabled), the lm_response and ntlm_response are the | |
77 // same. So just copy the ntlm_response into the lm_response. | |
78 memcpy(lm_response, ntlm_response, ntlm::RESPONSE_V1_LEN); | |
79 } | |
80 | |
81 void GenerateLMResponseV1WithSS(const uint8_t* client_challenge, | |
82 uint8_t* lm_response) { | |
83 // In NTLM v1 with Session Security (aka NTLM2) the lm_response is 8 bytes of | |
84 // client challenge and 16 bytes of zeros. (See 3.3.1) | |
85 memcpy(lm_response, client_challenge, ntlm::CHALLENGE_LEN); | |
86 memset(lm_response + ntlm::CHALLENGE_LEN, 0, | |
87 ntlm::RESPONSE_V1_LEN - ntlm::CHALLENGE_LEN); | |
88 } | |
89 | |
90 void GenerateSessionHashV1WithSS(const uint8_t* server_challenge, | |
91 const uint8_t* client_challenge, | |
92 base::MD5Digest* session_hash) { | |
93 base::MD5Context ctx; | |
94 base::MD5Init(&ctx); | |
95 base::MD5Update( | |
96 &ctx, base::StringPiece(reinterpret_cast<const char*>(server_challenge), | |
97 ntlm::CHALLENGE_LEN)); | |
98 base::MD5Update( | |
99 &ctx, base::StringPiece(reinterpret_cast<const char*>(client_challenge), | |
100 ntlm::CHALLENGE_LEN)); | |
101 | |
102 base::MD5Final(session_hash, &ctx); | |
103 } | |
104 | |
105 void GenerateNtlmResponseV1WithSS(const base::string16& password, | |
106 const uint8_t* server_challenge, | |
107 const uint8_t* client_challenge, | |
108 uint8_t* ntlm_response) { | |
109 // Generate the NTLMv1 Hash. | |
110 uint8_t ntlm_hash[ntlm::NTLM_HASH_LEN]; | |
111 GenerateNtlmHashV1(password, ntlm_hash); | |
112 | |
113 // Generate the NTLMv1 Session Hash. | |
114 base::MD5Digest session_hash; | |
115 GenerateSessionHashV1WithSS(server_challenge, client_challenge, | |
116 &session_hash); | |
117 | |
118 // Only the first 8 bytes of |session_hash.a| are actually used. | |
119 GenerateResponseDesl(ntlm_hash, session_hash.a, ntlm_response); | |
120 } | |
121 | |
122 void GenerateResponsesV1WithSS(const base::string16& password, | |
123 const uint8_t* server_challenge, | |
124 const uint8_t* client_challenge, | |
125 uint8_t* lm_response, | |
126 uint8_t* ntlm_response) { | |
127 GenerateLMResponseV1WithSS(client_challenge, lm_response); | |
128 GenerateNtlmResponseV1WithSS(password, server_challenge, client_challenge, | |
129 ntlm_response); | |
130 } | |
131 | |
132 } // namespace ntlm | |
133 } // namespace net | |
OLD | NEW |