From c8a3627a48f96a878bb1908f614a6ad1003234ac Mon Sep 17 00:00:00 2001 From: adriangzz Date: Fri, 17 May 2024 18:40:04 -0400 Subject: [PATCH] SERVER-84609 Define a version for Aladdin MD5 (#19406) GitOrigin-RevId: 6f66f4d07b5c7e263d18d028410f445e943c2d88 --- SConstruct | 4 + buildscripts/linter/mongolint.py | 3 - distsrc/THIRD-PARTY-NOTICES | 25 - etc/third_party_components.yml | 8 - src/SConscript | 1 + src/mongo/client/authenticate.h | 1 - src/mongo/client/authenticate_test.cpp | 3 +- src/mongo/db/commands/dbcommands_d.cpp | 3 +- src/mongo/db/commands/dbhash.cpp | 5 +- .../db/exec/sbe/column_store_encoder_test.cpp | 3 +- src/mongo/db/fts/fts_index_format.cpp | 2 +- src/mongo/db/hasher.cpp | 2 +- src/mongo/db/repl/dbcheck.cpp | 3 +- src/mongo/db/repl/dbcheck.h | 1 - .../db/repl/idempotency_test_fixture.cpp | 3 +- src/mongo/scripting/utils.cpp | 3 +- src/mongo/shell/mongodbcr.cpp | 3 +- src/mongo/shell/shell_utils_extended.cpp | 3 +- src/mongo/util/SConscript | 6 +- src/mongo/util/md5.cpp | 426 +++--------------- src/mongo/util/md5.h | 131 +++--- src/mongo/util/md5.hpp | 77 ---- src/mongo/util/md5_test.cpp | 50 +- src/mongo/util/md5main.cpp | 145 ------ src/mongo/util/password_digest.cpp | 3 +- src/mongo/util/password_digest.h | 1 - src/third_party/SConscript | 21 + .../scripts/tomcrypt_get_sources.sh | 1 + src/third_party/tomcrypt-1.18.2/BUILD.bazel | 35 +- .../tomcrypt-1.18.2/src/hashes/md5.c | 366 +++++++++++++++ 30 files changed, 608 insertions(+), 730 deletions(-) delete mode 100644 src/mongo/util/md5.hpp delete mode 100644 src/mongo/util/md5main.cpp create mode 100644 src/third_party/tomcrypt-1.18.2/src/hashes/md5.c diff --git a/SConstruct b/SConstruct index fe626d8cfe3..757453ea380 100644 --- a/SConstruct +++ b/SConstruct @@ -501,6 +501,7 @@ for pack in [ ('intel_decimal128', 'intel decimal128'), ('bson', ), ('libmongocrypt', ), + ('tomcrypt', ), ('pcre2', ), ('protobuf', "Protocol Buffers"), ('snappy', ), @@ -5212,6 +5213,9 @@ def doConfigure(myenv): if use_system_version_of_library("fmt"): conf.FindSysLibDep("fmt", ["fmt"]) + if use_system_version_of_library("tomcrypt"): + conf.FindSysLibDep("tomcrypt", ["tomcrypt"]) + if use_system_version_of_library("libunwind"): conf.FindSysLibDep("unwind", ["unwind"]) diff --git a/buildscripts/linter/mongolint.py b/buildscripts/linter/mongolint.py index 6ea8840de22..a6ec5b799e0 100644 --- a/buildscripts/linter/mongolint.py +++ b/buildscripts/linter/mongolint.py @@ -234,9 +234,6 @@ class Linter: "src/mongo/shell/linenoise.h", "src/mongo/shell/mk_wcwidth.cpp", "src/mongo/shell/mk_wcwidth.h", - "src/mongo/util/md5.cpp", - "src/mongo/util/md5.h", - "src/mongo/util/md5main.cpp", "src/mongo/util/net/ssl_stream.cpp", "src/mongo/util/scopeguard.h", ] diff --git a/distsrc/THIRD-PARTY-NOTICES b/distsrc/THIRD-PARTY-NOTICES index cc595767cf4..639339fa93e 100644 --- a/distsrc/THIRD-PARTY-NOTICES +++ b/distsrc/THIRD-PARTY-NOTICES @@ -139,31 +139,6 @@ PCRE2, it must respect the condition, but if package B is software that includes package A, the condition is not imposed on package B unless it uses PCRE2 independently. - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - 5) License notice for Snappy - http://code.google.com/p/snappy/ --------------------------------- Copyright 2005 and onwards Google Inc. diff --git a/etc/third_party_components.yml b/etc/third_party_components.yml index a4cb9aed39c..e5857fd1301 100644 --- a/etc/third_party_components.yml +++ b/etc/third_party_components.yml @@ -45,14 +45,6 @@ components: team_owner: "Service Architecture" upgrade_suppression: TODO SERVER-58675 - Aladdin MD5: - homepage_url: N/A - open_hub_url: N/A - release_monitoring_id: -1 - local_directory_path: [src/mongo/util/md5.h, src/mongo/util/md5.cpp] - team_owner: "Security" - # Not covered in Black Duck - "Asio C++ Library": homepage_url: http://think-async.com/Asio/ open_hub_url: N/A diff --git a/src/SConscript b/src/SConscript index 73265ab1b2a..605168a5794 100644 --- a/src/SConscript +++ b/src/SConscript @@ -38,6 +38,7 @@ env.InjectThirdParty(libraries=[ 'croaring', 'fmt', 'immer', + 'tomcrypt_md5', 'murmurhash3', 'safeint', 'stemmer', diff --git a/src/mongo/client/authenticate.h b/src/mongo/client/authenticate.h index a91fcfeb43a..6ef0d198c11 100644 --- a/src/mongo/client/authenticate.h +++ b/src/mongo/client/authenticate.h @@ -48,7 +48,6 @@ #include "mongo/executor/remote_command_response.h" #include "mongo/rpc/op_msg.h" #include "mongo/util/future.h" -#include "mongo/util/md5.h" #include "mongo/util/net/hostandport.h" namespace mongo { diff --git a/src/mongo/client/authenticate_test.cpp b/src/mongo/client/authenticate_test.cpp index 1e09e6bd176..66df6c96c96 100644 --- a/src/mongo/client/authenticate_test.cpp +++ b/src/mongo/client/authenticate_test.cpp @@ -42,7 +42,6 @@ #include "mongo/util/assert_util.h" #include "mongo/util/duration.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/net/hostandport.h" #include "mongo/util/password_digest.h" @@ -73,7 +72,7 @@ public: md5digest d; { md5_state_t st; - md5_init(&st); + md5_init_state(&st); md5_append(&st, (const md5_byte_t*)_nonce.c_str(), _nonce.size()); md5_append(&st, (const md5_byte_t*)_username.c_str(), _username.size()); md5_append(&st, (const md5_byte_t*)_password_digest.c_str(), _password_digest.size()); diff --git a/src/mongo/db/commands/dbcommands_d.cpp b/src/mongo/db/commands/dbcommands_d.cpp index 55d2eafac3b..bf286daadfc 100644 --- a/src/mongo/db/commands/dbcommands_d.cpp +++ b/src/mongo/db/commands/dbcommands_d.cpp @@ -79,7 +79,6 @@ #include "mongo/util/assert_util.h" #include "mongo/util/fail_point.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/namespace_string_util.h" #include "mongo/util/str.h" @@ -248,7 +247,7 @@ public: md5digest d; md5_state_t st; - md5_init(&st); + md5_init_state(&st); int n = 0; diff --git a/src/mongo/db/commands/dbhash.cpp b/src/mongo/db/commands/dbhash.cpp index 0fd5be7f710..ada2c590451 100644 --- a/src/mongo/db/commands/dbhash.cpp +++ b/src/mongo/db/commands/dbhash.cpp @@ -75,7 +75,6 @@ #include "mongo/logv2/log_component.h" #include "mongo/util/assert_util.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/net/socket_utils.h" #include "mongo/util/str.h" #include "mongo/util/timer.h" @@ -311,7 +310,7 @@ public: result.append("host", prettyHostName(opCtx->getClient()->getLocalPort())); md5_state_t globalState; - md5_init(&globalState); + md5_init_state(&globalState); std::map collectionToHashMap; std::map collectionToUUIDMap; @@ -480,7 +479,7 @@ private: } md5_state_t st; - md5_init(&st); + md5_init_state(&st); try { MONGO_verify(nullptr != exec.get()); diff --git a/src/mongo/db/exec/sbe/column_store_encoder_test.cpp b/src/mongo/db/exec/sbe/column_store_encoder_test.cpp index a2fa68d7d50..78df1f59e20 100644 --- a/src/mongo/db/exec/sbe/column_store_encoder_test.cpp +++ b/src/mongo/db/exec/sbe/column_store_encoder_test.cpp @@ -51,7 +51,6 @@ #include "mongo/unittest/bson_test_util.h" #include "mongo/unittest/framework.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/safe_num.h" #include "mongo/util/string_map.h" #include "mongo/util/time_support.h" @@ -204,7 +203,7 @@ TEST(SBEColumnStoreEncoder, RoundTripConversionThroughSplitCellView) { // auto cellDigest = [&]() { md5_state_t digestState; - md5_init(&digestState); + md5_init_state(&digestState); md5_append( &digestState, reinterpret_cast(cellBuffer.buf()), cellBuffer.len()); diff --git a/src/mongo/db/fts/fts_index_format.cpp b/src/mongo/db/fts/fts_index_format.cpp index 5ad04c1b731..2327ebdf52f 100644 --- a/src/mongo/db/fts/fts_index_format.cpp +++ b/src/mongo/db/fts/fts_index_format.cpp @@ -50,7 +50,7 @@ #include "mongo/db/index/multikey_paths.h" #include "mongo/util/assert_util.h" #include "mongo/util/hex.h" -#include "mongo/util/md5.hpp" +#include "mongo/util/md5.h" #include "mongo/util/murmur3.h" #include "mongo/util/str.h" diff --git a/src/mongo/db/hasher.cpp b/src/mongo/db/hasher.cpp index 5a5851a3494..08f33e8f46c 100644 --- a/src/mongo/db/hasher.cpp +++ b/src/mongo/db/hasher.cpp @@ -87,7 +87,7 @@ private: }; Hasher::Hasher(HashSeed seed) : _seed(seed) { - md5_init(&_md5State); + md5_init_state(&_md5State); addSeed(seed); } diff --git a/src/mongo/db/repl/dbcheck.cpp b/src/mongo/db/repl/dbcheck.cpp index eb2cae668dc..086757ef404 100644 --- a/src/mongo/db/repl/dbcheck.cpp +++ b/src/mongo/db/repl/dbcheck.cpp @@ -73,7 +73,6 @@ #include "mongo/util/debug_util.h" #include "mongo/util/duration.h" #include "mongo/util/fail_point.h" -#include "mongo/util/md5.hpp" #include "mongo/util/uuid.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand @@ -390,7 +389,7 @@ DbCheckHasher::DbCheckHasher( _dataThrottle(dataThrottle) { // Get the MD5 hasher set up. - md5_init(&_state); + md5_init_state(&_state); auto& collection = acquisition.coll.getCollectionPtr(); diff --git a/src/mongo/db/repl/dbcheck.h b/src/mongo/db/repl/dbcheck.h index dd1f19f3da0..230cd4e0469 100644 --- a/src/mongo/db/repl/dbcheck.h +++ b/src/mongo/db/repl/dbcheck.h @@ -53,7 +53,6 @@ #include "mongo/db/repl/optime.h" #include "mongo/db/storage/recovery_unit.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/time_support.h" namespace mongo { diff --git a/src/mongo/db/repl/idempotency_test_fixture.cpp b/src/mongo/db/repl/idempotency_test_fixture.cpp index 8b1f53900de..828de0a6a0e 100644 --- a/src/mongo/db/repl/idempotency_test_fixture.cpp +++ b/src/mongo/db/repl/idempotency_test_fixture.cpp @@ -63,7 +63,6 @@ #include "mongo/db/session/logical_session_id.h" #include "mongo/unittest/assert.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/time_support.h" namespace mongo { @@ -345,7 +344,7 @@ std::string IdempotencyTest::computeDataHash(const CollectionPtr& collection) { InternalPlanner::IXSCAN_FETCH); ASSERT(nullptr != exec.get()); md5_state_t st; - md5_init(&st); + md5_init_state(&st); PlanExecutor::ExecState state; BSONObj obj; diff --git a/src/mongo/scripting/utils.cpp b/src/mongo/scripting/utils.cpp index 19cde946831..8c7d71dafec 100644 --- a/src/mongo/scripting/utils.cpp +++ b/src/mongo/scripting/utils.cpp @@ -40,7 +40,6 @@ #include "mongo/scripting/engine.h" #include "mongo/util/assert_util.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" namespace mongo { @@ -52,7 +51,7 @@ static BSONObj native_hex_md5(const BSONObj& args, void* data) { md5digest d; md5_state_t st; - md5_init(&st); + md5_init_state(&st); md5_append(&st, reinterpret_cast(sd.rawData()), sd.size()); md5_finish(&st, d); diff --git a/src/mongo/shell/mongodbcr.cpp b/src/mongo/shell/mongodbcr.cpp index 9bd12873697..1934e267da4 100644 --- a/src/mongo/shell/mongodbcr.cpp +++ b/src/mongo/shell/mongodbcr.cpp @@ -52,7 +52,6 @@ #include "mongo/util/future.h" #include "mongo/util/future_impl.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/password_digest.h" namespace mongo { @@ -113,7 +112,7 @@ OpMsgRequest createMongoCRAuthenticateCmd(const BSONObj& params, StringData nonc md5digest d; { md5_state_t st; - md5_init(&st); + md5_init_state(&st); md5_append(&st, reinterpret_cast(nonce.rawData()), nonce.size()); md5_append(&st, reinterpret_cast(username.c_str()), username.size()); md5_append(&st, reinterpret_cast(digested.c_str()), digested.size()); diff --git a/src/mongo/shell/shell_utils_extended.cpp b/src/mongo/shell/shell_utils_extended.cpp index ab0b835573c..83d6695524e 100644 --- a/src/mongo/shell/shell_utils_extended.cpp +++ b/src/mongo/shell/shell_utils_extended.cpp @@ -67,7 +67,6 @@ #include "mongo/util/errno_util.h" #include "mongo/util/icu.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" #include "mongo/util/net/socket_utils.h" #include "mongo/util/password.h" #include "mongo/util/scopeguard.h" @@ -287,7 +286,7 @@ BSONObj md5sumFile(const BSONObj& args, void* data) { md5digest d; md5_state_t st; - md5_init(&st); + md5_init_state(&st); enum { BUFLEN = 4 * 1024 }; char buffer[BUFLEN]; diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index ca57aca13d0..bd5288b198c 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -140,6 +140,9 @@ env.Library( 'md5.cpp', 'password_digest.cpp', ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/third_party/shim_tomcrypt_md5', + ], ) env.Library( @@ -862,7 +865,6 @@ icuEnv.CppUnitTest( 'log_with_sampling_test.cpp', 'lru_cache_test.cpp', 'md5_test.cpp', - 'md5main.cpp', 'concurrent_memory_aggregator_test.cpp', 'memory_usage_tracker_test.cpp', 'optional_util_test.cpp', @@ -903,6 +905,7 @@ icuEnv.CppUnitTest( '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/third_party/croaring/croaring', + '$BUILD_DIR/third_party/shim_tomcrypt_md5', 'alarm', 'background_job', 'caching', @@ -915,7 +918,6 @@ icuEnv.CppUnitTest( 'future_util', 'icu', 'latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [], - 'md5', 'pcre_util', 'pcre_wrapper', 'periodic_runner_impl', diff --git a/src/mongo/util/md5.cpp b/src/mongo/util/md5.cpp index e4e5c2f44c4..dbb9f2c4113 100644 --- a/src/mongo/util/md5.cpp +++ b/src/mongo/util/md5.cpp @@ -1,374 +1,80 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. +/** + * Copyright (C) 2024-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. */ #include +#include -#include "md5.h" +#include "mongo/util/md5.h" -extern "C" { +namespace mongo { -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -#define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void md5_process(md5_state_t* pms, const md5_byte_t* data /*[64]*/) { - md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t* X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t*)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t*)nullptr) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t*)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t* xp = data; - int i; - -#if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -#else -#define xbuf X /* (static only) */ -#endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - -/* Round 1. */ -/* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti) \ - t = a + F(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - -/* Round 2. */ -/* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti) \ - t = a + G(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - -/* Round 3. */ -/* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti) \ - t = a + H(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - -/* Round 4. */ -/* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti) \ - t = a + I(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void md5_init(md5_state_t* pms) { - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; +void md5_init_state(md5_state_t* pms) { + md5_init(pms); } void md5_append(md5_state_t* pms, const md5_byte_t* data, int nbytes) { - const md5_byte_t* p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); + md5_process(pms, data, nbytes); } void md5_finish(md5_state_t* pms, md5_byte_t digest[16]) { - static const md5_byte_t pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + md5_done(pms, digest); } -} // extern "C" +void md5(const void* buf, int nbytes, md5digest digest) { + md5_state_t st; + md5_init_state(&st); + md5_append(&st, (const md5_byte_t*)buf, nbytes); + md5_finish(&st, digest); +} + +void md5(const char* str, md5digest digest) { + md5(str, strlen(str), digest); +} + +std::string digestToString(md5digest digest) { + static const char* letters = "0123456789abcdef"; + std::stringstream ss; + for (int i = 0; i < 16; i++) { + unsigned char c = digest[i]; + ss << letters[(c >> 4) & 0xf] << letters[c & 0xf]; + } + return ss.str(); +} + +std::string md5simpledigest(const void* buf, int nbytes) { + md5digest d; + md5(buf, nbytes, d); + return digestToString(d); +} + +std::string md5simpledigest(const std::string& s) { + return md5simpledigest(s.data(), s.size()); +} + +} // namespace mongo diff --git a/src/mongo/util/md5.h b/src/mongo/util/md5.h index 4fda82abab5..ec72c388388 100644 --- a/src/mongo/util/md5.h +++ b/src/mongo/util/md5.h @@ -1,93 +1,66 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.h is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . - 1999-05-03 lpd Original version. +/** + * Copyright (C) 2024-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. */ -#ifndef md5_INCLUDED -#define md5_INCLUDED +#pragma once -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ +#include -// Don't do this. Turns out its actually slower... -// #define ARCH_IS_BIG_ENDIAN 0 +#include -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +namespace mongo { -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; +using md5digest = unsigned char[16]; +using md5_byte_t = unsigned char; /* 8-bit byte */ +using md5_word_t = unsigned int; /* 32-bit word */ +using md5_state_t = hash_state; -#ifdef __cplusplus -extern "C" { -#endif - -/* Initialize the algorithm. */ -void md5_init(md5_state_t* pms); +void md5_init_state(md5_state_t* pms); /* Append a std::string to the message. */ void md5_append(md5_state_t* pms, const md5_byte_t* data, int nbytes); -/* Finish the message and return the digest. */ +/* Finish the message and store the result in the digest. */ void md5_finish(md5_state_t* pms, md5_byte_t digest[16]); -#ifdef __cplusplus -} /* end extern "C" */ -#endif +// Calculate the MD5 digest for the given buffer and store the result in the specified digest array. +void md5(const void* buf, int nbytes, md5digest digest); -#endif /* md5_INCLUDED */ +// Calculate the MD5 digest for the input string and store the result in the specified digest array. +void md5(const char* str, md5digest digest); + +// Convert the MD5 digest array into a hexadecimal string representation. +std::string digestToString(md5digest digest); + +// Calculate the MD5 digest for the given buffer and return the result as a hexadecimal string. +std::string md5simpledigest(const void* buf, int nbytes); + +// Calculate the MD5 digest for the input string and return the result as a hexadecimal string. +std::string md5simpledigest(const std::string& s); + +} // namespace mongo diff --git a/src/mongo/util/md5.hpp b/src/mongo/util/md5.hpp deleted file mode 100644 index 79a6ae5521e..00000000000 --- a/src/mongo/util/md5.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// md5.hpp - - -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * . - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/util/md5.h" - -#include -#include -#include - -namespace mongo { - -typedef unsigned char md5digest[16]; - -inline void md5(const void* buf, int nbytes, md5digest digest) { - md5_state_t st; - md5_init(&st); - md5_append(&st, (const md5_byte_t*)buf, nbytes); - md5_finish(&st, digest); -} - -inline void md5(const char* str, md5digest digest) { - md5(str, strlen(str), digest); -} - -inline std::string digestToString(md5digest digest) { - static const char* letters = "0123456789abcdef"; - std::stringstream ss; - for (int i = 0; i < 16; i++) { - unsigned char c = digest[i]; - ss << letters[(c >> 4) & 0xf] << letters[c & 0xf]; - } - return ss.str(); -} - -inline std::string md5simpledigest(const void* buf, int nbytes) { - md5digest d; - md5(buf, nbytes, d); - return digestToString(d); -} - -inline std::string md5simpledigest(const std::string& s) { - return md5simpledigest(s.data(), s.size()); -} - - -} // namespace mongo diff --git a/src/mongo/util/md5_test.cpp b/src/mongo/util/md5_test.cpp index 71865e535d8..8c95da8730b 100644 --- a/src/mongo/util/md5_test.cpp +++ b/src/mongo/util/md5_test.cpp @@ -27,14 +27,58 @@ * it in the license file. */ -#include "mongo/base/string_data.h" +#include + #include "mongo/unittest/assert.h" #include "mongo/unittest/framework.h" - -extern int do_md5_test(void); +#include "mongo/util/md5.h" namespace mongo { + +// Test from old Aladdin MD5 library we used to vendor +int do_md5_test(void) { + static const char* const test[7 * 2] = { + "", + "d41d8cd98f00b204e9800998ecf8427e", + "a", + "0cc175b9c0f1b6a831c399e269772661", + "abc", + "900150983cd24fb0d6963f7d28e17f72", + "message digest", + "f96b697d7cb7938d525a2f31aaf161d0", + "abcdefghijklmnopqrstuvwxyz", + "c3fcd3d76192e4007dfb496cca67e13b", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"}; + int i; + int status = 0; + + for (i = 0; i < 7 * 2; i += 2) { + md5_state_t state; + md5_byte_t digest[16]; + char hex_output[16 * 2 + 1]; + int di; + + md5_init_state(&state); + md5_append(&state, (const md5_byte_t*)test[i], strlen(test[i])); + md5_finish(&state, digest); + for (di = 0; di < 16; ++di) + sprintf(hex_output + di * 2, "%02x", digest[di]); + if (strcmp(hex_output, test[i + 1]) != 0) { + printf("MD5 (\"%s\") = ", test[i]); + puts(hex_output); + printf("**** ERROR, should be: %s\n", test[i + 1]); + status = 1; + } + } + return status; +} + TEST(MD5, BuiltIn1) { ASSERT_EQUALS(0, do_md5_test()); + // Run tomcrypt test + ASSERT_EQUALS(0, md5_test()); } } // namespace mongo diff --git a/src/mongo/util/md5main.cpp b/src/mongo/util/md5main.cpp deleted file mode 100644 index c5b41395fea..00000000000 --- a/src/mongo/util/md5main.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - Copyright (C) 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5main.c,v 1.1 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Splits off main program into a separate file, md5main.c. - */ - -#include -#include -#include - -#include "md5.h" - -/* - * This file builds an executable that performs various functions related - * to the MD5 library. Typical compilation: - * gcc -o md5main -lm md5main.c md5.c - */ -static const char* const usage = - "Usage:\n" - " md5main --test # run the self-test (A.5 of RFC 1321)\n " - " md5main --t-values # print the T values for the library\n " - " md5main --version # print the version of the package\n "; - -static const char* const version = "2002-04-13"; - -/* modified: not static, renamed */ -/* Run the self-test. */ -/*static*/ int -// do_test(void) -do_md5_test(void) { - static const char* const test[7 * 2] = { - "", - "d41d8cd98f00b204e9800998ecf8427e", - "a", - "0cc175b9c0f1b6a831c399e269772661", - "abc", - "900150983cd24fb0d6963f7d28e17f72", - "message digest", - "f96b697d7cb7938d525a2f31aaf161d0", - "abcdefghijklmnopqrstuvwxyz", - "c3fcd3d76192e4007dfb496cca67e13b", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "d174ab98d277d9f5a5611c2c9f419d9f", - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "57edf4a22be3c955ac49da2e2107b67a"}; - int i; - int status = 0; - - for (i = 0; i < 7 * 2; i += 2) { - md5_state_t state; - md5_byte_t digest[16]; - char hex_output[16 * 2 + 1]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t*)test[i], strlen(test[i])); - md5_finish(&state, digest); - for (di = 0; di < 16; ++di) - sprintf(hex_output + di * 2, "%02x", digest[di]); - if (strcmp(hex_output, test[i + 1]) != 0) { - printf("MD5 (\"%s\") = ", test[i]); - puts(hex_output); - printf("**** ERROR, should be: %s\n", test[i + 1]); - status = 1; - } - } - // if (status == 0) - /*modified commented out: puts("md5 self-test completed successfully."); */ - return status; -} - -/* Print the T values. */ -static int do_t_values(void) { - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - - /* - * The following nonsense is only to avoid compiler warnings about - * "integer constant is unsigned in ANSI C, signed with -traditional". - */ - if (v >> 31) { - printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", - i, - v, - (unsigned long)(unsigned int)(~v)); - } else { - printf("#define T%d 0x%08lx\n", i, v); - } - } - return 0; -} - -/* modified from original code changed function name main->md5main */ -/* Main program */ -int md5main(int argc, char* argv[]) { - if (argc == 2) { - if (!strcmp(argv[1], "--test")) - return do_md5_test(); - if (!strcmp(argv[1], "--t-values")) - return do_t_values(); - if (!strcmp(argv[1], "--version")) { - puts(version); - return 0; - } - } - puts(usage); - return 0; -} diff --git a/src/mongo/util/password_digest.cpp b/src/mongo/util/password_digest.cpp index 227277804d7..9de2ce7c334 100644 --- a/src/mongo/util/password_digest.cpp +++ b/src/mongo/util/password_digest.cpp @@ -29,7 +29,6 @@ #include "mongo/util/password_digest.h" #include "mongo/util/md5.h" -#include "mongo/util/md5.hpp" namespace mongo { @@ -37,7 +36,7 @@ std::string createPasswordDigest(StringData username, StringData clearTextPasswo md5digest d; { md5_state_t st; - md5_init(&st); + md5_init_state(&st); md5_append(&st, (const md5_byte_t*)username.rawData(), username.size()); md5_append(&st, (const md5_byte_t*)":mongo:", 7); md5_append(&st, (const md5_byte_t*)clearTextPassword.rawData(), clearTextPassword.size()); diff --git a/src/mongo/util/password_digest.h b/src/mongo/util/password_digest.h index 6c21387b4d6..bacf829f276 100644 --- a/src/mongo/util/password_digest.h +++ b/src/mongo/util/password_digest.h @@ -32,7 +32,6 @@ #include #include "mongo/base/string_data.h" -#include "mongo/util/md5.hpp" namespace mongo { diff --git a/src/third_party/SConscript b/src/third_party/SConscript index 9b3f34c03f0..5f4b545c92f 100644 --- a/src/third_party/SConscript +++ b/src/third_party/SConscript @@ -169,6 +169,12 @@ if "tom" in env["MONGO_CRYPTO"]: 'CPPPATH': ['#/src/third_party/tomcrypt' + tomcryptSuffix + '/src/headers'], } +if not use_system_version_of_library('tomcrypt'): + thirdPartyEnvironmentModifications['tomcrypt_md5'] = { + 'CPPPATH': ['#/src/third_party/tomcrypt' + tomcryptSuffix + '/src/headers'], + 'CPPDEFINES': ['LTC_NO_PROTOTYPES'] if env.TargetOSIs('windows') else [], + } + if not use_system_version_of_library('stemmer'): thirdPartyEnvironmentModifications['stemmer'] = { 'CPPPATH': ['#/src/third_party/libstemmer_c/include'], @@ -509,6 +515,21 @@ if "tom" in env["MONGO_CRYPTO"]: tomcryptEnv.ShimLibrary(name="tomcrypt", ) +md5Env = env.Clone() +if use_system_version_of_library("tomcrypt"): + md5Env = md5Env.Clone(SYSLIBDEPS=[ + env['LIBDEPS_TOMCRYPT_SYSLIBDEP'], + ]) +else: + md5Env = md5Env.Clone() + md5Env.InjectThirdParty(libraries=['tomcrypt_md5']) + md5Env.SConscript('tomcrypt' + tomcryptSuffix + '/SConscript', exports={'env': md5Env}) + md5Env = md5Env.Clone(LIBDEPS_INTERFACE=[ + 'tomcrypt' + tomcryptSuffix + '/tomcrypt_md5', + ]) + +md5Env.ShimLibrary(name="tomcrypt_md5") + # libunwind and tcmalloc are both added as global dependencies. Skip # inheriting global dependencies to avoid a circular dependency. tcmallocEnv = env.Clone( diff --git a/src/third_party/scripts/tomcrypt_get_sources.sh b/src/third_party/scripts/tomcrypt_get_sources.sh index 02d6830dcde..de2c51f7851 100755 --- a/src/third_party/scripts/tomcrypt_get_sources.sh +++ b/src/third_party/scripts/tomcrypt_get_sources.sh @@ -45,6 +45,7 @@ mkdir src/modes/cbc FILES=( hashes/helper/hash_memory.c + hashes/md5.c hashes/sha1.c hashes/sha2/sha256.c hashes/sha2/sha512.c diff --git a/src/third_party/tomcrypt-1.18.2/BUILD.bazel b/src/third_party/tomcrypt-1.18.2/BUILD.bazel index 83512c9e3fc..a17d1e24e2c 100644 --- a/src/third_party/tomcrypt-1.18.2/BUILD.bazel +++ b/src/third_party/tomcrypt-1.18.2/BUILD.bazel @@ -2,6 +2,20 @@ load("//bazel:mongo_src_rules.bzl", "mongo_cc_library") package(default_visibility = ["//visibility:public"]) +mongo_cc_library( + name = "tomcrypt_deps", + srcs = [ + "src/misc/compare_testvector.c", + "src/misc/crypt/crypt_argchk.c", + ], + hdrs = glob([ + "src/headers/*.h", + ]), + copts = [ + "-Isrc/third_party/tomcrypt-1.18.2/src/headers", + ], +) + mongo_cc_library( name = "tomcrypt", srcs = [ @@ -15,8 +29,6 @@ mongo_cc_library( "src/mac/hmac/hmac_init.c", "src/mac/hmac/hmac_memory.c", "src/mac/hmac/hmac_process.c", - "src/misc/compare_testvector.c", - "src/misc/crypt/crypt_argchk.c", "src/misc/crypt/crypt_cipher_descriptor.c", "src/misc/crypt/crypt_cipher_is_valid.c", "src/misc/crypt/crypt_find_cipher.c", @@ -52,4 +64,23 @@ mongo_cc_library( local_defines = [ "LTC_NO_PROTOTYPES", ], + deps = [ + ":tomcrypt_deps", + ], +) + +mongo_cc_library( + name = "tomcrypt_md5", + srcs = [ + "src/hashes/md5.c", + ], + hdrs = glob([ + "src/headers/*.h", + ]), + copts = [ + "-Isrc/third_party/tomcrypt-1.18.2/src/headers", + ], + deps = [ + ":tomcrypt_deps", + ], ) diff --git a/src/third_party/tomcrypt-1.18.2/src/hashes/md5.c b/src/third_party/tomcrypt-1.18.2/src/hashes/md5.c new file mode 100644 index 00000000000..e7c12305b37 --- /dev/null +++ b/src/third_party/tomcrypt-1.18.2/src/hashes/md5.c @@ -0,0 +1,366 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + + +/** + @file md5.c + LTC_MD5 hash function by Tom St Denis +*/ + +#ifdef LTC_MD5 + +const struct ltc_hash_descriptor md5_desc = +{ + "md5", + 3, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 5, }, + 6, + + &md5_init, + &md5_process, + &md5_done, + &md5_test, + NULL +}; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y^(x|(~z))) + +#ifdef LTC_SMALL_CODE + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +static const unsigned char Worder[64] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, + 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, + 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 +}; + +static const unsigned char Rorder[64] = { + 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, + 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, + 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, + 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 +}; + +static const ulong32 Korder[64] = { +0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, +0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, +0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, +0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, +0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, +0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, +0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, +0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL +}; + +#else + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; + + +#endif + +#ifdef LTC_CLEAN_STACK +static int _md5_compress(hash_state *md, unsigned char *buf) +#else +static int md5_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong32 i, W[16], a, b, c, d; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->md5.state[0]; + b = md->md5.state[1]; + c = md->md5.state[2]; + d = md->md5.state[3]; + +#ifdef LTC_SMALL_CODE + for (i = 0; i < 16; ++i) { + FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 32; ++i) { + GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 48; ++i) { + HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 64; ++i) { + II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + +#else + FF(a,b,c,d,W[0],7,0xd76aa478UL) + FF(d,a,b,c,W[1],12,0xe8c7b756UL) + FF(c,d,a,b,W[2],17,0x242070dbUL) + FF(b,c,d,a,W[3],22,0xc1bdceeeUL) + FF(a,b,c,d,W[4],7,0xf57c0fafUL) + FF(d,a,b,c,W[5],12,0x4787c62aUL) + FF(c,d,a,b,W[6],17,0xa8304613UL) + FF(b,c,d,a,W[7],22,0xfd469501UL) + FF(a,b,c,d,W[8],7,0x698098d8UL) + FF(d,a,b,c,W[9],12,0x8b44f7afUL) + FF(c,d,a,b,W[10],17,0xffff5bb1UL) + FF(b,c,d,a,W[11],22,0x895cd7beUL) + FF(a,b,c,d,W[12],7,0x6b901122UL) + FF(d,a,b,c,W[13],12,0xfd987193UL) + FF(c,d,a,b,W[14],17,0xa679438eUL) + FF(b,c,d,a,W[15],22,0x49b40821UL) + GG(a,b,c,d,W[1],5,0xf61e2562UL) + GG(d,a,b,c,W[6],9,0xc040b340UL) + GG(c,d,a,b,W[11],14,0x265e5a51UL) + GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) + GG(a,b,c,d,W[5],5,0xd62f105dUL) + GG(d,a,b,c,W[10],9,0x02441453UL) + GG(c,d,a,b,W[15],14,0xd8a1e681UL) + GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) + GG(a,b,c,d,W[9],5,0x21e1cde6UL) + GG(d,a,b,c,W[14],9,0xc33707d6UL) + GG(c,d,a,b,W[3],14,0xf4d50d87UL) + GG(b,c,d,a,W[8],20,0x455a14edUL) + GG(a,b,c,d,W[13],5,0xa9e3e905UL) + GG(d,a,b,c,W[2],9,0xfcefa3f8UL) + GG(c,d,a,b,W[7],14,0x676f02d9UL) + GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + HH(a,b,c,d,W[5],4,0xfffa3942UL) + HH(d,a,b,c,W[8],11,0x8771f681UL) + HH(c,d,a,b,W[11],16,0x6d9d6122UL) + HH(b,c,d,a,W[14],23,0xfde5380cUL) + HH(a,b,c,d,W[1],4,0xa4beea44UL) + HH(d,a,b,c,W[4],11,0x4bdecfa9UL) + HH(c,d,a,b,W[7],16,0xf6bb4b60UL) + HH(b,c,d,a,W[10],23,0xbebfbc70UL) + HH(a,b,c,d,W[13],4,0x289b7ec6UL) + HH(d,a,b,c,W[0],11,0xeaa127faUL) + HH(c,d,a,b,W[3],16,0xd4ef3085UL) + HH(b,c,d,a,W[6],23,0x04881d05UL) + HH(a,b,c,d,W[9],4,0xd9d4d039UL) + HH(d,a,b,c,W[12],11,0xe6db99e5UL) + HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + HH(b,c,d,a,W[2],23,0xc4ac5665UL) + II(a,b,c,d,W[0],6,0xf4292244UL) + II(d,a,b,c,W[7],10,0x432aff97UL) + II(c,d,a,b,W[14],15,0xab9423a7UL) + II(b,c,d,a,W[5],21,0xfc93a039UL) + II(a,b,c,d,W[12],6,0x655b59c3UL) + II(d,a,b,c,W[3],10,0x8f0ccc92UL) + II(c,d,a,b,W[10],15,0xffeff47dUL) + II(b,c,d,a,W[1],21,0x85845dd1UL) + II(a,b,c,d,W[8],6,0x6fa87e4fUL) + II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + II(c,d,a,b,W[6],15,0xa3014314UL) + II(b,c,d,a,W[13],21,0x4e0811a1UL) + II(a,b,c,d,W[4],6,0xf7537e82UL) + II(d,a,b,c,W[11],10,0xbd3af235UL) + II(c,d,a,b,W[2],15,0x2ad7d2bbUL) + II(b,c,d,a,W[9],21,0xeb86d391UL) +#endif + + md->md5.state[0] = md->md5.state[0] + a; + md->md5.state[1] = md->md5.state[1] + b; + md->md5.state[2] = md->md5.state[2] + c; + md->md5.state[3] = md->md5.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int md5_compress(hash_state *md, unsigned char *buf) +{ + int err; + err = _md5_compress(md, buf); + burn_stack(sizeof(ulong32) * 21); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md5_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md5.state[0] = 0x67452301UL; + md->md5.state[1] = 0xefcdab89UL; + md->md5.state[2] = 0x98badcfeUL; + md->md5.state[3] = 0x10325476UL; + md->md5.curlen = 0; + md->md5.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(md5_process, md5_compress, md5, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md5_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md5.curlen >= sizeof(md->md5.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->md5.length += md->md5.curlen * 8; + + /* append the '1' bit */ + md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->md5.curlen > 56) { + while (md->md5.curlen < 64) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + md5_compress(md, md->md5.buf); + md->md5.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md5.curlen < 56) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md5.length, md->md5.buf+56); + md5_compress(md, md->md5.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md5.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + md5_init(&md); + md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + md5_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* ref: HEAD -> master, tag: v1.18.2 */ +/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */ +/* commit time: 2018-07-01 22:49:01 +0200 */