diff options
49 files changed, 3496 insertions, 1950 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a5702e1..7aa8010 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES) # Allow the user to enable/disable all system utility library options by # defining CMAKE_USE_SYSTEM_LIBRARIES or CMAKE_USE_SYSTEM_LIBRARY_${util}. - set(UTILITIES BZIP2 CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBUV ZLIB) + set(UTILITIES BZIP2 CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBRHASH LIBUV ZLIB) foreach(util ${UTILITIES}) if(NOT DEFINED CMAKE_USE_SYSTEM_LIBRARY_${util} AND DEFINED CMAKE_USE_SYSTEM_LIBRARIES) @@ -144,6 +144,7 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES) "${CMAKE_USE_SYSTEM_LIBRARY_LIBLZMA}" "NOT CMAKE_USE_SYSTEM_LIBARCHIVE" ON) option(CMAKE_USE_SYSTEM_FORM "Use system-installed libform" "${CMAKE_USE_SYSTEM_LIBRARY_FORM}") option(CMAKE_USE_SYSTEM_JSONCPP "Use system-installed jsoncpp" "${CMAKE_USE_SYSTEM_LIBRARY_JSONCPP}") + option(CMAKE_USE_SYSTEM_LIBRHASH "Use system-installed librhash" "${CMAKE_USE_SYSTEM_LIBRARY_LIBRHASH}") option(CMAKE_USE_SYSTEM_LIBUV "Use system-installed libuv" "${CMAKE_USE_SYSTEM_LIBRARY_LIBUV}") # For now use system KWIML only if explicitly requested rather @@ -298,6 +299,23 @@ macro (CMAKE_BUILD_UTILITIES) add_subdirectory(Utilities/KWIML) endif() + if(CMAKE_USE_SYSTEM_LIBRHASH) + if(NOT CMAKE_VERSION VERSION_LESS 3.0) + find_package(LibRHash) + else() + message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBRHASH requires CMake >= 3.0") + endif() + if(NOT LibRHash_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_LIBRHASH is ON but LibRHash is not found!") + endif() + set(CMAKE_LIBRHASH_LIBRARIES LibRHash::LibRHash) + else() + set(CMAKE_LIBRHASH_LIBRARIES cmlibrhash) + add_subdirectory(Utilities/cmlibrhash) + CMAKE_SET_TARGET_FOLDER(cmlibrhash "Utilities/3rdParty") + endif() + #--------------------------------------------------------------------- # Build zlib library for Curl, CMake, and CTest. set(CMAKE_ZLIB_HEADER "cm_zlib.h") diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 48dd3de..07a9fdb 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -17,7 +17,6 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "Utilities.cmbzip2." "Source.CTest.Curl" "Source.CursesDialog.form" - "Source.cm_sha2.*warning.*cast increases required alignment of target type" "Utilities.cmcurl" "Utilities.cmexpat." "Utilities.cmlibarchive" @@ -84,7 +83,6 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning: Value stored to 'yytoken' is never read" "index_encoder.c.241.2. warning: Value stored to .out_start. is never read" "index.c.*warning: Access to field.*results in a dereference of a null pointer.*loaded from variable.*" - "cm_sha2.*warning: Value stored to.*is never read" "cmFortranLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" "testProcess.*warning: Dereference of null pointer .loaded from variable .invalidAddress.." "liblzma/simple/x86.c:[0-9]+:[0-9]+: warning: The result of the '<<' expression is undefined" diff --git a/Source/.gitattributes b/Source/.gitattributes index 5002b2a..e9e35bd 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,6 +1,3 @@ -# Preserve upstream indentation style. -cm_sha2.* whitespace=indent-with-non-tab - # Preserve indentation style in generated code. cmListFileLexer.c whitespace=-tab-in-indent,-indent-with-non-tab cmFortranLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index cf9dbb8..718b022 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -626,8 +626,6 @@ set(SRCS cm_auto_ptr.hxx cm_get_date.h cm_get_date.c - cm_sha2.h - cm_sha2.c cm_utf8.h cm_utf8.c cm_codecvt.hxx @@ -788,6 +786,7 @@ target_link_libraries(CMakeLib cmsys ${CMAKE_CURL_LIBRARIES} ${CMAKE_JSONCPP_LIBRARIES} ${CMAKE_LIBUV_LIBRARIES} + ${CMAKE_LIBRHASH_LIBRARIES} ${CMake_KWIML_LIBRARIES} ) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 4c8abd9..0c4f573 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -1060,8 +1060,8 @@ std::string cmCPackWIXGenerator::CreateNewIdForPath(std::string const& path) std::string cmCPackWIXGenerator::CreateHashedId( std::string const& path, std::string const& normalizedFilename) { - CM_AUTO_PTR<cmCryptoHash> sha1 = cmCryptoHash::New("SHA1"); - std::string hash = sha1->HashString(path.c_str()); + cmCryptoHash sha1(cmCryptoHash::AlgoSHA1); + std::string const hash = sha1.HashString(path); std::string identifier; identifier += hash.substr(0, 7) + "_"; diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 224681a..f7a6e0b 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -4,6 +4,7 @@ #include <cmConfigure.h> +#include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -14,7 +15,6 @@ #include <cm_auto_ptr.hxx> #include <cmsys/FStream.hxx> -#include <cmsys/MD5.h> #include <cmsys/Process.h> #include <cmsys/RegularExpression.hxx> #include <iostream> @@ -167,17 +167,14 @@ void cmCTestLaunch::ComputeFileNames() // We hash the input command working dir and command line to obtain // a repeatable and (probably) unique name for log files. - char hash[32]; - cmsysMD5* md5 = cmsysMD5_New(); - cmsysMD5_Initialize(md5); - cmsysMD5_Append(md5, (unsigned char const*)(this->CWD.c_str()), -1); + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + md5.Initialize(); + md5.Append(this->CWD); for (std::vector<std::string>::const_iterator ai = this->RealArgs.begin(); ai != this->RealArgs.end(); ++ai) { - cmsysMD5_Append(md5, (unsigned char const*)ai->c_str(), -1); + md5.Append(*ai); } - cmsysMD5_FinalizeHex(md5, hash); - cmsysMD5_Delete(md5); - this->LogHash.assign(hash, 32); + this->LogHash = md5.FinalizeHex(); // We store stdout and stderr in temporary log files. this->LogOut = this->LogDir; diff --git a/Source/Modules/FindLibRHash.cmake b/Source/Modules/FindLibRHash.cmake new file mode 100644 index 0000000..86c6189 --- /dev/null +++ b/Source/Modules/FindLibRHash.cmake @@ -0,0 +1,73 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindLibRHash +------------ + +Find LibRHash include directory and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +An :ref:`imported target <Imported targets>` named +``LibRHash::LibRHash`` is provided if LibRHash has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``LibRHash_FOUND`` + True if LibRHash was found, false otherwise. +``LibRHash_INCLUDE_DIRS`` + Include directories needed to include LibRHash headers. +``LibRHash_LIBRARIES`` + Libraries needed to link to LibRHash. + +Cache Variables +^^^^^^^^^^^^^^^ + +This module uses the following cache variables: + +``LibRHash_LIBRARY`` + The location of the LibRHash library file. +``LibRHash_INCLUDE_DIR`` + The location of the LibRHash include directory containing ``rhash.h``. + +The cache variables should not be used by project code. +They may be set by end users to point at LibRHash components. +#]=======================================================================] + +#----------------------------------------------------------------------------- +find_library(LibRHash_LIBRARY + NAMES rhash + ) +mark_as_advanced(LibRHash_LIBRARY) + +find_path(LibRHash_INCLUDE_DIR + NAMES rhash.h + ) +mark_as_advanced(LibRHash_INCLUDE_DIR) + +#----------------------------------------------------------------------------- +include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibRHash + FOUND_VAR LibRHash_FOUND + REQUIRED_VARS LibRHash_LIBRARY LibRHash_INCLUDE_DIR + ) +set(LIBRHASH_FOUND ${LibRHash_FOUND}) + +#----------------------------------------------------------------------------- +# Provide documented result variables and targets. +if(LibRHash_FOUND) + set(LibRHash_INCLUDE_DIRS ${LibRHash_INCLUDE_DIR}) + set(LibRHash_LIBRARIES ${LibRHash_LIBRARY}) + if(NOT TARGET LibRHash::LibRHash) + add_library(LibRHash::LibRHash UNKNOWN IMPORTED) + set_target_properties(LibRHash::LibRHash PROPERTIES + IMPORTED_LOCATION "${LibRHash_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${LibRHash_INCLUDE_DIRS}" + ) + endif() +endif() diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 9b3f84a..f440999 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -2,31 +2,62 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCryptoHash.h" -#include "cm_sha2.h" - +#include <cm_kwiml.h> +#include <cm_rhash.h> #include <cmsys/FStream.hxx> -#include <cmsys/MD5.h> #include <string.h> +static unsigned int const cmCryptoHashAlgoToId[] = { + /* clang-format needs this comment to break after the opening brace */ + RHASH_MD5, // + RHASH_SHA1, // + RHASH_SHA224, // + RHASH_SHA256, // + RHASH_SHA384, // + RHASH_SHA512 +}; + +static int cmCryptoHash_rhash_library_initialized; + +static rhash cmCryptoHash_rhash_init(unsigned int id) +{ + if (!cmCryptoHash_rhash_library_initialized) { + cmCryptoHash_rhash_library_initialized = 1; + rhash_library_init(); + } + return rhash_init(id); +} + +cmCryptoHash::cmCryptoHash(Algo algo) + : Id(cmCryptoHashAlgoToId[algo]) + , CTX(cmCryptoHash_rhash_init(Id)) +{ +} + +cmCryptoHash::~cmCryptoHash() +{ + rhash_free(this->CTX); +} + CM_AUTO_PTR<cmCryptoHash> cmCryptoHash::New(const char* algo) { if (strcmp(algo, "MD5") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashMD5); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoMD5)); } if (strcmp(algo, "SHA1") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashSHA1); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA1)); } if (strcmp(algo, "SHA224") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashSHA224); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA224)); } if (strcmp(algo, "SHA256") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashSHA256); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA256)); } if (strcmp(algo, "SHA384") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashSHA384); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA384)); } if (strcmp(algo, "SHA512") == 0) { - return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHashSHA512); + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA512)); } return CM_AUTO_PTR<cmCryptoHash>(CM_NULLPTR); } @@ -80,7 +111,7 @@ std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file) this->Initialize(); { // Should be efficient enough on most system: - cm_sha2_uint64_t buffer[512]; + KWIML_INT_uint64_t buffer[512]; char* buffer_c = reinterpret_cast<char*>(buffer); unsigned char const* buffer_uc = reinterpret_cast<unsigned char const*>(buffer); @@ -117,51 +148,29 @@ std::string cmCryptoHash::HashFile(const std::string& file) return ByteHashToString(this->ByteHashFile(file)); } -cmCryptoHashMD5::cmCryptoHashMD5() - : MD5(cmsysMD5_New()) +void cmCryptoHash::Initialize() { + rhash_reset(this->CTX); } -cmCryptoHashMD5::~cmCryptoHashMD5() +void cmCryptoHash::Append(void const* buf, size_t sz) { - cmsysMD5_Delete(this->MD5); + rhash_update(this->CTX, buf, sz); } -void cmCryptoHashMD5::Initialize() +void cmCryptoHash::Append(std::string const& str) { - cmsysMD5_Initialize(this->MD5); + this->Append(str.c_str(), str.size()); } -void cmCryptoHashMD5::Append(unsigned char const* buf, int sz) +std::vector<unsigned char> cmCryptoHash::Finalize() { - cmsysMD5_Append(this->MD5, buf, sz); + std::vector<unsigned char> hash(rhash_get_digest_size(this->Id), 0); + rhash_final(this->CTX, &hash[0]); + return hash; } -std::vector<unsigned char> cmCryptoHashMD5::Finalize() +std::string cmCryptoHash::FinalizeHex() { - std::vector<unsigned char> hash(16, 0); - cmsysMD5_Finalize(this->MD5, &hash[0]); - return hash; + return cmCryptoHash::ByteHashToString(this->Finalize()); } - -#define cmCryptoHash_SHA_CLASS_IMPL(SHA) \ - cmCryptoHash##SHA::cmCryptoHash##SHA() \ - : SHA(new SHA_CTX) \ - { \ - } \ - cmCryptoHash##SHA::~cmCryptoHash##SHA() { delete this->SHA; } \ - void cmCryptoHash##SHA::Initialize() { SHA##_Init(this->SHA); } \ - void cmCryptoHash##SHA::Append(unsigned char const* buf, int sz) \ - { \ - SHA##_Update(this->SHA, buf, sz); \ - } \ - std::vector<unsigned char> cmCryptoHash##SHA::Finalize() \ - { \ - std::vector<unsigned char> hash(SHA##_DIGEST_LENGTH, 0); \ - SHA##_Final(&hash[0], this->SHA); \ - return hash; \ - } - -cmCryptoHash_SHA_CLASS_IMPL(SHA1) cmCryptoHash_SHA_CLASS_IMPL(SHA224) - cmCryptoHash_SHA_CLASS_IMPL(SHA256) cmCryptoHash_SHA_CLASS_IMPL(SHA384) - cmCryptoHash_SHA_CLASS_IMPL(SHA512) diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 5c2d3ca..95080ac 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -15,7 +15,18 @@ class cmCryptoHash { public: - virtual ~cmCryptoHash() {} + enum Algo + { + AlgoMD5, + AlgoSHA1, + AlgoSHA224, + AlgoSHA256, + AlgoSHA384, + AlgoSHA512 + }; + + cmCryptoHash(Algo algo); + ~cmCryptoHash(); /// @brief Returns a new hash generator of the requested type /// @arg algo Hash type name. Supported hash types are @@ -53,47 +64,15 @@ public: /// An empty string otherwise. std::string HashFile(const std::string& file); -protected: - virtual void Initialize() = 0; - virtual void Append(unsigned char const*, int) = 0; - virtual std::vector<unsigned char> Finalize() = 0; -}; - -class cmCryptoHashMD5 : public cmCryptoHash -{ - struct cmsysMD5_s* MD5; - -public: - cmCryptoHashMD5(); - ~cmCryptoHashMD5() CM_OVERRIDE; + void Initialize(); + void Append(void const*, size_t); + void Append(std::string const& str); + std::vector<unsigned char> Finalize(); + std::string FinalizeHex(); -protected: - void Initialize() CM_OVERRIDE; - void Append(unsigned char const* buf, int sz) CM_OVERRIDE; - std::vector<unsigned char> Finalize() CM_OVERRIDE; +private: + unsigned int Id; + struct rhash_context* CTX; }; -#define cmCryptoHash_SHA_CLASS_DECL(SHA) \ - class cmCryptoHash##SHA : public cmCryptoHash \ - { \ - union _SHA_CTX* SHA; \ - \ - public: \ - cmCryptoHash##SHA(); \ - ~cmCryptoHash##SHA(); \ - \ - protected: \ - virtual void Initialize(); \ - virtual void Append(unsigned char const* buf, int sz); \ - virtual std::vector<unsigned char> Finalize(); \ - } - -cmCryptoHash_SHA_CLASS_DECL(SHA1); -cmCryptoHash_SHA_CLASS_DECL(SHA224); -cmCryptoHash_SHA_CLASS_DECL(SHA256); -cmCryptoHash_SHA_CLASS_DECL(SHA384); -cmCryptoHash_SHA_CLASS_DECL(SHA512); - -#undef cmCryptoHash_SHA_CLASS_DECL - #endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index afff0f3..15257fc 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2554,7 +2554,8 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5."); return false; } - hash = CM_AUTO_PTR<cmCryptoHash>(cmCryptoHash::New("MD5")); + hash = + CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(cmCryptoHash::AlgoMD5)); hashMatchMSG = "MD5 sum"; expectedHash = cmSystemTools::LowerCase(*i); } else if (*i == "SHOW_PROGRESS") { diff --git a/Source/cmFilePathUuid.cxx b/Source/cmFilePathUuid.cxx index ad434e3..03d2524 100644 --- a/Source/cmFilePathUuid.cxx +++ b/Source/cmFilePathUuid.cxx @@ -107,8 +107,8 @@ std::string cmFilePathUuid::GetChecksumString( { // Calculate the file ( seed + relative path + name ) checksum std::vector<unsigned char> hashBytes = - cmCryptoHash::New("SHA256")->ByteHashString( - sourceRelSeed + sourceRelPath + sourceFilename); + cmCryptoHash(cmCryptoHash::AlgoSHA256) + .ByteHashString(sourceRelSeed + sourceRelPath + sourceFilename); checksumBase32 = cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2d0767f..fa447ff 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -45,9 +45,9 @@ #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) +#include "cmCryptoHash.h" #include <cm_jsoncpp_value.h> #include <cm_jsoncpp_writer.h> -#include <cmsys/MD5.h> #endif class cmInstalledFile; @@ -2617,14 +2617,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs, // Compute a hash of the rule. RuleHash hash; { - unsigned char const* data = - reinterpret_cast<unsigned char const*>(content.c_str()); - int length = static_cast<int>(content.length()); - cmsysMD5* sum = cmsysMD5_New(); - cmsysMD5_Initialize(sum); - cmsysMD5_Append(sum, data, length); - cmsysMD5_FinalizeHex(sum, hash.Data); - cmsysMD5_Delete(sum); + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + std::string const md5_hex = md5.HashString(content); + memcpy(hash.Data, md5_hex.c_str(), 32); } // Shorten the output name (in expected use case). diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7d3a2f0..e7dfed5 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -27,7 +27,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) #define CM_LG_ENCODE_OBJECT_NAMES -#include <cmsys/MD5.h> +#include "cmCryptoHash.h" #endif #include <algorithm> @@ -2002,17 +2002,6 @@ void cmLocalGenerator::GenerateTargetInstallRules( } #if defined(CM_LG_ENCODE_OBJECT_NAMES) -static std::string cmLocalGeneratorMD5(const char* input) -{ - char md5out[32]; - cmsysMD5* md5 = cmsysMD5_New(); - cmsysMD5_Initialize(md5); - cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1); - cmsysMD5_FinalizeHex(md5, md5out); - cmsysMD5_Delete(md5); - return std::string(md5out, 32); -} - static bool cmLocalGeneratorShortenObjectName(std::string& objName, std::string::size_type max_len) { @@ -2021,7 +2010,8 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName, std::string::size_type pos = objName.find('/', objName.size() - max_len + 32); if (pos != objName.npos) { - std::string md5name = cmLocalGeneratorMD5(objName.substr(0, pos).c_str()); + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + std::string md5name = md5.HashString(objName.substr(0, pos)); md5name += objName.substr(pos); objName = md5name; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 0a3a1ab..7738ab6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -847,8 +847,8 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname) bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out) { #if defined(CMAKE_BUILD_WITH_CMAKE) - cmCryptoHashMD5 md5; - std::string str = md5.HashFile(source); + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + std::string const str = md5.HashFile(source); strncpy(md5out, str.c_str(), 32); return !str.empty(); #else @@ -863,7 +863,7 @@ bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out) std::string cmSystemTools::ComputeStringMD5(const std::string& input) { #if defined(CMAKE_BUILD_WITH_CMAKE) - cmCryptoHashMD5 md5; + cmCryptoHash md5(cmCryptoHash::AlgoMD5); return md5.HashString(input); #else (void)input; diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx index 904bcbb..201e1cc 100644 --- a/Source/cmUuid.cxx +++ b/Source/cmUuid.cxx @@ -2,9 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmUuid.h" -#include "cm_sha2.h" +#include "cmCryptoHash.h" -#include <cmsys/MD5.h> #include <string.h> cmUuid::cmUuid() @@ -22,16 +21,12 @@ std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace, std::vector<unsigned char> hashInput; this->CreateHashInput(uuidNamespace, name, hashInput); - cmsysMD5_s* md5 = cmsysMD5_New(); - cmsysMD5_Initialize(md5); - cmsysMD5_Append(md5, &hashInput[0], int(hashInput.size())); + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + md5.Initialize(); + md5.Append(&hashInput[0], hashInput.size()); + std::vector<unsigned char> digest = md5.Finalize(); - unsigned char digest[16] = { 0 }; - cmsysMD5_Finalize(md5, digest); - - cmsysMD5_Delete(md5); - - return this->FromDigest(digest, 3); + return this->FromDigest(&digest[0], 3); } std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace, @@ -40,16 +35,12 @@ std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace, std::vector<unsigned char> hashInput; this->CreateHashInput(uuidNamespace, name, hashInput); - SHA_CTX* sha = new SHA_CTX; - SHA1_Init(sha); - SHA1_Update(sha, &hashInput[0], hashInput.size()); - - unsigned char digest[SHA1_DIGEST_LENGTH] = { 0 }; - SHA1_Final(digest, sha); - - delete sha; + cmCryptoHash sha1(cmCryptoHash::AlgoSHA1); + sha1.Initialize(); + sha1.Append(&hashInput[0], hashInput.size()); + std::vector<unsigned char> digest = sha1.Finalize(); - return this->FromDigest(digest, 5); + return this->FromDigest(&digest[0], 5); } void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace, diff --git a/Source/cm_sha2.c b/Source/cm_sha2.c deleted file mode 100644 index 649c39a..0000000 --- a/Source/cm_sha2.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* - * FILE: sha2.c - * AUTHOR: Aaron D. Gifford - * http://www.aarongifford.com/computers/sha.html - * - * Copyright (c) 2000-2003, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.c,v 1.4 2004/01/07 22:58:18 adg Exp $ - */ - -#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ -#include <assert.h> /* assert() */ -#include "cm_sha2.h" /* "sha2.h" -> "cm_sha2.h" renamed for CMake */ - -/* - * ASSERT NOTE: - * Some sanity checking code is included using assert(). On my FreeBSD - * system, this additional code can be removed by compiling with NDEBUG - * defined. Check your own systems manpage on assert() to see how to - * compile WITHOUT the sanity checking code on your system. - * - * UNROLLED TRANSFORM LOOP NOTE: - * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform - * loop version for the hash transform rounds (defined using macros - * later in this file). Either define on the command line, for example: - * - * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c - * - * or define below: - * - * #define SHA2_UNROLL_TRANSFORM - * - */ - - -/*** SHA-224/256/384/512 Machine Architecture Definitions *************/ -/* - * BYTE_ORDER NOTE: - * - * Please make sure that your system defines BYTE_ORDER. If your - * architecture is little-endian, make sure it also defines - * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivilent. - * - * If your system does not define the above, then you can do so by - * hand like this: - * - * #define LITTLE_ENDIAN 1234 - * #define BIG_ENDIAN 4321 - * - * And for little-endian machines, add: - * - * #define BYTE_ORDER LITTLE_ENDIAN - * - * Or for big-endian machines: - * - * #define BYTE_ORDER BIG_ENDIAN - * - * The FreeBSD machine this was written on defines BYTE_ORDER - * appropriately by including <sys/types.h> (which in turn includes - * <machine/endian.h> where the appropriate definitions are actually - * made). - */ -#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) -/* CMake modification: use byte order from KWIML. */ -# undef BYTE_ORDER -# undef BIG_ENDIAN -# undef LITTLE_ENDIAN -# define BYTE_ORDER KWIML_ABI_ENDIAN_ID -# define BIG_ENDIAN KWIML_ABI_ENDIAN_ID_BIG -# define LITTLE_ENDIAN KWIML_ABI_ENDIAN_ID_LITTLE -#endif - -/* CMake modification: use types computed in header. */ -typedef cm_sha2_uint8_t sha_byte; /* Exactly 1 byte */ -typedef cm_sha2_uint32_t sha_word32; /* Exactly 4 bytes */ -typedef cm_sha2_uint64_t sha_word64; /* Exactly 8 bytes */ -#define SHA_UINT32_C(x) KWIML_INT_UINT32_C(x) -#define SHA_UINT64_C(x) KWIML_INT_UINT64_C(x) -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wcast-align" -#endif - -/*** ENDIAN REVERSAL MACROS *******************************************/ -#if BYTE_ORDER == LITTLE_ENDIAN -#define REVERSE32(w,x) { \ - sha_word32 tmp = (w); \ - tmp = (tmp >> 16) | (tmp << 16); \ - (x) = ((tmp & SHA_UINT32_C(0xff00ff00)) >> 8) | \ - ((tmp & SHA_UINT32_C(0x00ff00ff)) << 8); \ -} -#define REVERSE64(w,x) { \ - sha_word64 tmp = (w); \ - tmp = (tmp >> 32) | (tmp << 32); \ - tmp = ((tmp & SHA_UINT64_C(0xff00ff00ff00ff00)) >> 8) | \ - ((tmp & SHA_UINT64_C(0x00ff00ff00ff00ff)) << 8); \ - (x) = ((tmp & SHA_UINT64_C(0xffff0000ffff0000)) >> 16) | \ - ((tmp & SHA_UINT64_C(0x0000ffff0000ffff)) << 16); \ -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* - * Macro for incrementally adding the unsigned 64-bit integer n to the - * unsigned 128-bit integer (represented using a two-element array of - * 64-bit words): - */ -#define ADDINC128(w,n) { \ - (w)[0] += (sha_word64)(n); \ - if ((w)[0] < (n)) { \ - (w)[1]++; \ - } \ -} - -/* - * Macros for copying blocks of memory and for zeroing out ranges - * of memory. Using these macros makes it easy to switch from - * using memset()/memcpy() and using bzero()/bcopy(). - * - * Please define either SHA2_USE_MEMSET_MEMCPY or define - * SHA2_USE_BZERO_BCOPY depending on which function set you - * choose to use: - */ -#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) -/* Default to memset()/memcpy() if no option is specified */ -#define SHA2_USE_MEMSET_MEMCPY 1 -#endif -#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) -/* Abort with an error if BOTH options are defined */ -#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! -#endif - -#ifdef SHA2_USE_MEMSET_MEMCPY -#define MEMSET_BZERO(p,l) memset((p), 0, (l)) -#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) -#endif -#ifdef SHA2_USE_BZERO_BCOPY -#define MEMSET_BZERO(p,l) bzero((p), (l)) -#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) -#endif - - -/*** THE SIX LOGICAL FUNCTIONS ****************************************/ -/* - * Bit shifting and rotation (used by the six SHA-XYZ logical functions: - * - * NOTE: In the original SHA-256/384/512 document, the shift-right - * function was named R and the rotate-right function was called S. - * (See: http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf on the - * web.) - * - * The newer NIST FIPS 180-2 document uses a much clearer naming - * scheme, SHR for shift-right, ROTR for rotate-right, and ROTL for - * rotate-left. (See: - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - * on the web.) - * - * WARNING: These macros must be used cautiously, since they reference - * supplied parameters sometimes more than once, and thus could have - * unexpected side-effects if used without taking this into account. - */ -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ -#define SHR(b,x) ((x) >> (b)) -/* 32-bit Rotate-right (used in SHA-256): */ -#define ROTR32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) -/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ -#define ROTR64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) -/* 32-bit Rotate-left (used in SHA-1): */ -#define ROTL32(b,x) (((x) << (b)) | ((x) >> (32 - (b)))) - -/* Two logical functions used in SHA-1, SHA-254, SHA-256, SHA-384, and SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* Function used in SHA-1: */ -#define Parity(x,y,z) ((x) ^ (y) ^ (z)) - -/* Four logical functions used in SHA-256: */ -#define Sigma0_256(x) (ROTR32(2, (x)) ^ ROTR32(13, (x)) ^ ROTR32(22, (x))) -#define Sigma1_256(x) (ROTR32(6, (x)) ^ ROTR32(11, (x)) ^ ROTR32(25, (x))) -#define sigma0_256(x) (ROTR32(7, (x)) ^ ROTR32(18, (x)) ^ SHR( 3 , (x))) -#define sigma1_256(x) (ROTR32(17, (x)) ^ ROTR32(19, (x)) ^ SHR( 10, (x))) - -/* Four of six logical functions used in SHA-384 and SHA-512: */ -#define Sigma0_512(x) (ROTR64(28, (x)) ^ ROTR64(34, (x)) ^ ROTR64(39, (x))) -#define Sigma1_512(x) (ROTR64(14, (x)) ^ ROTR64(18, (x)) ^ ROTR64(41, (x))) -#define sigma0_512(x) (ROTR64( 1, (x)) ^ ROTR64( 8, (x)) ^ SHR( 7, (x))) -#define sigma1_512(x) (ROTR64(19, (x)) ^ ROTR64(61, (x)) ^ SHR( 6, (x))) - -/*** INTERNAL FUNCTION PROTOTYPES *************************************/ - -/* SHA-224 and SHA-256: */ -void SHA256_Internal_Init(SHA_CTX*, const sha_word32*); -void SHA256_Internal_Last(SHA_CTX*); -void SHA256_Internal_Transform(SHA_CTX*, const sha_word32*); - -/* SHA-384 and SHA-512: */ -void SHA512_Internal_Init(SHA_CTX*, const sha_word64*); -void SHA512_Internal_Last(SHA_CTX*); -void SHA512_Internal_Transform(SHA_CTX*, const sha_word64*); - - -/*** SHA2 INITIAL HASH VALUES AND CONSTANTS ***************************/ - -/* Hash constant words K for SHA-1: */ -#define K1_0_TO_19 SHA_UINT32_C(0x5a827999) -#define K1_20_TO_39 SHA_UINT32_C(0x6ed9eba1) -#define K1_40_TO_59 SHA_UINT32_C(0x8f1bbcdc) -#define K1_60_TO_79 SHA_UINT32_C(0xca62c1d6) - -/* Initial hash value H for SHA-1: */ -static const sha_word32 sha1_initial_hash_value[5] = { - SHA_UINT32_C(0x67452301), - SHA_UINT32_C(0xefcdab89), - SHA_UINT32_C(0x98badcfe), - SHA_UINT32_C(0x10325476), - SHA_UINT32_C(0xc3d2e1f0) -}; - -/* Hash constant words K for SHA-224 and SHA-256: */ -static const sha_word32 K256[64] = { - SHA_UINT32_C(0x428a2f98), SHA_UINT32_C(0x71374491), - SHA_UINT32_C(0xb5c0fbcf), SHA_UINT32_C(0xe9b5dba5), - SHA_UINT32_C(0x3956c25b), SHA_UINT32_C(0x59f111f1), - SHA_UINT32_C(0x923f82a4), SHA_UINT32_C(0xab1c5ed5), - SHA_UINT32_C(0xd807aa98), SHA_UINT32_C(0x12835b01), - SHA_UINT32_C(0x243185be), SHA_UINT32_C(0x550c7dc3), - SHA_UINT32_C(0x72be5d74), SHA_UINT32_C(0x80deb1fe), - SHA_UINT32_C(0x9bdc06a7), SHA_UINT32_C(0xc19bf174), - SHA_UINT32_C(0xe49b69c1), SHA_UINT32_C(0xefbe4786), - SHA_UINT32_C(0x0fc19dc6), SHA_UINT32_C(0x240ca1cc), - SHA_UINT32_C(0x2de92c6f), SHA_UINT32_C(0x4a7484aa), - SHA_UINT32_C(0x5cb0a9dc), SHA_UINT32_C(0x76f988da), - SHA_UINT32_C(0x983e5152), SHA_UINT32_C(0xa831c66d), - SHA_UINT32_C(0xb00327c8), SHA_UINT32_C(0xbf597fc7), - SHA_UINT32_C(0xc6e00bf3), SHA_UINT32_C(0xd5a79147), - SHA_UINT32_C(0x06ca6351), SHA_UINT32_C(0x14292967), - SHA_UINT32_C(0x27b70a85), SHA_UINT32_C(0x2e1b2138), - SHA_UINT32_C(0x4d2c6dfc), SHA_UINT32_C(0x53380d13), - SHA_UINT32_C(0x650a7354), SHA_UINT32_C(0x766a0abb), - SHA_UINT32_C(0x81c2c92e), SHA_UINT32_C(0x92722c85), - SHA_UINT32_C(0xa2bfe8a1), SHA_UINT32_C(0xa81a664b), - SHA_UINT32_C(0xc24b8b70), SHA_UINT32_C(0xc76c51a3), - SHA_UINT32_C(0xd192e819), SHA_UINT32_C(0xd6990624), - SHA_UINT32_C(0xf40e3585), SHA_UINT32_C(0x106aa070), - SHA_UINT32_C(0x19a4c116), SHA_UINT32_C(0x1e376c08), - SHA_UINT32_C(0x2748774c), SHA_UINT32_C(0x34b0bcb5), - SHA_UINT32_C(0x391c0cb3), SHA_UINT32_C(0x4ed8aa4a), - SHA_UINT32_C(0x5b9cca4f), SHA_UINT32_C(0x682e6ff3), - SHA_UINT32_C(0x748f82ee), SHA_UINT32_C(0x78a5636f), - SHA_UINT32_C(0x84c87814), SHA_UINT32_C(0x8cc70208), - SHA_UINT32_C(0x90befffa), SHA_UINT32_C(0xa4506ceb), - SHA_UINT32_C(0xbef9a3f7), SHA_UINT32_C(0xc67178f2) -}; - -/* Initial hash value H for SHA-224: */ -static const sha_word32 sha224_initial_hash_value[8] = { - SHA_UINT32_C(0xc1059ed8), - SHA_UINT32_C(0x367cd507), - SHA_UINT32_C(0x3070dd17), - SHA_UINT32_C(0xf70e5939), - SHA_UINT32_C(0xffc00b31), - SHA_UINT32_C(0x68581511), - SHA_UINT32_C(0x64f98fa7), - SHA_UINT32_C(0xbefa4fa4) -}; - -/* Initial hash value H for SHA-256: */ -static const sha_word32 sha256_initial_hash_value[8] = { - SHA_UINT32_C(0x6a09e667), - SHA_UINT32_C(0xbb67ae85), - SHA_UINT32_C(0x3c6ef372), - SHA_UINT32_C(0xa54ff53a), - SHA_UINT32_C(0x510e527f), - SHA_UINT32_C(0x9b05688c), - SHA_UINT32_C(0x1f83d9ab), - SHA_UINT32_C(0x5be0cd19) -}; - -/* Hash constant words K for SHA-384 and SHA-512: */ -static const sha_word64 K512[80] = { - SHA_UINT64_C(0x428a2f98d728ae22), SHA_UINT64_C(0x7137449123ef65cd), - SHA_UINT64_C(0xb5c0fbcfec4d3b2f), SHA_UINT64_C(0xe9b5dba58189dbbc), - SHA_UINT64_C(0x3956c25bf348b538), SHA_UINT64_C(0x59f111f1b605d019), - SHA_UINT64_C(0x923f82a4af194f9b), SHA_UINT64_C(0xab1c5ed5da6d8118), - SHA_UINT64_C(0xd807aa98a3030242), SHA_UINT64_C(0x12835b0145706fbe), - SHA_UINT64_C(0x243185be4ee4b28c), SHA_UINT64_C(0x550c7dc3d5ffb4e2), - SHA_UINT64_C(0x72be5d74f27b896f), SHA_UINT64_C(0x80deb1fe3b1696b1), - SHA_UINT64_C(0x9bdc06a725c71235), SHA_UINT64_C(0xc19bf174cf692694), - SHA_UINT64_C(0xe49b69c19ef14ad2), SHA_UINT64_C(0xefbe4786384f25e3), - SHA_UINT64_C(0x0fc19dc68b8cd5b5), SHA_UINT64_C(0x240ca1cc77ac9c65), - SHA_UINT64_C(0x2de92c6f592b0275), SHA_UINT64_C(0x4a7484aa6ea6e483), - SHA_UINT64_C(0x5cb0a9dcbd41fbd4), SHA_UINT64_C(0x76f988da831153b5), - SHA_UINT64_C(0x983e5152ee66dfab), SHA_UINT64_C(0xa831c66d2db43210), - SHA_UINT64_C(0xb00327c898fb213f), SHA_UINT64_C(0xbf597fc7beef0ee4), - SHA_UINT64_C(0xc6e00bf33da88fc2), SHA_UINT64_C(0xd5a79147930aa725), - SHA_UINT64_C(0x06ca6351e003826f), SHA_UINT64_C(0x142929670a0e6e70), - SHA_UINT64_C(0x27b70a8546d22ffc), SHA_UINT64_C(0x2e1b21385c26c926), - SHA_UINT64_C(0x4d2c6dfc5ac42aed), SHA_UINT64_C(0x53380d139d95b3df), - SHA_UINT64_C(0x650a73548baf63de), SHA_UINT64_C(0x766a0abb3c77b2a8), - SHA_UINT64_C(0x81c2c92e47edaee6), SHA_UINT64_C(0x92722c851482353b), - SHA_UINT64_C(0xa2bfe8a14cf10364), SHA_UINT64_C(0xa81a664bbc423001), - SHA_UINT64_C(0xc24b8b70d0f89791), SHA_UINT64_C(0xc76c51a30654be30), - SHA_UINT64_C(0xd192e819d6ef5218), SHA_UINT64_C(0xd69906245565a910), - SHA_UINT64_C(0xf40e35855771202a), SHA_UINT64_C(0x106aa07032bbd1b8), - SHA_UINT64_C(0x19a4c116b8d2d0c8), SHA_UINT64_C(0x1e376c085141ab53), - SHA_UINT64_C(0x2748774cdf8eeb99), SHA_UINT64_C(0x34b0bcb5e19b48a8), - SHA_UINT64_C(0x391c0cb3c5c95a63), SHA_UINT64_C(0x4ed8aa4ae3418acb), - SHA_UINT64_C(0x5b9cca4f7763e373), SHA_UINT64_C(0x682e6ff3d6b2b8a3), - SHA_UINT64_C(0x748f82ee5defb2fc), SHA_UINT64_C(0x78a5636f43172f60), - SHA_UINT64_C(0x84c87814a1f0ab72), SHA_UINT64_C(0x8cc702081a6439ec), - SHA_UINT64_C(0x90befffa23631e28), SHA_UINT64_C(0xa4506cebde82bde9), - SHA_UINT64_C(0xbef9a3f7b2c67915), SHA_UINT64_C(0xc67178f2e372532b), - SHA_UINT64_C(0xca273eceea26619c), SHA_UINT64_C(0xd186b8c721c0c207), - SHA_UINT64_C(0xeada7dd6cde0eb1e), SHA_UINT64_C(0xf57d4f7fee6ed178), - SHA_UINT64_C(0x06f067aa72176fba), SHA_UINT64_C(0x0a637dc5a2c898a6), - SHA_UINT64_C(0x113f9804bef90dae), SHA_UINT64_C(0x1b710b35131c471b), - SHA_UINT64_C(0x28db77f523047d84), SHA_UINT64_C(0x32caab7b40c72493), - SHA_UINT64_C(0x3c9ebe0a15c9bebc), SHA_UINT64_C(0x431d67c49c100d4c), - SHA_UINT64_C(0x4cc5d4becb3e42b6), SHA_UINT64_C(0x597f299cfc657e2a), - SHA_UINT64_C(0x5fcb6fab3ad6faec), SHA_UINT64_C(0x6c44198c4a475817) -}; - -/* Initial hash value H for SHA-384 */ -static const sha_word64 sha384_initial_hash_value[8] = { - SHA_UINT64_C(0xcbbb9d5dc1059ed8), - SHA_UINT64_C(0x629a292a367cd507), - SHA_UINT64_C(0x9159015a3070dd17), - SHA_UINT64_C(0x152fecd8f70e5939), - SHA_UINT64_C(0x67332667ffc00b31), - SHA_UINT64_C(0x8eb44a8768581511), - SHA_UINT64_C(0xdb0c2e0d64f98fa7), - SHA_UINT64_C(0x47b5481dbefa4fa4) -}; - -/* Initial hash value H for SHA-512 */ -static const sha_word64 sha512_initial_hash_value[8] = { - SHA_UINT64_C(0x6a09e667f3bcc908), - SHA_UINT64_C(0xbb67ae8584caa73b), - SHA_UINT64_C(0x3c6ef372fe94f82b), - SHA_UINT64_C(0xa54ff53a5f1d36f1), - SHA_UINT64_C(0x510e527fade682d1), - SHA_UINT64_C(0x9b05688c2b3e6c1f), - SHA_UINT64_C(0x1f83d9abfb41bd6b), - SHA_UINT64_C(0x5be0cd19137e2179) -}; - -/* - * Constant used by SHA224/256/384/512_End() functions for converting the - * digest to a readable hexadecimal character string: - */ -static const char *sha_hex_digits = "0123456789abcdef"; - - -/*** SHA-1: ***********************************************************/ -void SHA1_Init(SHA_CTX* context) { - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - MEMCPY_BCOPY(context->s1.state, sha1_initial_hash_value, sizeof(sha_word32) * 5); - MEMSET_BZERO(context->s1.buffer, 64); - context->s1.bitcount = 0; -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-1 round macros: */ - -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND1_0_TO_15(a,b,c,d,e) \ - REVERSE32(*data++, W1[j]); \ - (e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \ - K1_0_TO_19 + W1[j]; \ - (b) = ROTL32(30, (b)); \ - j++; - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND1_0_TO_15(a,b,c,d,e) \ - (e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \ - K1_0_TO_19 + ( W1[j] = *data++ ); \ - (b) = ROTL32(30, (b)); \ - j++; - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND1_16_TO_19(a,b,c,d,e) \ - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ - (e) = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ - (b) = ROTL32(30, b); \ - j++; - -#define ROUND1_20_TO_39(a,b,c,d,e) \ - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ - (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ - (b) = ROTL32(30, b); \ - j++; - -#define ROUND1_40_TO_59(a,b,c,d,e) \ - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ - (e) = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ - (b) = ROTL32(30, b); \ - j++; - -#define ROUND1_60_TO_79(a,b,c,d,e) \ - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ - (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ - (b) = ROTL32(30, b); \ - j++; - -void SHA1_Internal_Transform(SHA_CTX* context, const sha_word32* data) { - sha_word32 a, b, c, d, e; - sha_word32 T1, *W1; - int j; - - W1 = (sha_word32*)context->s1.buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->s1.state[0]; - b = context->s1.state[1]; - c = context->s1.state[2]; - d = context->s1.state[3]; - e = context->s1.state[4]; - - j = 0; - - /* Rounds 0 to 15 unrolled: */ - ROUND1_0_TO_15(a,b,c,d,e); - ROUND1_0_TO_15(e,a,b,c,d); - ROUND1_0_TO_15(d,e,a,b,c); - ROUND1_0_TO_15(c,d,e,a,b); - ROUND1_0_TO_15(b,c,d,e,a); - ROUND1_0_TO_15(a,b,c,d,e); - ROUND1_0_TO_15(e,a,b,c,d); - ROUND1_0_TO_15(d,e,a,b,c); - ROUND1_0_TO_15(c,d,e,a,b); - ROUND1_0_TO_15(b,c,d,e,a); - ROUND1_0_TO_15(a,b,c,d,e); - ROUND1_0_TO_15(e,a,b,c,d); - ROUND1_0_TO_15(d,e,a,b,c); - ROUND1_0_TO_15(c,d,e,a,b); - ROUND1_0_TO_15(b,c,d,e,a); - ROUND1_0_TO_15(a,b,c,d,e); - - /* Rounds 16 to 19 unrolled: */ - ROUND1_16_TO_19(e,a,b,c,d); - ROUND1_16_TO_19(d,e,a,b,c); - ROUND1_16_TO_19(c,d,e,a,b); - ROUND1_16_TO_19(b,c,d,e,a); - - /* Rounds 20 to 39 unrolled: */ - ROUND1_20_TO_39(a,b,c,d,e); - ROUND1_20_TO_39(e,a,b,c,d); - ROUND1_20_TO_39(d,e,a,b,c); - ROUND1_20_TO_39(c,d,e,a,b); - ROUND1_20_TO_39(b,c,d,e,a); - ROUND1_20_TO_39(a,b,c,d,e); - ROUND1_20_TO_39(e,a,b,c,d); - ROUND1_20_TO_39(d,e,a,b,c); - ROUND1_20_TO_39(c,d,e,a,b); - ROUND1_20_TO_39(b,c,d,e,a); - ROUND1_20_TO_39(a,b,c,d,e); - ROUND1_20_TO_39(e,a,b,c,d); - ROUND1_20_TO_39(d,e,a,b,c); - ROUND1_20_TO_39(c,d,e,a,b); - ROUND1_20_TO_39(b,c,d,e,a); - ROUND1_20_TO_39(a,b,c,d,e); - ROUND1_20_TO_39(e,a,b,c,d); - ROUND1_20_TO_39(d,e,a,b,c); - ROUND1_20_TO_39(c,d,e,a,b); - ROUND1_20_TO_39(b,c,d,e,a); - - /* Rounds 40 to 59 unrolled: */ - ROUND1_40_TO_59(a,b,c,d,e); - ROUND1_40_TO_59(e,a,b,c,d); - ROUND1_40_TO_59(d,e,a,b,c); - ROUND1_40_TO_59(c,d,e,a,b); - ROUND1_40_TO_59(b,c,d,e,a); - ROUND1_40_TO_59(a,b,c,d,e); - ROUND1_40_TO_59(e,a,b,c,d); - ROUND1_40_TO_59(d,e,a,b,c); - ROUND1_40_TO_59(c,d,e,a,b); - ROUND1_40_TO_59(b,c,d,e,a); - ROUND1_40_TO_59(a,b,c,d,e); - ROUND1_40_TO_59(e,a,b,c,d); - ROUND1_40_TO_59(d,e,a,b,c); - ROUND1_40_TO_59(c,d,e,a,b); - ROUND1_40_TO_59(b,c,d,e,a); - ROUND1_40_TO_59(a,b,c,d,e); - ROUND1_40_TO_59(e,a,b,c,d); - ROUND1_40_TO_59(d,e,a,b,c); - ROUND1_40_TO_59(c,d,e,a,b); - ROUND1_40_TO_59(b,c,d,e,a); - - /* Rounds 60 to 79 unrolled: */ - ROUND1_60_TO_79(a,b,c,d,e); - ROUND1_60_TO_79(e,a,b,c,d); - ROUND1_60_TO_79(d,e,a,b,c); - ROUND1_60_TO_79(c,d,e,a,b); - ROUND1_60_TO_79(b,c,d,e,a); - ROUND1_60_TO_79(a,b,c,d,e); - ROUND1_60_TO_79(e,a,b,c,d); - ROUND1_60_TO_79(d,e,a,b,c); - ROUND1_60_TO_79(c,d,e,a,b); - ROUND1_60_TO_79(b,c,d,e,a); - ROUND1_60_TO_79(a,b,c,d,e); - ROUND1_60_TO_79(e,a,b,c,d); - ROUND1_60_TO_79(d,e,a,b,c); - ROUND1_60_TO_79(c,d,e,a,b); - ROUND1_60_TO_79(b,c,d,e,a); - ROUND1_60_TO_79(a,b,c,d,e); - ROUND1_60_TO_79(e,a,b,c,d); - ROUND1_60_TO_79(d,e,a,b,c); - ROUND1_60_TO_79(c,d,e,a,b); - ROUND1_60_TO_79(b,c,d,e,a); - - /* Compute the current intermediate hash value */ - context->s1.state[0] += a; - context->s1.state[1] += b; - context->s1.state[2] += c; - context->s1.state[3] += d; - context->s1.state[4] += e; - - /* Clean up */ - a = b = c = d = e = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -void SHA1_Internal_Transform(SHA_CTX* context, const sha_word32* data) { - sha_word32 a, b, c, d, e; - sha_word32 T1, *W1; - int j; - - W1 = (sha_word32*)context->s1.buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->s1.state[0]; - b = context->s1.state[1]; - c = context->s1.state[2]; - d = context->s1.state[3]; - e = context->s1.state[4]; - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - T1 = data[j]; - /* Copy data while converting to host byte order */ - REVERSE32(*data++, W1[j]); - T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + W1[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + (W1[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - e = d; - d = c; - c = ROTL32(30, b); - b = a; - a = T1; - j++; - } while (j < 16); - - do { - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; - T1 = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + (W1[j&0x0f] = ROTL32(1, T1)); - e = d; - d = c; - c = ROTL32(30, b); - b = a; - a = T1; - j++; - } while (j < 20); - - do { - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; - T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + (W1[j&0x0f] = ROTL32(1, T1)); - e = d; - d = c; - c = ROTL32(30, b); - b = a; - a = T1; - j++; - } while (j < 40); - - do { - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; - T1 = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + (W1[j&0x0f] = ROTL32(1, T1)); - e = d; - d = c; - c = ROTL32(30, b); - b = a; - a = T1; - j++; - } while (j < 60); - - do { - T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; - T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + (W1[j&0x0f] = ROTL32(1, T1)); - e = d; - d = c; - c = ROTL32(30, b); - b = a; - a = T1; - j++; - } while (j < 80); - - - /* Compute the current intermediate hash value */ - context->s1.state[0] += a; - context->s1.state[1] += b; - context->s1.state[2] += c; - context->s1.state[3] += d; - context->s1.state[4] += e; - - /* Clean up */ - a = b = c = d = e = T1 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -void SHA1_Update(SHA_CTX* context, const sha_byte *data, size_t len) { - unsigned int freespace, usedspace; - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA_CTX*)0 && data != (sha_byte*)0); - - usedspace = (unsigned int)((context->s1.bitcount >> 3) % 64); - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = 64 - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->s1.buffer[usedspace], data, freespace); - context->s1.bitcount += freespace << 3; - len -= freespace; - data += freespace; - SHA1_Internal_Transform(context, (const sha_word32*)context->s1.buffer); - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->s1.buffer[usedspace], data, len); - context->s1.bitcount += len << 3; - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= 64) { - /* Process as many complete blocks as we can */ - SHA1_Internal_Transform(context, (const sha_word32*)data); - context->s1.bitcount += 512; - len -= 64; - data += 64; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->s1.buffer, data, len); - context->s1.bitcount += len << 3; - } - /* Clean up: */ - usedspace = freespace = 0; -} - -void SHA1_Final(sha_byte digest[], SHA_CTX* context) { - sha_word32 *d = (sha_word32*)digest; - unsigned int usedspace; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (digest == (sha_byte*)0) { - /* - * No digest buffer, so we can do nothing - * except clean up and go home - */ - MEMSET_BZERO(context, sizeof(*context)); - return; - } - - usedspace = (unsigned int)((context->s1.bitcount >> 3) % 64); - if (usedspace == 0) { - /* Set-up for the last transform: */ - MEMSET_BZERO(context->s1.buffer, 56); - - /* Begin padding with a 1 bit: */ - *context->s1.buffer = 0x80; - } else { - /* Begin padding with a 1 bit: */ - context->s1.buffer[usedspace++] = 0x80; - - if (usedspace <= 56) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->s1.buffer[usedspace], 56 - usedspace); - } else { - if (usedspace < 64) { - MEMSET_BZERO(&context->s1.buffer[usedspace], 64 - usedspace); - } - /* Do second-to-last transform: */ - SHA1_Internal_Transform(context, (const sha_word32*)context->s1.buffer); - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->s1.buffer, 56); - } - /* Clean up: */ - usedspace = 0; - } - /* Set the bit count: */ -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->s1.bitcount,context->s1.bitcount); -#endif - MEMCPY_BCOPY(&context->s1.buffer[56], &context->s1.bitcount, - sizeof(sha_word64)); - - /* Final transform: */ - SHA1_Internal_Transform(context, (const sha_word32*)context->s1.buffer); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < (SHA1_DIGEST_LENGTH >> 2); j++) { - REVERSE32(context->s1.state[j],context->s1.state[j]); - *d++ = context->s1.state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->s1.state, SHA1_DIGEST_LENGTH); -#endif - - /* Clean up: */ - MEMSET_BZERO(context, sizeof(*context)); -} - -char *SHA1_End(SHA_CTX* context, char buffer[]) { - sha_byte digest[SHA1_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (buffer != (char*)0) { - SHA1_Final(digest, context); - - for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { - *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(*context)); - } - MEMSET_BZERO(digest, SHA1_DIGEST_LENGTH); - return buffer; -} - -char* SHA1_Data(const sha_byte* data, size_t len, char digest[SHA1_DIGEST_STRING_LENGTH]) { - SHA_CTX context; - - SHA1_Init(&context); - SHA1_Update(&context, data, len); - return SHA1_End(&context, digest); -} - - -/*** SHA-256: *********************************************************/ -void SHA256_Internal_Init(SHA_CTX* context, const sha_word32* ihv) { - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - MEMCPY_BCOPY(context->s256.state, ihv, sizeof(sha_word32) * 8); - MEMSET_BZERO(context->s256.buffer, 64); - context->s256.bitcount = 0; -} - -void SHA256_Init(SHA_CTX* context) { - SHA256_Internal_Init(context, sha256_initial_hash_value); -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-256 round macros: */ - -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - REVERSE32(*data++, W256[j]); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + W256[j]; \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + (W256[j] = *data++); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256(a,b,c,d,e,f,g,h) \ - s0 = W256[(j+1)&0x0f]; \ - s0 = sigma0_256(s0); \ - s1 = W256[(j+14)&0x0f]; \ - s1 = sigma1_256(s1); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -void SHA256_Internal_Transform(SHA_CTX* context, const sha_word32* data) { - sha_word32 a, b, c, d, e, f, g, h, s0, s1; - sha_word32 T1, *W256; - int j; - - W256 = (sha_word32*)context->s256.buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->s256.state[0]; - b = context->s256.state[1]; - c = context->s256.state[2]; - d = context->s256.state[3]; - e = context->s256.state[4]; - f = context->s256.state[5]; - g = context->s256.state[6]; - h = context->s256.state[7]; - - j = 0; - do { - /* Rounds 0 to 15 (unrolled): */ - ROUND256_0_TO_15(a,b,c,d,e,f,g,h); - ROUND256_0_TO_15(h,a,b,c,d,e,f,g); - ROUND256_0_TO_15(g,h,a,b,c,d,e,f); - ROUND256_0_TO_15(f,g,h,a,b,c,d,e); - ROUND256_0_TO_15(e,f,g,h,a,b,c,d); - ROUND256_0_TO_15(d,e,f,g,h,a,b,c); - ROUND256_0_TO_15(c,d,e,f,g,h,a,b); - ROUND256_0_TO_15(b,c,d,e,f,g,h,a); - } while (j < 16); - - /* Now for the remaining rounds to 64: */ - do { - ROUND256(a,b,c,d,e,f,g,h); - ROUND256(h,a,b,c,d,e,f,g); - ROUND256(g,h,a,b,c,d,e,f); - ROUND256(f,g,h,a,b,c,d,e); - ROUND256(e,f,g,h,a,b,c,d); - ROUND256(d,e,f,g,h,a,b,c); - ROUND256(c,d,e,f,g,h,a,b); - ROUND256(b,c,d,e,f,g,h,a); - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->s256.state[0] += a; - context->s256.state[1] += b; - context->s256.state[2] += c; - context->s256.state[3] += d; - context->s256.state[4] += e; - context->s256.state[5] += f; - context->s256.state[6] += g; - context->s256.state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -void SHA256_Internal_Transform(SHA_CTX* context, const sha_word32* data) { - sha_word32 a, b, c, d, e, f, g, h, s0, s1; - sha_word32 T1, T2, *W256; - int j; - - W256 = (sha_word32*)context->s256.buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->s256.state[0]; - b = context->s256.state[1]; - c = context->s256.state[2]; - d = context->s256.state[3]; - e = context->s256.state[4]; - f = context->s256.state[5]; - g = context->s256.state[6]; - h = context->s256.state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Copy data while converting to host byte order */ - REVERSE32(*data++,W256[j]); - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-256 compression function to update a..h with copy */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W256[(j+1)&0x0f]; - s0 = sigma0_256(s0); - s1 = W256[(j+14)&0x0f]; - s1 = sigma1_256(s1); - - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->s256.state[0] += a; - context->s256.state[1] += b; - context->s256.state[2] += c; - context->s256.state[3] += d; - context->s256.state[4] += e; - context->s256.state[5] += f; - context->s256.state[6] += g; - context->s256.state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -void SHA256_Update(SHA_CTX* context, const sha_byte *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA_CTX*)0 && data != (sha_byte*)0); - - usedspace = (unsigned int)((context->s256.bitcount >> 3) % 64); - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = 64 - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->s256.buffer[usedspace], data, freespace); - context->s256.bitcount += freespace << 3; - len -= freespace; - data += freespace; - SHA256_Internal_Transform(context, (const sha_word32*)context->s256.buffer); - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->s256.buffer[usedspace], data, len); - context->s256.bitcount += len << 3; - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= 64) { - /* Process as many complete blocks as we can */ - SHA256_Internal_Transform(context, (const sha_word32*)data); - context->s256.bitcount += 512; - len -= 64; - data += 64; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->s256.buffer, data, len); - context->s256.bitcount += len << 3; - } - /* Clean up: */ - usedspace = freespace = 0; -} - -void SHA256_Internal_Last(SHA_CTX* context) { - unsigned int usedspace; - - usedspace = (unsigned int)((context->s256.bitcount >> 3) % 64); -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->s256.bitcount,context->s256.bitcount); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->s256.buffer[usedspace++] = 0x80; - - if (usedspace <= 56) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->s256.buffer[usedspace], 56 - usedspace); - } else { - if (usedspace < 64) { - MEMSET_BZERO(&context->s256.buffer[usedspace], 64 - usedspace); - } - /* Do second-to-last transform: */ - SHA256_Internal_Transform(context, (const sha_word32*)context->s256.buffer); - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->s256.buffer, 56); - } - /* Clean up: */ - usedspace = 0; - } else { - /* Set-up for the last transform: */ - MEMSET_BZERO(context->s256.buffer, 56); - - /* Begin padding with a 1 bit: */ - *context->s256.buffer = 0x80; - } - /* Set the bit count: */ - MEMCPY_BCOPY(&context->s256.buffer[56], &context->s256.bitcount, - sizeof(sha_word64)); - - /* Final transform: */ - SHA256_Internal_Transform(context, (const sha_word32*)context->s256.buffer); -} - -void SHA256_Final(sha_byte digest[], SHA_CTX* context) { - sha_word32 *d = (sha_word32*)digest; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha_byte*)0) { - SHA256_Internal_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < (SHA256_DIGEST_LENGTH >> 2); j++) { - REVERSE32(context->s256.state[j],context->s256.state[j]); - *d++ = context->s256.state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->s256.state, SHA256_DIGEST_LENGTH); -#endif - } - - /* Clean up state data: */ - MEMSET_BZERO(context, sizeof(*context)); -} - -char *SHA256_End(SHA_CTX* context, char buffer[]) { - sha_byte digest[SHA256_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (buffer != (char*)0) { - SHA256_Final(digest, context); - - for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { - *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(*context)); - } - MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); - return buffer; -} - -char* SHA256_Data(const sha_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { - SHA_CTX context; - - SHA256_Init(&context); - SHA256_Update(&context, data, len); - return SHA256_End(&context, digest); -} - - -/*** SHA-224: *********************************************************/ -void SHA224_Init(SHA_CTX* context) { - SHA256_Internal_Init(context, sha224_initial_hash_value); -} - -void SHA224_Internal_Transform(SHA_CTX* context, const sha_word32* data) { - SHA256_Internal_Transform(context, data); -} - -void SHA224_Update(SHA_CTX* context, const sha_byte *data, size_t len) { - SHA256_Update(context, data, len); -} - -void SHA224_Final(sha_byte digest[], SHA_CTX* context) { - sha_word32 *d = (sha_word32*)digest; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha_byte*)0) { - SHA256_Internal_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < (SHA224_DIGEST_LENGTH >> 2); j++) { - REVERSE32(context->s256.state[j],context->s256.state[j]); - *d++ = context->s256.state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->s256.state, SHA224_DIGEST_LENGTH); -#endif - } - - /* Clean up state data: */ - MEMSET_BZERO(context, sizeof(*context)); -} - -char *SHA224_End(SHA_CTX* context, char buffer[]) { - sha_byte digest[SHA224_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (buffer != (char*)0) { - SHA224_Final(digest, context); - - for (i = 0; i < SHA224_DIGEST_LENGTH; i++) { - *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(*context)); - } - MEMSET_BZERO(digest, SHA224_DIGEST_LENGTH); - return buffer; -} - -char* SHA224_Data(const sha_byte* data, size_t len, char digest[SHA224_DIGEST_STRING_LENGTH]) { - SHA_CTX context; - - SHA224_Init(&context); - SHA224_Update(&context, data, len); - return SHA224_End(&context, digest); -} - - -/*** SHA-512: *********************************************************/ -void SHA512_Internal_Init(SHA_CTX* context, const sha_word64* ihv) { - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - MEMCPY_BCOPY(context->s512.state, ihv, sizeof(sha_word64) * 8); - MEMSET_BZERO(context->s512.buffer, 128); - context->s512.bitcount[0] = context->s512.bitcount[1] = 0; -} - -void SHA512_Init(SHA_CTX* context) { - SHA512_Internal_Init(context, sha512_initial_hash_value); -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-512 round macros: */ -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ - REVERSE64(*data++, W512[j]); \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ - K512[j] + W512[j]; \ - (d) += T1, \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ - j++ - - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ - K512[j] + (W512[j] = *data++); \ - (d) += T1; \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ - j++ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND512(a,b,c,d,e,f,g,h) \ - s0 = W512[(j+1)&0x0f]; \ - s0 = sigma0_512(s0); \ - s1 = W512[(j+14)&0x0f]; \ - s1 = sigma1_512(s1); \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ - (d) += T1; \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ - j++ - -void SHA512_Internal_Transform(SHA_CTX* context, const sha_word64* data) { - sha_word64 a, b, c, d, e, f, g, h, s0, s1; - sha_word64 T1, *W512 = (sha_word64*)context->s512.buffer; - int j; - - /* Initialize registers with the prev. intermediate value */ - a = context->s512.state[0]; - b = context->s512.state[1]; - c = context->s512.state[2]; - d = context->s512.state[3]; - e = context->s512.state[4]; - f = context->s512.state[5]; - g = context->s512.state[6]; - h = context->s512.state[7]; - - j = 0; - do { - ROUND512_0_TO_15(a,b,c,d,e,f,g,h); - ROUND512_0_TO_15(h,a,b,c,d,e,f,g); - ROUND512_0_TO_15(g,h,a,b,c,d,e,f); - ROUND512_0_TO_15(f,g,h,a,b,c,d,e); - ROUND512_0_TO_15(e,f,g,h,a,b,c,d); - ROUND512_0_TO_15(d,e,f,g,h,a,b,c); - ROUND512_0_TO_15(c,d,e,f,g,h,a,b); - ROUND512_0_TO_15(b,c,d,e,f,g,h,a); - } while (j < 16); - - /* Now for the remaining rounds up to 79: */ - do { - ROUND512(a,b,c,d,e,f,g,h); - ROUND512(h,a,b,c,d,e,f,g); - ROUND512(g,h,a,b,c,d,e,f); - ROUND512(f,g,h,a,b,c,d,e); - ROUND512(e,f,g,h,a,b,c,d); - ROUND512(d,e,f,g,h,a,b,c); - ROUND512(c,d,e,f,g,h,a,b); - ROUND512(b,c,d,e,f,g,h,a); - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->s512.state[0] += a; - context->s512.state[1] += b; - context->s512.state[2] += c; - context->s512.state[3] += d; - context->s512.state[4] += e; - context->s512.state[5] += f; - context->s512.state[6] += g; - context->s512.state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -void SHA512_Internal_Transform(SHA_CTX* context, const sha_word64* data) { - sha_word64 a, b, c, d, e, f, g, h, s0, s1; - sha_word64 T1, T2, *W512 = (sha_word64*)context->s512.buffer; - int j; - - /* Initialize registers with the prev. intermediate value */ - a = context->s512.state[0]; - b = context->s512.state[1]; - c = context->s512.state[2]; - d = context->s512.state[3]; - e = context->s512.state[4]; - f = context->s512.state[5]; - g = context->s512.state[6]; - h = context->s512.state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert TO host byte order */ - REVERSE64(*data++, W512[j]); - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-512 compression function to update a..h with copy */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W512[(j+1)&0x0f]; - s0 = sigma0_512(s0); - s1 = W512[(j+14)&0x0f]; - s1 = sigma1_512(s1); - - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->s512.state[0] += a; - context->s512.state[1] += b; - context->s512.state[2] += c; - context->s512.state[3] += d; - context->s512.state[4] += e; - context->s512.state[5] += f; - context->s512.state[6] += g; - context->s512.state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -void SHA512_Update(SHA_CTX* context, const sha_byte *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA_CTX*)0 && data != (sha_byte*)0); - - usedspace = (unsigned int)((context->s512.bitcount[0] >> 3) % 128); - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = 128 - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->s512.buffer[usedspace], data, freespace); - ADDINC128(context->s512.bitcount, freespace << 3); - len -= freespace; - data += freespace; - SHA512_Internal_Transform(context, (const sha_word64*)context->s512.buffer); - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->s512.buffer[usedspace], data, len); - ADDINC128(context->s512.bitcount, len << 3); - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= 128) { - /* Process as many complete blocks as we can */ - SHA512_Internal_Transform(context, (const sha_word64*)data); - ADDINC128(context->s512.bitcount, 1024); - len -= 128; - data += 128; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->s512.buffer, data, len); - ADDINC128(context->s512.bitcount, len << 3); - } - /* Clean up: */ - usedspace = freespace = 0; -} - -void SHA512_Internal_Last(SHA_CTX* context) { - unsigned int usedspace; - - usedspace = (unsigned int)((context->s512.bitcount[0] >> 3) % 128); -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->s512.bitcount[0],context->s512.bitcount[0]); - REVERSE64(context->s512.bitcount[1],context->s512.bitcount[1]); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->s512.buffer[usedspace++] = 0x80; - - if (usedspace <= 112) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->s512.buffer[usedspace], 112 - usedspace); - } else { - if (usedspace < 128) { - MEMSET_BZERO(&context->s512.buffer[usedspace], 128 - usedspace); - } - /* Do second-to-last transform: */ - SHA512_Internal_Transform(context, (const sha_word64*)context->s512.buffer); - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->s512.buffer, 112); - } - /* Clean up: */ - usedspace = 0; - } else { - /* Prepare for final transform: */ - MEMSET_BZERO(context->s512.buffer, 112); - - /* Begin padding with a 1 bit: */ - *context->s512.buffer = 0x80; - } - /* Store the length of input data (in bits): */ - MEMCPY_BCOPY(&context->s512.buffer[112], &context->s512.bitcount[1], - sizeof(sha_word64)); - MEMCPY_BCOPY(&context->s512.buffer[120], &context->s512.bitcount[0], - sizeof(sha_word64)); - - /* Final transform: */ - SHA512_Internal_Transform(context, (const sha_word64*)context->s512.buffer); -} - -void SHA512_Final(sha_byte digest[], SHA_CTX* context) { - sha_word64 *d = (sha_word64*)digest; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha_byte*)0) { - SHA512_Internal_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < (SHA512_DIGEST_LENGTH >> 3); j++) { - REVERSE64(context->s512.state[j],context->s512.state[j]); - *d++ = context->s512.state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->s512.state, SHA512_DIGEST_LENGTH); -#endif - } - - /* Zero out state data */ - MEMSET_BZERO(context, sizeof(*context)); -} - -char *SHA512_End(SHA_CTX* context, char buffer[]) { - sha_byte digest[SHA512_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (buffer != (char*)0) { - SHA512_Final(digest, context); - - for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { - *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(*context)); - } - MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); - return buffer; -} - -char* SHA512_Data(const sha_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { - SHA_CTX context; - - SHA512_Init(&context); - SHA512_Update(&context, data, len); - return SHA512_End(&context, digest); -} - - -/*** SHA-384: *********************************************************/ -void SHA384_Init(SHA_CTX* context) { - SHA512_Internal_Init(context, sha384_initial_hash_value); -} - -void SHA384_Update(SHA_CTX* context, const sha_byte* data, size_t len) { - SHA512_Update(context, data, len); -} - -void SHA384_Final(sha_byte digest[], SHA_CTX* context) { - sha_word64 *d = (sha_word64*)digest; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha_byte*)0) { - SHA512_Internal_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < (SHA384_DIGEST_LENGTH >> 3); j++) { - REVERSE64(context->s512.state[j],context->s512.state[j]); - *d++ = context->s512.state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->s512.state, SHA384_DIGEST_LENGTH); -#endif - } - - /* Zero out state data */ - MEMSET_BZERO(context, sizeof(*context)); -} - -char *SHA384_End(SHA_CTX* context, char buffer[]) { - sha_byte digest[SHA384_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA_CTX*)0); - - if (buffer != (char*)0) { - SHA384_Final(digest, context); - - for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { - *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(*context)); - } - MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); - return buffer; -} - -char* SHA384_Data(const sha_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { - SHA_CTX context; - - SHA384_Init(&context); - SHA384_Update(&context, data, len); - return SHA384_End(&context, digest); -} diff --git a/Source/cm_sha2.h b/Source/cm_sha2.h deleted file mode 100644 index f151031..0000000 --- a/Source/cm_sha2.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * FILE: sha2.h - * AUTHOR: Aaron D. Gifford - * http://www.aarongifford.com/computers/sha.html - * - * Copyright (c) 2000-2003, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.h,v 1.4 2004/01/07 19:06:18 adg Exp $ - */ - -#ifndef __SHA2_H__ -#define __SHA2_H__ - -#include "cm_sha2_mangle.h" - -/* CMake modification: use integer types from KWIML. */ -#include <cm_kwiml.h> -typedef KWIML_INT_uint8_t cm_sha2_uint8_t; -typedef KWIML_INT_uint32_t cm_sha2_uint32_t; -typedef KWIML_INT_uint64_t cm_sha2_uint64_t; - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Import u_intXX_t size_t type definitions from system headers. You - * may need to change this, or define these things yourself in this - * file. - */ -#include <sys/types.h> - -/*** SHA-224/256/384/512 Various Length Definitions *******************/ - -/* Digest lengths for SHA-1/224/256/384/512 */ -#define SHA1_DIGEST_LENGTH 20 -#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) -#define SHA224_DIGEST_LENGTH 28 -#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1) -#define SHA256_DIGEST_LENGTH 32 -#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) -#define SHA384_DIGEST_LENGTH 48 -#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) - - -/*** SHA-224/256/384/512 Context Structures ***************************/ - -typedef union _SHA_CTX { - /* SHA-1 uses this part of the union: */ - struct { - cm_sha2_uint32_t state[5]; - cm_sha2_uint64_t bitcount; - cm_sha2_uint8_t buffer[64]; - } s1; - - /* SHA-224 and SHA-256 use this part of the union: */ - struct { - cm_sha2_uint32_t state[8]; - cm_sha2_uint64_t bitcount; - cm_sha2_uint8_t buffer[64]; - } s256; - - /* SHA-384 and SHA-512 use this part of the union: */ - struct { - cm_sha2_uint64_t state[8]; - cm_sha2_uint64_t bitcount[2]; - cm_sha2_uint8_t buffer[128]; - } s512; -} SHA_CTX; - -/*** SHA-256/384/512 Function Prototypes ******************************/ - -void SHA1_Init(SHA_CTX*); -void SHA1_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t); -void SHA1_Final(cm_sha2_uint8_t[SHA1_DIGEST_LENGTH], SHA_CTX*); -char* SHA1_End(SHA_CTX*, char[SHA1_DIGEST_STRING_LENGTH]); -char* SHA1_Data(const cm_sha2_uint8_t*, size_t, - char[SHA1_DIGEST_STRING_LENGTH]); - -void SHA224_Init(SHA_CTX*); -void SHA224_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t); -void SHA224_Final(cm_sha2_uint8_t[SHA224_DIGEST_LENGTH], SHA_CTX*); -char* SHA224_End(SHA_CTX*, char[SHA224_DIGEST_STRING_LENGTH]); -char* SHA224_Data(const cm_sha2_uint8_t*, size_t, - char[SHA224_DIGEST_STRING_LENGTH]); - -void SHA256_Init(SHA_CTX*); -void SHA256_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t); -void SHA256_Final(cm_sha2_uint8_t[SHA256_DIGEST_LENGTH], SHA_CTX*); -char* SHA256_End(SHA_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); -char* SHA256_Data(const cm_sha2_uint8_t*, size_t, - char[SHA256_DIGEST_STRING_LENGTH]); - -void SHA384_Init(SHA_CTX*); -void SHA384_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t); -void SHA384_Final(cm_sha2_uint8_t[SHA384_DIGEST_LENGTH], SHA_CTX*); -char* SHA384_End(SHA_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); -char* SHA384_Data(const cm_sha2_uint8_t*, size_t, - char[SHA384_DIGEST_STRING_LENGTH]); - -void SHA512_Init(SHA_CTX*); -void SHA512_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t); -void SHA512_Final(cm_sha2_uint8_t[SHA512_DIGEST_LENGTH], SHA_CTX*); -char* SHA512_End(SHA_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); -char* SHA512_Data(const cm_sha2_uint8_t*, size_t, - char[SHA512_DIGEST_STRING_LENGTH]); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SHA2_H__ */ diff --git a/Source/cm_sha2_mangle.h b/Source/cm_sha2_mangle.h deleted file mode 100644 index 3dce819..0000000 --- a/Source/cm_sha2_mangle.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cm_sha2_mangle_h -#define cm_sha2_mangle_h - -/* Mangle sha2 symbol names to avoid possible conflict with - implementations in other libraries to which CMake links. */ -#define SHA1_Data cmSHA1_Data -#define SHA1_End cmSHA1_End -#define SHA1_Final cmSHA1_Final -#define SHA1_Init cmSHA1_Init -#define SHA1_Internal_Transform cmSHA1_Internal_Transform -#define SHA1_Update cmSHA1_Update -#define SHA224_Data cmSHA224_Data -#define SHA224_End cmSHA224_End -#define SHA224_Final cmSHA224_Final -#define SHA224_Init cmSHA224_Init -#define SHA224_Internal_Transform cmSHA224_Internal_Transform -#define SHA224_Update cmSHA224_Update -#define SHA256_Data cmSHA256_Data -#define SHA256_End cmSHA256_End -#define SHA256_Final cmSHA256_Final -#define SHA256_Init cmSHA256_Init -#define SHA256_Internal_Init cmSHA256_Internal_Init -#define SHA256_Internal_Last cmSHA256_Internal_Last -#define SHA256_Internal_Transform cmSHA256_Internal_Transform -#define SHA256_Update cmSHA256_Update -#define SHA384_Data cmSHA384_Data -#define SHA384_End cmSHA384_End -#define SHA384_Final cmSHA384_Final -#define SHA384_Init cmSHA384_Init -#define SHA384_Update cmSHA384_Update -#define SHA512_Data cmSHA512_Data -#define SHA512_End cmSHA512_End -#define SHA512_Final cmSHA512_Final -#define SHA512_Init cmSHA512_Init -#define SHA512_Internal_Init cmSHA512_Internal_Init -#define SHA512_Internal_Last cmSHA512_Internal_Last -#define SHA512_Internal_Transform cmSHA512_Internal_Transform -#define SHA512_Update cmSHA512_Update - -#endif diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index c0ffa46..e914d00 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1377,6 +1377,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindJsonCpp) endif() + if(CMake_TEST_FindLibRHash) + add_subdirectory(FindLibRHash) + endif() + if(CMake_TEST_FindLibUV) add_subdirectory(FindLibUV) endif() diff --git a/Tests/FindLibRHash/CMakeLists.txt b/Tests/FindLibRHash/CMakeLists.txt new file mode 100644 index 0000000..4d3954d --- /dev/null +++ b/Tests/FindLibRHash/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindLibRHash.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindLibRHash/Test" + "${CMake_BINARY_DIR}/Tests/FindLibRHash/Test" + ${build_generator_args} + --build-project TestFindLibRHash + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindLibRHash/Test/CMakeLists.txt b/Tests/FindLibRHash/Test/CMakeLists.txt new file mode 100644 index 0000000..37e062a --- /dev/null +++ b/Tests/FindLibRHash/Test/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.7) +project(TestFindLibRHash C) +include(CTest) + +# CMake does not actually provide FindLibRHash publicly. +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules) + +find_package(LibRHash REQUIRED) + +add_executable(test_librhash_tgt main.c) +target_link_libraries(test_librhash_tgt LibRHash::LibRHash) +add_test(NAME test_librhash_tgt COMMAND test_librhash_tgt) + +add_executable(test_librhash_var main.c) +target_include_directories(test_librhash_var PRIVATE ${LibRHash_INCLUDE_DIRS}) +target_link_libraries(test_librhash_var PRIVATE ${LibRHash_LIBRARIES}) +add_test(NAME test_librhash_var COMMAND test_librhash_var) diff --git a/Tests/FindLibRHash/Test/main.c b/Tests/FindLibRHash/Test/main.c new file mode 100644 index 0000000..201dced --- /dev/null +++ b/Tests/FindLibRHash/Test/main.c @@ -0,0 +1,7 @@ +#include <rhash.h> + +int main() +{ + rhash_library_init(); + return 0; +} diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash index ad3b3a1..8e07c99 100755 --- a/Utilities/Scripts/clang-format.bash +++ b/Utilities/Scripts/clang-format.bash @@ -121,7 +121,7 @@ $git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' | egrep -z -v '^Source/cmListFileLexer(\.in\.l|\.c)' | # Exclude third-party sources. - egrep -z -v '^Source/(cm_sha2|bindexplib)' | + egrep -z -v '^Source/bindexplib' | egrep -z -v '^Source/(kwsys|CursesDialog/form)/' | egrep -z -v '^Utilities/(KW|cm).*/' | diff --git a/Utilities/Scripts/update-librhash.bash b/Utilities/Scripts/update-librhash.bash new file mode 100755 index 0000000..2f67ea2 --- /dev/null +++ b/Utilities/Scripts/update-librhash.bash @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +set -e +set -x +shopt -s dotglob + +readonly name="librhash" +readonly ownership="librhash upstream <kwrobot@kitware.com>" +readonly subtree="Utilities/cmlibrhash" +readonly repo="https://github.com/rhash/rhash.git" +readonly tag="master" +readonly shortlog=false +readonly paths=" + COPYING + README + librhash/algorithms.c + librhash/algorithms.h + librhash/byte_order.c + librhash/byte_order.h + librhash/hex.c + librhash/hex.h + librhash/md5.c + librhash/md5.h + librhash/rhash.c + librhash/rhash.h + librhash/sha1.c + librhash/sha1.h + librhash/sha256.c + librhash/sha256.h + librhash/sha512.c + librhash/sha512.h + librhash/ustd.h + librhash/util.h +" + +extract_source () { + git_archive + pushd "${extractdir}/${name}-reduced" + echo "* -whitespace" > .gitattributes + popd +} + +. "${BASH_SOURCE%/*}/update-third-party.bash" diff --git a/Utilities/cmThirdParty.h.in b/Utilities/cmThirdParty.h.in index 210e727..a547f0d 100644 --- a/Utilities/cmThirdParty.h.in +++ b/Utilities/cmThirdParty.h.in @@ -13,6 +13,7 @@ #cmakedefine CMAKE_USE_SYSTEM_LIBLZMA #cmakedefine CMAKE_USE_SYSTEM_FORM #cmakedefine CMAKE_USE_SYSTEM_JSONCPP +#cmakedefine CMAKE_USE_SYSTEM_LIBRHASH #cmakedefine CMAKE_USE_SYSTEM_LIBUV #cmakedefine CTEST_USE_XMLRPC diff --git a/Utilities/cm_rhash.h b/Utilities/cm_rhash.h new file mode 100644 index 0000000..c793627 --- /dev/null +++ b/Utilities/cm_rhash.h @@ -0,0 +1,14 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_rhash_h +#define cm_rhash_h + +/* Use the LibRHash library configured for CMake. */ +#include "cmThirdParty.h" +#ifdef CMAKE_USE_SYSTEM_LIBRHASH +#include <rhash.h> +#else +#include <cmlibrhash/librhash/rhash.h> +#endif + +#endif diff --git a/Utilities/cmlibrhash/.gitattributes b/Utilities/cmlibrhash/.gitattributes new file mode 100644 index 0000000..562b12e --- /dev/null +++ b/Utilities/cmlibrhash/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/Utilities/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt new file mode 100644 index 0000000..340d946 --- /dev/null +++ b/Utilities/cmlibrhash/CMakeLists.txt @@ -0,0 +1,38 @@ +project(librhash C) + +# Disable warnings to avoid changing 3rd party code. +if(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +endif() + +set(librhash_sources + librhash/algorithms.c + librhash/algorithms.h + librhash/byte_order.c + librhash/byte_order.h + librhash/hex.c + librhash/hex.h + librhash/md5.c + librhash/md5.h + librhash/rhash.c + librhash/rhash.h + librhash/sha1.c + librhash/sha1.h + librhash/sha256.c + librhash/sha256.h + librhash/sha512.c + librhash/sha512.h + librhash/ustd.h + librhash/util.h + ) + +include_directories( + ${KWSYS_HEADER_ROOT} + ) + +add_library(cmlibrhash ${librhash_sources}) + +install(FILES COPYING README DESTINATION ${CMAKE_DOC_DIR}/cmlibrhash) diff --git a/Utilities/cmlibrhash/COPYING b/Utilities/cmlibrhash/COPYING new file mode 100644 index 0000000..bf65ee1 --- /dev/null +++ b/Utilities/cmlibrhash/COPYING @@ -0,0 +1,15 @@ + + RHash License + +Copyright (c) 2005-2014 Aleksey Kravchenko <rhash.admin@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so. + +The Software 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. Use this program at your own risk! diff --git a/Utilities/cmlibrhash/README b/Utilities/cmlibrhash/README new file mode 100644 index 0000000..4ea492f --- /dev/null +++ b/Utilities/cmlibrhash/README @@ -0,0 +1,7 @@ + === Notes on RHash License === + +The RHash program and LibRHash library are distributed under RHash License, +see the COPYING file for details. In particular, the program, the library +and source code can be used free of charge under the MIT, BSD, GPL, +commercial or freeware license without additional restrictions. In the case +the OSI-approved license is required the MIT license should be used. diff --git a/Utilities/cmlibrhash/librhash/algorithms.c b/Utilities/cmlibrhash/librhash/algorithms.c new file mode 100644 index 0000000..56d20b8 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/algorithms.c @@ -0,0 +1,220 @@ +/* algorithms.c - the algorithms supported by the rhash library + * + * Copyright: 2011-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include <stdio.h> +#include <assert.h> + +#include "byte_order.h" +#include "rhash.h" +#include "algorithms.h" + +/* header files of all supported hash sums */ +#if 0 +#include "aich.h" +#include "crc32.h" +#include "ed2k.h" +#include "edonr.h" +#include "gost.h" +#include "has160.h" +#include "md4.h" +#endif +#include "md5.h" +#if 0 +#include "ripemd-160.h" +#include "snefru.h" +#endif +#include "sha1.h" +#include "sha256.h" +#include "sha512.h" +#if 0 +#include "sha3.h" +#include "tiger.h" +#include "tth.h" +#include "whirlpool.h" +#endif + +#ifdef USE_OPENSSL +/* note: BTIH and AICH depends on the used SHA1 algorithm */ +# define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \ + RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \ + RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL) +#else +# define NEED_OPENSSL_INIT 0 +#endif /* USE_OPENSSL */ +#ifdef GENERATE_GOST_LOOKUP_TABLE +# define NEED_GOST_INIT (RHASH_GOST | RHASH_GOST_CRYPTOPRO) +#else +# define NEED_GOST_INIT 0 +#endif /* GENERATE_GOST_LOOKUP_TABLE */ +#ifdef GENERATE_CRC32_TABLE +# define NEED_CRC32_INIT RHASH_CRC32 +#else +# define NEED_CRC32_INIT 0 +#endif /* GENERATE_CRC32_TABLE */ + +#define RHASH_NEED_INIT_ALG (NEED_CRC32_INIT | NEED_GOST_INIT | NEED_OPENSSL_INIT) +unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG; + +rhash_hash_info* rhash_info_table = rhash_hash_info_default; +int rhash_info_size = RHASH_HASH_COUNT; + +#if 0 +static void rhash_crc32_init(uint32_t* crc32); +static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size); +static void rhash_crc32_final(uint32_t* crc32, unsigned char* result); +#endif + +#if 0 +rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" }; +rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" }; +#endif +rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" }; +rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" }; +#if 0 +rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" }; +rhash_info info_tth = { RHASH_TTH, F_BS32, 24, "TTH", "tree:tiger" }; +rhash_info info_btih = { RHASH_BTIH, 0, 20, "BTIH", "btih" }; +rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" }; +rhash_info info_aich = { RHASH_AICH, F_BS32, 20, "AICH", "aich" }; +rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" }; +rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" }; +rhash_info info_gost = { RHASH_GOST, F_LE32, 32, "GOST", "gost" }; +rhash_info info_gostpro = { RHASH_GOST_CRYPTOPRO, F_LE32, 32, "GOST-CRYPTOPRO", "gost-cryptopro" }; +rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" }; +rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" }; +rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" }; +#endif +rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" }; +rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" }; +rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" }; +rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" }; +#if 0 +rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" }; +rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" }; +rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" }; +rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" }; +rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" }; +rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" }; +#endif + +/* some helper macros */ +#define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0) +#define dgshft2(name, field) (((char*)&((name##_ctx*)0)->field) - (char*)0) +#define ini(name) ((pinit_t)(name##_init)) +#define upd(name) ((pupdate_t)(name##_update)) +#define fin(name) ((pfinal_t)(name##_final)) +#define iuf(name) ini(name), upd(name), fin(name) +#define diuf(name) dgshft(name), ini(name), upd(name), fin(name) + +/* information about all hashes */ +rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] = +{ +#if 0 + { &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */ + { &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */ +#endif + { &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */ + { &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */ +#if 0 + { &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */ + { &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */ + { &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */ + { &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */ + { &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */ + { &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */ + { &info_gost, sizeof(gost_ctx), dgshft(gost), iuf(rhash_gost), 0 }, /* 256 bit */ + { &info_gostpro, sizeof(gost_ctx), dgshft(gost), ini(rhash_gost_cryptopro), upd(rhash_gost), fin(rhash_gost), 0 }, /* 256 bit */ + { &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */ + { &info_snf128, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru128), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 128 bit */ + { &info_snf256, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru256), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 256 bit */ +#endif + { &info_sha224, sizeof(sha256_ctx), dgshft(sha256), ini(rhash_sha224), upd(rhash_sha256), fin(rhash_sha256), 0 }, /* 224 bit */ + { &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */ + { &info_sha384, sizeof(sha512_ctx), dgshft(sha512), ini(rhash_sha384), upd(rhash_sha512), fin(rhash_sha512), 0 }, /* 384 bit */ + { &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */ +#if 0 + { &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */ + { &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */ + { &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_224), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 224 bit */ + { &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_256), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 256 bit */ + { &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_384), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 384 bit */ + { &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_512), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 512 bit */ +#endif +}; + +/** + * Initialize requested algorithms. + */ +void rhash_init_algorithms(unsigned mask) +{ + (void)mask; /* unused now */ + + /* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */ + assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1))); + +#ifdef GENERATE_CRC32_TABLE + rhash_crc32_init_table(); +#endif +#ifdef GENERATE_GOST_LOOKUP_TABLE + rhash_gost_init_table(); +#endif + rhash_uninitialized_algorithms = 0; +} + +#if 0 +/* CRC32 helper functions */ + +/** + * Initialize crc32 hash. + * + * @param crc32 pointer to the hash to initialize + */ +static void rhash_crc32_init(uint32_t* crc32) +{ + *crc32 = 0; /* note: context size is sizeof(uint32_t) */ +} + +/** + * Calculate message CRC32 hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param crc32 pointer to the hash + * @param msg message chunk + * @param size length of the message chunk + */ +static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size) +{ + *crc32 = rhash_get_crc32(*crc32, msg, size); +} + +/** + * Store calculated hash into the given array. + * + * @param crc32 pointer to the current hash value + * @param result calculated hash in binary form + */ +static void rhash_crc32_final(uint32_t* crc32, unsigned char* result) +{ +#if defined(CPU_IA32) || defined(CPU_X64) + /* intel CPUs support assigment with non 32-bit aligned pointers */ + *(unsigned*)result = be2me_32(*crc32); +#else + /* correct saving BigEndian integer on all archs */ + result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16); + result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32); +#endif +} +#endif diff --git a/Utilities/cmlibrhash/librhash/algorithms.h b/Utilities/cmlibrhash/librhash/algorithms.h new file mode 100644 index 0000000..4db2517 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/algorithms.h @@ -0,0 +1,120 @@ +/* algorithms.h - rhash library algorithms */ +#ifndef RHASH_ALGORITHMS_H +#define RHASH_ALGORITHMS_H + +#include <stddef.h> /* for ptrdiff_t */ +#include "rhash.h" +#include "byte_order.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef RHASH_API +/* modifier for RHash library functions */ +# define RHASH_API +#endif + +typedef void (*pinit_t)(void*); +typedef void (*pupdate_t)(void *ctx, const void* msg, size_t size); +typedef void (*pfinal_t)(void*, unsigned char*); +typedef void (*pcleanup_t)(void*); + +/** + * Information about a hash function + */ +typedef struct rhash_hash_info +{ + rhash_info *info; + size_t context_size; + ptrdiff_t digest_diff; + pinit_t init; + pupdate_t update; + pfinal_t final; + pcleanup_t cleanup; +} rhash_hash_info; + +/** + * Information on a hash function and its context + */ +typedef struct rhash_vector_item +{ + struct rhash_hash_info* hash_info; + void *context; +} rhash_vector_item; + +/** + * The rhash context containing contexts for several hash functions + */ +typedef struct rhash_context_ext +{ + struct rhash_context rc; + unsigned hash_vector_size; /* number of contained hash sums */ + unsigned flags; + unsigned state; + void *callback, *callback_data; + void *bt_ctx; + rhash_vector_item vector[1]; /* contexts of contained hash sums */ +} rhash_context_ext; + +extern rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT]; +extern rhash_hash_info* rhash_info_table; +extern int rhash_info_size; +extern unsigned rhash_uninitialized_algorithms; + +extern rhash_info info_crc32; +extern rhash_info info_md4; +extern rhash_info info_md5; +extern rhash_info info_sha1; +extern rhash_info info_tiger; +extern rhash_info info_tth ; +extern rhash_info info_btih; +extern rhash_info info_ed2k; +extern rhash_info info_aich; +extern rhash_info info_whirlpool; +extern rhash_info info_rmd160; +extern rhash_info info_gost; +extern rhash_info info_gostpro; +extern rhash_info info_has160; +extern rhash_info info_snf128; +extern rhash_info info_snf256; +extern rhash_info info_sha224; +extern rhash_info info_sha256; +extern rhash_info info_sha384; +extern rhash_info info_sha512; +extern rhash_info info_sha3_224; +extern rhash_info info_sha3_256; +extern rhash_info info_sha3_384; +extern rhash_info info_sha3_512; +extern rhash_info info_edr256; +extern rhash_info info_edr512; + +/* rhash_info flags */ +#define F_BS32 1 /* default output in base32 */ +#define F_SWAP32 2 /* Big endian flag */ +#define F_SWAP64 4 + +/* define endianness flags */ +#ifndef CPU_BIG_ENDIAN +#define F_LE32 0 +#define F_LE64 0 +#define F_BE32 F_SWAP32 +#define F_BE64 F_SWAP64 +#else +#define F_LE32 F_SWAP32 +#define F_LE64 F_SWAP64 +#define F_BE32 0 +#define F_BE64 0 +#endif + +void rhash_init_algorithms(unsigned mask); + +#if defined(OPENSSL_RUNTIME) && !defined(USE_OPENSSL) +# define USE_OPENSSL +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* RHASH_ALGORITHMS_H */ diff --git a/Utilities/cmlibrhash/librhash/byte_order.c b/Utilities/cmlibrhash/librhash/byte_order.c new file mode 100644 index 0000000..8ce6fc8 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/byte_order.c @@ -0,0 +1,150 @@ +/* byte_order.c - byte order related platform dependent routines, + * + * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ +#include "byte_order.h" + +#if !(__GNUC__ >= 4 || (__GNUC__ ==3 && __GNUC_MINOR__ >= 4)) /* if !GCC or GCC < 4.3 */ + +# if _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) /* if MSVC++ >= 2002 on x86/x64 */ +# include <intrin.h> +# pragma intrinsic(_BitScanForward) + +/** + * Returns index of the trailing bit of x. + * + * @param x the number to process + * @return zero-based index of the trailing bit + */ +unsigned rhash_ctz(unsigned x) +{ + unsigned long index; + unsigned char isNonzero = _BitScanForward(&index, x); /* MSVC intrinsic */ + return (isNonzero ? (unsigned)index : 0); +} +# else /* _MSC_VER >= 1300... */ + +/** + * Returns index of the trailing bit of a 32-bit number. + * This is a plain C equivalent for GCC __builtin_ctz() bit scan. + * + * @param x the number to process + * @return zero-based index of the trailing bit + */ +unsigned rhash_ctz(unsigned x) +{ + /* array for conversion to bit position */ + static unsigned char bit_pos[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + /* The De Bruijn bit-scan was devised in 1997, according to Donald Knuth + * by Martin Lauter. The constant 0x077CB531UL is a De Bruijn sequence, + * which produces a unique pattern of bits into the high 5 bits for each + * possible bit position that it is multiplied against. + * See http://graphics.stanford.edu/~seander/bithacks.html + * and http://chessprogramming.wikispaces.com/BitScan */ + return (unsigned)bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; +} +# endif /* _MSC_VER >= 1300... */ +#endif /* !(GCC >= 4.3) */ + +/** + * Copy a memory block with simultaneous exchanging byte order. + * The byte order is changed from little-endian 32-bit integers + * to big-endian (or vice-versa). + * + * @param to the pointer where to copy memory block + * @param index the index to start writing from + * @param from the source block to copy + * @param length length of the memory block + */ +void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length) +{ + /* if all pointers and length are 32-bits aligned */ + if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 3) ) { + /* copy memory as 32-bit words */ + const uint32_t* src = (const uint32_t*)from; + const uint32_t* end = (const uint32_t*)((const char*)src + length); + uint32_t* dst = (uint32_t*)((char*)to + index); + while (src < end) *(dst++) = bswap_32( *(src++) ); + } else { + const char* src = (const char*)from; + for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 3] = *(src++); + } +} + +/** + * Copy a memory block with changed byte order. + * The byte order is changed from little-endian 64-bit integers + * to big-endian (or vice-versa). + * + * @param to the pointer where to copy memory block + * @param index the index to start writing from + * @param from the source block to copy + * @param length length of the memory block + */ +void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length) +{ + /* if all pointers and length are 64-bits aligned */ + if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 7) ) { + /* copy aligned memory block as 64-bit integers */ + const uint64_t* src = (const uint64_t*)from; + const uint64_t* end = (const uint64_t*)((const char*)src + length); + uint64_t* dst = (uint64_t*)((char*)to + index); + while (src < end) *(dst++) = bswap_64( *(src++) ); + } else { + const char* src = (const char*)from; + for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 7] = *(src++); + } +} + +/** + * Copy data from a sequence of 64-bit words to a binary string of given length, + * while changing byte order. + * + * @param to the binary string to receive data + * @param from the source sequence of 64-bit words + * @param length the size in bytes of the data being copied + */ +void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length) +{ + /* if all pointers and length are 64-bits aligned */ + if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | length ) & 7) ) { + /* copy aligned memory block as 64-bit integers */ + const uint64_t* src = (const uint64_t*)from; + const uint64_t* end = (const uint64_t*)((const char*)src + length); + uint64_t* dst = (uint64_t*)to; + while (src < end) *(dst++) = bswap_64( *(src++) ); + } else { + size_t index; + char* dst = (char*)to; + for (index = 0; index < length; index++) *(dst++) = ((char*)from)[index ^ 7]; + } +} + +/** + * Exchange byte order in the given array of 32-bit integers. + * + * @param arr the array to process + * @param length array length + */ +void rhash_u32_mem_swap(unsigned *arr, int length) +{ + unsigned* end = arr + length; + for (; arr < end; arr++) { + *arr = bswap_32(*arr); + } +} diff --git a/Utilities/cmlibrhash/librhash/byte_order.h b/Utilities/cmlibrhash/librhash/byte_order.h new file mode 100644 index 0000000..d34a020 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/byte_order.h @@ -0,0 +1,156 @@ +/* byte_order.h */ +#ifndef BYTE_ORDER_H +#define BYTE_ORDER_H +#include "ustd.h" +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* if x86 compatible cpu */ +#if defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(__pentium__) || \ + defined(__pentiumpro__) || defined(__pentium4__) || \ + defined(__nocona__) || defined(prescott) || defined(__core2__) || \ + defined(__k6__) || defined(__k8__) || defined(__athlon__) || \ + defined(__amd64) || defined(__amd64__) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \ + defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64) +/* detect if x86-64 instruction set is supported */ +# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \ + defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +# define CPU_X64 +# else +# define CPU_IA32 +# endif +#endif + + +/* detect CPU endianness */ +#include <cm_kwiml.h> +#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE +# define CPU_LITTLE_ENDIAN +# define IS_BIG_ENDIAN 0 +# define IS_LITTLE_ENDIAN 1 +#elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_BIG +# define CPU_BIG_ENDIAN +# define IS_BIG_ENDIAN 1 +# define IS_LITTLE_ENDIAN 0 +#else +# error "Can't detect CPU architechture" +#endif + +#define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0))) +#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) + +#if defined(_MSC_VER) +#define ALIGN_ATTR(n) __declspec(align(n)) +#elif defined(__GNUC__) +#define ALIGN_ATTR(n) __attribute__((aligned (n))) +#else +#define ALIGN_ATTR(n) /* nothing */ +#endif + + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define I64(x) x##ui64 +#else +#define I64(x) x##LL +#endif + +/* convert a hash flag to index */ +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */ +# define rhash_ctz(x) __builtin_ctz(x) +#else +unsigned rhash_ctz(unsigned); /* define as function */ +#endif + +void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length); +void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length); +void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length); +void rhash_u32_mem_swap(unsigned *p, int length_in_u32); + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* define bswap_32 */ +#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__) +/* for intel x86 CPU */ +static inline uint32_t bswap_32(uint32_t x) { + __asm("bswap\t%0" : "=r" (x) : "0" (x)); + return x; +} +#elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) +/* for GCC >= 4.3 */ +# define bswap_32(x) __builtin_bswap32(x) +#elif defined(__clang__) && __has_builtin(__builtin_bswap32) +# define bswap_32(x) __builtin_bswap32(x) +#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ +# define bswap_32(x) _byteswap_ulong((unsigned long)x) +#else +/* general bswap_32 definition */ +static uint32_t bswap_32(uint32_t x) { + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); + return (x >> 16) | (x << 16); +} +#endif /* bswap_32 */ + +#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) +# define bswap_64(x) __builtin_bswap64(x) +#elif defined(__clang__) && __has_builtin(__builtin_bswap64) +# define bswap_64(x) __builtin_bswap64(x) +#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ +# define bswap_64(x) _byteswap_uint64((__int64)x) +#else +static uint64_t bswap_64(uint64_t x) { + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32(w.l[1]); + r.l[1] = bswap_32(w.l[0]); + return r.ll; +} +#endif + +#ifdef CPU_BIG_ENDIAN +# define be2me_32(x) (x) +# define be2me_64(x) (x) +# define le2me_32(x) bswap_32(x) +# define le2me_64(x) bswap_64(x) + +# define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) +# define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) +# define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) +# define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) +# define me64_to_be_str(to, from, length) memcpy((to), (from), (length)) +# define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) + +#else /* CPU_BIG_ENDIAN */ +# define be2me_32(x) bswap_32(x) +# define be2me_64(x) bswap_64(x) +# define le2me_32(x) (x) +# define le2me_64(x) (x) + +# define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) +# define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) +# define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) +# define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) +# define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) +# define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) +#endif /* CPU_BIG_ENDIAN */ + +/* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */ +#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n)))) +#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n)))) +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n)))) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* BYTE_ORDER_H */ diff --git a/Utilities/cmlibrhash/librhash/hex.c b/Utilities/cmlibrhash/librhash/hex.c new file mode 100644 index 0000000..c941149 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/hex.c @@ -0,0 +1,188 @@ +/* hex.c - conversion for hexadecimal and base32 strings. + * + * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ +#include <string.h> +#include <ctype.h> +#include "hex.h" + +/** +* Convert a byte to a hexadecimal number. The result, consisting of two +* hexadecimal digits is stored into a buffer. + * + * @param dest the buffer to receive two symbols of hex representation + * @param byte the byte to decode + * @param upper_case flag to print string in uppercase + * @return pointer to the chararcter just after the written number (dest + 2) + */ +char* rhash_print_hex_byte(char *dest, const unsigned char byte, int upper_case) +{ + const char add = (upper_case ? 'A' - 10 : 'a' - 10); + unsigned char c = (byte >> 4) & 15; + *dest++ = (c > 9 ? c + add : c + '0'); + c = byte & 15; + *dest++ = (c > 9 ? c + add : c + '0'); + return dest; +} + +/** + * Store hexadecimal representation of a binary string to given buffer. + * + * @param dest the buffer to receive hexadecimal representation + * @param src binary string + * @param len string length + * @param upper_case flag to print string in uppercase + */ +void rhash_byte_to_hex(char *dest, const unsigned char *src, unsigned len, int upper_case) +{ + while (len-- > 0) { + dest = rhash_print_hex_byte(dest, *src++, upper_case); + } + *dest = '\0'; +} + +/** + * Encode a binary string to base32. + * + * @param dest the buffer to store result + * @param src binary string + * @param len string length + * @param upper_case flag to print string in uppercase + */ +void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, int upper_case) +{ + const char a = (upper_case ? 'A' : 'a'); + unsigned shift = 0; + unsigned char word; + const unsigned char* e = src + len; + while (src < e) { + if (shift > 3) { + word = (*src & (0xFF >> shift)); + shift = (shift + 5) % 8; + word <<= shift; + if (src + 1 < e) + word |= *(src + 1) >> (8 - shift); + ++src; + } else { + shift = (shift + 5) % 8; + word = ( *src >> ( (8 - shift) & 7 ) ) & 0x1F; + if (shift == 0) src++; + } + *dest++ = ( word < 26 ? word + a : word + '2' - 26 ); + } + *dest = '\0'; +} + +/** + * Encode a binary string to base64. + * Encoded output length is always a multiple of 4 bytes. + * + * @param dest the buffer to store result + * @param src binary string + * @param len string length + */ +void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len) +{ + static const char* tail = "0123456789+/"; + unsigned shift = 0; + unsigned char word; + const unsigned char* e = src + len; + while (src < e) { + if (shift > 2) { + word = (*src & (0xFF >> shift)); + shift = (shift + 6) % 8; + word <<= shift; + if (src + 1 < e) + word |= *(src + 1) >> (8 - shift); + ++src; + } else { + shift = (shift + 6) % 8; + word = ( *src >> ( (8 - shift) & 7 ) ) & 0x3F; + if (shift == 0) src++; + } + *dest++ = ( word < 52 ? (word < 26 ? word + 'A' : word - 26 + 'a') : tail[word - 52]); + } + if (shift > 0) { + *dest++ = '='; + if (shift == 4) *dest++ = '='; + } + *dest = '\0'; +} + +/* unsafe characters are "<>{}[]%#/|\^~`@:;?=&+ */ +#define IS_GOOD_URL_CHAR(c) (isalnum((unsigned char)c) || strchr("$-_.!'(),", c)) + +/** + * URL-encode a string. + * + * @param dst buffer to receive result or NULL to calculate + * the lengths of encoded string + * @param filename the file name + * @return the length of the result string + */ +int rhash_urlencode(char *dst, const char *name) +{ + const char *start; + if (!dst) { + int len; + for (len = 0; *name; name++) len += (IS_GOOD_URL_CHAR(*name) ? 1 : 3); + return len; + } + /* encode URL as specified by RFC 1738 */ + for (start = dst; *name; name++) { + if ( IS_GOOD_URL_CHAR(*name) ) { + *dst++ = *name; + } else { + *dst++ = '%'; + dst = rhash_print_hex_byte(dst, *name, 'A'); + } + } + *dst = 0; + return (int)(dst - start); +} + +/** + * Print 64-bit number with trailing '\0' to a string buffer. + * if dst is NULL, then just return the length of the number. + * + * @param dst output buffer + * @param number the number to print + * @return length of the printed number (without trailing '\0') + */ +int rhash_sprintI64(char *dst, uint64_t number) +{ + /* The biggest number has 20 digits: 2^64 = 18 446 744 073 709 551 616 */ + char buf[24], *p; + size_t length; + + if (dst == NULL) { + /* just calculate the length of the number */ + if (number == 0) return 1; + for (length = 0; number != 0; number /= 10) length++; + return (int)length; + } + + p = buf + 23; + *p = '\0'; /* last symbol should be '\0' */ + if (number == 0) { + *(--p) = '0'; + } else { + for (; p >= buf && number != 0; number /= 10) { + *(--p) = '0' + (char)(number % 10); + } + } + length = buf + 23 - p; + memcpy(dst, p, length + 1); + return (int)length; +} diff --git a/Utilities/cmlibrhash/librhash/hex.h b/Utilities/cmlibrhash/librhash/hex.h new file mode 100644 index 0000000..2b365e2 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/hex.h @@ -0,0 +1,25 @@ +/* hex.h - conversion for hexadecimal and base32 strings. */ +#ifndef HEX_H +#define HEX_H + +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void rhash_byte_to_hex(char *dest, const unsigned char *src, unsigned len, int upper_case); +void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, int upper_case); +void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len); +char* rhash_print_hex_byte(char *dest, const unsigned char byte, int upper_case); +int rhash_urlencode(char *dst, const char *name); +int rhash_sprintI64(char *dst, uint64_t number); + +#define BASE32_LENGTH(bytes) (((bytes) * 8 + 4) / 5) +#define BASE64_LENGTH(bytes) ((((bytes) + 2) / 3) * 4) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* HEX_H */ diff --git a/Utilities/cmlibrhash/librhash/md5.c b/Utilities/cmlibrhash/librhash/md5.c new file mode 100644 index 0000000..b20de45 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/md5.c @@ -0,0 +1,236 @@ +/* md5.c - an implementation of the MD5 algorithm, based on RFC 1321. + * + * Copyright: 2007-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include <string.h> +#include "byte_order.h" +#include "md5.h" + +/** + * Initialize context before calculaing hash. + * + * @param ctx context to initialize + */ +void rhash_md5_init(md5_ctx *ctx) +{ + ctx->length = 0; + + /* initialize state */ + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; +} + +/* First, define four auxiliary functions that each take as input + * three 32-bit words and returns a 32-bit word.*/ + +/* F(x,y,z) = ((y XOR z) AND x) XOR z - is faster then original version */ +#define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z)) +#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) + +/* transformations for rounds 1, 2, 3, and 4. */ +#define MD5_ROUND1(a, b, c, d, x, s, ac) { \ + (a) += MD5_F((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} +#define MD5_ROUND2(a, b, c, d, x, s, ac) { \ + (a) += MD5_G((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} +#define MD5_ROUND3(a, b, c, d, x, s, ac) { \ + (a) += MD5_H((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} +#define MD5_ROUND4(a, b, c, d, x, s, ac) { \ + (a) += MD5_I((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} + +/** + * The core transformation. Process a 512-bit block. + * The function has been taken from RFC 1321 with little changes. + * + * @param state algorithm state + * @param x the message block to process + */ +static void rhash_md5_process_block(unsigned state[4], const unsigned* x) +{ + register unsigned a, b, c, d; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + MD5_ROUND1(a, b, c, d, x[ 0], 7, 0xd76aa478); + MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756); + MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db); + MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee); + MD5_ROUND1(a, b, c, d, x[ 4], 7, 0xf57c0faf); + MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a); + MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613); + MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501); + MD5_ROUND1(a, b, c, d, x[ 8], 7, 0x698098d8); + MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af); + MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1); + MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be); + MD5_ROUND1(a, b, c, d, x[12], 7, 0x6b901122); + MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193); + MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e); + MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821); + + MD5_ROUND2(a, b, c, d, x[ 1], 5, 0xf61e2562); + MD5_ROUND2(d, a, b, c, x[ 6], 9, 0xc040b340); + MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51); + MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); + MD5_ROUND2(a, b, c, d, x[ 5], 5, 0xd62f105d); + MD5_ROUND2(d, a, b, c, x[10], 9, 0x2441453); + MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681); + MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); + MD5_ROUND2(a, b, c, d, x[ 9], 5, 0x21e1cde6); + MD5_ROUND2(d, a, b, c, x[14], 9, 0xc33707d6); + MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87); + MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed); + MD5_ROUND2(a, b, c, d, x[13], 5, 0xa9e3e905); + MD5_ROUND2(d, a, b, c, x[ 2], 9, 0xfcefa3f8); + MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9); + MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + MD5_ROUND3(a, b, c, d, x[ 5], 4, 0xfffa3942); + MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681); + MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122); + MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c); + MD5_ROUND3(a, b, c, d, x[ 1], 4, 0xa4beea44); + MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9); + MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60); + MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70); + MD5_ROUND3(a, b, c, d, x[13], 4, 0x289b7ec6); + MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa); + MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085); + MD5_ROUND3(b, c, d, a, x[ 6], 23, 0x4881d05); + MD5_ROUND3(a, b, c, d, x[ 9], 4, 0xd9d4d039); + MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5); + MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8); + MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665); + + MD5_ROUND4(a, b, c, d, x[ 0], 6, 0xf4292244); + MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97); + MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7); + MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039); + MD5_ROUND4(a, b, c, d, x[12], 6, 0x655b59c3); + MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92); + MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d); + MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1); + MD5_ROUND4(a, b, c, d, x[ 8], 6, 0x6fa87e4f); + MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314); + MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1); + MD5_ROUND4(a, b, c, d, x[ 4], 6, 0xf7537e82); + MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235); + MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); + MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void rhash_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size) +{ + unsigned index = (unsigned)ctx->length & 63; + ctx->length += size; + + /* fill partial block */ + if (index) { + unsigned left = md5_block_size - index; + le32_copy((char*)ctx->message, index, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + rhash_md5_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + while (size >= md5_block_size) { + unsigned* aligned_message_block; + if (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) { + /* the most common case is processing a 32-bit aligned message + on a little-endian CPU without copying it */ + aligned_message_block = (unsigned*)msg; + } else { + le32_copy(ctx->message, 0, msg, md5_block_size); + aligned_message_block = ctx->message; + } + + rhash_md5_process_block(ctx->hash, aligned_message_block); + msg += md5_block_size; + size -= md5_block_size; + } + if (size) { + /* save leftovers */ + le32_copy(ctx->message, 0, msg, size); + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void rhash_md5_final(md5_ctx *ctx, unsigned char* result) +{ + unsigned index = ((unsigned)ctx->length & 63) >> 2; + unsigned shift = ((unsigned)ctx->length & 3) * 8; + + /* pad message and run for last block */ + + /* append the byte 0x80 to the message */ + ctx->message[index] &= ~(0xFFFFFFFFu << shift); + ctx->message[index++] ^= 0x80u << shift; + + /* if no room left in the message to store 64-bit message length */ + if (index > 14) { + /* then fill the rest with zeros and process it */ + while (index < 16) { + ctx->message[index++] = 0; + } + rhash_md5_process_block(ctx->hash, ctx->message); + index = 0; + } + while (index < 14) { + ctx->message[index++] = 0; + } + ctx->message[14] = (unsigned)(ctx->length << 3); + ctx->message[15] = (unsigned)(ctx->length >> 29); + rhash_md5_process_block(ctx->hash, ctx->message); + + if (result) le32_copy(result, 0, &ctx->hash, 16); +} diff --git a/Utilities/cmlibrhash/librhash/md5.h b/Utilities/cmlibrhash/librhash/md5.h new file mode 100644 index 0000000..1af6f13 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/md5.h @@ -0,0 +1,31 @@ +/* md5.h */ +#ifndef MD5_HIDER +#define MD5_HIDER +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define md5_block_size 64 +#define md5_hash_size 16 + +/* algorithm context */ +typedef struct md5_ctx +{ + unsigned message[md5_block_size / 4]; /* 512-bit buffer for leftovers */ + uint64_t length; /* number of processed bytes */ + unsigned hash[4]; /* 128-bit algorithm internal hashing state */ +} md5_ctx; + +/* hash functions */ + +void rhash_md5_init(md5_ctx *ctx); +void rhash_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size); +void rhash_md5_final(md5_ctx *ctx, unsigned char result[16]); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MD5_HIDER */ diff --git a/Utilities/cmlibrhash/librhash/rhash.c b/Utilities/cmlibrhash/librhash/rhash.c new file mode 100644 index 0000000..ad6249b --- /dev/null +++ b/Utilities/cmlibrhash/librhash/rhash.c @@ -0,0 +1,872 @@ +/* rhash.c - implementation of LibRHash library calls + * + * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +/* macros for large file support, must be defined before any include file */ +#define _LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include <string.h> /* memset() */ +#include <stdlib.h> /* free() */ +#include <stddef.h> /* ptrdiff_t */ +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +/* modifier for Windows DLL */ +#if defined(_WIN32) && defined(RHASH_EXPORTS) +# define RHASH_API __declspec(dllexport) +#endif + +#include "byte_order.h" +#include "algorithms.h" +#include "util.h" +#include "hex.h" +#include "rhash.h" /* RHash library interface */ + +#define STATE_ACTIVE 0xb01dbabe +#define STATE_STOPED 0xdeadbeef +#define STATE_DELETED 0xdecea5ed +#define RCTX_AUTO_FINAL 0x1 +#define RCTX_FINALIZED 0x2 +#define RCTX_FINALIZED_MASK (RCTX_AUTO_FINAL | RCTX_FINALIZED) +#define RHPR_FORMAT (RHPR_RAW | RHPR_HEX | RHPR_BASE32 | RHPR_BASE64) +#define RHPR_MODIFIER (RHPR_UPPERCASE | RHPR_REVERSE) + +/** + * Initialize static data of rhash algorithms + */ +void rhash_library_init(void) +{ + rhash_init_algorithms(RHASH_ALL_HASHES); +#ifdef USE_OPENSSL + rhash_plug_openssl(); +#endif +} + +/** + * Returns the number of supported hash algorithms. + * + * @return the number of supported hash functions + */ +int RHASH_API rhash_count(void) +{ + return rhash_info_size; +} + +/* Lo-level rhash library functions */ + +/** + * Allocate and initialize RHash context for calculating hash(es). + * After initializing rhash_update()/rhash_final() functions should be used. + * Then the context must be freed by calling rhash_free(). + * + * @param hash_id union of bit flags, containing ids of hashes to calculate. + * @return initialized rhash context, NULL on error and errno is set + */ +RHASH_API rhash rhash_init(unsigned hash_id) +{ + unsigned tail_bit_index; /* index of hash_id trailing bit */ + unsigned num = 0; /* number of hashes to compute */ + rhash_context_ext *rctx = NULL; /* allocated rhash context */ + size_t hash_size_sum = 0; /* size of hash contexts to store in rctx */ + + unsigned i, bit_index, id; + struct rhash_hash_info* info; + size_t aligned_size; + char* phash_ctx; + + hash_id &= RHASH_ALL_HASHES; + if (hash_id == 0) { + errno = EINVAL; + return NULL; + } + + tail_bit_index = rhash_ctz(hash_id); /* get trailing bit index */ + assert(tail_bit_index < RHASH_HASH_COUNT); + + id = 1 << tail_bit_index; + + if (hash_id == id) { + /* handle the most common case of only one hash */ + num = 1; + info = &rhash_info_table[tail_bit_index]; + hash_size_sum = info->context_size; + } else { + /* another case: hash_id contains several hashes */ + for (bit_index = tail_bit_index; id <= hash_id; bit_index++, id = id << 1) { + assert(id != 0); + assert(bit_index < RHASH_HASH_COUNT); + info = &rhash_info_table[bit_index]; + if (hash_id & id) { + /* align sizes by 8 bytes */ + aligned_size = (info->context_size + 7) & ~7; + hash_size_sum += aligned_size; + num++; + } + } + assert(num > 1); + } + + /* align the size of the rhash context common part */ + aligned_size = (offsetof(rhash_context_ext, vector[num]) + 7) & ~7; + assert(aligned_size >= sizeof(rhash_context_ext)); + + /* allocate rhash context with enough memory to store contexts of all used hashes */ + rctx = (rhash_context_ext*)malloc(aligned_size + hash_size_sum); + if (rctx == NULL) return NULL; + + /* initialize common fields of the rhash context */ + memset(rctx, 0, sizeof(rhash_context_ext)); + rctx->rc.hash_id = hash_id; + rctx->flags = RCTX_AUTO_FINAL; /* turn on auto-final by default */ + rctx->state = STATE_ACTIVE; + rctx->hash_vector_size = num; + + /* aligned hash contexts follows rctx->vector[num] in the same memory block */ + phash_ctx = (char*)rctx + aligned_size; + assert(phash_ctx >= (char*)&rctx->vector[num]); + + /* initialize context for every hash in a loop */ + for (bit_index = tail_bit_index, id = 1 << tail_bit_index, i = 0; + id <= hash_id; bit_index++, id = id << 1) + { + /* check if a hash function with given id shall be included into rctx */ + if ((hash_id & id) != 0) { + info = &rhash_info_table[bit_index]; + assert(info->context_size > 0); + assert(((phash_ctx - (char*)0) & 7) == 0); /* hash context is aligned */ + assert(info->init != NULL); + + rctx->vector[i].hash_info = info; + rctx->vector[i].context = phash_ctx; + +#if 0 + /* BTIH initialization is complex, save pointer for later */ + if ((id & RHASH_BTIH) != 0) rctx->bt_ctx = phash_ctx; +#endif + phash_ctx += (info->context_size + 7) & ~7; + + /* initialize the i-th hash context */ + info->init(rctx->vector[i].context); + i++; + } + } + + return &rctx->rc; /* return allocated and initialized rhash context */ +} + +/** + * Free RHash context memory. + * + * @param ctx the context to free. + */ +void rhash_free(rhash ctx) +{ + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + unsigned i; + + if (ctx == 0) return; + assert(ectx->hash_vector_size <= RHASH_HASH_COUNT); + ectx->state = STATE_DELETED; /* mark memory block as being removed */ + + /* clean the hash functions, which require additional clean up */ + for (i = 0; i < ectx->hash_vector_size; i++) { + struct rhash_hash_info* info = ectx->vector[i].hash_info; + if (info->cleanup != 0) { + info->cleanup(ectx->vector[i].context); + } + } + + free(ectx); +} + +/** + * Re-initialize RHash context to reuse it. + * Useful to speed up processing of many small messages. + * + * @param ctx context to reinitialize + */ +RHASH_API void rhash_reset(rhash ctx) +{ + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + unsigned i; + + assert(ectx->hash_vector_size > 0); + assert(ectx->hash_vector_size <= RHASH_HASH_COUNT); + ectx->state = STATE_ACTIVE; /* re-activate the structure */ + + /* re-initialize every hash in a loop */ + for (i = 0; i < ectx->hash_vector_size; i++) { + struct rhash_hash_info* info = ectx->vector[i].hash_info; + if (info->cleanup != 0) { + info->cleanup(ectx->vector[i].context); + } + + assert(info->init != NULL); + info->init(ectx->vector[i].context); + } + ectx->flags &= ~RCTX_FINALIZED; /* clear finalized state */ +} + +/** + * Calculate hashes of message. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the rhash context + * @param message message chunk + * @param length length of the message chunk + * @return 0 on success; On fail return -1 and set errno + */ +RHASH_API int rhash_update(rhash ctx, const void* message, size_t length) +{ + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + unsigned i; + + assert(ectx->hash_vector_size <= RHASH_HASH_COUNT); + if (ectx->state != STATE_ACTIVE) return 0; /* do nothing if canceled */ + + ctx->msg_size += length; + + /* call update method for every algorithm */ + for (i = 0; i < ectx->hash_vector_size; i++) { + struct rhash_hash_info* info = ectx->vector[i].hash_info; + assert(info->update != 0); + info->update(ectx->vector[i].context, message, length); + } + return 0; /* no error processing at the moment */ +} + +/** + * Finalize hash calculation and optionally store the first hash. + * + * @param ctx the rhash context + * @param first_result optional buffer to store a calculated hash with the lowest available id + * @return 0 on success; On fail return -1 and set errno + */ +RHASH_API int rhash_final(rhash ctx, unsigned char* first_result) +{ + unsigned i = 0; + unsigned char buffer[130]; + unsigned char* out = (first_result ? first_result : buffer); + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + assert(ectx->hash_vector_size <= RHASH_HASH_COUNT); + + /* skip final call if already finalized and auto-final is on */ + if ((ectx->flags & RCTX_FINALIZED_MASK) == + (RCTX_AUTO_FINAL | RCTX_FINALIZED)) return 0; + + /* call final method for every algorithm */ + for (i = 0; i < ectx->hash_vector_size; i++) { + struct rhash_hash_info* info = ectx->vector[i].hash_info; + assert(info->final != 0); + assert(info->info->digest_size < sizeof(buffer)); + info->final(ectx->vector[i].context, out); + out = buffer; + } + ectx->flags |= RCTX_FINALIZED; + return 0; /* no error processing at the moment */ +} + +/** + * Store digest for given hash_id. + * If hash_id is zero, function stores digest for a hash with the lowest id found in the context. + * For nonzero hash_id the context must contain it, otherwise function silently does nothing. + * + * @param ctx rhash context + * @param hash_id id of hash to retrieve or zero for hash with the lowest available id + * @param result buffer to put the hash into + */ +static void rhash_put_digest(rhash ctx, unsigned hash_id, unsigned char* result) +{ + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + unsigned i; + rhash_vector_item *item; + struct rhash_hash_info* info; + unsigned char* digest; + + assert(ectx); + assert(ectx->hash_vector_size > 0 && ectx->hash_vector_size <= RHASH_HASH_COUNT); + + /* finalize context if not yet finalized and auto-final is on */ + if ((ectx->flags & RCTX_FINALIZED_MASK) == RCTX_AUTO_FINAL) { + rhash_final(ctx, NULL); + } + + if (hash_id == 0) { + item = &ectx->vector[0]; /* get the first hash */ + info = item->hash_info; + } else { + for (i = 0;; i++) { + if (i >= ectx->hash_vector_size) { + return; /* hash_id not found, do nothing */ + } + item = &ectx->vector[i]; + info = item->hash_info; + if (info->info->hash_id == hash_id) break; + } + } + digest = ((unsigned char*)item->context + info->digest_diff); + if (info->info->flags & F_SWAP32) { + assert((info->info->digest_size & 3) == 0); + /* NB: the next call is correct only for multiple of 4 byte size */ + rhash_swap_copy_str_to_u32(result, 0, digest, info->info->digest_size); + } else if (info->info->flags & F_SWAP64) { + rhash_swap_copy_u64_to_str(result, digest, info->info->digest_size); + } else { + memcpy(result, digest, info->info->digest_size); + } +} + +/** + * Set the callback function to be called from the + * rhash_file() and rhash_file_update() functions + * on processing every file block. The file block + * size is set internally by rhash and now is 8 KiB. + * + * @param ctx rhash context + * @param callback pointer to the callback function + * @param callback_data pointer to data passed to the callback + */ +RHASH_API void rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data) +{ + ((rhash_context_ext*)ctx)->callback = callback; + ((rhash_context_ext*)ctx)->callback_data = callback_data; +} + + +/* hi-level message hashing interface */ + +/** + * Compute a hash of the given message. + * + * @param hash_id id of hash sum to compute + * @param message the message to process + * @param length message length + * @param result buffer to receive binary hash string + * @return 0 on success, -1 on error + */ +RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result) +{ + rhash ctx; + hash_id &= RHASH_ALL_HASHES; + ctx = rhash_init(hash_id); + if (ctx == NULL) return -1; + rhash_update(ctx, message, length); + rhash_final(ctx, result); + rhash_free(ctx); + return 0; +} + +/** + * Hash a file or stream. Multiple hashes can be computed. + * First, inintialize ctx parameter with rhash_init() before calling + * rhash_file_update(). Then use rhash_final() and rhash_print() + * to retrive hash values. Finaly call rhash_free() on ctx + * to free allocated memory or call rhash_reset() to reuse ctx. + * + * @param ctx rhash context + * @param fd descriptor of the file to hash + * @return 0 on success, -1 on error and errno is set + */ +RHASH_API int rhash_file_update(rhash ctx, FILE* fd) +{ + rhash_context_ext* const ectx = (rhash_context_ext*)ctx; + const size_t block_size = 8192; + unsigned char *buffer, *pmem; + size_t length = 0, align8; + int res = 0; + if (ectx->state != STATE_ACTIVE) return 0; /* do nothing if canceled */ + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + pmem = (unsigned char*)malloc(block_size + 8); + if (!pmem) return -1; /* errno is set to ENOMEM according to UNIX 98 */ + + align8 = ((unsigned char*)0 - pmem) & 7; + buffer = pmem + align8; + + while (!feof(fd)) { + /* stop if canceled */ + if (ectx->state != STATE_ACTIVE) break; + + length = fread(buffer, 1, block_size, fd); + + if (ferror(fd)) { + res = -1; /* note: errno contains error code */ + break; + } else if (length) { + rhash_update(ctx, buffer, length); + + if (ectx->callback) { + ((rhash_callback_t)ectx->callback)(ectx->callback_data, ectx->rc.msg_size); + } + } + } + + free(buffer); + return res; +} + +/** + * Compute a single hash for given file. + * + * @param hash_id id of hash sum to compute + * @param filepath path to the file to hash + * @param result buffer to receive hash value with the lowest requested id + * @return 0 on success, -1 on error and errno is set + */ +RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result) +{ + FILE* fd; + rhash ctx; + int res; + + hash_id &= RHASH_ALL_HASHES; + if (hash_id == 0) { + errno = EINVAL; + return -1; + } + + if ((fd = fopen(filepath, "rb")) == NULL) return -1; + + if ((ctx = rhash_init(hash_id)) == NULL) return -1; + + res = rhash_file_update(ctx, fd); /* hash the file */ + fclose(fd); + + rhash_final(ctx, result); + rhash_free(ctx); + return res; +} + +#ifdef _WIN32 /* windows only function */ +#include <share.h> + +/** + * Compute a single hash for given file. + * + * @param hash_id id of hash sum to compute + * @param filepath path to the file to hash + * @param result buffer to receive hash value with the lowest requested id + * @return 0 on success, -1 on error, -1 on error and errno is set + */ +RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result) +{ + FILE* fd; + rhash ctx; + int res; + + hash_id &= RHASH_ALL_HASHES; + if (hash_id == 0) { + errno = EINVAL; + return -1; + } + + if ((fd = _wfsopen(filepath, L"rb", _SH_DENYWR)) == NULL) return -1; + + if ((ctx = rhash_init(hash_id)) == NULL) return -1; + + res = rhash_file_update(ctx, fd); /* hash the file */ + fclose(fd); + + rhash_final(ctx, result); + rhash_free(ctx); + return res; +} +#endif + +/* RHash information functions */ + +/** + * Returns information about a hash function by its hash_id. + * + * @param hash_id the id of hash algorithm + * @return pointer to the rhash_info structure containing the information + */ +const rhash_info* rhash_info_by_id(unsigned hash_id) +{ + hash_id &= RHASH_ALL_HASHES; + /* check that only one bit is set */ + if (hash_id != (hash_id & -(int)hash_id)) return NULL; + /* note: alternative condition is (hash_id == 0 || (hash_id & (hash_id - 1)) != 0) */ + return rhash_info_table[rhash_ctz(hash_id)].info; +} + +#if 0 +/** + * Detect default digest output format for given hash algorithm. + * + * @param hash_id the id of hash algorithm + * @return 1 for base32 format, 0 for hexadecimal + */ +RHASH_API int rhash_is_base32(unsigned hash_id) +{ + /* fast method is just to test a bit-mask */ + return ((hash_id & (RHASH_TTH | RHASH_AICH)) != 0); +} +#endif + +/** + * Returns size of binary digest for given hash algorithm. + * + * @param hash_id the id of hash algorithm + * @return digest size in bytes + */ +RHASH_API int rhash_get_digest_size(unsigned hash_id) +{ + hash_id &= RHASH_ALL_HASHES; + if (hash_id == 0 || (hash_id & (hash_id - 1)) != 0) return -1; + return (int)rhash_info_table[rhash_ctz(hash_id)].info->digest_size; +} + +/** + * Returns length of digest hash string in default output format. + * + * @param hash_id the id of hash algorithm + * @return the length of hash string + */ +RHASH_API int rhash_get_hash_length(unsigned hash_id) +{ + const rhash_info* info = rhash_info_by_id(hash_id); + return (int)(info ? (info->flags & F_BS32 ? + BASE32_LENGTH(info->digest_size) : info->digest_size * 2) : 0); +} + +/** + * Returns a name of given hash algorithm. + * + * @param hash_id the id of hash algorithm + * @return algorithm name + */ +RHASH_API const char* rhash_get_name(unsigned hash_id) +{ + const rhash_info* info = rhash_info_by_id(hash_id); + return (info ? info->name : 0); +} + +/** + * Returns a name part of magnet urn of the given hash algorithm. + * Such magnet_name is used to generate a magnet link of the form + * urn:<magnet_name>=<hash_value>. + * + * @param hash_id the id of hash algorithm + * @return name + */ +RHASH_API const char* rhash_get_magnet_name(unsigned hash_id) +{ + const rhash_info* info = rhash_info_by_id(hash_id); + return (info ? info->magnet_name : 0); +} + +#if 0 +static size_t rhash_get_magnet_url_size(const char* filepath, + rhash context, unsigned hash_mask, int flags) +{ + size_t size = 0; /* count terminating '\0' */ + unsigned bit, hash = context->hash_id & hash_mask; + + /* RHPR_NO_MAGNET, RHPR_FILESIZE */ + if ((flags & RHPR_NO_MAGNET) == 0) { + size += 8; + } + + if ((flags & RHPR_FILESIZE) != 0) { + uint64_t num = context->msg_size; + + size += 4; + if (num == 0) size++; + else { + for (; num; num /= 10, size++); + } + } + + if (filepath) { + size += 4 + rhash_urlencode(NULL, filepath); + } + + /* loop through hash values */ + for (bit = hash & -(int)hash; bit <= hash; bit <<= 1) { + const char* name; + if ((bit & hash) == 0) continue; + if ((name = rhash_get_magnet_name(bit)) == 0) continue; + + size += (7 + 2) + strlen(name); + size += rhash_print(NULL, context, bit, + (bit & (RHASH_SHA1 | RHASH_BTIH) ? RHPR_BASE32 : 0)); + } + + return size; +} + +/** + * Print magnet link with given filepath and calculated hash sums into the + * output buffer. The hash_mask can limit which hash values will be printed. + * The function returns the size of the required buffer. + * If output is NULL the . + * + * @param output a string buffer to receive the magnet link or NULL + * @param filepath the file path to be printed or NULL + * @param context algorithms state + * @param hash_mask bit mask of the hash sums to add to the link + * @param flags can be combination of bits RHPR_UPPERCASE, RHPR_NO_MAGNET, + * RHPR_FILESIZE + * @return number of written characters, including terminating '\0' on success, 0 on fail + */ +RHASH_API size_t rhash_print_magnet(char* output, const char* filepath, + rhash context, unsigned hash_mask, int flags) +{ + int i; + const char* begin = output; + + if (output == NULL) return rhash_get_magnet_url_size( + filepath, context, hash_mask, flags); + + /* RHPR_NO_MAGNET, RHPR_FILESIZE */ + if ((flags & RHPR_NO_MAGNET) == 0) { + strcpy(output, "magnet:?"); + output += 8; + } + + if ((flags & RHPR_FILESIZE) != 0) { + strcpy(output, "xl="); + output += 3; + output += rhash_sprintI64(output, context->msg_size); + *(output++) = '&'; + } + + if (filepath) { + strcpy(output, "dn="); + output += 3; + output += rhash_urlencode(output, filepath); + *(output++) = '&'; + } + flags &= RHPR_UPPERCASE; + + for (i = 0; i < 2; i++) { + unsigned bit; + unsigned hash = context->hash_id & hash_mask; + hash = (i == 0 ? hash & (RHASH_ED2K | RHASH_AICH) + : hash & ~(RHASH_ED2K | RHASH_AICH)); + if (!hash) continue; + + /* loop through hash values */ + for (bit = hash & -(int)hash; bit <= hash; bit <<= 1) { + const char* name; + if ((bit & hash) == 0) continue; + if (!(name = rhash_get_magnet_name(bit))) continue; + + strcpy(output, "xt=urn:"); + output += 7; + strcpy(output, name); + output += strlen(name); + *(output++) = ':'; + output += rhash_print(output, context, bit, + (bit & (RHASH_SHA1 | RHASH_BTIH) ? flags | RHPR_BASE32 : flags)); + *(output++) = '&'; + } + } + output[-1] = '\0'; /* terminate the line */ + + return (output - begin); +} + +/* hash sum output */ + +/** + * Print a text presentation of a given hash sum to the specified buffer, + * + * @param output a buffer to print the hash to + * @param bytes a hash sum to print + * @param size a size of hash sum in bytes + * @param flags a bit-mask controlling how to format the hash sum, + * can be a mix of the flags: RHPR_RAW, RHPR_HEX, RHPR_BASE32, + * RHPR_BASE64, RHPR_UPPERCASE, RHPR_REVERSE + * @return the number of written characters + */ +size_t rhash_print_bytes(char* output, const unsigned char* bytes, + size_t size, int flags) +{ + size_t str_len; + int upper_case = (flags & RHPR_UPPERCASE); + int format = (flags & ~RHPR_MODIFIER); + + switch (format) { + case RHPR_HEX: + str_len = size * 2; + rhash_byte_to_hex(output, bytes, (unsigned)size, upper_case); + break; + case RHPR_BASE32: + str_len = BASE32_LENGTH(size); + rhash_byte_to_base32(output, bytes, (unsigned)size, upper_case); + break; + case RHPR_BASE64: + str_len = BASE64_LENGTH(size); + rhash_byte_to_base64(output, bytes, (unsigned)size); + break; + default: + str_len = size; + memcpy(output, bytes, size); + break; + } + return str_len; +} + +/** + * Print text presentation of a hash sum with given hash_id to the specified + * output buffer. If the hash_id is zero, then print the hash sum with + * the lowest id stored in the hash context. + * The function call fails if the context doesn't include a hash with the + * given hash_id. + * + * @param output a buffer to print the hash to + * @param context algorithms state + * @param hash_id id of the hash sum to print or 0 to print the first hash + * saved in the context. + * @param flags a bitmask controlling how to print the hash. Can contain flags + * RHPR_UPPERCASE, RHPR_HEX, RHPR_BASE32, RHPR_BASE64, etc. + * @return the number of written characters on success or 0 on fail + */ +size_t RHASH_API rhash_print(char* output, rhash context, unsigned hash_id, int flags) +{ + const rhash_info* info; + unsigned char digest[80]; + size_t digest_size; + + info = (hash_id != 0 ? rhash_info_by_id(hash_id) : + ((rhash_context_ext*)context)->vector[0].hash_info->info); + + if (info == NULL) return 0; + digest_size = info->digest_size; + assert(digest_size <= 64); + + flags &= (RHPR_FORMAT | RHPR_MODIFIER); + if ((flags & RHPR_FORMAT) == 0) { + /* use default format if not specified by flags */ + flags |= (info->flags & RHASH_INFO_BASE32 ? RHPR_BASE32 : RHPR_HEX); + } + + if (output == NULL) { + switch (flags & RHPR_FORMAT) { + case RHPR_HEX: + return (digest_size * 2); + case RHPR_BASE32: + return BASE32_LENGTH(digest_size); + case RHPR_BASE64: + return BASE64_LENGTH(digest_size); + default: + return digest_size; + } + } + + /* note: use info->hash_id, cause hash_id can be 0 */ + rhash_put_digest(context, info->hash_id, digest); + + if ((flags & ~RHPR_UPPERCASE) == (RHPR_REVERSE | RHPR_HEX)) { + /* reverse the digest */ + unsigned char *p = digest, *r = digest + digest_size - 1; + char tmp; + for (; p < r; p++, r--) { + tmp = *p; + *p = *r; + *r = tmp; + } + } + + return rhash_print_bytes(output, digest, digest_size, flags); +} + +#if defined(_WIN32) && defined(RHASH_EXPORTS) +#include <windows.h> +BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved); +BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) +{ + (void)hModule; + (void)reserved; + switch (reason) { + case DLL_PROCESS_ATTACH: + rhash_library_init(); + break; + case DLL_PROCESS_DETACH: + /*rhash_library_free();*/ + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} +#endif + +#define PVOID2UPTR(p) ((rhash_uptr_t)((char*)p - 0)) + +/** + * Process a rhash message. + * + * @param msg_id message identifier + * @param dst message destination (can be NULL for generic messages) + * @param ldata data depending on message + * @param rdata data depending on message + * @return message-specific data + */ +RHASH_API rhash_uptr_t rhash_transmit(unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata) +{ + /* for messages working with rhash context */ + rhash_context_ext* const ctx = (rhash_context_ext*)dst; + + switch (msg_id) { + case RMSG_GET_CONTEXT: + { + unsigned i; + for (i = 0; i < ctx->hash_vector_size; i++) { + struct rhash_hash_info* info = ctx->vector[i].hash_info; + if (info->info->hash_id == (unsigned)ldata) + return PVOID2UPTR(ctx->vector[i].context); + } + return (rhash_uptr_t)0; + } + + case RMSG_CANCEL: + /* mark rhash context as canceled, in a multithreaded program */ + atomic_compare_and_swap(&ctx->state, STATE_ACTIVE, STATE_STOPED); + return 0; + + case RMSG_IS_CANCELED: + return (ctx->state == STATE_STOPED); + + case RMSG_GET_FINALIZED: + return ((ctx->flags & RCTX_FINALIZED) != 0); + case RMSG_SET_AUTOFINAL: + ctx->flags &= ~RCTX_AUTO_FINAL; + if (ldata) ctx->flags |= RCTX_AUTO_FINAL; + break; + + /* OpenSSL related messages */ +#ifdef USE_OPENSSL + case RMSG_SET_OPENSSL_MASK: + rhash_openssl_hash_mask = (unsigned)ldata; + break; + case RMSG_GET_OPENSSL_MASK: + return rhash_openssl_hash_mask; +#endif + + default: + return RHASH_ERROR; /* unknown message */ + } + return 0; +} +#endif diff --git a/Utilities/cmlibrhash/librhash/rhash.h b/Utilities/cmlibrhash/librhash/rhash.h new file mode 100644 index 0000000..6d18c18 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/rhash.h @@ -0,0 +1,280 @@ +/** @file rhash.h LibRHash interface */ +#ifndef RHASH_H +#define RHASH_H + +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef RHASH_API +/* modifier for LibRHash functions */ +# define RHASH_API +#endif + +/** + * Identifiers of supported hash functions. + * The rhash_init() function allows mixing several ids using + * binary OR, to calculate several hash functions for one message. + */ +enum rhash_ids +{ +#if 0 + RHASH_CRC32 = 0x01, + RHASH_MD4 = 0x02, + RHASH_MD5 = 0x04, + RHASH_SHA1 = 0x08, + RHASH_TIGER = 0x10, + RHASH_TTH = 0x20, + RHASH_BTIH = 0x40, + RHASH_ED2K = 0x80, + RHASH_AICH = 0x100, + RHASH_WHIRLPOOL = 0x200, + RHASH_RIPEMD160 = 0x400, + RHASH_GOST = 0x800, + RHASH_GOST_CRYPTOPRO = 0x1000, + RHASH_HAS160 = 0x2000, + RHASH_SNEFRU128 = 0x4000, + RHASH_SNEFRU256 = 0x8000, + RHASH_SHA224 = 0x10000, + RHASH_SHA256 = 0x20000, + RHASH_SHA384 = 0x40000, + RHASH_SHA512 = 0x80000, + RHASH_EDONR256 = 0x0100000, + RHASH_EDONR512 = 0x0200000, + RHASH_SHA3_224 = 0x0400000, + RHASH_SHA3_256 = 0x0800000, + RHASH_SHA3_384 = 0x1000000, + RHASH_SHA3_512 = 0x2000000, + + /** The bit-mask containing all supported hashe functions */ + RHASH_ALL_HASHES = RHASH_CRC32 | RHASH_MD4 | RHASH_MD5 | RHASH_ED2K | RHASH_SHA1 | + RHASH_TIGER | RHASH_TTH | RHASH_GOST | RHASH_GOST_CRYPTOPRO | + RHASH_BTIH | RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 | + RHASH_HAS160 | RHASH_SNEFRU128 | RHASH_SNEFRU256 | + RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | + RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512 | + RHASH_EDONR256 | RHASH_EDONR512, + + /** The number of supported hash functions */ + RHASH_HASH_COUNT = 26 +#else + RHASH_MD5 = 0x01, + RHASH_SHA1 = 0x02, + RHASH_SHA224 = 0x04, + RHASH_SHA256 = 0x08, + RHASH_SHA384 = 0x10, + RHASH_SHA512 = 0x20, + RHASH_ALL_HASHES = + RHASH_MD5 | + RHASH_SHA1 | + RHASH_SHA224 | + RHASH_SHA256 | + RHASH_SHA384 | + RHASH_SHA512, + RHASH_HASH_COUNT = 6 +#endif +}; + +/** + * The rhash context structure contains contexts for several hash functions + */ +typedef struct rhash_context +{ + /** The size of the hashed message */ + unsigned long long msg_size; + + /** + * The bit-mask containing identifiers of the hashes being calculated + */ + unsigned hash_id; +} rhash_context; + +#ifndef LIBRHASH_RHASH_CTX_DEFINED +#define LIBRHASH_RHASH_CTX_DEFINED +/** + * Hashing context. + */ +typedef struct rhash_context* rhash; +#endif /* LIBRHASH_RHASH_CTX_DEFINED */ + +/** type of a callback to be called periodically while hashing a file */ +typedef void (*rhash_callback_t)(void* data, unsigned long long offset); + +RHASH_API void rhash_library_init(void); /* initialize static data */ + +/* hi-level hashing functions */ +RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result); +RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result); +RHASH_API int rhash_file_update(rhash ctx, FILE* fd); + +#ifdef _WIN32 /* windows only function */ +RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result); +#endif + +/* lo-level interface */ +RHASH_API rhash rhash_init(unsigned hash_id); +/*RHASH_API rhash rhash_init_by_ids(unsigned hash_ids[], unsigned count);*/ +RHASH_API int rhash_update(rhash ctx, const void* message, size_t length); +RHASH_API int rhash_final(rhash ctx, unsigned char* first_result); +RHASH_API void rhash_reset(rhash ctx); /* reinitialize the context */ +RHASH_API void rhash_free(rhash ctx); + +/* additional lo-level functions */ +RHASH_API void rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data); + +/** bit-flag: default hash output format is base32 */ +#define RHASH_INFO_BASE32 1 + +/** + * Information about a hash function. + */ +typedef struct rhash_info +{ + /** hash function indentifier */ + unsigned hash_id; + /** flags bit-mask, including RHASH_INFO_BASE32 bit */ + unsigned flags; + /** size of binary message digest in bytes */ + size_t digest_size; + const char* name; + const char* magnet_name; +} rhash_info; + +/* information functions */ +RHASH_API int rhash_count(void); /* number of supported hashes */ +RHASH_API int rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */ +RHASH_API int rhash_get_hash_length(unsigned hash_id); /* length of formated hash string */ +RHASH_API int rhash_is_base32(unsigned hash_id); /* default digest output format */ +RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */ +RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */ + +/* note, that rhash_info_by_id() is not exported to a shared library or DLL */ +const rhash_info* rhash_info_by_id(unsigned hash_id); /* get hash sum info by hash id */ + +#if 0 +/** + * Flags for printing a hash sum + */ +enum rhash_print_sum_flags +{ + /** print in a default format */ + RHPR_DEFAULT = 0x0, + /** output as binary message digest */ + RHPR_RAW = 0x1, + /** print as a hexadecimal string */ + RHPR_HEX = 0x2, + /** print as a base32-encoded string */ + RHPR_BASE32 = 0x3, + /** print as a base64-encoded string */ + RHPR_BASE64 = 0x4, + + /** + * Print as an uppercase string. Can be used + * for base32 or hexadecimal format only. + */ + RHPR_UPPERCASE = 0x8, + + /** + * Reverse hash bytes. Can be used for GOST hash. + */ + RHPR_REVERSE = 0x10, + + /** don't print 'magnet:?' prefix in rhash_print_magnet */ + RHPR_NO_MAGNET = 0x20, + /** print file size in rhash_print_magnet */ + RHPR_FILESIZE = 0x40, +}; +#endif + +/* output hash into the given buffer */ +RHASH_API size_t rhash_print_bytes(char* output, + const unsigned char* bytes, size_t size, int flags); + +RHASH_API size_t rhash_print(char* output, rhash ctx, unsigned hash_id, + int flags); + +/* output magnet URL into the given buffer */ +RHASH_API size_t rhash_print_magnet(char* output, const char* filepath, + rhash context, unsigned hash_mask, int flags); + +/* macros for message API */ + +/** The type of an unsigned integer large enough to hold a pointer */ +#if defined(UINTPTR_MAX) +typedef uintptr_t rhash_uptr_t; +#elif defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \ + defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +typedef unsigned long long rhash_uptr_t; +#else +typedef unsigned long rhash_uptr_t; +#endif + +/** The value returned by rhash_transmit on error */ +#define RHASH_ERROR ((rhash_uptr_t)-1) +/** Convert a pointer to rhash_uptr_t */ +#define RHASH_STR2UPTR(str) ((rhash_uptr_t)(char*)(str)) +/** Convert a rhash_uptr_t to a void* pointer */ +#define RHASH_UPTR2PVOID(u) ((void*)((char*)0 + (u))) + +/* rhash API to set/get data via messages */ +RHASH_API rhash_uptr_t rhash_transmit( + unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata); + +/* rhash message constants */ + +#define RMSG_GET_CONTEXT 1 +#define RMSG_CANCEL 2 +#define RMSG_IS_CANCELED 3 +#define RMSG_GET_FINALIZED 4 +#define RMSG_SET_AUTOFINAL 5 +#define RMSG_SET_OPENSSL_MASK 10 +#define RMSG_GET_OPENSSL_MASK 11 + +/* helper macros */ + +/** Get a pointer to context of the specified hash function */ +#define rhash_get_context_ptr(ctx, hash_id) RHASH_UPTR2PVOID(rhash_transmit(RMSG_GET_CONTEXT, ctx, hash_id, 0)) +/** Cancel hash calculation of a file */ +#define rhash_cancel(ctx) rhash_transmit(RMSG_CANCEL, ctx, 0, 0) +/** Return non-zero if hash calculation was canceled, zero otherwise */ +#define rhash_is_canceled(ctx) rhash_transmit(RMSG_IS_CANCELED, ctx, 0, 0) +/** Return non-zero if rhash_final was called for rhash_context */ +#define rhash_get_finalized(ctx) rhash_transmit(RMSG_GET_FINALIZED, ctx, 0, 0) + +/** + * Turn on/off the auto-final flag for the given rhash_context. By default + * auto-final is on, which means rhash_final is called automatically, if + * needed when a hash value is retrived by rhash_print call. + */ +#define rhash_set_autofinal(ctx, on) rhash_transmit(RMSG_SET_AUTOFINAL, ctx, on, 0) + +/** + * Set the bit-mask of hash algorithms to be calculated by OpenSSL library. + * The call rhash_set_openssl_mask(0) made before rhash_library_init(), + * turns off loading of the OpenSSL dynamic library. + * This call works if the LibRHash was compiled with OpenSSL support. + */ +#define rhash_set_openssl_mask(mask) rhash_transmit(RMSG_SET_OPENSSL_MASK, NULL, mask, 0) + +/** + * Return current bit-mask of hash algorithms selected to be calculated + * by OpenSSL library. + */ +#define rhash_get_openssl_mask() rhash_transmit(RMSG_GET_OPENSSL_MASK, NULL, 0, 0) + +/** The bit mask of hash algorithms implemented by OpenSSL */ +#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME) +# define RHASH_OPENSSL_SUPPORTED_HASHES (RHASH_MD4 | RHASH_MD5 | \ + RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | \ + RHASH_SHA512 | RHASH_RIPEMD160 | RHASH_WHIRLPOOL) +#else +# define RHASH_OPENSSL_SUPPORTED_HASHES 0 +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* RHASH_H */ diff --git a/Utilities/cmlibrhash/librhash/sha1.c b/Utilities/cmlibrhash/librhash/sha1.c new file mode 100644 index 0000000..f5a053b --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha1.c @@ -0,0 +1,196 @@ +/* sha1.c - an implementation of Secure Hash Algorithm 1 (SHA1) + * based on RFC 3174. + * + * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include <string.h> +#include "byte_order.h" +#include "sha1.h" + +/** + * Initialize context before calculaing hash. + * + * @param ctx context to initialize + */ +void rhash_sha1_init(sha1_ctx *ctx) +{ + ctx->length = 0; + + /* initialize algorithm state */ + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; +} + +/** + * The core transformation. Process a 512-bit block. + * The function has been taken from RFC 3174 with little changes. + * + * @param hash algorithm state + * @param block the message block to process + */ +static void rhash_sha1_process_block(unsigned* hash, const unsigned* block) +{ + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* initialize the first 16 words in the array W */ + for (t = 0; t < 16; t++) { + /* note: it is much faster to apply be2me here, then using be32_copy */ + W[t] = be2me_32(block[t]); + } + + /* initialize the rest */ + for (t = 16; t < 80; t++) { + W[t] = ROTL32(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); + } + + A = hash[0]; + B = hash[1]; + C = hash[2]; + D = hash[3]; + E = hash[4]; + + for (t = 0; t < 20; t++) { + /* the following is faster than ((B & C) | ((~B) & D)) */ + temp = ROTL32(A, 5) + (((C ^ D) & B) ^ D) + + E + W[t] + 0x5A827999; + E = D; + D = C; + C = ROTL32(B, 30); + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = ROTL32(A, 5) + (B ^ C ^ D) + E + W[t] + 0x6ED9EBA1; + E = D; + D = C; + C = ROTL32(B, 30); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = ROTL32(A, 5) + ((B & C) | (B & D) | (C & D)) + + E + W[t] + 0x8F1BBCDC; + E = D; + D = C; + C = ROTL32(B, 30); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = ROTL32(A, 5) + (B ^ C ^ D) + E + W[t] + 0xCA62C1D6; + E = D; + D = C; + C = ROTL32(B, 30); + B = A; + A = temp; + } + + hash[0] += A; + hash[1] += B; + hash[2] += C; + hash[3] += D; + hash[4] += E; +} + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void rhash_sha1_update(sha1_ctx *ctx, const unsigned char* msg, size_t size) +{ + unsigned index = (unsigned)ctx->length & 63; + ctx->length += size; + + /* fill partial block */ + if (index) { + unsigned left = sha1_block_size - index; + memcpy(ctx->message + index, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + rhash_sha1_process_block(ctx->hash, (unsigned*)ctx->message); + msg += left; + size -= left; + } + while (size >= sha1_block_size) { + unsigned* aligned_message_block; + if (IS_ALIGNED_32(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (unsigned*)msg; + } else { + memcpy(ctx->message, msg, sha1_block_size); + aligned_message_block = (unsigned*)ctx->message; + } + + rhash_sha1_process_block(ctx->hash, aligned_message_block); + msg += sha1_block_size; + size -= sha1_block_size; + } + if (size) { + /* save leftovers */ + memcpy(ctx->message, msg, size); + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void rhash_sha1_final(sha1_ctx *ctx, unsigned char* result) +{ + unsigned index = (unsigned)ctx->length & 63; + unsigned* msg32 = (unsigned*)ctx->message; + + /* pad message and run for last block */ + ctx->message[index++] = 0x80; + while ((index & 3) != 0) { + ctx->message[index++] = 0; + } + index >>= 2; + + /* if no room left in the message to store 64-bit message length */ + if (index > 14) { + /* then fill the rest with zeros and process it */ + while (index < 16) { + msg32[index++] = 0; + } + rhash_sha1_process_block(ctx->hash, msg32); + index = 0; + } + while (index < 14) { + msg32[index++] = 0; + } + msg32[14] = be2me_32( (unsigned)(ctx->length >> 29) ); + msg32[15] = be2me_32( (unsigned)(ctx->length << 3) ); + rhash_sha1_process_block(ctx->hash, msg32); + + if (result) be32_copy(result, 0, &ctx->hash, sha1_hash_size); +} diff --git a/Utilities/cmlibrhash/librhash/sha1.h b/Utilities/cmlibrhash/librhash/sha1.h new file mode 100644 index 0000000..74b2f94 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha1.h @@ -0,0 +1,31 @@ +/* sha1.h */ +#ifndef SHA1_H +#define SHA1_H +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha1_block_size 64 +#define sha1_hash_size 20 + +/* algorithm context */ +typedef struct sha1_ctx +{ + unsigned char message[sha1_block_size]; /* 512-bit buffer for leftovers */ + uint64_t length; /* number of processed bytes */ + unsigned hash[5]; /* 160-bit algorithm internal hashing state */ +} sha1_ctx; + +/* hash functions */ + +void rhash_sha1_init(sha1_ctx *ctx); +void rhash_sha1_update(sha1_ctx *ctx, const unsigned char* msg, size_t size); +void rhash_sha1_final(sha1_ctx *ctx, unsigned char* result); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SHA1_H */ diff --git a/Utilities/cmlibrhash/librhash/sha256.c b/Utilities/cmlibrhash/librhash/sha256.c new file mode 100644 index 0000000..064dfe2 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha256.c @@ -0,0 +1,241 @@ +/* sha256.c - an implementation of SHA-256/224 hash functions + * based on FIPS 180-3 (Federal Information Processing Standart). + * + * Copyright: 2010-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include <string.h> +#include "byte_order.h" +#include "sha256.h" + +/* SHA-224 and SHA-256 constants for 64 rounds. These words represent + * the first 32 bits of the fractional parts of the cube + * roots of the first 64 prime numbers. */ +static const unsigned rhash_k256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* The SHA256/224 functions defined by FIPS 180-3, 4.1.2 */ +/* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */ +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +/* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */ +#define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y)))) + +#define Sigma0(x) (ROTR32((x), 2) ^ ROTR32((x), 13) ^ ROTR32((x), 22)) +#define Sigma1(x) (ROTR32((x), 6) ^ ROTR32((x), 11) ^ ROTR32((x), 25)) +#define sigma0(x) (ROTR32((x), 7) ^ ROTR32((x), 18) ^ ((x) >> 3)) +#define sigma1(x) (ROTR32((x),17) ^ ROTR32((x), 19) ^ ((x) >> 10)) + +/* Recalculate element n-th of circular buffer W using formula + * W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */ +#define RECALCULATE_W(W,n) (W[n] += \ + (sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15]))) + +#define ROUND(a,b,c,d,e,f,g,h,k,data) { \ + unsigned T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \ + d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); } +#define ROUND_1_16(a,b,c,d,e,f,g,h,n) \ + ROUND(a,b,c,d,e,f,g,h, rhash_k256[n], W[n] = be2me_32(block[n])) +#define ROUND_17_64(a,b,c,d,e,f,g,h,n) \ + ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n)) + +/** + * Initialize context before calculaing hash. + * + * @param ctx context to initialize + */ +void rhash_sha256_init(sha256_ctx *ctx) +{ + /* Initial values. These words were obtained by taking the first 32 + * bits of the fractional parts of the square roots of the first + * eight prime numbers. */ + static const unsigned SHA256_H0[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + }; + + ctx->length = 0; + ctx->digest_length = sha256_hash_size; + + /* initialize algorithm state */ + memcpy(ctx->hash, SHA256_H0, sizeof(ctx->hash)); +} + +/** + * Initialize context before calculaing hash. + * + * @param ctx context to initialize + */ +void rhash_sha224_init(struct sha256_ctx *ctx) +{ + /* Initial values from FIPS 180-3. These words were obtained by taking + * bits from 33th to 64th of the fractional parts of the square + * roots of ninth through sixteenth prime numbers. */ + static const unsigned SHA224_H0[8] = { + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + }; + + ctx->length = 0; + ctx->digest_length = sha224_hash_size; + + memcpy(ctx->hash, SHA224_H0, sizeof(ctx->hash)); +} + +/** + * The core transformation. Process a 512-bit block. + * + * @param hash algorithm state + * @param block the message block to process + */ +static void rhash_sha256_process_block(unsigned hash[8], unsigned block[16]) +{ + unsigned A, B, C, D, E, F, G, H; + unsigned W[16]; + const unsigned *k; + int i; + + A = hash[0], B = hash[1], C = hash[2], D = hash[3]; + E = hash[4], F = hash[5], G = hash[6], H = hash[7]; + + /* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */ + ROUND_1_16(A, B, C, D, E, F, G, H, 0); + ROUND_1_16(H, A, B, C, D, E, F, G, 1); + ROUND_1_16(G, H, A, B, C, D, E, F, 2); + ROUND_1_16(F, G, H, A, B, C, D, E, 3); + ROUND_1_16(E, F, G, H, A, B, C, D, 4); + ROUND_1_16(D, E, F, G, H, A, B, C, 5); + ROUND_1_16(C, D, E, F, G, H, A, B, 6); + ROUND_1_16(B, C, D, E, F, G, H, A, 7); + ROUND_1_16(A, B, C, D, E, F, G, H, 8); + ROUND_1_16(H, A, B, C, D, E, F, G, 9); + ROUND_1_16(G, H, A, B, C, D, E, F, 10); + ROUND_1_16(F, G, H, A, B, C, D, E, 11); + ROUND_1_16(E, F, G, H, A, B, C, D, 12); + ROUND_1_16(D, E, F, G, H, A, B, C, 13); + ROUND_1_16(C, D, E, F, G, H, A, B, 14); + ROUND_1_16(B, C, D, E, F, G, H, A, 15); + + for (i = 16, k = &rhash_k256[16]; i < 64; i += 16, k += 16) { + ROUND_17_64(A, B, C, D, E, F, G, H, 0); + ROUND_17_64(H, A, B, C, D, E, F, G, 1); + ROUND_17_64(G, H, A, B, C, D, E, F, 2); + ROUND_17_64(F, G, H, A, B, C, D, E, 3); + ROUND_17_64(E, F, G, H, A, B, C, D, 4); + ROUND_17_64(D, E, F, G, H, A, B, C, 5); + ROUND_17_64(C, D, E, F, G, H, A, B, 6); + ROUND_17_64(B, C, D, E, F, G, H, A, 7); + ROUND_17_64(A, B, C, D, E, F, G, H, 8); + ROUND_17_64(H, A, B, C, D, E, F, G, 9); + ROUND_17_64(G, H, A, B, C, D, E, F, 10); + ROUND_17_64(F, G, H, A, B, C, D, E, 11); + ROUND_17_64(E, F, G, H, A, B, C, D, 12); + ROUND_17_64(D, E, F, G, H, A, B, C, 13); + ROUND_17_64(C, D, E, F, G, H, A, B, 14); + ROUND_17_64(B, C, D, E, F, G, H, A, 15); + } + + hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D; + hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H; +} + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void rhash_sha256_update(sha256_ctx *ctx, const unsigned char *msg, size_t size) +{ + size_t index = (size_t)ctx->length & 63; + ctx->length += size; + + /* fill partial block */ + if (index) { + size_t left = sha256_block_size - index; + memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + rhash_sha256_process_block(ctx->hash, (unsigned*)ctx->message); + msg += left; + size -= left; + } + while (size >= sha256_block_size) { + unsigned* aligned_message_block; + if (IS_ALIGNED_32(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (unsigned*)msg; + } else { + memcpy(ctx->message, msg, sha256_block_size); + aligned_message_block = (unsigned*)ctx->message; + } + + rhash_sha256_process_block(ctx->hash, aligned_message_block); + msg += sha256_block_size; + size -= sha256_block_size; + } + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void rhash_sha256_final(sha256_ctx *ctx, unsigned char* result) +{ + size_t index = ((unsigned)ctx->length & 63) >> 2; + unsigned shift = ((unsigned)ctx->length & 3) * 8; + + /* pad message and run for last block */ + + /* append the byte 0x80 to the message */ + ctx->message[index] &= le2me_32(~(0xFFFFFFFF << shift)); + ctx->message[index++] ^= le2me_32(0x80 << shift); + + /* if no room left in the message to store 64-bit message length */ + if (index > 14) { + /* then fill the rest with zeros and process it */ + while (index < 16) { + ctx->message[index++] = 0; + } + rhash_sha256_process_block(ctx->hash, ctx->message); + index = 0; + } + while (index < 14) { + ctx->message[index++] = 0; + } + ctx->message[14] = be2me_32( (unsigned)(ctx->length >> 29) ); + ctx->message[15] = be2me_32( (unsigned)(ctx->length << 3) ); + rhash_sha256_process_block(ctx->hash, ctx->message); + + if (result) be32_copy(result, 0, ctx->hash, ctx->digest_length); +} diff --git a/Utilities/cmlibrhash/librhash/sha256.h b/Utilities/cmlibrhash/librhash/sha256.h new file mode 100644 index 0000000..f87ebaa --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha256.h @@ -0,0 +1,32 @@ +/* sha.h sha256 and sha224 hash functions */ +#ifndef SHA256_H +#define SHA256_H +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha256_block_size 64 +#define sha256_hash_size 32 +#define sha224_hash_size 28 + +/* algorithm context */ +typedef struct sha256_ctx +{ + unsigned message[16]; /* 512-bit buffer for leftovers */ + uint64_t length; /* number of processed bytes */ + unsigned hash[8]; /* 256-bit algorithm internal hashing state */ + unsigned digest_length; /* length of the algorithm digest in bytes */ +} sha256_ctx; + +void rhash_sha224_init(sha256_ctx *ctx); +void rhash_sha256_init(sha256_ctx *ctx); +void rhash_sha256_update(sha256_ctx *ctx, const unsigned char* data, size_t length); +void rhash_sha256_final(sha256_ctx *ctx, unsigned char result[32]); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SHA256_H */ diff --git a/Utilities/cmlibrhash/librhash/sha512.c b/Utilities/cmlibrhash/librhash/sha512.c new file mode 100644 index 0000000..a3e681d --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha512.c @@ -0,0 +1,255 @@ +/* sha512.c - an implementation of SHA-384/512 hash functions + * based on FIPS 180-3 (Federal Information Processing Standart). + * + * Copyright: 2010-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include <string.h> +#include "byte_order.h" +#include "sha512.h" + +/* SHA-384 and SHA-512 constants for 80 rounds. These qwords represent + * the first 64 bits of the fractional parts of the cube + * roots of the first 80 prime numbers. */ +static const uint64_t rhash_k512[80] = { + I64(0x428a2f98d728ae22), I64(0x7137449123ef65cd), I64(0xb5c0fbcfec4d3b2f), + I64(0xe9b5dba58189dbbc), I64(0x3956c25bf348b538), I64(0x59f111f1b605d019), + I64(0x923f82a4af194f9b), I64(0xab1c5ed5da6d8118), I64(0xd807aa98a3030242), + I64(0x12835b0145706fbe), I64(0x243185be4ee4b28c), I64(0x550c7dc3d5ffb4e2), + I64(0x72be5d74f27b896f), I64(0x80deb1fe3b1696b1), I64(0x9bdc06a725c71235), + I64(0xc19bf174cf692694), I64(0xe49b69c19ef14ad2), I64(0xefbe4786384f25e3), + I64(0x0fc19dc68b8cd5b5), I64(0x240ca1cc77ac9c65), I64(0x2de92c6f592b0275), + I64(0x4a7484aa6ea6e483), I64(0x5cb0a9dcbd41fbd4), I64(0x76f988da831153b5), + I64(0x983e5152ee66dfab), I64(0xa831c66d2db43210), I64(0xb00327c898fb213f), + I64(0xbf597fc7beef0ee4), I64(0xc6e00bf33da88fc2), I64(0xd5a79147930aa725), + I64(0x06ca6351e003826f), I64(0x142929670a0e6e70), I64(0x27b70a8546d22ffc), + I64(0x2e1b21385c26c926), I64(0x4d2c6dfc5ac42aed), I64(0x53380d139d95b3df), + I64(0x650a73548baf63de), I64(0x766a0abb3c77b2a8), I64(0x81c2c92e47edaee6), + I64(0x92722c851482353b), I64(0xa2bfe8a14cf10364), I64(0xa81a664bbc423001), + I64(0xc24b8b70d0f89791), I64(0xc76c51a30654be30), I64(0xd192e819d6ef5218), + I64(0xd69906245565a910), I64(0xf40e35855771202a), I64(0x106aa07032bbd1b8), + I64(0x19a4c116b8d2d0c8), I64(0x1e376c085141ab53), I64(0x2748774cdf8eeb99), + I64(0x34b0bcb5e19b48a8), I64(0x391c0cb3c5c95a63), I64(0x4ed8aa4ae3418acb), + I64(0x5b9cca4f7763e373), I64(0x682e6ff3d6b2b8a3), I64(0x748f82ee5defb2fc), + I64(0x78a5636f43172f60), I64(0x84c87814a1f0ab72), I64(0x8cc702081a6439ec), + I64(0x90befffa23631e28), I64(0xa4506cebde82bde9), I64(0xbef9a3f7b2c67915), + I64(0xc67178f2e372532b), I64(0xca273eceea26619c), I64(0xd186b8c721c0c207), + I64(0xeada7dd6cde0eb1e), I64(0xf57d4f7fee6ed178), I64(0x06f067aa72176fba), + I64(0x0a637dc5a2c898a6), I64(0x113f9804bef90dae), I64(0x1b710b35131c471b), + I64(0x28db77f523047d84), I64(0x32caab7b40c72493), I64(0x3c9ebe0a15c9bebc), + I64(0x431d67c49c100d4c), I64(0x4cc5d4becb3e42b6), I64(0x597f299cfc657e2a), + I64(0x5fcb6fab3ad6faec), I64(0x6c44198c4a475817) +}; + +/* The SHA512/384 functions defined by FIPS 180-3, 4.1.3 */ +/* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */ +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +/* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */ +#define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y)))) + +#define Sigma0(x) (ROTR64((x), 28) ^ ROTR64((x), 34) ^ ROTR64((x), 39)) +#define Sigma1(x) (ROTR64((x), 14) ^ ROTR64((x), 18) ^ ROTR64((x), 41)) +#define sigma0(x) (ROTR64((x), 1) ^ ROTR64((x), 8) ^ ((x) >> 7)) +#define sigma1(x) (ROTR64((x), 19) ^ ROTR64((x), 61) ^ ((x) >> 6)) + +/* Recalculate element n-th of circular buffer W using formula + * W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */ +#define RECALCULATE_W(W,n) (W[n] += \ + (sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15]))) + +#define ROUND(a,b,c,d,e,f,g,h,k,data) { \ + uint64_t T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \ + d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); } +#define ROUND_1_16(a,b,c,d,e,f,g,h,n) \ + ROUND(a,b,c,d,e,f,g,h, rhash_k512[n], W[n] = be2me_64(block[n])) +#define ROUND_17_80(a,b,c,d,e,f,g,h,n) \ + ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n)) + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void rhash_sha512_init(sha512_ctx *ctx) +{ + /* Initial values. These words were obtained by taking the first 32 + * bits of the fractional parts of the square roots of the first + * eight prime numbers. */ + static const uint64_t SHA512_H0[8] = { + I64(0x6a09e667f3bcc908), I64(0xbb67ae8584caa73b), I64(0x3c6ef372fe94f82b), + I64(0xa54ff53a5f1d36f1), I64(0x510e527fade682d1), I64(0x9b05688c2b3e6c1f), + I64(0x1f83d9abfb41bd6b), I64(0x5be0cd19137e2179) + }; + + ctx->length = 0; + ctx->digest_length = sha512_hash_size; + + /* initialize algorithm state */ + memcpy(ctx->hash, SHA512_H0, sizeof(ctx->hash)); +} + +/** + * Initialize context before calculaing hash. + * + * @param ctx context to initialize + */ +void rhash_sha384_init(struct sha512_ctx *ctx) +{ + /* Initial values from FIPS 180-3. These words were obtained by taking + * the first sixty-four bits of the fractional parts of the square + * roots of ninth through sixteenth prime numbers. */ + static const uint64_t SHA384_H0[8] = { + I64(0xcbbb9d5dc1059ed8), I64(0x629a292a367cd507), I64(0x9159015a3070dd17), + I64(0x152fecd8f70e5939), I64(0x67332667ffc00b31), I64(0x8eb44a8768581511), + I64(0xdb0c2e0d64f98fa7), I64(0x47b5481dbefa4fa4) + }; + + ctx->length = 0; + ctx->digest_length = sha384_hash_size; + + memcpy(ctx->hash, SHA384_H0, sizeof(ctx->hash)); +} + +/** + * The core transformation. Process a 512-bit block. + * + * @param hash algorithm state + * @param block the message block to process + */ +static void rhash_sha512_process_block(uint64_t hash[8], uint64_t block[16]) +{ + uint64_t A, B, C, D, E, F, G, H; + uint64_t W[16]; + const uint64_t *k; + int i; + + A = hash[0], B = hash[1], C = hash[2], D = hash[3]; + E = hash[4], F = hash[5], G = hash[6], H = hash[7]; + + /* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */ + ROUND_1_16(A, B, C, D, E, F, G, H, 0); + ROUND_1_16(H, A, B, C, D, E, F, G, 1); + ROUND_1_16(G, H, A, B, C, D, E, F, 2); + ROUND_1_16(F, G, H, A, B, C, D, E, 3); + ROUND_1_16(E, F, G, H, A, B, C, D, 4); + ROUND_1_16(D, E, F, G, H, A, B, C, 5); + ROUND_1_16(C, D, E, F, G, H, A, B, 6); + ROUND_1_16(B, C, D, E, F, G, H, A, 7); + ROUND_1_16(A, B, C, D, E, F, G, H, 8); + ROUND_1_16(H, A, B, C, D, E, F, G, 9); + ROUND_1_16(G, H, A, B, C, D, E, F, 10); + ROUND_1_16(F, G, H, A, B, C, D, E, 11); + ROUND_1_16(E, F, G, H, A, B, C, D, 12); + ROUND_1_16(D, E, F, G, H, A, B, C, 13); + ROUND_1_16(C, D, E, F, G, H, A, B, 14); + ROUND_1_16(B, C, D, E, F, G, H, A, 15); + + for (i = 16, k = &rhash_k512[16]; i < 80; i += 16, k += 16) { + ROUND_17_80(A, B, C, D, E, F, G, H, 0); + ROUND_17_80(H, A, B, C, D, E, F, G, 1); + ROUND_17_80(G, H, A, B, C, D, E, F, 2); + ROUND_17_80(F, G, H, A, B, C, D, E, 3); + ROUND_17_80(E, F, G, H, A, B, C, D, 4); + ROUND_17_80(D, E, F, G, H, A, B, C, 5); + ROUND_17_80(C, D, E, F, G, H, A, B, 6); + ROUND_17_80(B, C, D, E, F, G, H, A, 7); + ROUND_17_80(A, B, C, D, E, F, G, H, 8); + ROUND_17_80(H, A, B, C, D, E, F, G, 9); + ROUND_17_80(G, H, A, B, C, D, E, F, 10); + ROUND_17_80(F, G, H, A, B, C, D, E, 11); + ROUND_17_80(E, F, G, H, A, B, C, D, 12); + ROUND_17_80(D, E, F, G, H, A, B, C, 13); + ROUND_17_80(C, D, E, F, G, H, A, B, 14); + ROUND_17_80(B, C, D, E, F, G, H, A, 15); + } + + hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D; + hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H; +} + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void rhash_sha512_update(sha512_ctx *ctx, const unsigned char *msg, size_t size) +{ + size_t index = (size_t)ctx->length & 127; + ctx->length += size; + + /* fill partial block */ + if (index) { + size_t left = sha512_block_size - index; + memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + rhash_sha512_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + while (size >= sha512_block_size) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (uint64_t*)msg; + } else { + memcpy(ctx->message, msg, sha512_block_size); + aligned_message_block = ctx->message; + } + + rhash_sha512_process_block(ctx->hash, aligned_message_block); + msg += sha512_block_size; + size -= sha512_block_size; + } + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void rhash_sha512_final(sha512_ctx *ctx, unsigned char* result) +{ + size_t index = ((unsigned)ctx->length & 127) >> 3; + unsigned shift = ((unsigned)ctx->length & 7) * 8; + + /* pad message and process the last block */ + + /* append the byte 0x80 to the message */ + ctx->message[index] &= le2me_64( ~(I64(0xFFFFFFFFFFFFFFFF) << shift) ); + ctx->message[index++] ^= le2me_64( I64(0x80) << shift ); + + /* if no room left in the message to store 128-bit message length */ + if (index >= 15) { + if (index == 15) ctx->message[index] = 0; + rhash_sha512_process_block(ctx->hash, ctx->message); + index = 0; + } + while (index < 15) { + ctx->message[index++] = 0; + } + ctx->message[15] = be2me_64(ctx->length << 3); + rhash_sha512_process_block(ctx->hash, ctx->message); + + if (result) be64_copy(result, 0, ctx->hash, ctx->digest_length); +} diff --git a/Utilities/cmlibrhash/librhash/sha512.h b/Utilities/cmlibrhash/librhash/sha512.h new file mode 100644 index 0000000..7c689be --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha512.h @@ -0,0 +1,32 @@ +/* sha.h sha512 and sha384 hash functions */ +#ifndef SHA512_H +#define SHA512_H +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha512_block_size 128 +#define sha512_hash_size 64 +#define sha384_hash_size 48 + +/* algorithm context */ +typedef struct sha512_ctx +{ + uint64_t message[16]; /* 1024-bit buffer for leftovers */ + uint64_t length; /* number of processed bytes */ + uint64_t hash[8]; /* 512-bit algorithm internal hashing state */ + unsigned digest_length; /* length of the algorithm digest in bytes */ +} sha512_ctx; + +void rhash_sha384_init(sha512_ctx *ctx); +void rhash_sha512_init(sha512_ctx *ctx); +void rhash_sha512_update(sha512_ctx *ctx, const unsigned char* data, size_t length); +void rhash_sha512_final(sha512_ctx *ctx, unsigned char* result); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SHA512_H */ diff --git a/Utilities/cmlibrhash/librhash/ustd.h b/Utilities/cmlibrhash/librhash/ustd.h new file mode 100644 index 0000000..019b931 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/ustd.h @@ -0,0 +1,39 @@ +/* ustd.h common macros and includes */ +#ifndef LIBRHASH_USTD_H +#define LIBRHASH_USTD_H + +/* Include KWSys Large File Support configuration. */ +#include <cmsys/Configure.h> + +#if defined(_MSC_VER) +# pragma warning(push,1) +#endif + +#include <cm_kwiml.h> + +#ifndef KWIML_INT_HAVE_INT64_T +# define int64_t KWIML_INT_int64_t +#endif +#ifndef KWIML_INT_HAVE_INT32_T +# define int32_t KWIML_INT_int32_t +#endif +#ifndef KWIML_INT_HAVE_INT16_T +# define int16_t KWIML_INT_int16_t +#endif +#ifndef KWIML_INT_HAVE_INT8_T +# define int8_t KWIML_INT_int8_t +#endif +#ifndef KWIML_INT_HAVE_UINT64_T +# define uint64_t KWIML_INT_uint64_t +#endif +#ifndef KWIML_INT_HAVE_UINT32_T +# define uint32_t KWIML_INT_uint32_t +#endif +#ifndef KWIML_INT_HAVE_UINT16_T +# define uint16_t KWIML_INT_uint16_t +#endif +#ifndef KWIML_INT_HAVE_UINT8_T +# define uint8_t KWIML_INT_uint8_t +#endif + +#endif /* LIBRHASH_USTD_H */ diff --git a/Utilities/cmlibrhash/librhash/util.h b/Utilities/cmlibrhash/librhash/util.h new file mode 100644 index 0000000..9f37157 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/util.h @@ -0,0 +1,31 @@ +/* util.h */ +#ifndef UTIL_H +#define UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if (defined(__GNUC__) && __GNUC__ >= 4 && (__GNUC__ > 4 || __GNUC_MINOR__ >= 1) \ + && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \ + || (defined(__INTEL_COMPILER) && !defined(_WIN32)) +/* atomic operations are defined by ICC and GCC >= 4.1, but by the later one supposedly not for ARM */ +/* note: ICC on ia64 platform possibly require ia64intrin.h, need testing */ +# define atomic_compare_and_swap(ptr, oldval, newval) __sync_val_compare_and_swap(ptr, oldval, newval) +#elif defined(_MSC_VER) +# include <windows.h> +# define atomic_compare_and_swap(ptr, oldval, newval) InterlockedCompareExchange(ptr, newval, oldval) +#elif defined(__sun) +# include <atomic.h> +# define atomic_compare_and_swap(ptr, oldval, newval) atomic_cas_32(ptr, oldval, newval) +#else +/* pray that it will work */ +# define atomic_compare_and_swap(ptr, oldval, newval) { if(*(ptr) == (oldval)) *(ptr) = (newval); } +# define NO_ATOMIC_BUILTINS +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* UTIL_H */ @@ -493,6 +493,8 @@ Configuration: --no-system-liblzma use cmake-provided liblzma library (default) --system-libarchive use system-installed libarchive library --no-system-libarchive use cmake-provided libarchive library (default) + --system-librhash use system-installed librhash library + --no-system-librhash use cmake-provided librhash library (default) --qt-gui build the Qt-based GUI (requires Qt >= 4.2) --no-qt-gui do not build the Qt-based GUI (default) @@ -726,10 +728,10 @@ while test $# != 0; do --init=*) cmake_init_file=`cmake_arg "$1"` ;; --system-libs) cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARIES=1" ;; --no-system-libs) cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARIES=0" ;; - --system-bzip2|--system-curl|--system-expat|--system-jsoncpp|--system-libarchive|--system-zlib|--system-liblzma) + --system-bzip2|--system-curl|--system-expat|--system-jsoncpp|--system-libarchive|--system-librhash|--system-zlib|--system-liblzma) lib=`cmake_arg "$1" "--system-"` cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARY_`cmake_toupper $lib`=1" ;; - --no-system-bzip2|--no-system-curl|--no-system-expat|--no-system-jsoncpp|--no-system-libarchive|--no-system-zlib|--no-system-liblzma) + --no-system-bzip2|--no-system-curl|--no-system-expat|--no-system-jsoncpp|--no-system-libarchive|--no-system-librhash|--no-system-zlib|--no-system-liblzma) lib=`cmake_arg "$1" "--no-system-"` cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARY_`cmake_toupper $lib`=0" ;; --qt-gui) cmake_bootstrap_qt_gui="1" ;; |