Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: net/http/ntlm_client.cc

Issue 2873673002: Add unit tests for NTLMv1 portable implementation (Closed)
Patch Set: Cleanup Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 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/http/des.h"
12 #include "net/http/md4.h"
13 #include "net/http/ntlm_buffer_writer.h"
14
15 namespace net {
16
17 namespace ntlm {
18
19 void GenerateNtlmHashV1(const base::string16& password, uint8_t* hash) {
20 size_t length = password.length() * 2;
21 // hash param must have at least 16 bytes of space.
22 NtlmBufferWriter writer(length);
23
24 // The writer will handle the big endian case if necessary.
25 bool result = writer.WriteUtf16String(password);
26 DCHECK(result);
27
28 std::unique_ptr<uint8_t[]> buffer = writer.ReleaseBuffer();
29
30 weak_crypto::MD4Sum(buffer.get(), length, hash);
31 }
32
33 void GenerateResponseDesl(const uint8_t* hash,
34 const uint8_t* challenge,
35 uint8_t* response) {
36 // hash param must be 16 bytes.
37 // challenge param must be 8 bytes.
38 // response param must be at least 24 bytes.
39
40 // See DESL(K, D) function in Section 6 Appendix A of NTLMSSP specification.
41 uint8_t key1[8];
42 uint8_t key2[8];
43 uint8_t key3[8];
44
45 // The last 2 bytes of the hash are zero padded (5 zeros) as the
46 // input to generate key3.
47 uint8_t padded_hash[7];
48 padded_hash[0] = hash[14];
49 padded_hash[1] = hash[15];
50 memset(padded_hash + 2, 0, 5);
51
52 DESMakeKey(hash, key1);
53 DESMakeKey(hash + 7, key2);
54 DESMakeKey(padded_hash, key3);
55
56 DESEncrypt(key1, challenge, response);
57 DESEncrypt(key2, challenge, response + 8);
58 DESEncrypt(key3, challenge, response + 16);
59 }
60
61 void GenerateNtlmResponseV1(const base::string16& password,
62 const uint8_t* challenge,
63 uint8_t* ntlm_response) {
64 uint8_t ntlm_hash[NTLM_HASH_LEN];
65 GenerateNtlmHashV1(password, ntlm_hash);
66 GenerateResponseDesl(ntlm_hash, challenge, ntlm_response);
67 }
68
69 void GenerateResponsesV1(const base::string16& password,
70 const uint8_t* server_challenge,
71 uint8_t* lm_response,
72 uint8_t* ntlm_response) {
73 GenerateNtlmResponseV1(password, server_challenge, ntlm_response);
74
75 // In NTLM v1 (with LMv1 disabled), the lm_response and ntlm_response are the
76 // same. So just copy the ntlm_response into the lm_response.
77 memcpy(lm_response, ntlm_response, RESPONSE_V1_LEN);
78 }
79
80 void GenerateLMResponseV1WithSS(const uint8_t* client_challenge,
81 uint8_t* lm_response) {
82 // In NTLM v1 with Session Security (aka NTLM2) the lm_response is 8 bytes of
83 // client challenge and 16 bytes of zeros. (See 3.3.1)
84 memcpy(lm_response, client_challenge, CHALLENGE_LEN);
85 memset(lm_response + CHALLENGE_LEN, 0, RESPONSE_V1_LEN - CHALLENGE_LEN);
86 }
87
88 void GenerateSessionHashV1WithSS(const uint8_t* server_challenge,
89 const uint8_t* client_challenge,
90 base::MD5Digest* session_hash) {
91 base::MD5Context ctx;
92 base::MD5Init(&ctx);
93 base::MD5Update(
94 &ctx, base::StringPiece(reinterpret_cast<const char*>(server_challenge),
95 CHALLENGE_LEN));
96 base::MD5Update(
97 &ctx, base::StringPiece(reinterpret_cast<const char*>(client_challenge),
98 CHALLENGE_LEN));
99
100 base::MD5Final(session_hash, &ctx);
101 }
102
103 void GenerateNtlmResponseV1WithSS(const base::string16& password,
104 const uint8_t* server_challenge,
105 const uint8_t* client_challenge,
106 uint8_t* ntlm_response) {
107 // Generate the NTLMv1 Hash.
108 uint8_t ntlm_hash[NTLM_HASH_LEN];
109 GenerateNtlmHashV1(password, ntlm_hash);
asanka 2017/06/23 21:29:11 Minor nit: It's easier to follow along with the sp
110
111 // Generate the NTLMv1 Session Hash.
112 base::MD5Digest session_hash;
113 GenerateSessionHashV1WithSS(server_challenge, client_challenge,
114 &session_hash);
115
116 // Only the first 8 bytes of |session_hash.a| are actually used.
117 GenerateResponseDesl(ntlm_hash, session_hash.a, ntlm_response);
118 }
119
120 void GenerateResponsesV1WithSS(const base::string16& password,
121 const uint8_t* server_challenge,
122 const uint8_t* client_challenge,
123 uint8_t* lm_response,
124 uint8_t* ntlm_response) {
125 GenerateLMResponseV1WithSS(client_challenge, lm_response);
126 GenerateNtlmResponseV1WithSS(password, server_challenge, client_challenge,
127 ntlm_response);
128 }
129
130 } // namespace ntlm
131 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698