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

Unified Diff: net/ntlm/ntlm.cc

Issue 2873673002: Add unit tests for NTLMv1 portable implementation (Closed)
Patch Set: Rebase Created 3 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/ntlm/ntlm.h ('k') | net/ntlm/ntlm_constants.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/ntlm/ntlm.cc
diff --git a/net/ntlm/ntlm.cc b/net/ntlm/ntlm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..14cc4bcdf64bf60a618e725068dc4bea9f75c543
--- /dev/null
+++ b/net/ntlm/ntlm.cc
@@ -0,0 +1,125 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/ntlm/ntlm.h"
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/md5.h"
+#include "net/ntlm/des.h"
+#include "net/ntlm/md4.h"
+#include "net/ntlm/ntlm_buffer_writer.h"
+
+namespace net {
+namespace ntlm {
+
+void GenerateNtlmHashV1(const base::string16& password, uint8_t* hash) {
+ size_t length = password.length() * 2;
+ NtlmBufferWriter writer(length);
+
+ // The writer will handle the big endian case if necessary.
+ bool result = writer.WriteUtf16String(password);
+ DCHECK(result);
+
+ weak_crypto::MD4Sum(
+ reinterpret_cast<const uint8_t*>(writer.GetBuffer().data()), length,
+ hash);
+}
+
+void GenerateResponseDesl(const uint8_t* hash,
+ const uint8_t* challenge,
+ uint8_t* response) {
+ // See DESL(K, D) function in [MS-NLMP] Section 6
+ uint8_t key1[8];
+ uint8_t key2[8];
+ uint8_t key3[8];
+
+ // The last 2 bytes of the hash are zero padded (5 zeros) as the
+ // input to generate key3.
+ uint8_t padded_hash[7];
+ padded_hash[0] = hash[14];
+ padded_hash[1] = hash[15];
+ memset(padded_hash + 2, 0, 5);
+
+ DESMakeKey(hash, key1);
+ DESMakeKey(hash + 7, key2);
+ DESMakeKey(padded_hash, key3);
+
+ DESEncrypt(key1, challenge, response);
+ DESEncrypt(key2, challenge, response + 8);
+ DESEncrypt(key3, challenge, response + 16);
+}
+
+void GenerateNtlmResponseV1(const base::string16& password,
+ const uint8_t* challenge,
+ uint8_t* ntlm_response) {
+ uint8_t ntlm_hash[kNtlmHashLen];
+ GenerateNtlmHashV1(password, ntlm_hash);
+ GenerateResponseDesl(ntlm_hash, challenge, ntlm_response);
+}
+
+void GenerateResponsesV1(const base::string16& password,
+ const uint8_t* server_challenge,
+ uint8_t* lm_response,
+ uint8_t* ntlm_response) {
+ GenerateNtlmResponseV1(password, server_challenge, ntlm_response);
+
+ // In NTLM v1 (with LMv1 disabled), the lm_response and ntlm_response are the
+ // same. So just copy the ntlm_response into the lm_response.
+ memcpy(lm_response, ntlm_response, kResponseLenV1);
+}
+
+void GenerateLMResponseV1WithSessionSecurity(const uint8_t* client_challenge,
+ uint8_t* lm_response) {
+ // In NTLM v1 with Session Security (aka NTLM2) the lm_response is 8 bytes of
+ // client challenge and 16 bytes of zeros. (See 3.3.1)
+ memcpy(lm_response, client_challenge, kChallengeLen);
+ memset(lm_response + kChallengeLen, 0, kResponseLenV1 - kChallengeLen);
+}
+
+void GenerateSessionHashV1WithSessionSecurity(const uint8_t* server_challenge,
+ const uint8_t* client_challenge,
+ base::MD5Digest* session_hash) {
+ base::MD5Context ctx;
+ base::MD5Init(&ctx);
+ base::MD5Update(
+ &ctx, base::StringPiece(reinterpret_cast<const char*>(server_challenge),
+ kChallengeLen));
+ base::MD5Update(
+ &ctx, base::StringPiece(reinterpret_cast<const char*>(client_challenge),
+ kChallengeLen));
+
+ base::MD5Final(session_hash, &ctx);
+}
+
+void GenerateNtlmResponseV1WithSessionSecurity(const base::string16& password,
+ const uint8_t* server_challenge,
+ const uint8_t* client_challenge,
+ uint8_t* ntlm_response) {
+ // Generate the NTLMv1 Hash.
+ uint8_t ntlm_hash[kNtlmHashLen];
+ GenerateNtlmHashV1(password, ntlm_hash);
+
+ // Generate the NTLMv1 Session Hash.
+ base::MD5Digest session_hash;
+ GenerateSessionHashV1WithSessionSecurity(server_challenge, client_challenge,
+ &session_hash);
+
+ // Only the first 8 bytes of |session_hash.a| are actually used.
+ GenerateResponseDesl(ntlm_hash, session_hash.a, ntlm_response);
+}
+
+void GenerateResponsesV1WithSessionSecurity(const base::string16& password,
+ const uint8_t* server_challenge,
+ const uint8_t* client_challenge,
+ uint8_t* lm_response,
+ uint8_t* ntlm_response) {
+ GenerateLMResponseV1WithSessionSecurity(client_challenge, lm_response);
+ GenerateNtlmResponseV1WithSessionSecurity(password, server_challenge,
+ client_challenge, ntlm_response);
+}
+
+} // namespace ntlm
+} // namespace net
« no previous file with comments | « net/ntlm/ntlm.h ('k') | net/ntlm/ntlm_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698