diff --git a/JMMContracts/JMMContracts.csproj b/JMMContracts/JMMContracts.csproj index 01889de1e..62384fa7f 100644 --- a/JMMContracts/JMMContracts.csproj +++ b/JMMContracts/JMMContracts.csproj @@ -32,13 +32,14 @@ prompt 4 false + AnyCPU true bin\x86\Debug\ DEBUG;TRACE full - x86 + x64 prompt true true @@ -187,6 +188,10 @@ + + + + ecx=_nLength mov esi, ebp - lea edi, [edi+m_nBuffer+eax] + lea edi, [edi+m_pBuffer+eax] rep movsb get_out: popa - ret + ret 12 MD4_Add_p5 ENDP - end + end \ No newline at end of file diff --git a/hasher/MD5.cpp b/hasher/MD5.cpp new file mode 100644 index 000000000..84880c957 --- /dev/null +++ b/hasher/MD5.cpp @@ -0,0 +1,276 @@ +// +// MD5.cpp +// +// Copyright (c) Shareaza Development Team, 2002-2008. +// This file is part of SHAREAZA (shareaza.sourceforge.net) +// +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Shareaza is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// other copyright notices: see end of file + +#include "StdAfx.h" +#include "MD5.h" + + +#ifdef HASHLIB_USE_ASM +extern "C" void __stdcall MD5_Add_p5(CMD5::MD5State*, const void* pData, std::size_t nLength); +#endif + +const unsigned char hashPadding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +CMD5::CMD5() +{ + Reset(); +} + +void CMD5::GetHash(__in_bcount(16) uchar* pHash) const +{ + std::transform(m_State.m_nState, + m_State.m_nState + sizeof(m_State.m_nState) / sizeof(m_State.m_nState[0]), + (uint32*)pHash, transformToLE< uint32 >); +} + +void CMD5::Reset() +{ + m_State.m_nCount = 0; + // Load magic initialization constants + m_State.m_nState[0] = 0x67452301; + m_State.m_nState[1] = 0xefcdab89; + m_State.m_nState[2] = 0x98badcfe; + m_State.m_nState[3] = 0x10325476; +} + +void CMD5::Finish() +{ + // Save number of bits + uint64 bits = transformToLE(m_State.m_nCount * 8); + // Pad out to 56 mod 64. + uint32 index = static_cast< uint32 >(m_State.m_nCount % m_State.blockSize); + Add(hashPadding, m_State.blockSize - sizeof(bits) - index + + (index < m_State.blockSize - sizeof(bits) ? 0 : m_State.blockSize)); + Add(&bits, sizeof(bits)); +} + +#ifdef HASHLIB_USE_ASM + +void CMD5::Add(const void* pData, std::size_t nLength) +{ + MD5_Add_p5(&m_State, pData, nLength); +} + +#else // HASHLIB_USE_ASM + +namespace +{ + // Constants for Transform routine. + template< uint32 tier, uint32 stage > struct S; + template<> struct S< 0, 0 > { static const uint32 value = 7; }; + template<> struct S< 0, 1 > { static const uint32 value = 12; }; + template<> struct S< 0, 2 > { static const uint32 value = 17; }; + template<> struct S< 0, 3 > { static const uint32 value = 22; }; + template<> struct S< 1, 0 > { static const uint32 value = 5; }; + template<> struct S< 1, 1 > { static const uint32 value = 9; }; + template<> struct S< 1, 2 > { static const uint32 value = 14; }; + template<> struct S< 1, 3 > { static const uint32 value = 20; }; + template<> struct S< 2, 0 > { static const uint32 value = 4; }; + template<> struct S< 2, 1 > { static const uint32 value = 11; }; + template<> struct S< 2, 2 > { static const uint32 value = 16; }; + template<> struct S< 2, 3 > { static const uint32 value = 23; }; + template<> struct S< 3, 0 > { static const uint32 value = 6; }; + template<> struct S< 3, 1 > { static const uint32 value = 10; }; + template<> struct S< 3, 2 > { static const uint32 value = 15; }; + template<> struct S< 3, 3 > { static const uint32 value = 21; }; + + // F transformation + template< uint32 round, uint32 magic > + __forceinline void F(const uint32* data, uint32& a, uint32 b, uint32 c, uint32 d) + { + static const uint32 x = round; + static const uint32 s = S< 0, round % 4 >::value; + a += (d ^ (b & (c ^ d))) + transformFromLE(data[x]) + magic; + a = rotateLeft(a, s) + b; + } + // G transformation + template< uint32 round, uint32 magic > + __forceinline void G(const uint32* data, uint32& a, uint32 b, uint32 c, uint32 d) + { + static const uint32 x = (1 + (round & 3) * 5 + (round & 12)) & 15; + static const uint32 s = S< 1, round % 4 >::value; + a += (c ^ (d & (b ^ c))) + transformFromLE(data[x]) + magic; + a = rotateLeft(a, s) + b; + } + // H transformation + template< uint32 round, uint32 magic > + __forceinline void H(const uint32* data, uint32& a, uint32 b, uint32 c, uint32 d) + { + static const uint32 x = (5 + (round & 7) * 3 + (round & 8)) & 15; + static const uint32 s = S< 2, round % 4 >::value; + a += (b ^ c ^ d) + transformFromLE(data[x]) + magic; + a = rotateLeft(a, s) + b; + } + // I transformation + template< uint32 round, uint32 magic > + __forceinline void I(const uint32* data, uint32& a, uint32 b, uint32 c, uint32 d) + { + static const uint32 x = ((round & 3) * 7 + (round & 4) * 3 + (round & 8)) & 15; + static const uint32 s = S< 3, round % 4 >::value; + a += (c ^ (b | ~d)) + transformFromLE(data[x]) + magic; + a = rotateLeft(a, s) + b; + } +} // namespace + +// MD5 basic transformation. Transforms state based on block. +void CMD5::Transform(const uint32* data) +{ + uint32 a = m_State.m_nState[0]; + uint32 b = m_State.m_nState[1]; + uint32 c = m_State.m_nState[2]; + uint32 d = m_State.m_nState[3]; + + F< 0, 0xd76aa478 >(data, a, b, c, d); + F< 1, 0xe8c7b756 >(data, d, a, b, c); + F< 2, 0x242070db >(data, c, d, a, b); + F< 3, 0xc1bdceee >(data, b, c, d, a); + F< 4, 0xf57c0faf >(data, a, b, c, d); + F< 5, 0x4787c62a >(data, d, a, b, c); + F< 6, 0xa8304613 >(data, c, d, a, b); + F< 7, 0xfd469501 >(data, b, c, d, a); + F< 8, 0x698098d8 >(data, a, b, c, d); + F< 9, 0x8b44f7af >(data, d, a, b, c); + F< 10, 0xffff5bb1 >(data, c, d, a, b); + F< 11, 0x895cd7be >(data, b, c, d, a); + F< 12, 0x6b901122 >(data, a, b, c, d); + F< 13, 0xfd987193 >(data, d, a, b, c); + F< 14, 0xa679438e >(data, c, d, a, b); + F< 15, 0x49b40821 >(data, b, c, d, a); + + G< 0, 0xf61e2562 >(data, a, b, c, d); + G< 1, 0xc040b340 >(data, d, a, b, c); + G< 2, 0x265e5a51 >(data, c, d, a, b); + G< 3, 0xe9b6c7aa >(data, b, c, d, a); + G< 4, 0xd62f105d >(data, a, b, c, d); + G< 5, 0x02441453 >(data, d, a, b, c); + G< 6, 0xd8a1e681 >(data, c, d, a, b); + G< 7, 0xe7d3fbc8 >(data, b, c, d, a); + G< 8, 0x21e1cde6 >(data, a, b, c, d); + G< 9, 0xc33707d6 >(data, d, a, b, c); + G< 10, 0xf4d50d87 >(data, c, d, a, b); + G< 11, 0x455a14ed >(data, b, c, d, a); + G< 12, 0xa9e3e905 >(data, a, b, c, d); + G< 13, 0xfcefa3f8 >(data, d, a, b, c); + G< 14, 0x676f02d9 >(data, c, d, a, b); + G< 15, 0x8d2a4c8a >(data, b, c, d, a); + + H< 0, 0xfffa3942 >(data, a, b, c, d); + H< 1, 0x8771f681 >(data, d, a, b, c); + H< 2, 0x6d9d6122 >(data, c, d, a, b); + H< 3, 0xfde5380c >(data, b, c, d, a); + H< 4, 0xa4beea44 >(data, a, b, c, d); + H< 5, 0x4bdecfa9 >(data, d, a, b, c); + H< 6, 0xf6bb4b60 >(data, c, d, a, b); + H< 7, 0xbebfbc70 >(data, b, c, d, a); + H< 8, 0x289b7ec6 >(data, a, b, c, d); + H< 9, 0xeaa127fa >(data, d, a, b, c); + H< 10, 0xd4ef3085 >(data, c, d, a, b); + H< 11, 0x04881d05 >(data, b, c, d, a); + H< 12, 0xd9d4d039 >(data, a, b, c, d); + H< 13, 0xe6db99e5 >(data, d, a, b, c); + H< 14, 0x1fa27cf8 >(data, c, d, a, b); + H< 15, 0xc4ac5665 >(data, b, c, d, a); + + I< 0, 0xf4292244 >(data, a, b, c, d); + I< 1, 0x432aff97 >(data, d, a, b, c); + I< 2, 0xab9423a7 >(data, c, d, a, b); + I< 3, 0xfc93a039 >(data, b, c, d, a); + I< 4, 0x655b59c3 >(data, a, b, c, d); + I< 5, 0x8f0ccc92 >(data, d, a, b, c); + I< 6, 0xffeff47d >(data, c, d, a, b); + I< 7, 0x85845dd1 >(data, b, c, d, a); + I< 8, 0x6fa87e4f >(data, a, b, c, d); + I< 9, 0xfe2ce6e0 >(data, d, a, b, c); + I< 10, 0xa3014314 >(data, c, d, a, b); + I< 11, 0x4e0811a1 >(data, b, c, d, a); + I< 12, 0xf7537e82 >(data, a, b, c, d); + I< 13, 0xbd3af235 >(data, d, a, b, c); + I< 14, 0x2ad7d2bb >(data, c, d, a, b); + I< 15, 0xeb86d391 >(data, b, c, d, a); + + m_State.m_nState[0] += a; + m_State.m_nState[1] += b; + m_State.m_nState[2] += c; + m_State.m_nState[3] += d; +} + +void CMD5::Add(const void* pData, std::size_t nLength) +{ + // Update number of bytes + const char* input = static_cast< const char* >(pData); + { + uint32 index = static_cast< uint32 >(m_State.m_nCount % m_State.blockSize); + m_State.m_nCount += nLength; + if (index) + { + // buffer has some data already - lets fill it + // before doing the rest of the transformation on the original data + if (index + nLength < m_State.blockSize) + { + std::memcpy(m_State.m_oBuffer + index, input, nLength); + return; + } + std::memcpy(m_State.m_oBuffer + index, input, m_State.blockSize - index); + nLength -= m_State.blockSize - index; + input += m_State.blockSize - index; + Transform(reinterpret_cast< const uint32* >(m_State.m_oBuffer)); + } + } + // Transform as many times as possible using the original data stream + const char* const end = input + nLength - nLength % m_State.blockSize; + nLength %= m_State.blockSize; + for (; input != end; input += m_State.blockSize) + Transform(reinterpret_cast< const uint32* >(input)); + // Buffer remaining input + if (nLength) + std::memcpy(m_State.m_oBuffer, input, nLength); +} + +#endif // HASHLIB_USE_ASM + +// MD5.CPP - RSA Data Security, Inc., MD5 message-digest algorithm + +// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +// Copyrights reserved. +// +// License to copy and use this software is granted provided that it +// is identified as the "RSA Data Security, Inc. MD5 Message-Digest +// Algorithm" in all material mentioning or referencing this software +// or this function. +// +// License is also granted to make and use derivative works provided +// that such works are identified as "derived from the RSA Data +// Security, Inc. MD5 Message-Digest Algorithm" in all material +// mentioning or referencing the derived work. +// +// RSA Data Security, Inc. makes no representations concerning either +// the merchantability of this software or the suitability of this +// software for any particular purpose. It is provided "as is" +// without express or implied warranty of any kind. +// +// These notices must be retained in any copies of any part of this +// documentation and/or software. diff --git a/hasher/MD5.h b/hasher/MD5.h new file mode 100644 index 000000000..eaf4038f9 --- /dev/null +++ b/hasher/MD5.h @@ -0,0 +1,58 @@ +// +// MD5.h +// +// Copyright (c) Shareaza Development Team, 2002-2014. +// This file is part of SHAREAZA (shareaza.sourceforge.net) +// +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Shareaza is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#pragma once +#include "Utility.hpp" + +class CMD5 +{ +public: + CMD5(); + ~CMD5() {} + + void Reset(); + void Add(const void* pData, size_t nLength); + void Finish(); + + struct Digest // 128 bit + { + uint32& operator[](size_t i) { return data[i]; } + const uint32& operator[](size_t i) const { return data[i]; } + uint32 data[4]; + }; + + void GetHash(__in_bcount(16) uchar* pHash) const; + + struct MD5State + { + static const size_t blockSize = 64; + uint64 m_nCount; + uint32 m_nState[4]; + uchar m_oBuffer[blockSize]; + }; + +private: + MD5State m_State; + +#ifndef HASHLIB_USE_ASM + __forceinline void Transform(const uint32* data); +#endif +}; diff --git a/hasher/MD5_asm.asm b/hasher/MD5_asm.asm new file mode 100644 index 000000000..24152d9a6 --- /dev/null +++ b/hasher/MD5_asm.asm @@ -0,0 +1,303 @@ +; ##################################################################################################################### +; +; MD5_asm.asm +; +; Copyright (c) Shareaza Development Team, 2002-2007. +; This file is part of SHAREAZA (shareaza.sourceforge.net) +; +; Shareaza is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation; either version 2 of +; the License, or (at your option) any later version. +; +; Shareaza is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Shareaza; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ##################################################################################################################### +; +; MD5_asm - Implementation of MD5 for x86 - use together with MD5.cpp and MD5.h +; +; ##################################################################################################################### + + .586p + .model flat, stdcall + option casemap:none ; case sensitive + option prologue:none ; we generate our own entry/exit code + option epilogue:none + +; ##################################################################################################################### + + +m_nCount0 equ 0 +m_nCount1 equ 4 + +m_nState0 equ 8 ; offsets as laid out in MD5.h +m_nState1 equ 12 +m_nState2 equ 16 +m_nState3 equ 20 + +m_pBuffer equ 24 + +; Some magic numbers for Transform... +MD5_S11 equ 7 +MD5_S12 equ 12 +MD5_S13 equ 17 +MD5_S14 equ 22 +MD5_S21 equ 5 +MD5_S22 equ 9 +MD5_S23 equ 14 +MD5_S24 equ 20 +MD5_S31 equ 4 +MD5_S32 equ 11 +MD5_S33 equ 16 +MD5_S34 equ 23 +MD5_S41 equ 6 +MD5_S42 equ 10 +MD5_S43 equ 15 +MD5_S44 equ 21 + +MD5FF MACRO count:REQ,s:REQ,ac:REQ +; a = b+(a+x[count]+ac+((b&c)|(~b&d)))rol s +; a = b+(a+x[count]+ax+(d^(b&(c^d))))rol s + mov reg_temp1, reg_c +reg_t textequ reg_temp1 +reg_temp1 textequ reg_c +reg_c textequ reg_t + xor reg_temp1, reg_d + add reg_a, [reg_base+count*4] + and reg_temp1, reg_b + add reg_a, ac + xor reg_temp1, reg_d + add reg_a, reg_temp1 + rol reg_a, s + add reg_a, reg_b +reg_t textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_a +reg_a textequ reg_t + ENDM + + +MD5GG MACRO count:REQ,s:REQ,ac:REQ +; a = b+(a+x[count]+ac+((d&b)|(~d&c)))rol s +; a = b+(a+x[count]+ac+(c^(d&(b^c))))rols s + mov reg_temp1, reg_b +reg_t textequ reg_temp1 +reg_temp1 textequ reg_b +reg_b textequ reg_t + xor reg_temp1, reg_c + add reg_a, [reg_base+count*4] + and reg_temp1, reg_d + add reg_a, ac + xor reg_temp1, reg_c + add reg_a, reg_temp1 + rol reg_a, s + add reg_a, reg_b +reg_t textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_a +reg_a textequ reg_t + ENDM + +MD5HH MACRO count:REQ,s:REQ,ac:REQ +; a = b+(a+x[count]+ac+(b^c^d)) rol s + mov reg_temp1, reg_b +reg_t textequ reg_temp1 +reg_temp1 textequ reg_b +reg_b textequ reg_t + xor reg_temp1, reg_c + add reg_a, [reg_base+count*4] + xor reg_temp1, reg_d + add reg_a, ac + add reg_a, reg_temp1 + rol reg_a, s + add reg_a, reg_b +reg_t textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_a +reg_a textequ reg_t + ENDM + +MD5II MACRO count:REQ,s:REQ,ac:REQ +; a = b+(a+x[count]+ac+(c^(~d|b))) rol s + mov reg_temp1, reg_d +reg_t textequ reg_temp1 +reg_temp1 textequ reg_d +reg_d textequ reg_t + not reg_temp1 + add reg_a, [reg_base+count*4] + or reg_temp1, reg_b + add reg_a, ac + xor reg_temp1, reg_c + add reg_a, reg_temp1 + rol reg_a, s + add reg_a, reg_b +reg_t textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_a +reg_a textequ reg_t + ENDM + + .code + +MD5_Transform_p5 PROC ; we expect ebp to point to the Data stream + ; all other registers (eax,ebx,ecx,edx,esi,edi) will be destroyed +__this textequ <[esp+32+2*4]> ; 1*pusha+2*call + +; set alias for registers +reg_a textequ +reg_b textequ +reg_c textequ +reg_d textequ +reg_temp1 textequ +reg_temp2 textequ +reg_base textequ + mov reg_temp2, __this + mov reg_a, [reg_temp2+m_nState0] + mov reg_b, [reg_temp2+m_nState1] + mov reg_c, [reg_temp2+m_nState2] + mov reg_d, [reg_temp2+m_nState3] +; round 1 + MD5FF 0, MD5_S11,0D76AA478H ; 1 + MD5FF 1, MD5_S12,0E8C7B756H ; 2 + MD5FF 2, MD5_S13, 242070DBH ; 3 + MD5FF 3, MD5_S14,0C1BDCEEEH ; 4 + MD5FF 4, MD5_S11,0F57C0FAFH ; 5 + MD5FF 5, MD5_S12, 4787C62AH ; 6 + MD5FF 6, MD5_S13,0A8304613H ; 7 + MD5FF 7, MD5_S14,0FD469501H ; 8 + MD5FF 8, MD5_S11, 698098D8H ; 9 + MD5FF 9, MD5_S12, 8B44F7AFH ; 10 + MD5FF 10, MD5_S13,0FFFF5BB1H ; 11 + MD5FF 11, MD5_S14, 895CD7BEH ; 12 + MD5FF 12, MD5_S11, 6B901122H ; 13 + MD5FF 13, MD5_S12,0FD987193H ; 14 + MD5FF 14, MD5_S13,0A679438EH ; 15 + MD5FF 15, MD5_S14, 49B40821H ; 16 +; round 2 + MD5GG 1, MD5_S21,0F61E2562H ; 17 + MD5GG 6, MD5_S22,0C040B340H ; 18 + MD5GG 11, MD5_S23, 265E5A51H ; 19 + MD5GG 0, MD5_S24,0E9B6C7AAH ; 20 + MD5GG 5, MD5_S21,0D62F105DH ; 21 + MD5GG 10, MD5_S22, 2441453H ; 22 + MD5GG 15, MD5_S23,0D8A1E681H ; 23 + MD5GG 4, MD5_S24,0E7D3FBC8H ; 24 + MD5GG 9, MD5_S21, 21E1CDE6H ; 25 + MD5GG 14, MD5_S22,0C33707D6H ; 26 + MD5GG 3, MD5_S23,0F4D50D87H ; 27 + MD5GG 8, MD5_S24, 455A14EDH ; 28 + MD5GG 13, MD5_S21,0A9E3E905H ; 29 + MD5GG 2, MD5_S22,0FCEFA3F8H ; 30 + MD5GG 7, MD5_S23, 676F02D9H ; 31 + MD5GG 12, MD5_S24, 8D2A4C8AH ; 32 +; round 3 + MD5HH 5, MD5_S31,0FFFA3942H ; 33 + MD5HH 8, MD5_S32, 8771F681H ; 34 + MD5HH 11, MD5_S33, 6D9D6122H ; 35 + MD5HH 14, MD5_S34,0FDE5380CH ; 36 + MD5HH 1, MD5_S31,0A4BEEA44H ; 37 + MD5HH 4, MD5_S32, 4BDECFA9H ; 38 + MD5HH 7, MD5_S33,0F6BB4B60H ; 39 + MD5HH 10, MD5_S34,0BEBFBC70H ; 40 + MD5HH 13, MD5_S31, 289B7EC6H ; 41 + MD5HH 0, MD5_S32,0EAA127FAH ; 42 + MD5HH 3, MD5_S33,0D4EF3085H ; 43 + MD5HH 6, MD5_S34, 4881D05H ; 44 + MD5HH 9, MD5_S31,0D9D4D039H ; 45 + MD5HH 12, MD5_S32,0E6DB99E5H ; 46 + MD5HH 15, MD5_S33, 1FA27CF8H ; 47 + MD5HH 2, MD5_S34,0C4AC5665H ; 48 +; round 4 + MD5II 0, MD5_S41,0F4292244H ; 49 + MD5II 7, MD5_S42, 432AFF97H ; 50 + MD5II 14, MD5_S43,0AB9423A7H ; 51 + MD5II 5, MD5_S44,0FC93A039H ; 52 + MD5II 12, MD5_S41, 655B59C3H ; 53 + MD5II 3, MD5_S42, 8F0CCC92H ; 54 + MD5II 10, MD5_S43,0FFEFF47DH ; 55 + MD5II 1, MD5_S44, 85845DD1H ; 56 + MD5II 8, MD5_S41, 6FA87E4FH ; 57 + MD5II 15, MD5_S42,0FE2CE6E0H ; 58 + MD5II 6, MD5_S43,0A3014314H ; 59 + MD5II 13, MD5_S44, 4E0811A1H ; 60 + MD5II 4, MD5_S41,0F7537E82H ; 61 + MD5II 11, MD5_S42,0BD3AF235H ; 62 + MD5II 2, MD5_S43, 2AD7D2BBH ; 63 + MD5II 9, MD5_S44,0EB86D391H ; 64 + add [reg_temp2+m_nState0], reg_a + add [reg_temp2+m_nState1], reg_b + add [reg_temp2+m_nState2], reg_c + add [reg_temp2+m_nState3], reg_d + ret +MD5_Transform_p5 ENDP + +MD5_Add_p5 PROC PUBLIC, _this:DWORD, _Data:DWORD, _nLength:DWORD + pusha +__this textequ <[esp+36]> ; different offset due to pusha +__Data textequ <[esp+40]> +__nLength textequ <[esp+44]> + mov ecx, __nLength + and ecx, ecx + jz get_out + xor edx, edx + mov ebp, __Data + mov edi, __this + mov ebx, [edi+m_nCount0] + mov eax, ebx + add ebx, ecx + mov [edi+m_nCount0], ebx + adc [edi+m_nCount1], edx + and eax, 63 + jnz partial_buffer +full_blocks: mov ecx, __nLength + and ecx, ecx + jz get_out + sub ecx, 64 + jb end_of_stream + mov __nLength, ecx + call MD5_Transform_p5 + add ebp, 64 + jmp full_blocks +end_of_stream: mov edi, __this + mov esi, ebp + lea edi, [edi+m_pBuffer] + add ecx, 64 + rep movsb + jmp get_out +partial_buffer: add ecx, eax ; eax = offset in buffer, ecx = _nLength + cmp ecx, 64 + jb short_stream ; we can't fill the buffer + mov ecx, -64 + add ecx, eax + add __nLength, ecx ; _nlength += (offset-64) +@@: mov bl, [ebp] + inc ebp + mov byte ptr [edi+m_pBuffer+64+ecx], bl + inc ecx + jnz @B ; offset = 64 + mov __Data, ebp + lea ebp, [edi+m_pBuffer] + call MD5_Transform_p5 + mov ebp, __Data + jmp full_blocks +short_stream: sub ecx, eax ; --> ecx=_nLength + mov esi, ebp + lea edi, [edi+m_pBuffer+eax] + rep movsb +get_out: popa + ret 12 + +MD5_Add_p5 ENDP + + end diff --git a/hasher/SHA.cpp b/hasher/SHA.cpp index b5d947bfa..a1237eb96 100644 --- a/hasher/SHA.cpp +++ b/hasher/SHA.cpp @@ -1,251 +1,372 @@ // -// This file is part of the aMule Project. +// MD5.cpp // -// Copyright (c) 2003-2006 Angel Vidal (Kry) ( kry@amule.org ) -// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org ) +// Copyright (c) Shareaza Development Team, 2002-2008. +// This file is part of SHAREAZA (shareaza.sourceforge.net) // -// Any parts of this program derived from the xMule, lMule or eMule project, -// or contributed by third-party developers are copyrighted by their -// respective authors. +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, +// Shareaza is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // -// Kry - Modified version of the original SHA.cpp to work on linux and -// use wxWidgets. Original license follows. +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: +// other copyright notices: see end of file - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; +#include "StdAfx.h" +#include "SHA.h" - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER +#ifdef HASHLIB_USE_ASM +extern "C" void __stdcall SHA1_Add_p5(CSHA::SHA1State*, const void* pData, std::size_t nLength); +#endif - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 30/11/2002 - - This is a byte oriented version of SHA1 that operates on arrays of bytes - stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor -*/ -#include "stdafx.h" -#include "SHA.h" +const unsigned char hashPadding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; CSHA::CSHA() { Reset(); } -/* - To obtain the highest speed on processors with 32-bit words, this code - needs to determine the order in which bytes are packed into such words. - The following block of code is an attempt to capture the most obvious - ways in which various environemnts specify their endian definitions. - It may well fail, in which case the definitions will need to be set by - editing at the points marked **** EDIT HERE IF NECESSARY **** below. -*/ -#define SHA_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ -#define SHA_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ - -// Kry - Use wxWidgets byte order definitions -#if wxBYTE_ORDER == wxLITTLE_ENDIAN - #define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN -#else - #define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN -#endif - -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) - -#if (PLATFORM_BYTE_ORDER == SHA_BIG_ENDIAN) -#define swap_b32(x) (x) -#elif defined(bswap_32) -#define swap_b32(x) bswap_32(x) -#else -#define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00)) -#endif - -#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) - -/* reverse byte order in 32-bit words */ -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* A normal version as set out in the FIPS. This version uses */ -/* partial loop unrolling and is optimised for the Pentium 4 */ - -#define rnd(f,k) t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; e = d; d = c; c = rotl32(b, 30); b = t - -void CSHA::Compile() +void CSHA::GetHash(__in_bcount(20) uchar* pHash) const { - uint32 w[80], i, a, b, c, d, e, t; - - /* note that words are compiled from the buffer into 32-bit */ - /* words in big-endian order so an order reversal is needed */ - /* here on little endian machines */ - for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i) - w[i] = swap_b32(m_nBuffer[i]); - - for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i) - w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); - - a = m_nHash[0]; - b = m_nHash[1]; - c = m_nHash[2]; - d = m_nHash[3]; - e = m_nHash[4]; - - for(i = 0; i < 20; ++i) - { - rnd(ch, 0x5a827999); - } - - for(i = 20; i < 40; ++i) - { - rnd(parity, 0x6ed9eba1); - } - - for(i = 40; i < 60; ++i) - { - rnd(maj, 0x8f1bbcdc); - } - - for(i = 60; i < 80; ++i) - { - rnd(parity, 0xca62c1d6); - } - - m_nHash[0] += a; - m_nHash[1] += b; - m_nHash[2] += c; - m_nHash[3] += d; - m_nHash[4] += e; + std::transform(m_State.m_nState, + m_State.m_nState + sizeof(m_State.m_nState) / sizeof(m_State.m_nState[0]), + (uint32*)pHash, transformToBE< uint32 >); } void CSHA::Reset() { - m_nCount[0] = m_nCount[1] = 0; - m_nHash[0] = 0x67452301; - m_nHash[1] = 0xefcdab89; - m_nHash[2] = 0x98badcfe; - m_nHash[3] = 0x10325476; - m_nHash[4] = 0xc3d2e1f0; + m_State.m_nCount = 0; + m_State.m_nState[0] = 0x67452301; + m_State.m_nState[1] = 0xefcdab89; + m_State.m_nState[2] = 0x98badcfe; + m_State.m_nState[3] = 0x10325476; + m_State.m_nState[4] = 0xc3d2e1f0; } -void CSHA::GetHash(CAICHHash& Hash) +void CSHA::Finish() { - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words*/ + // Save number of bits + uint64 bits = transformToBE(m_State.m_nCount * 8); + // Pad out to 56 mod 64. + uint32 index = static_cast< uint32 >(m_State.m_nCount % m_State.blockSize); + Add(hashPadding, m_State.blockSize - sizeof(bits) - index + + (index < m_State.blockSize - sizeof(bits) ? 0 : m_State.blockSize)); + Add(&bits, sizeof(bits)); +} - //wxASSERT( Hash.GetHashSize() == 20 ); - for(int i = 0; i < SHA1_DIGEST_SIZE; ++i) - Hash.GetRawHash()[i] = (unsigned char)(m_nHash[i >> 2] >> 8 * (~i & 3)); +#ifdef HASHLIB_USE_ASM + +void CSHA::Add(const void* pData, std::size_t nLength) +{ + SHA1_Add_p5(&m_State, pData, nLength); } -/* SHA1 hash data in an array of bytes into hash buffer and call the */ -/* hash_compile function as required. */ +#else // HASHLIB_USE_ASM -void CSHA::Add(const void* pData, uint32 nLength) +CSHA::TransformArray::TransformArray(const uint32* const buffer) { - const unsigned char* data = (const unsigned char*)pData; - - uint32 pos = (uint32)(m_nCount[0] & SHA1_MASK), - space = SHA1_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((m_nCount[0] += nLength) < nLength) - ++(m_nCount[1]); - - while(nLength >= space) /* tranfer whole blocks while possible */ - { - memcpy(((unsigned char*)m_nBuffer) + pos, sp, space); - sp += space; nLength -= space; space = SHA1_BLOCK_SIZE; pos = 0; - Compile(); - } - - memcpy(((unsigned char*)m_nBuffer) + pos, sp, nLength); + m_buffer[0] = transformFromBE(buffer[0]), + m_buffer[1] = transformFromBE(buffer[1]), + m_buffer[2] = transformFromBE(buffer[2]), + m_buffer[3] = transformFromBE(buffer[3]), + m_buffer[4] = transformFromBE(buffer[4]), + m_buffer[5] = transformFromBE(buffer[5]), + m_buffer[6] = transformFromBE(buffer[6]), + m_buffer[7] = transformFromBE(buffer[7]), + m_buffer[8] = transformFromBE(buffer[8]), + m_buffer[9] = transformFromBE(buffer[9]), + m_buffer[10] = transformFromBE(buffer[10]), + m_buffer[11] = transformFromBE(buffer[11]), + m_buffer[12] = transformFromBE(buffer[12]), + m_buffer[13] = transformFromBE(buffer[13]), + m_buffer[14] = transformFromBE(buffer[14]), + m_buffer[15] = transformFromBE(buffer[15]); + + m_buffer[16] = rotateLeft(m_buffer[0] ^ m_buffer[2] ^ m_buffer[8] ^ m_buffer[13], 1); + m_buffer[17] = rotateLeft(m_buffer[1] ^ m_buffer[3] ^ m_buffer[9] ^ m_buffer[14], 1); + m_buffer[18] = rotateLeft(m_buffer[2] ^ m_buffer[4] ^ m_buffer[10] ^ m_buffer[15], 1); + m_buffer[19] = rotateLeft(m_buffer[3] ^ m_buffer[5] ^ m_buffer[11] ^ m_buffer[16], 1); + m_buffer[20] = rotateLeft(m_buffer[4] ^ m_buffer[6] ^ m_buffer[12] ^ m_buffer[17], 1); + m_buffer[21] = rotateLeft(m_buffer[5] ^ m_buffer[7] ^ m_buffer[13] ^ m_buffer[18], 1); + m_buffer[22] = rotateLeft(m_buffer[6] ^ m_buffer[8] ^ m_buffer[14] ^ m_buffer[19], 1); + m_buffer[23] = rotateLeft(m_buffer[7] ^ m_buffer[9] ^ m_buffer[15] ^ m_buffer[20], 1); + m_buffer[24] = rotateLeft(m_buffer[8] ^ m_buffer[10] ^ m_buffer[16] ^ m_buffer[21], 1); + m_buffer[25] = rotateLeft(m_buffer[9] ^ m_buffer[11] ^ m_buffer[17] ^ m_buffer[22], 1); + m_buffer[26] = rotateLeft(m_buffer[10] ^ m_buffer[12] ^ m_buffer[18] ^ m_buffer[23], 1); + m_buffer[27] = rotateLeft(m_buffer[11] ^ m_buffer[13] ^ m_buffer[19] ^ m_buffer[24], 1); + m_buffer[28] = rotateLeft(m_buffer[12] ^ m_buffer[14] ^ m_buffer[20] ^ m_buffer[25], 1); + m_buffer[29] = rotateLeft(m_buffer[13] ^ m_buffer[15] ^ m_buffer[21] ^ m_buffer[26], 1); + m_buffer[30] = rotateLeft(m_buffer[14] ^ m_buffer[16] ^ m_buffer[22] ^ m_buffer[27], 1); + m_buffer[31] = rotateLeft(m_buffer[15] ^ m_buffer[17] ^ m_buffer[23] ^ m_buffer[28], 1); + + m_buffer[32] = rotateLeft(m_buffer[16] ^ m_buffer[18] ^ m_buffer[24] ^ m_buffer[29], 1); + m_buffer[33] = rotateLeft(m_buffer[17] ^ m_buffer[19] ^ m_buffer[25] ^ m_buffer[30], 1); + m_buffer[34] = rotateLeft(m_buffer[18] ^ m_buffer[20] ^ m_buffer[26] ^ m_buffer[31], 1); + m_buffer[35] = rotateLeft(m_buffer[19] ^ m_buffer[21] ^ m_buffer[27] ^ m_buffer[32], 1); + m_buffer[36] = rotateLeft(m_buffer[20] ^ m_buffer[22] ^ m_buffer[28] ^ m_buffer[33], 1); + m_buffer[37] = rotateLeft(m_buffer[21] ^ m_buffer[23] ^ m_buffer[29] ^ m_buffer[34], 1); + m_buffer[38] = rotateLeft(m_buffer[22] ^ m_buffer[24] ^ m_buffer[30] ^ m_buffer[35], 1); + m_buffer[39] = rotateLeft(m_buffer[23] ^ m_buffer[25] ^ m_buffer[31] ^ m_buffer[36], 1); + m_buffer[40] = rotateLeft(m_buffer[24] ^ m_buffer[26] ^ m_buffer[32] ^ m_buffer[37], 1); + m_buffer[41] = rotateLeft(m_buffer[25] ^ m_buffer[27] ^ m_buffer[33] ^ m_buffer[38], 1); + m_buffer[42] = rotateLeft(m_buffer[26] ^ m_buffer[28] ^ m_buffer[34] ^ m_buffer[39], 1); + m_buffer[43] = rotateLeft(m_buffer[27] ^ m_buffer[29] ^ m_buffer[35] ^ m_buffer[40], 1); + m_buffer[44] = rotateLeft(m_buffer[28] ^ m_buffer[30] ^ m_buffer[36] ^ m_buffer[41], 1); + m_buffer[45] = rotateLeft(m_buffer[29] ^ m_buffer[31] ^ m_buffer[37] ^ m_buffer[42], 1); + m_buffer[46] = rotateLeft(m_buffer[30] ^ m_buffer[32] ^ m_buffer[38] ^ m_buffer[43], 1); + m_buffer[47] = rotateLeft(m_buffer[31] ^ m_buffer[33] ^ m_buffer[39] ^ m_buffer[44], 1); + + m_buffer[48] = rotateLeft(m_buffer[32] ^ m_buffer[34] ^ m_buffer[40] ^ m_buffer[45], 1); + m_buffer[49] = rotateLeft(m_buffer[33] ^ m_buffer[35] ^ m_buffer[41] ^ m_buffer[46], 1); + m_buffer[50] = rotateLeft(m_buffer[34] ^ m_buffer[36] ^ m_buffer[42] ^ m_buffer[47], 1); + m_buffer[51] = rotateLeft(m_buffer[35] ^ m_buffer[37] ^ m_buffer[43] ^ m_buffer[48], 1); + m_buffer[52] = rotateLeft(m_buffer[36] ^ m_buffer[38] ^ m_buffer[44] ^ m_buffer[49], 1); + m_buffer[53] = rotateLeft(m_buffer[37] ^ m_buffer[39] ^ m_buffer[45] ^ m_buffer[50], 1); + m_buffer[54] = rotateLeft(m_buffer[38] ^ m_buffer[40] ^ m_buffer[46] ^ m_buffer[51], 1); + m_buffer[55] = rotateLeft(m_buffer[39] ^ m_buffer[41] ^ m_buffer[47] ^ m_buffer[52], 1); + m_buffer[56] = rotateLeft(m_buffer[40] ^ m_buffer[42] ^ m_buffer[48] ^ m_buffer[53], 1); + m_buffer[57] = rotateLeft(m_buffer[41] ^ m_buffer[43] ^ m_buffer[49] ^ m_buffer[54], 1); + m_buffer[58] = rotateLeft(m_buffer[42] ^ m_buffer[44] ^ m_buffer[50] ^ m_buffer[55], 1); + m_buffer[59] = rotateLeft(m_buffer[43] ^ m_buffer[45] ^ m_buffer[51] ^ m_buffer[56], 1); + m_buffer[60] = rotateLeft(m_buffer[44] ^ m_buffer[46] ^ m_buffer[52] ^ m_buffer[57], 1); + m_buffer[61] = rotateLeft(m_buffer[45] ^ m_buffer[47] ^ m_buffer[53] ^ m_buffer[58], 1); + m_buffer[62] = rotateLeft(m_buffer[46] ^ m_buffer[48] ^ m_buffer[54] ^ m_buffer[59], 1); + m_buffer[63] = rotateLeft(m_buffer[47] ^ m_buffer[49] ^ m_buffer[55] ^ m_buffer[60], 1); + + m_buffer[64] = rotateLeft(m_buffer[48] ^ m_buffer[50] ^ m_buffer[56] ^ m_buffer[61], 1); + m_buffer[65] = rotateLeft(m_buffer[49] ^ m_buffer[51] ^ m_buffer[57] ^ m_buffer[62], 1); + m_buffer[66] = rotateLeft(m_buffer[50] ^ m_buffer[52] ^ m_buffer[58] ^ m_buffer[63], 1); + m_buffer[67] = rotateLeft(m_buffer[51] ^ m_buffer[53] ^ m_buffer[59] ^ m_buffer[64], 1); + m_buffer[68] = rotateLeft(m_buffer[52] ^ m_buffer[54] ^ m_buffer[60] ^ m_buffer[65], 1); + m_buffer[69] = rotateLeft(m_buffer[53] ^ m_buffer[55] ^ m_buffer[61] ^ m_buffer[66], 1); + m_buffer[70] = rotateLeft(m_buffer[54] ^ m_buffer[56] ^ m_buffer[62] ^ m_buffer[67], 1); + m_buffer[71] = rotateLeft(m_buffer[55] ^ m_buffer[57] ^ m_buffer[63] ^ m_buffer[68], 1); + m_buffer[72] = rotateLeft(m_buffer[56] ^ m_buffer[58] ^ m_buffer[64] ^ m_buffer[69], 1); + m_buffer[73] = rotateLeft(m_buffer[57] ^ m_buffer[59] ^ m_buffer[65] ^ m_buffer[70], 1); + m_buffer[74] = rotateLeft(m_buffer[58] ^ m_buffer[60] ^ m_buffer[66] ^ m_buffer[71], 1); + m_buffer[75] = rotateLeft(m_buffer[59] ^ m_buffer[61] ^ m_buffer[67] ^ m_buffer[72], 1); + m_buffer[76] = rotateLeft(m_buffer[60] ^ m_buffer[62] ^ m_buffer[68] ^ m_buffer[73], 1); + m_buffer[77] = rotateLeft(m_buffer[61] ^ m_buffer[63] ^ m_buffer[69] ^ m_buffer[74], 1); + m_buffer[78] = rotateLeft(m_buffer[62] ^ m_buffer[64] ^ m_buffer[70] ^ m_buffer[75], 1); + m_buffer[79] = rotateLeft(m_buffer[63] ^ m_buffer[65] ^ m_buffer[71] ^ m_buffer[76], 1); } -/* SHA1 final padding and digest calculation */ - -#if (PLATFORM_BYTE_ORDER == SHA_LITTLE_ENDIAN) -static uint32 mask[4] = - { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; -static uint32 bits[4] = - { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; -#else -static uint32 mask[4] = - { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; -static uint32 bits[4] = - { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; -#endif +namespace +{ + // ch transformation + template< uint32 round > + __forceinline void F(const CSHA::TransformArray& data, uint32& a, uint32& b, uint32 c, uint32 d, uint32 e, uint32& t) + { + t = a; + a = rotateLeft(a, 5) + e + data[round] + 0x5a827999 + (d ^ (b & (c ^ d))); + b = rotateLeft(b, 30); + } + // parity transformation + template< uint32 round > + __forceinline void G(const CSHA::TransformArray& data, uint32& a, uint32& b, uint32 c, uint32 d, uint32 e, uint32& t) + { + t = a; + a = rotateLeft(a, 5) + e + data[round + 20] + 0x6ed9eba1 + (b ^ c ^ d); + b = rotateLeft(b, 30); + } + // maj transformation + template< uint32 round > + __forceinline void H(const CSHA::TransformArray& data, uint32& a, uint32& b, uint32 c, uint32 d, uint32 e, uint32& t) + { + t = a; + a = rotateLeft(a, 5) + e + data[round + 40] + 0x8f1bbcdc + ((c & d) ^ (b & (c ^ d))); + b = rotateLeft(b, 30); + } + // parity transformation + template< uint32 round > + __forceinline void I(const CSHA::TransformArray& data, uint32& a, uint32& b, uint32 c, uint32 d, uint32 e, uint32& t) + { + t = a; + a = rotateLeft(a, 5) + e + data[round + 60] + 0xca62c1d6 + (b ^ c ^ d); + b = rotateLeft(b, 30); + } +} // namespace + +void CSHA::Transform(TransformArray w) +{ + uint32 a = m_State.m_nState[0]; + uint32 b = m_State.m_nState[1]; + uint32 c = m_State.m_nState[2]; + uint32 d = m_State.m_nState[3]; + uint32 e = m_State.m_nState[4]; + uint32 t; + + F< 0 >(w, a, b, c, d, e, t); + F< 1 >(w, a, t, b, c, d, e); + F< 2 >(w, a, e, t, b, c, d); + F< 3 >(w, a, d, e, t, b, c); + F< 4 >(w, a, c, d, e, t, b); + F< 5 >(w, a, b, c, d, e, t); + F< 6 >(w, a, t, b, c, d, e); + F< 7 >(w, a, e, t, b, c, d); + F< 8 >(w, a, d, e, t, b, c); + F< 9 >(w, a, c, d, e, t, b); + F< 10 >(w, a, b, c, d, e, t); + F< 11 >(w, a, t, b, c, d, e); + F< 12 >(w, a, e, t, b, c, d); + F< 13 >(w, a, d, e, t, b, c); + F< 14 >(w, a, c, d, e, t, b); + F< 15 >(w, a, b, c, d, e, t); + F< 16 >(w, a, t, b, c, d, e); + F< 17 >(w, a, e, t, b, c, d); + F< 18 >(w, a, d, e, t, b, c); + F< 19 >(w, a, c, d, e, t, b); + + G< 0 >(w, a, b, c, d, e, t); + G< 1 >(w, a, t, b, c, d, e); + G< 2 >(w, a, e, t, b, c, d); + G< 3 >(w, a, d, e, t, b, c); + G< 4 >(w, a, c, d, e, t, b); + G< 5 >(w, a, b, c, d, e, t); + G< 6 >(w, a, t, b, c, d, e); + G< 7 >(w, a, e, t, b, c, d); + G< 8 >(w, a, d, e, t, b, c); + G< 9 >(w, a, c, d, e, t, b); + G< 10 >(w, a, b, c, d, e, t); + G< 11 >(w, a, t, b, c, d, e); + G< 12 >(w, a, e, t, b, c, d); + G< 13 >(w, a, d, e, t, b, c); + G< 14 >(w, a, c, d, e, t, b); + G< 15 >(w, a, b, c, d, e, t); + G< 16 >(w, a, t, b, c, d, e); + G< 17 >(w, a, e, t, b, c, d); + G< 18 >(w, a, d, e, t, b, c); + G< 19 >(w, a, c, d, e, t, b); + + H< 0 >(w, a, b, c, d, e, t); + H< 1 >(w, a, t, b, c, d, e); + H< 2 >(w, a, e, t, b, c, d); + H< 3 >(w, a, d, e, t, b, c); + H< 4 >(w, a, c, d, e, t, b); + H< 5 >(w, a, b, c, d, e, t); + H< 6 >(w, a, t, b, c, d, e); + H< 7 >(w, a, e, t, b, c, d); + H< 8 >(w, a, d, e, t, b, c); + H< 9 >(w, a, c, d, e, t, b); + H< 10 >(w, a, b, c, d, e, t); + H< 11 >(w, a, t, b, c, d, e); + H< 12 >(w, a, e, t, b, c, d); + H< 13 >(w, a, d, e, t, b, c); + H< 14 >(w, a, c, d, e, t, b); + H< 15 >(w, a, b, c, d, e, t); + H< 16 >(w, a, t, b, c, d, e); + H< 17 >(w, a, e, t, b, c, d); + H< 18 >(w, a, d, e, t, b, c); + H< 19 >(w, a, c, d, e, t, b); + + I< 0 >(w, a, b, c, d, e, t); + I< 1 >(w, a, t, b, c, d, e); + I< 2 >(w, a, e, t, b, c, d); + I< 3 >(w, a, d, e, t, b, c); + I< 4 >(w, a, c, d, e, t, b); + I< 5 >(w, a, b, c, d, e, t); + I< 6 >(w, a, t, b, c, d, e); + I< 7 >(w, a, e, t, b, c, d); + I< 8 >(w, a, d, e, t, b, c); + I< 9 >(w, a, c, d, e, t, b); + I< 10 >(w, a, b, c, d, e, t); + I< 11 >(w, a, t, b, c, d, e); + I< 12 >(w, a, e, t, b, c, d); + I< 13 >(w, a, d, e, t, b, c); + I< 14 >(w, a, c, d, e, t, b); + I< 15 >(w, a, b, c, d, e, t); + I< 16 >(w, a, t, b, c, d, e); + I< 17 >(w, a, e, t, b, c, d); + I< 18 >(w, a, d, e, t, b, c); + I< 19 >(w, a, c, d, e, t, b); + + m_State.m_nState[0] += a; + m_State.m_nState[1] += b; + m_State.m_nState[2] += c; + m_State.m_nState[3] += d; + m_State.m_nState[4] += e; +} -void CSHA::Finish(CAICHHash& Hash) +void CSHA::Add(const void* pData, std::size_t nLength) { - uint32 i = (uint32)(m_nCount[0] & SHA1_MASK); - - /* mask out the rest of any partial 32-bit word and then set */ - /* the next byte to 0x80. On big-endian machines any bytes in */ - /* the buffer will be at the top end of 32 bit words, on little */ - /* endian machines they will be at the bottom. Hence the AND */ - /* and OR masks above are reversed for little endian systems */ - /* Note that we can always add the first padding byte at this */ - /* because the buffer always contains at least one empty slot */ - m_nBuffer[i >> 2] = (m_nBuffer[i >> 2] & mask[i & 3]) | bits[i & 3]; - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space pad and empty the buffer */ - if(i > SHA1_BLOCK_SIZE - 9) - { - if(i < 60) m_nBuffer[15] = 0; - Compile(); - i = 0; - } - else /* compute a word index for the empty buffer positions */ - i = (i >> 2) + 1; - - while(i < 14) /* and zero pad all but last two positions */ - m_nBuffer[i++] = 0; - - /* assemble the eight byte counter in in big-endian format */ - m_nBuffer[14] = swap_b32((m_nCount[1] << 3) | (m_nCount[0] >> 29)); - m_nBuffer[15] = swap_b32(m_nCount[0] << 3); - - Compile(); - GetHash(Hash); + // Update number of bytes + const char* input = static_cast< const char* >(pData); + { + uint32 index = static_cast< uint32 >(m_State.m_nCount % m_State.blockSize); + m_State.m_nCount += nLength; + if (index) + { + // buffer has some data already - lets fill it + // before doing the rest of the transformation on the original data + if (index + nLength < m_State.blockSize) + { + std::memcpy(m_State.m_oBuffer + index, input, nLength); + return; + } + std::memcpy(m_State.m_oBuffer + index, input, m_State.blockSize - index); + nLength -= m_State.blockSize - index; + input += m_State.blockSize - index; + Transform(reinterpret_cast< const uint32* >(m_State.m_oBuffer)); + } + } + // Transform as many times as possible using the original data stream + const char* const end = input + nLength - nLength % m_State.blockSize; + nLength %= m_State.blockSize; + for (; input != end; input += m_State.blockSize) + { + Transform(reinterpret_cast< const uint32* >(input)); + } + // Buffer remaining input + if (nLength) + std::memcpy(m_State.m_oBuffer, input, nLength); } + +#endif // HASHLIB_USE_ASM + +// --------------------------------------------------------------------------- +// Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. +// All rights reserved. + +// LICENSE TERMS + +// The free distribution and use of this software in both source and binary +// form is allowed (with or without changes) provided that: + +// 1. distributions of this source code include the above copyright +// notice, this list of conditions and the following disclaimer; + +// 2. distributions in binary form include the above copyright +// notice, this list of conditions and the following disclaimer +// in the documentation and/or other associated materials; + +// 3. the copyright holder's name is not used to endorse products +// built using this software without specific written permission. + +// ALTERNATIVELY, provided that this notice is retained in full, this product +// may be distributed under the terms of the GNU General Public License (GPL), +// in which case the provisions of the GPL apply INSTEAD OF those given above. +// +// DISCLAIMER + +// This software is provided 'as is' with no explicit or implied warranties +// in respect of its properties, including, but not limited to, correctness +// and/or fitness for purpose. +// --------------------------------------------------------------------------- +// Issue Date: 30/11/2002 + +// This is a byte oriented version of SHA1 that operates on arrays of bytes +// stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor \ No newline at end of file diff --git a/hasher/SHA.h b/hasher/SHA.h index f9175732c..a9efa0c4b 100644 --- a/hasher/SHA.h +++ b/hasher/SHA.h @@ -1,93 +1,69 @@ // -// This file is part of the aMule Project. +// SHA.h // -// Copyright (c) 2003-2006 Angel Vidal (Kry) ( kry@amule.org ) -// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org ) +// Copyright (c) Shareaza Development Team, 2002-2014. +// This file is part of SHAREAZA (shareaza.sourceforge.net) // -// Any parts of this program derived from the xMule, lMule or eMule project, -// or contributed by third-party developers are copyrighted by their -// respective authors. +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, +// Shareaza is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // -// Kry - Modified version of the original SHA.cpp to work on linux and -// use wxWidgets. Original license follows. +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. +#pragma once +#include "Utility.hpp" +class CSHA +{ +public: + CSHA(); + ~CSHA() {} - DISCLAIMER + void Reset(); + void Add(const void* pData, size_t nLength); + void Finish(); - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 30/11/2002 + struct Digest // 160 bit + { + uint32& operator[](size_t i) { return data[i]; } + const uint32& operator[](size_t i) const { return data[i]; } + uint32 data[5]; + }; - This is a byte oriented version of SHA1 that operates on arrays of bytes - stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor -*/ + void GetHash(__in_bcount(20) uchar* pHash) const; -#ifndef __SHA_H__ -#define __SHA_H__ +#ifndef HASHLIB_USE_ASM + struct TransformArray + { + __forceinline TransformArray(const uint32* const buffer); + __forceinline uint32 operator[](uint32 index) const + { + return m_buffer[index]; + } + uint32 m_buffer[80]; + }; +#endif -#include "ShaHashSet.h" + struct SHA1State + { + static const size_t blockSize = 64; + uint64 m_nCount; + uint32 m_nState[5]; + uchar m_oBuffer[blockSize]; + }; -class CSHA : public CAICHHashAlgo -{ -// Construction -public: - CSHA(); - virtual ~CSHA() {}; -// Operations -public: - virtual void Reset(); - virtual void Add(const void* pData, uint32 nLength); - virtual void Finish(CAICHHash& Hash); - virtual void GetHash(CAICHHash& Hash); -protected: - void Compile(); private: - uint32 m_nCount[2]; - uint32 m_nHash[5]; - uint32 m_nBuffer[16]; -}; - -#define SHA1_BLOCK_SIZE 64 -#define SHA1_DIGEST_SIZE 20 + SHA1State m_State; -#endif // __SHA_H__ +#ifndef HASHLIB_USE_ASM + __forceinline void Transform(const TransformArray w); +#endif +}; \ No newline at end of file diff --git a/hasher/SHAHashSet.cpp b/hasher/SHAHashSet.cpp deleted file mode 100644 index 86cbcf572..000000000 --- a/hasher/SHAHashSet.cpp +++ /dev/null @@ -1,957 +0,0 @@ -// -// This file is part of the aMule Project. -// -// Copyright (c) 2003-2006 Angel Vidal (Kry) ( kry@amule.org ) -// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org ) -// Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net ) -// -// Any parts of this program derived from the xMule, lMule or eMule project, -// or contributed by third-party developers are copyrighted by their -// respective authors. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -// -#include "StdAfx.h" -#include "SHAHashSet.h" -//#include "Types.h" -//#include "OPCodes.h" -//#include "amule.h" -//#include "MemFile.h" -//#include "KnownFile.h" -//#include "Preferences.h" -#include "SHA.h" -//#include "updownclient.h" -//#include "DownloadQueue.h" -//#include "PartFile.h" -//#include "Logger.h" -//#include - -#define ASSERT(b){if(!(b))printf("ASSERT!\n");} -#define VERIFY(b){if(!(b))printf("VERIFY!\n");} -void out(const char * str){ - printf("OUT: %s\n",str); -} - -//#include - -//using namespace std; - -/*#ifdef _DEBUG -#undef THIS_FILE -static char THIS_FILE[]=__FILE__; -#define new DEBUG_NEW -#endif*/ - -// for this version the limits are set very high, they might be lowered later -// to make a hash trustworthy, at least 10 unique Ips (255.255.128.0) must have send it -// and if we have received more than one hash for the file, one hash has to be send by more than 95% of all unique IPs -//#define MINUNIQUEIPS_TOTRUST 10 // how many unique IPs most have send us a hash to make it trustworthy -//#define MINPERCENTAGE_TOTRUST 92 // how many percentage of clients most have sent the same hash to make it trustworthy - -//CAICHRequestedDataList CAICHHashSet::m_liRequestedData; - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHash -/*wxString CAICHHash::GetString() const{ - return EncodeBase32(m_abyBuffer, HASHSIZE); -}*/ - - -/*void CAICHHash::Read(CFileDataIO* file) { - file->Read(m_abyBuffer,HASHSIZE); -} - - -void CAICHHash::Write(CFileDataIO* file) const{ - file->Write(m_abyBuffer,HASHSIZE); -}*/ - -/*unsigned int CAICHHash::DecodeBase32(const wxString &base32) -{ - return ::DecodeBase32(base32, HASHSIZE, m_abyBuffer); -} */ - - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHashTree - -CAICHHashTree::CAICHHashTree(uint64 nDataSize, bool bLeftBranch, uint64 nBaseSize){ - m_nDataSize = nDataSize; - m_nBaseSize = nBaseSize; - m_bIsLeftBranch = bLeftBranch; - m_pLeftTree = NULL; - m_pRightTree = NULL; - m_bHashValid = false; -} - -CAICHHashTree::~CAICHHashTree(){ - if (m_pLeftTree) - delete m_pLeftTree; - if (m_pRightTree) - delete m_pRightTree; -} - -// recursive -CAICHHashTree* CAICHHashTree::FindHash(uint64 nStartPos, uint64 nSize, uint8* nLevel){ - (*nLevel)++; - if (*nLevel > 22){ // sanity - ASSERT ( false ); - return false; - } - if (nStartPos + nSize > m_nDataSize){ // sanity - ASSERT ( false ); - return NULL; - } - if (nSize > m_nDataSize){ // sanity - ASSERT ( false ); - return NULL; - } - - if (nStartPos == 0 && nSize == m_nDataSize){ - // this is the searched hash - return this; - } - else if (m_nDataSize <= m_nBaseSize){ // sanity - // this is already the last level, cant go deeper - ASSERT( false ); - return NULL; - } - else{ - uint64 nBlocks = m_nDataSize / m_nBaseSize + ((m_nDataSize % m_nBaseSize != 0 )? 1:0); - uint64 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* m_nBaseSize; - uint64 nRight = m_nDataSize - nLeft; - if (nStartPos < nLeft){ - if (nStartPos + nSize > nLeft){ // sanity - ASSERT ( false ); - return NULL; - } - if (m_pLeftTree == NULL) - m_pLeftTree = new CAICHHashTree(nLeft, true, (nLeft <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pLeftTree->m_nDataSize == nLeft ); - } - return m_pLeftTree->FindHash(nStartPos, nSize, nLevel); - } - else{ - nStartPos -= nLeft; - if (nStartPos + nSize > nRight){ // sanity - ASSERT ( false ); - return NULL; - } - if (m_pRightTree == NULL) - m_pRightTree = new CAICHHashTree(nRight, false, (nRight <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pRightTree->m_nDataSize == nRight ); - } - return m_pRightTree->FindHash(nStartPos, nSize, nLevel); - } - } -} - -// recursive -// calculates missing hash fromt he existing ones -// overwrites existing hashs -// fails if no hash is found for any branch -bool CAICHHashTree::ReCalculateHash(CAICHHashAlgo* hashalg, bool bDontReplace){ - ASSERT ( !( (m_pLeftTree != NULL) ^ (m_pRightTree != NULL)) ); - if (m_pLeftTree && m_pRightTree){ - if ( !m_pLeftTree->ReCalculateHash(hashalg, bDontReplace) || !m_pRightTree->ReCalculateHash(hashalg, bDontReplace) ) - return false; - if (bDontReplace && m_bHashValid) - return true; - if (m_pRightTree->m_bHashValid && m_pLeftTree->m_bHashValid){ - hashalg->Reset(); - hashalg->Add(m_pLeftTree->m_Hash.GetRawHash(), HASHSIZE); - hashalg->Add(m_pRightTree->m_Hash.GetRawHash(), HASHSIZE); - hashalg->Finish(m_Hash); - m_bHashValid = true; - return true; - } - else - return m_bHashValid; - } - else - return true; -} - -bool CAICHHashTree::VerifyHashTree(CAICHHashAlgo* hashalg, bool bDeleteBadTrees){ - if (!m_bHashValid){ - ASSERT ( false ); - if (bDeleteBadTrees){ - if (m_pLeftTree){ - delete m_pLeftTree; - m_pLeftTree = NULL; - } - if (m_pRightTree){ - delete m_pRightTree; - m_pRightTree = NULL; - } - } - //AddDebugLogLineM( false, logSHAHashSet, wxT("VerifyHashTree - No masterhash available")); - printf("VerifyHashTree - No masterhash available\n"); - return false; - } - - // calculated missing hashs without overwriting anything - if (m_pLeftTree && !m_pLeftTree->m_bHashValid) - m_pLeftTree->ReCalculateHash(hashalg, true); - if (m_pRightTree && !m_pRightTree->m_bHashValid) - m_pRightTree->ReCalculateHash(hashalg, true); - - if ((m_pRightTree && m_pRightTree->m_bHashValid) ^ (m_pLeftTree && m_pLeftTree->m_bHashValid)){ - // one branch can never be verified - if (bDeleteBadTrees){ - if (m_pLeftTree){ - delete m_pLeftTree; - m_pLeftTree = NULL; - } - if (m_pRightTree){ - delete m_pRightTree; - m_pRightTree = NULL; - } - } - //AddDebugLogLineM( false, logSHAHashSet, wxT("VerifyHashSet failed - Hashtree incomplete")); - printf("VerifyHashSet failed - Hashtree incomplete\n"); - return false; - } - if ((m_pRightTree && m_pRightTree->m_bHashValid) && (m_pLeftTree && m_pLeftTree->m_bHashValid)){ - // check verify the hashs of both child nodes against my hash - - CAICHHash CmpHash; - hashalg->Reset(); - hashalg->Add(m_pLeftTree->m_Hash.GetRawHash(), HASHSIZE); - hashalg->Add(m_pRightTree->m_Hash.GetRawHash(), HASHSIZE); - hashalg->Finish(CmpHash); - - if (m_Hash != CmpHash){ - if (bDeleteBadTrees){ - if (m_pLeftTree){ - delete m_pLeftTree; - m_pLeftTree = NULL; - } - if (m_pRightTree){ - delete m_pRightTree; - m_pRightTree = NULL; - } - } - return false; - } - return m_pLeftTree->VerifyHashTree(hashalg, bDeleteBadTrees) && m_pRightTree->VerifyHashTree(hashalg, bDeleteBadTrees); - } - else - // last hash in branch - nothing below to verify - return true; - -} - -void CAICHHashTree::SetBlockHash(uint64 nSize, uint64 nStartPos, CAICHHashAlgo* pHashAlg){ - ASSERT ( nSize <= EMBLOCKSIZE ); - CAICHHashTree* pToInsert = FindHash(nStartPos, nSize); - if (pToInsert == NULL){ // sanity - ASSERT ( false ); - //AddDebugLogLineM( false, logSHAHashSet, wxT("Critical Error: Failed to Insert SHA-HashBlock, FindHash() failed!")); - out("Critical Error: Failed to Insert SHA-HashBlock, FindHash() failed!"); - return; - } - - //sanity - if (pToInsert->m_nBaseSize != EMBLOCKSIZE || pToInsert->m_nDataSize != nSize){ - ASSERT ( false ); - //AddDebugLogLineM( false, logSHAHashSet, wxT("Critical Error: Logical error on values in SetBlockHashFromData")); - out("Critical Error: Logical error on values in SetBlockHashFromData"); - return; - } - - pHashAlg->Finish(pToInsert->m_Hash); - pToInsert->m_bHashValid = true; -} -/* -bool CAICHHashTree::CreatePartRecoveryData(uint32 nStartPos, uint32 nSize, CFileDataIO* fileDataOut, uint16 wHashIdent){ - if (nStartPos + nSize > m_nDataSize){ // sanity - ASSERT ( false ); - return false; - } - if (nSize > m_nDataSize){ // sanity - ASSERT ( false ); - return false; - } - - if (nStartPos == 0 && nSize == m_nDataSize){ - // this is the searched part, now write all blocks of this part - // hashident for this level will be adjsuted by WriteLowestLevelHash - return WriteLowestLevelHashs(fileDataOut, wHashIdent); - } - else if (m_nDataSize <= m_nBaseSize){ // sanity - // this is already the last level, cant go deeper - ASSERT( false ); - return false; - } - else{ - wHashIdent <<= 1; - wHashIdent |= (m_bIsLeftBranch) ? 1: 0; - - uint32 nBlocks = m_nDataSize / m_nBaseSize + ((m_nDataSize % m_nBaseSize != 0 )? 1:0); - uint32 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* m_nBaseSize; - uint32 nRight = m_nDataSize - nLeft; - if (m_pLeftTree == NULL || m_pRightTree == NULL){ - ASSERT( false ); - return false; - } - if (nStartPos < nLeft){ - if (nStartPos + nSize > nLeft || !m_pRightTree->m_bHashValid){ // sanity - ASSERT ( false ); - return false; - } - m_pRightTree->WriteHash(fileDataOut, wHashIdent); - return m_pLeftTree->CreatePartRecoveryData(nStartPos, nSize, fileDataOut, wHashIdent); - } - else{ - nStartPos -= nLeft; - if (nStartPos + nSize > nRight || !m_pLeftTree->m_bHashValid){ // sanity - ASSERT ( false ); - return false; - } - m_pLeftTree->WriteHash(fileDataOut, wHashIdent); - return m_pRightTree->CreatePartRecoveryData(nStartPos, nSize, fileDataOut, wHashIdent); - - } - } -} - -void CAICHHashTree::WriteHash(CFileDataIO* fileDataOut, uint16 wHashIdent) const{ - ASSERT( m_bHashValid ); - wHashIdent <<= 1; - wHashIdent |= (m_bIsLeftBranch) ? 1: 0; - fileDataOut->WriteUInt16(wHashIdent); - m_Hash.Write(fileDataOut); -} - -// write lowest level hashs into file, ordered from left to right optional without identifier -bool CAICHHashTree::WriteLowestLevelHashs(CFileDataIO* fileDataOut, uint16 wHashIdent, bool bNoIdent) const{ - wHashIdent <<= 1; - wHashIdent |= (m_bIsLeftBranch) ? 1: 0; - if (m_pLeftTree == NULL && m_pRightTree == NULL){ - if (m_nDataSize <= m_nBaseSize && m_bHashValid ){ - if (!bNoIdent) - fileDataOut->WriteUInt16(wHashIdent); - m_Hash.Write(fileDataOut); - return true; - } - else{ - ASSERT( false ); - return false; - } - } - else if (m_pLeftTree == NULL || m_pRightTree == NULL){ - ASSERT( false ); - return false; - } - else{ - return m_pLeftTree->WriteLowestLevelHashs(fileDataOut, wHashIdent, bNoIdent) - && m_pRightTree->WriteLowestLevelHashs(fileDataOut, wHashIdent, bNoIdent); - } -} - -// recover all low level hashs from given data. hashs are assumed to be ordered in left to right - no identifier used -bool CAICHHashTree::LoadLowestLevelHashs(CFileDataIO* fileInput){ - if (m_nDataSize <= m_nBaseSize){ // sanity - // lowest level, read hash - m_Hash.Read(fileInput); - m_bHashValid = true; - return true; - } - else{ - uint32 nBlocks = m_nDataSize / m_nBaseSize + ((m_nDataSize % m_nBaseSize != 0 )? 1:0); - uint32 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* m_nBaseSize; - uint32 nRight = m_nDataSize - nLeft; - if (m_pLeftTree == NULL) - m_pLeftTree = new CAICHHashTree(nLeft, true, (nLeft <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pLeftTree->m_nDataSize == nLeft ); - } - if (m_pRightTree == NULL) - m_pRightTree = new CAICHHashTree(nRight, false, (nRight <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pRightTree->m_nDataSize == nRight ); - } - return m_pLeftTree->LoadLowestLevelHashs(fileInput) - && m_pRightTree->LoadLowestLevelHashs(fileInput); - } -} - - -// write the hash, specified by wHashIdent, with Data from fileInput. -bool CAICHHashTree::SetHash(CFileDataIO* fileInput, uint16 wHashIdent, sint8 nLevel, bool bAllowOverwrite){ - if (nLevel == (-1)){ - // first call, check how many level we need to go - uint8 i; - for (i = 0; i != 16 && (wHashIdent & 0x8000) == 0; ++i){ - wHashIdent <<= 1; - } - if (i > 15){ - AddDebugLogLineM( false, logSHAHashSet, wxT("CAICHHashTree::SetHash - found invalid HashIdent (0)")); - return false; - } - else{ - nLevel = 15 - i; - } - } - if (nLevel == 0){ - // this is the searched hash - if (m_bHashValid && !bAllowOverwrite){ - // not allowed to overwrite this hash, however move the filepointer by reading a hash - CAICHHash(file); - return true; - } - m_Hash.Read(fileInput); - m_bHashValid = true; - return true; - } - else if (m_nDataSize <= m_nBaseSize){ // sanity - // this is already the last level, cant go deeper - ASSERT( false ); - return false; - } - else{ - // adjust ident to point the path to the next node - wHashIdent <<= 1; - nLevel--; - uint32 nBlocks = m_nDataSize / m_nBaseSize + ((m_nDataSize % m_nBaseSize != 0 )? 1:0); - uint32 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* m_nBaseSize; - uint32 nRight = m_nDataSize - nLeft; - if ((wHashIdent & 0x8000) > 0){ - if (m_pLeftTree == NULL) - m_pLeftTree = new CAICHHashTree(nLeft, true, (nLeft <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pLeftTree->m_nDataSize == nLeft ); - } - return m_pLeftTree->SetHash(fileInput, wHashIdent, nLevel); - } - else{ - if (m_pRightTree == NULL) - m_pRightTree = new CAICHHashTree(nRight, false, (nRight <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); - else{ - ASSERT( m_pRightTree->m_nDataSize == nRight ); - } - return m_pRightTree->SetHash(fileInput, wHashIdent, nLevel); - } - } -}*/ - - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHUntrustedHash -/*bool CAICHUntrustedHash::AddSigningIP(uint32 dwIP){ - dwIP &= 0x00F0FFFF; // we use only the 20 most significant bytes for unique IPs - return m_adwIpsSigning.insert(dwIP).second; -}*/ - - - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHashSet - -CAICHHashSet::CAICHHashSet()//CKnownFile* pOwner) - : m_pHashTree(0, true, PARTSIZE) -{ - m_eStatus = AICH_EMPTY; - //m_pOwner = pOwner; -} - -CAICHHashSet::~CAICHHashSet(void) -{ - FreeHashSet(); -} -/* -bool CAICHHashSet::CreatePartRecoveryData(uint32 nPartStartPos, CFileDataIO* fileDataOut, bool bDbgDontLoad){ - ASSERT( m_pOwner ); - if (m_pOwner->IsPartFile() || m_eStatus != AICH_HASHSETCOMPLETE){ - ASSERT( false ); - return false; - } - if (m_pHashTree.m_nDataSize <= EMBLOCKSIZE){ - ASSERT( false ); - return false; - } - if (!bDbgDontLoad){ - if (!LoadHashSet()){ - AddDebugLogLineM( false, logSHAHashSet, wxT("Created RecoveryData error: failed to load hashset. File:") + m_pOwner->GetFileName() ); - SetStatus(AICH_ERROR); - return false; - } - } - bool bResult; - uint8 nLevel = 0; - uint32 nPartSize = min(PARTSIZE, m_pOwner->GetFileSize()-nPartStartPos); - m_pHashTree.FindHash(nPartStartPos, nPartSize,&nLevel); - uint16 nHashsToWrite = (nLevel-1) + nPartSize/EMBLOCKSIZE + ((nPartSize % EMBLOCKSIZE != 0 )? 1:0); - fileDataOut->WriteUInt16(nHashsToWrite); - uint32 nCheckFilePos = fileDataOut->GetPosition(); - if (m_pHashTree.CreatePartRecoveryData(nPartStartPos, nPartSize, fileDataOut, 0)){ - if (nHashsToWrite*(HASHSIZE+2u) != fileDataOut->GetPosition() - nCheckFilePos){ - ASSERT( false ); - AddDebugLogLineM( false, logSHAHashSet, wxT("Created RecoveryData has wrong length. File: ") + m_pOwner->GetFileName() ); - bResult = false; - SetStatus(AICH_ERROR); - } - else - bResult = true; - } else { - AddDebugLogLineM( false, logSHAHashSet, wxT("Failed to create RecoveryData for ") + m_pOwner->GetFileName() ); - bResult = false; - SetStatus(AICH_ERROR); - } - if (!bDbgDontLoad){ - FreeHashSet(); - } - return bResult; -} - -bool CAICHHashSet::ReadRecoveryData(uint32 nPartStartPos, CMemFile* fileDataIn) -{ - if (!(m_eStatus == AICH_VERIFIED || m_eStatus == AICH_TRUSTED) ){ - ASSERT( false ); - return false; - } - // at this time we check the recoverydata for the correct ammounts of hashs only - // all hash are then taken into the tree, depending on there hashidentifier (except the masterhash) - - uint8 nLevel = 0; - uint32 nPartSize = min(PARTSIZE, m_pOwner->GetFileSize()-nPartStartPos); - m_pHashTree.FindHash(nPartStartPos, nPartSize,&nLevel); - uint16 nHashsToRead = (nLevel-1) + nPartSize/EMBLOCKSIZE + ((nPartSize % EMBLOCKSIZE != 0 )? 1:0); - uint16 nHashsAvailable = fileDataIn->ReadUInt16(); - if (fileDataIn->GetLength()-fileDataIn->GetPosition() < nHashsToRead*(HASHSIZE+2u) || nHashsToRead != nHashsAvailable){ - // this check is redunant, CSafememfile would catch such an error too - AddDebugLogLineM( false, logSHAHashSet, wxT("Failed to read RecoveryData for ") + m_pOwner->GetFileName() + wxT("%s - Received datasize/amounts of hashs was invalid")); - return false; - } - for (uint32 i = 0; i != nHashsToRead; ++i){ - uint16 wHashIdent = fileDataIn->ReadUInt16(); - if (wHashIdent == 1 //never allow masterhash to be overwritten - || !m_pHashTree.SetHash(fileDataIn, wHashIdent,(-1), false)) - { - AddDebugLogLineM( false, logSHAHashSet, wxT("Failed to read RecoveryData for ") + m_pOwner->GetFileName() + wxT(" - Error when trying to read hash into tree")); - VerifyHashTree(true); // remove invalid hashs which we have already written - return false; - } - } - if (VerifyHashTree(true)){ - // some final check if all hashs we wanted are there - for (uint32 nPartPos = 0; nPartPos < nPartSize; nPartPos += EMBLOCKSIZE){ - CAICHHashTree* phtToCheck = m_pHashTree.FindHash(nPartStartPos+nPartPos, min(EMBLOCKSIZE, nPartSize-nPartPos)); - if (phtToCheck == NULL || !phtToCheck->m_bHashValid){ - AddDebugLogLineM( false, logSHAHashSet, wxT("Failed to read RecoveryData for ") + m_pOwner->GetFileName() + wxT(" - Error while verifying presence of all lowest level hashs")); - return false; - } - } - // all done - return true; - } - else{ - AddDebugLogLineM( false, logSHAHashSet, wxT("Failed to read RecoveryData for ") + m_pOwner->GetFileName() + wxT(" - Verifying received hashtree failed")); - return false; - } -} - -// this function is only allowed to be called right after successfully calculating the hashset (!) -// will delete the hashset, after saving to free the memory -bool CAICHHashSet::SaveHashSet(){ - if (m_eStatus != AICH_HASHSETCOMPLETE){ - ASSERT( false ); - return false; - } - if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize()){ - ASSERT( false ); - return false; - } - wxString fullpath = theApp.ConfigDir + KNOWN2_MET_FILENAME; - CFile file; - if (wxFileExists(fullpath)) { - if (!file.Open(fullpath, CFile::read_write)) { - // Add logline about unable to open file - return false; - } - } else { - if (!file.Create(fullpath)) { - // Add logline about unable to create file - return false; - } - } - - try { - // first we check if the hashset we want to write is already stored - CAICHHash CurrentHash; - uint32 nExistingSize = file.GetLength(); - while (file.GetPosition() < nExistingSize){ - CurrentHash.Read(&file); - if (m_pHashTree.m_Hash == CurrentHash){ - // this hashset if already available, no need to save it again - return true; - } - uint16 nHashCount = file.ReadUInt16(); - if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize){ - throw fullpath; - } - // skip the rest of this hashset - file.Seek(nHashCount*HASHSIZE, wxFromCurrent); - } - // write hashset - m_pHashTree.m_Hash.Write(&file); - uint16 nHashCount = (PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE); - if (m_pHashTree.m_nDataSize % PARTSIZE != 0) - nHashCount += (m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0); - file.WriteUInt16(nHashCount); - if (!m_pHashTree.WriteLowestLevelHashs(&file, 0, true)){ - // thats bad... really - file.SetLength(nExistingSize); - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to save HashSet: WriteLowestLevelHashs() failed!")); - return false; - } - if (file.GetLength() != nExistingSize + (nHashCount+1)*HASHSIZE + 2){ - // thats even worse - file.SetLength(nExistingSize); - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to save HashSet: Calculated and real size of hashset differ!")); - return false; - } - AddDebugLogLineM( false, logSHAHashSet, wxString::Format(wxT("Sucessfully saved eMuleAC Hashset, %u Hashs + 1 Masterhash written"), nHashCount)); - } catch (const wxString& error){ - AddDebugLogLineM(true, logSHAHashSet, wxT("Error: ") + error); - return false; - } catch (const CSafeIOException& e) { - AddDebugLogLineM(true, logSHAHashSet, wxT("IO error while saving AICH HashSet: ") + e.what()); - return false; - } - - FreeHashSet(); - return true; -} - - -bool CAICHHashSet::LoadHashSet() -{ - if (m_eStatus != AICH_HASHSETCOMPLETE){ - ASSERT( false ); - return false; - } - if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize() || m_pHashTree.m_nDataSize == 0){ - ASSERT( false ); - return false; - } - wxString fullpath = theApp.ConfigDir + KNOWN2_MET_FILENAME; - CFile file(fullpath, CFile::read_write); - if (!file.IsOpened()){ - if (wxFileExists(fullpath)) { - wxString strError(wxT("Failed to load ") KNOWN2_MET_FILENAME wxT(" file")); - AddDebugLogLineM( true, logSHAHashSet, strError); - } - return false; - } - - try { - //setvbuf(file.m_pStream, NULL, _IOFBF, 16384); - CAICHHash CurrentHash; - uint32 nExistingSize = file.GetLength(); - uint16 nHashCount; - while (file.GetPosition() < nExistingSize){ - CurrentHash.Read(&file); - if (m_pHashTree.m_Hash == CurrentHash){ - // found Hashset - uint32 nExpectedCount = (PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE); - if (m_pHashTree.m_nDataSize % PARTSIZE != 0) - nExpectedCount += (m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0); - nHashCount = file.ReadUInt16(); - if (nHashCount != nExpectedCount){ - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Available Hashs and expected hashcount differ!")); - return false; - } - if (!m_pHashTree.LoadLowestLevelHashs(&file)){ - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: LoadLowestLevelHashs failed!")); - return false; - } - if (!ReCalculateHash(false)){ - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Calculating loaded hashs failed!")); - return false; - } - if (CurrentHash != m_pHashTree.m_Hash){ - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Calculated Masterhash differs from given Masterhash - hashset corrupt!")); - return false; - } - return true; - } - nHashCount = file.ReadUInt16(); - if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize){ - throw fullpath; - } - // skip the rest of this hashset - file.Seek(nHashCount*HASHSIZE, wxFromCurrent); - } - AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: HashSet not found!")); - } catch (const wxString& error) { - AddDebugLogLineM(true, logSHAHashSet, wxT("Error: ") + error); - return false; - } catch (const CSafeIOException& e) { - AddDebugLogLineM(true, logSHAHashSet, wxT("IO error while loading AICH HashSet: ") + e.what()); - return false; - } - - - return false; -}*/ - -// delete the hashset except the masterhash (we dont keep aich hashsets in memory to save ressources) -void CAICHHashSet::FreeHashSet(){ - if (m_pHashTree.m_pLeftTree){ - delete m_pHashTree.m_pLeftTree; - m_pHashTree.m_pLeftTree = NULL; - } - if (m_pHashTree.m_pRightTree){ - delete m_pHashTree.m_pRightTree; - m_pHashTree.m_pRightTree = NULL; - } -} - -/*void CAICHHashSet::SetMasterHash(const CAICHHash& Hash, EAICHStatus eNewStatus){ - m_pHashTree.m_Hash = Hash; - m_pHashTree.m_bHashValid = true; - SetStatus(eNewStatus); -}*/ - -CAICHHashAlgo* CAICHHashSet::GetNewHashAlgo(){ - return new CSHA(); -} - -bool CAICHHashSet::ReCalculateHash(bool bDontReplace){ - CAICHHashAlgo* hashalg = GetNewHashAlgo(); - bool bResult = m_pHashTree.ReCalculateHash(hashalg, bDontReplace); - delete hashalg; - return bResult; -} - -bool CAICHHashSet::VerifyHashTree(bool bDeleteBadTrees){ - CAICHHashAlgo* hashalg = GetNewHashAlgo(); - bool bResult = m_pHashTree.VerifyHashTree(hashalg, bDeleteBadTrees); - delete hashalg; - return bResult; -} - -void CAICHHashSet::SetFileSize(EMFileSize nSize){ - m_pHashTree.m_nDataSize = nSize; - m_pHashTree.m_nBaseSize = (nSize <= (uint64)PARTSIZE) ? EMBLOCKSIZE : PARTSIZE; -} -/* -void CAICHHashSet::UntrustedHashReceived(const CAICHHash& Hash, uint32 dwFromIP){ - switch(GetStatus()){ - case AICH_EMPTY: - case AICH_UNTRUSTED: - case AICH_TRUSTED: - break; - default: - return; - } - bool bFound = false; - bool bAdded = false; - for (uint32 i = 0; i < m_aUntrustedHashs.size(); ++i){ - if (m_aUntrustedHashs[i].m_Hash == Hash){ - bAdded = m_aUntrustedHashs[i].AddSigningIP(dwFromIP); - bFound = true; - break; - } - } - if (!bFound){ - bAdded = true; - CAICHUntrustedHash uhToAdd; - uhToAdd.m_Hash = Hash; - uhToAdd.AddSigningIP(dwFromIP); - m_aUntrustedHashs.push_back(uhToAdd); - } - - uint32 nSigningIPsTotal = 0; // unique clients who send us a hash - sint32 nMostTrustedPos = (-1); // the hash which most clients send us - uint32 nMostTrustedIPs = 0; - for (uint32 i = 0; i < (uint32)m_aUntrustedHashs.size(); ++i){ - nSigningIPsTotal += m_aUntrustedHashs[i].m_adwIpsSigning.size(); - if ((uint32)m_aUntrustedHashs[i].m_adwIpsSigning.size() > nMostTrustedIPs){ - nMostTrustedIPs = m_aUntrustedHashs[i].m_adwIpsSigning.size(); - nMostTrustedPos = i; - } - } - if (nMostTrustedPos == (-1) || nSigningIPsTotal == 0){ - ASSERT( false ); - return; - } - // the check if we trust any hash - if ( thePrefs::IsTrustingEveryHash() || - (nMostTrustedIPs >= MINUNIQUEIPS_TOTRUST && (100 * nMostTrustedIPs)/nSigningIPsTotal >= MINPERCENTAGE_TOTRUST)){ - //trusted - AddDebugLogLineM(false, logSHAHashSet, - CFormat(wxT("IACH Hash recieved (%sadded), We have now %u hash(es) from %u unique IP(s). ") - wxT("We trust the Hash %s from %u client(s) (%u%%). File: %s")) - % (bAdded ? wxT("") : wxT("not ")) - % m_aUntrustedHashs.size() - % nSigningIPsTotal - % m_aUntrustedHashs[nMostTrustedPos].m_Hash.GetString() - % nMostTrustedIPs - % ((100 * nMostTrustedIPs) / nSigningIPsTotal) - % m_pOwner->GetFileName()); - - SetStatus(AICH_TRUSTED); - if (!HasValidMasterHash() || GetMasterHash() != m_aUntrustedHashs[nMostTrustedPos].m_Hash){ - SetMasterHash(m_aUntrustedHashs[nMostTrustedPos].m_Hash, AICH_TRUSTED); - FreeHashSet(); - } - } else { - // untrusted - AddDebugLogLineM(false, logSHAHashSet, - CFormat(wxT("IACH Hash recieved (%sadded), We have now %u hash(es) from %u unique IP(s). ") - wxT("Best Hash %s from %u clients (%u%%) - but we dont trust it yet. File: %s")) - % (bAdded ? wxT(""): wxT("not ")) - % m_aUntrustedHashs.size() - % nSigningIPsTotal - % m_aUntrustedHashs[nMostTrustedPos].m_Hash.GetString() - % nMostTrustedIPs - % ((100 * nMostTrustedIPs) / nSigningIPsTotal) - % m_pOwner->GetFileName()); - - SetStatus(AICH_UNTRUSTED); - if (!HasValidMasterHash() || GetMasterHash() != m_aUntrustedHashs[nMostTrustedPos].m_Hash){ - SetMasterHash(m_aUntrustedHashs[nMostTrustedPos].m_Hash, AICH_UNTRUSTED); - FreeHashSet(); - } - } -} - -#ifndef CLIENT_GUI - -void CAICHHashSet::ClientAICHRequestFailed(CUpDownClient* pClient){ - pClient->SetReqFileAICHHash(NULL); - CAICHRequestedData data = GetAICHReqDetails(pClient); - RemoveClientAICHRequest(pClient); - if (data.m_pClient != pClient) - return; - if( theApp.downloadqueue->IsPartFile(data.m_pPartFile)){ - AddDebugLogLineM( false, logSHAHashSet, wxT("IACH Request failed, Trying to ask another client (file ") + data.m_pPartFile->GetFileName() + wxString::Format(wxT(", Part: %u, Client"),data.m_nPart) + pClient->GetClientFullInfo()); - data.m_pPartFile->RequestAICHRecovery(data.m_nPart); - } -} - -#endif - -void CAICHHashSet::RemoveClientAICHRequest(const CUpDownClient* pClient) { - - for (CAICHRequestedDataList::iterator it = m_liRequestedData.begin();it != m_liRequestedData.end(); ++it) { - if ((*(it)).m_pClient == pClient){ - m_liRequestedData.erase(it); - return; - } - } - ASSERT( false ); -} - -bool CAICHHashSet::IsClientRequestPending(const CPartFile* pForFile, uint16 nPart){ - for (CAICHRequestedDataList::iterator it = m_liRequestedData.begin();it != m_liRequestedData.end(); ++it) { - if ((*(it)).m_pPartFile == pForFile && (*(it)).m_nPart == nPart){ - return true; - } - } - return false; -} - -CAICHRequestedData CAICHHashSet::GetAICHReqDetails(const CUpDownClient* pClient){ - for (CAICHRequestedDataList::iterator it = m_liRequestedData.begin();it != m_liRequestedData.end(); ++it) { - if ((*(it)).m_pClient == pClient){ - return *(it); - } - } - ASSERT( false ); - CAICHRequestedData empty; - return empty; -} - -bool CAICHHashSet::IsPartDataAvailable(uint32 nPartStartPos){ - if (!(m_eStatus == AICH_VERIFIED || m_eStatus == AICH_TRUSTED || m_eStatus == AICH_HASHSETCOMPLETE) ){ - ASSERT( false ); - return false; - } - uint32 nPartSize = min(PARTSIZE, m_pOwner->GetFileSize()-nPartStartPos); - for (uint32 nPartPos = 0; nPartPos < nPartSize; nPartPos += EMBLOCKSIZE){ - CAICHHashTree* phtToCheck = m_pHashTree.FindHash(nPartStartPos+nPartPos, min(EMBLOCKSIZE, nPartSize-nPartPos)); - if (phtToCheck == NULL || !phtToCheck->m_bHashValid){ - return false; - } - } - return true; -} - -// VC++ defines Assert as ASSERT. VC++ also defines VERIFY MACRO, which is the equivalent of ASSERT but also works in Released builds. - -#define VERIFY(x) ASSERT(x) - -void CAICHHashSet::DbgTest(){ - - //define TESTSIZE 4294567295 - uint8 maxLevel = 0; - uint32 cHash = 1; - uint8 curLevel = 0; - maxLevel = 0; - -#define TESTSIZE m_pHashTree.m_nDataSize - if (m_pHashTree.m_nDataSize <= EMBLOCKSIZE) - return; - CAICHHashSet TestHashSet(m_pOwner); - TestHashSet.SetFileSize(m_pOwner->GetFileSize()); - TestHashSet.SetMasterHash(GetMasterHash(), AICH_VERIFIED); - CMemFile file; - uint64 i = 0; - for (i = 0; i+9728000 < TESTSIZE; i += 9728000){ - VERIFY( CreatePartRecoveryData(i, &file) ); - - file.Seek(0,wxFromStart); - VERIFY( TestHashSet.ReadRecoveryData(i, &file) ); - file.Seek(0,wxFromStart); - TestHashSet.FreeHashSet(); - uint32 j = 0; - for (j = 0; j+EMBLOCKSIZE < 9728000; j += EMBLOCKSIZE){ - VERIFY( m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel) ); - //TRACE(wxT("%u - %s\r\n"), cHash, m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel)->m_Hash.GetString()); - maxLevel = max(curLevel, maxLevel); - curLevel = 0; - cHash++; - } - VERIFY( m_pHashTree.FindHash(i+j, 9728000-j, &curLevel) ); - //TRACE(wxT("%u - %s\r\n"), cHash, m_pHashTree.FindHash(i+j, 9728000-j, &curLevel)->m_Hash.GetString()); - maxLevel = max(curLevel, maxLevel); - curLevel = 0; - cHash++; - - } - VERIFY( CreatePartRecoveryData(i, &file) ); - file.Seek(0,wxFromStart); - VERIFY( TestHashSet.ReadRecoveryData(i, &file) ); - file.Seek(0,wxFromStart); - TestHashSet.FreeHashSet(); - uint64 j = 0; - for (j = 0; j+EMBLOCKSIZE < TESTSIZE-i; j += EMBLOCKSIZE){ - VERIFY( m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel) ); - //TRACE(wxT("%u - %s\r\n"), cHash,m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel)->m_Hash.GetString()); - maxLevel = max(curLevel, maxLevel); - curLevel = 0; - cHash++; - } - //VERIFY( m_pHashTree.FindHash(i+j, (TESTSIZE-i)-j, &curLevel) ); -// TRACE(wxT("%u - %s\r\n"), cHash,m_pHashTree.FindHash(i+j, (TESTSIZE-i)-j, &curLevel)->m_Hash.GetString()); - maxLevel = max(curLevel, maxLevel); - -}*/ diff --git a/hasher/SHAHashSet.h b/hasher/SHAHashSet.h deleted file mode 100644 index 76fe51149..000000000 --- a/hasher/SHAHashSet.h +++ /dev/null @@ -1,257 +0,0 @@ -// -// This file is part of the aMule Project. -// -// Copyright (c) 2003-2006 Angel Vidal (Kry) ( kry@amule.org ) -// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org ) -// Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net ) -// -// Any parts of this program derived from the xMule, lMule or eMule project, -// or contributed by third-party developers are copyrighted by their -// respective authors. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -// - -/* - SHA haset basically exists of 1 Tree for all Parts (9.28MB) + n Trees - for all blocks (180KB) while n is the number of Parts. - This means it is NOT a complete hashtree, since the 9.28MB is a given level, in order - to be able to create a hashset format similar to the MD4 one. - - If the number of elements for the next level are odd (for example 21 blocks to spread into 2 hashs) - the majority of elements will go into the left branch if the parent node was a left branch - and into the right branch if the parent node was a right branch. The first node is always - taken as a left branch. - -Example tree: - FileSize: 19506000 Bytes = 18,6 MB - - X (18,6) MasterHash - / \ - X (18,55) \ - / \ \ - X(9,28) x(9,28) X (0,05MB) PartHashs - / \ / \ \ - X(4,75) X(4,57) X(4,57) X(4,75) \ - - [...............] -X(180KB) X(180KB) [...] X(140KB) | X(180KB) X(180KB [...] BlockHashs - v - Border between first and second Part (9.28MB) - -HashsIdentifier: -When sending hashs, they are send with a 16bit identifier which specifies its postion in the -tree (so StartPosition + HashDataSize would lead to the same hash) -The identifier basically describes the way from the top of the tree to the hash. a set bit (1) -means follow the left branch, a 0 means follow the right. The highest bit which is set is seen as the start- -postion (since the first node is always seend as left). - -Example - - x 0000000000000001 - / \ - x \ 0000000000000011 - / \ \ - x _X_ x 0000000000000110 - - -*/ - -#ifndef __SHAHAHSET_H__ -#define __SHAHAHSET_H__ - -/*#include -#include -#include */ - -#include "Types.h" -#define PARTSIZE 9728000 -#define EMBLOCKSIZE 184320 -//typedef unsigned char uint8; -//typedef unsigned char uchar; - -#include "stdinc.h" - - -//typedef unsigned int uint32; -//typedef unsigned __int64 uint64; -#define HASHSIZE 20 -//#define KNOWN2_MET_FILENAME wxT("known2.met") - -enum EAICHStatus { - AICH_ERROR = 0, - AICH_EMPTY, - AICH_UNTRUSTED, - AICH_TRUSTED, - AICH_VERIFIED, - AICH_HASHSETCOMPLETE -}; - -/*class CFileDataIO; -class CKnownFile; -class CMemFile; -class CPartFile; -class CUpDownClient;*/ - -//using namespace std; - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHash -typedef unsigned char byte; - -class CAICHHash -{ -public: - ~CAICHHash() {;} - CAICHHash() { memset(m_abyBuffer, 0, HASHSIZE); } - //CAICHHash(CFileDataIO* file) { Read(file); } - CAICHHash(byte* data) { Read(data); } - CAICHHash(const CAICHHash& k1) { *this = k1; } - CAICHHash& operator=(const CAICHHash& k1) { memcpy(m_abyBuffer, k1.m_abyBuffer, HASHSIZE); return *this; } - friend bool operator==(const CAICHHash& k1,const CAICHHash& k2) { return memcmp(k1.m_abyBuffer, k2.m_abyBuffer, HASHSIZE) == 0;} - friend bool operator!=(const CAICHHash& k1,const CAICHHash& k2) { return !(k1 == k2); } - //void Read(CFileDataIO* file); - //void Write(CFileDataIO* file) const; - void Read(byte* data) { memcpy(m_abyBuffer, data, HASHSIZE); } -// wxString GetString() const; - byte* GetRawHash() { return m_abyBuffer; } - - static unsigned int GetHashSize() { return HASHSIZE;} - - //unsigned int DecodeBase32(const wxString &base32); - -private: - byte m_abyBuffer[HASHSIZE]; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHashAlgo -class CAICHHashAlgo -{ -public: - virtual ~CAICHHashAlgo() {}; - virtual void Reset() = 0; - virtual void Add(const void* pData, uint32 nLength) = 0; - virtual void Finish(CAICHHash& Hash) = 0; - virtual void GetHash(CAICHHash& Hash) = 0; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHashTree -class CAICHHashTree -{ - // Madness from eMule, and gcc don't like being friend with itself... - // That probably means gcc is not friend of gcc. So gcc hates itself. - // friend class CAICHHashTree; - friend class CAICHHashSet; -public: - CAICHHashTree(uint64 nDataSize, bool bLeftBranch, uint64 nBaseSize); - ~CAICHHashTree(); - void SetBlockHash(uint64 nSize, uint64 nStartPos, CAICHHashAlgo* pHashAlg); - bool ReCalculateHash(CAICHHashAlgo* hashalg, bool bDontReplace ); - bool VerifyHashTree(CAICHHashAlgo* hashalg, bool bDeleteBadTrees); - CAICHHashTree* FindHash(uint64 nStartPos, uint64 nSize) {uint8 buffer = 0; return FindHash(nStartPos, nSize, &buffer);} - -protected: - CAICHHashTree* FindHash(uint64 nStartPos, uint64 nSize, uint8* nLevel); -// bool CreatePartRecoveryData(uint32 nStartPos, uint32 nSize, CFileDataIO* fileDataOut, uint16 wHashIdent); -// void WriteHash(CFileDataIO* fileDataOut, uint16 wHashIdent) const; -// bool WriteLowestLevelHashs(CFileDataIO* fileDataOut, uint16 wHashIdent, bool bNoIdent = false) const; -// bool LoadLowestLevelHashs(CFileDataIO* fileInput); -// bool SetHash(CFileDataIO* fileInput, uint16 wHashIdent, sint8 nLevel = (-1), bool bAllowOverwrite = true); - CAICHHashTree* m_pLeftTree; - CAICHHashTree* m_pRightTree; - -public: - CAICHHash m_Hash; - uint64 m_nDataSize; // size of data which is covered by this hash - uint64 m_nBaseSize; // blocksize on which the lowest hash is based on - bool m_bIsLeftBranch; // left or right branch of the tree - bool m_bHashValid; // the hash is valid and not empty -}; - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHUntrustedHashs -/*class CAICHUntrustedHash { -public: - CAICHUntrustedHash& operator=(const CAICHUntrustedHash& k1) { m_adwIpsSigning = k1.m_adwIpsSigning; m_Hash = k1.m_Hash ; return *this; } - bool AddSigningIP(uint32 dwIP); - - CAICHHash m_Hash; - set m_adwIpsSigning; -};*/ - -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHUntrustedHashs -/*class CAICHRequestedData { -public: - CAICHRequestedData() {m_nPart = 0; m_pPartFile = NULL; m_pClient= NULL;} - CAICHRequestedData& operator=(const CAICHRequestedData& k1) { m_nPart = k1.m_nPart; m_pPartFile = k1.m_pPartFile; m_pClient = k1.m_pClient; return *this; } - uint16 m_nPart; - CPartFile* m_pPartFile; - CUpDownClient* m_pClient; -}; - - -using namespace std; - -typedef std::list CAICHRequestedDataList; -*/ -///////////////////////////////////////////////////////////////////////////////////////// -///CAICHHashSet -class CAICHHashSet -{ -public: - CAICHHashSet();//CKnownFile* pOwner); - ~CAICHHashSet(void); -// bool CreatePartRecoveryData(uint32 nPartStartPos, CFileDataIO* fileDataOut, bool bDbgDontLoad = false); -// bool ReadRecoveryData(uint32 nPartStartPos, CMemFile* fileDataIn); - bool ReCalculateHash(bool bDontReplace = false); - bool VerifyHashTree(bool bDeleteBadTrees); -// void UntrustedHashReceived(const CAICHHash& Hash, uint32 dwFromIP); -// bool IsPartDataAvailable(uint32 nPartStartPos); - void SetStatus(EAICHStatus bNewValue) {m_eStatus = bNewValue;} - EAICHStatus GetStatus() const {return m_eStatus;} -// - void FreeHashSet(); - void SetFileSize(uint64 nSize); -// - CAICHHash& GetMasterHash() {return m_pHashTree.m_Hash;} -// void SetMasterHash(const CAICHHash& Hash, EAICHStatus eNewStatus); - bool HasValidMasterHash() {return m_pHashTree.m_bHashValid;} - -// bool SaveHashSet(); -// bool LoadHashSet(); // only call directly when debugging - - CAICHHashAlgo* GetNewHashAlgo(); -// static void ClientAICHRequestFailed(CUpDownClient* pClient); -// static void RemoveClientAICHRequest(const CUpDownClient* pClient); -// static bool IsClientRequestPending(const CPartFile* pForFile, uint16 nPart); -// static CAICHRequestedData GetAICHReqDetails(const CUpDownClient* pClient); -// void DbgTest(); - -// void SetOwner(CKnownFile* owner) { m_pOwner = owner;} - - CAICHHashTree m_pHashTree; - - //static CAICHRequestedDataList m_liRequestedData; - -private: - //CKnownFile* m_pOwner; - EAICHStatus m_eStatus; - //deque m_aUntrustedHashs; -}; - -#endif //__SHAHAHSET_H__ diff --git a/hasher/SHA_asm.asm b/hasher/SHA_asm.asm new file mode 100644 index 000000000..fc02c1375 --- /dev/null +++ b/hasher/SHA_asm.asm @@ -0,0 +1,298 @@ +; ##################################################################################################################### +; +; SHA_asm.asm +; +; Copyright (c) Shareaza Development Team, 2002-2007. +; This file is part of SHAREAZA (shareaza.sourceforge.net) +; +; Shareaza is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation; either version 2 of +; the License, or (at your option) any later version. +; +; Shareaza is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Shareaza; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ##################################################################################################################### +; +; SHA_asm - Implementation of SHA-1 for x86 - use together with SHA.cpp and SHA.h +; +; ##################################################################################################################### + + .586p + .model flat, stdcall + option casemap:none ; case sensitive + option prologue:none ; we generate our own entry/exit code + option epilogue:none + +; ##################################################################################################################### + +m_nCount0 equ 0 ; offsets as found in SHA.h +m_nCount1 equ 4 + +m_nHash0 equ 8 +m_nHash1 equ 12 +m_nHash2 equ 16 +m_nHash3 equ 20 +m_nHash4 equ 24 + +m_nBuffer equ 28 + +RND_CH MACRO const:REQ +; t=a; a=rotl32(a,5)+e+k+w[i]+((b&c)^(~b&d)); e=d; d=c; c=rotl32(b,30); b=t +; a=rotl32(a,5)+e+k+w[i]+(d^(b&(c^d))); + mov reg_temp1, reg_a ; t=a + mov reg_temp2, reg_c + rol reg_a, 5 + xor reg_temp2, reg_d + add reg_a, reg_e + and reg_temp2, reg_b + add reg_a, const + xor reg_temp2, reg_d + add reg_a, [_w+count*4] + ror reg_b, 2 + add reg_a, reg_temp2 +reg_t textequ reg_e +reg_e textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_temp1 +reg_temp1 textequ reg_t +count = count + 1 + ENDM ; RND_CH + +RND_PARITY MACRO const:REQ +; t=a; a=rotl32(a,5)+e+k+w[i]+(b^c^d); e=d; d=c; c=rotl32(b,30); b=t + mov reg_temp1, reg_a ; t=a + rol reg_a, 5 + mov reg_temp2, reg_d + add reg_a, reg_e + xor reg_temp2, reg_c + add reg_a, const + xor reg_temp2, reg_b + add reg_a, [_w+count*4] + ror reg_b, 2 + add reg_a, reg_temp2 +reg_t textequ reg_e +reg_e textequ reg_d ; e=d +reg_d textequ reg_c ; d=c +reg_c textequ reg_b ; c=rotl(b,30) +reg_b textequ reg_temp1 ; b=t +reg_temp1 textequ reg_t +count = count + 1 + ENDM ; RND_PARITY + +RND_MAJ MACRO const:REQ +; t=a; a=rotl32(a,5)+e+k+w[i]+((b&c)^(b&d)^(c&d)); e=d; d=c; c=rotl32(b,30); b=t +; a=rotl32(a,5)+e+k+w[i]+((c&d)^(b&(c^d))) + mov reg_temp2, reg_d + mov reg_temp1, reg_a + rol reg_a, 5 + xor reg_temp2, reg_c + add reg_a, reg_e + and reg_temp2, reg_b + add reg_a, const + mov reg_e, reg_c + add reg_a, [_w+count*4] + and reg_e, reg_d + xor reg_temp2, reg_e + ror reg_b, 2 + add reg_a, reg_temp2 +reg_t textequ reg_e +reg_e textequ reg_d +reg_d textequ reg_c +reg_c textequ reg_b +reg_b textequ reg_temp1 +reg_temp1 textequ reg_t +count = count + 1 + ENDM ; RND_MAJ + +INIT_REG_ALIAS MACRO +reg_accu textequ +reg_base textequ +reg_i_1 textequ +reg_i_2 textequ +reg_i_3 textequ +reg_i_15 textequ +reg_i_16 textequ + ENDM + + .code + + ALIGN 16 + +SHA_Compile_p5 PROC + +__this textequ <[esp+40+320]> ; pusha + 2 * ret addr in between +_w textequ + + INIT_REG_ALIAS + +count = 0 + REPEAT 16 + IF count eq 0 + mov reg_i_16, [ebp+count*4] + bswap reg_i_16 + mov [_w+count*4], reg_i_16 + ELSEIF count eq 1 + mov reg_i_15, [ebp+count*4] + bswap reg_i_15 + mov [_w+count*4], reg_i_15 + ELSEIF count eq 13 + mov reg_i_3, [ebp+count*4] + bswap reg_i_3 + mov [_w+count*4], reg_i_3 + ELSEIF count eq 14 + mov reg_i_2, [ebp+count*4] + bswap reg_i_2 + mov [_w+count*4], reg_i_2 + ELSE + mov reg_i_1, [ebp+count*4] + bswap reg_i_1 + mov [_w+count*4], reg_i_1 + ENDIF +count = count + 1 + ENDM +count = 16 + REPEAT 64 + xor reg_i_3, reg_i_16 ; w[i-16]^w[i-3] +reg_i_14 textequ reg_i_16 ; we forget w[i-16] + IF count le 77 + mov reg_i_14, [_w+(count-14)*4] + xor reg_i_3, reg_i_14 + ELSE + xor reg_i_3, [_w+(count-14)*4] + ENDIF + xor reg_i_3, [_w+(count-8)*4] + rol reg_i_3, 1 + mov [_w+count*4], reg_i_3 +;now we prepare for the next iteration +reg_i_0 textequ reg_i_3 +reg_i_3 textequ reg_i_2 +reg_i_2 textequ reg_i_1 +reg_i_1 textequ reg_i_0 +reg_i_16 textequ reg_i_15 +reg_i_15 textequ reg_i_14 +count = count + 1 + ENDM + +reg_a textequ +reg_b textequ +reg_c textequ +reg_d textequ +reg_e textequ +reg_temp1 textequ +reg_temp2 textequ + + mov reg_temp2, __this + mov reg_a, [reg_temp2+m_nHash0] + mov reg_b, [reg_temp2+m_nHash1] + mov reg_c, [reg_temp2+m_nHash2] + mov reg_d, [reg_temp2+m_nHash3] + mov reg_e, [reg_temp2+m_nHash4] + +count = 0 + + REPEAT 20 + RND_CH 05a827999H + ENDM + REPEAT 20 + RND_PARITY 06ed9eba1H + ENDM + REPEAT 20 + RND_MAJ 08f1bbcdcH + ENDM + REPEAT 20 + RND_PARITY 0ca62c1d6H + ENDM + + mov reg_temp2, __this + add [reg_temp2+m_nHash0], reg_a + add [reg_temp2+m_nHash1], reg_b + add [reg_temp2+m_nHash2], reg_c + add [reg_temp2+m_nHash3], reg_d + add [reg_temp2+m_nHash4], reg_e + + ret + +SHA_Compile_p5 ENDP + + ALIGN 16 + +SHA1_Add_p5 PROC PUBLIC, _this:DWORD, _Data:DWORD, _nLength:DWORD + + pusha +__this textequ <[esp+36+320]> ; different offset due to pusha +__Data textequ <[esp+40+320]> +__nLength textequ <[esp+44+320]> + + sub esp, 320 + + mov ecx, __nLength + and ecx, ecx + jz get_out + xor edx, edx + mov ebp, __Data + mov edi, __this + mov ebx, [edi+m_nCount0] + mov eax, ebx + add ebx, ecx + mov [edi+m_nCount0], ebx + adc [edi+m_nCount1], edx + + and eax, 63 + jnz partial_buffer +full_blocks: mov ecx, __nLength + and ecx, ecx + jz get_out + sub ecx, 64 + jb end_of_stream + mov __nLength, ecx + call SHA_Compile_p5 + mov ebp, __Data + add ebp, 64 + mov __Data, ebp + jmp full_blocks + +end_of_stream: mov edi, __this + mov esi, ebp + lea edi, [edi+m_nBuffer] + add ecx, 64 + rep movsb + jmp get_out + +partial_buffer: add ecx, eax ; eax = offset in buffer, ecx = _nLength + cmp ecx, 64 + jb short_stream ; we can't fill the buffer + mov ecx, -64 + add ecx, eax + add __nLength, ecx ; _nlength += (offset-64) +@@: mov bl, [ebp] + inc ebp + mov byte ptr [edi+m_nBuffer+64+ecx], bl + inc ecx + jnz @B ; offset = 64 + mov __Data, ebp + lea ebp, [edi+m_nBuffer] + call SHA_Compile_p5 + mov ebp, __Data + jmp full_blocks + +short_stream: sub ecx, eax ; --> ecx=_nLength + mov esi, ebp + lea edi, [edi+m_nBuffer+eax] + rep movsb + +get_out: add esp, 320 + popa + ret 12 + +SHA1_Add_p5 ENDP + + end diff --git a/hasher/StdAfx.h b/hasher/StdAfx.h index af43e51f2..5a55c6cd2 100644 --- a/hasher/StdAfx.h +++ b/hasher/StdAfx.h @@ -1,27 +1,38 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently +// +// stdafx.h +// +// Copyright (c) Shareaza Development Team, 2002-2014. +// This file is part of SHAREAZA (shareaza.sourceforge.net) +// +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Shareaza is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -#if !defined(AFX_STDAFX_H__FE1C0E5C_BC20_4818_BC9B_601686BB10FA__INCLUDED_) -#define AFX_STDAFX_H__FE1C0E5C_BC20_4818_BC9B_601686BB10FA__INCLUDED_ - -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 +// For /Wall +#pragma warning(disable:4668) +#pragma warning(disable:4820) +#pragma warning(disable:4548) -// Insert your headers here -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _WIN32_WINNT 0x0600 -#define UNICODE -#define _UNICODE +#define STRICT +#define WIN32_LEAN_AND_MEAN +#define BOOST_USE_WINDOWS_H #include +#include -// TODO: reference additional headers your program requires here - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__FE1C0E5C_BC20_4818_BC9B_601686BB10FA__INCLUDED_) +// define HASHLIB_USE_ASM for assembler use (several times faster) \ No newline at end of file diff --git a/hasher/Types.h b/hasher/Types.h deleted file mode 100644 index c6a90c469..000000000 --- a/hasher/Types.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -typedef unsigned char uchar; -typedef unsigned char uint8; -typedef signed char sint8; - -typedef unsigned short uint16; -typedef signed short sint16; - -typedef unsigned int uint32; -typedef signed int sint32; - -typedef unsigned __int64 uint64; -typedef signed __int64 sint64; - -//#ifdef _DEBUG -//#include "Debug_FileSize.h" -//typedef CEMFileSize EMFileSize; -//#else -typedef unsigned __int64 EMFileSize; -//#endif \ No newline at end of file diff --git a/hasher/Utility.hpp b/hasher/Utility.hpp new file mode 100644 index 000000000..65e0ba1cb --- /dev/null +++ b/hasher/Utility.hpp @@ -0,0 +1,338 @@ +// +// Utility.hpp +// +// Copyright (c) Shareaza Development Team, 2002-2008. +// This file is part of SHAREAZA (shareaza.sourceforge.net) +// +// Shareaza is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Shareaza is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Shareaza; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#pragma once + +#include + +// Work-around for Microsoft double declaration +#define _interlockedbittestandset _ms_set +#define _interlockedbittestandreset _ms_reset +#define _interlockedbittestandset64 _ms_set64 +#define _interlockedbittestandreset64 _ms_reset64 +#include +#undef _interlockedbittestandset +#undef _interlockedbittestandreset +#undef _interlockedbittestandset +#undef _interlockedbittestandreset + +//! \brief platform independent signed 8 bit integer type. +typedef char int8; +//! \brief platform independent signed 16 bit integer type. +typedef short int16; +//! \brief platform independent signed 32 bit integer type. +typedef long int32; +//! \brief platform independent signed 64 bit integer type. +typedef __int64 int64; + +//! \brief platform independent unsigned 8 bit integer type. +typedef unsigned char uint8; +//! \brief platform independent unsigned 16 bit integer type. +typedef unsigned short uint16; +//! \brief platform independent unsigned 32 bit integer type. +typedef unsigned long uint32; +//! \brief platform independent unsigned 64 bit integer type. +typedef unsigned __int64 uint64; + +//! \brief alias for unsigned char. +typedef unsigned char uchar; +//! \brief alias for signed char. +typedef signed char schar; +//! \brief alias for wchar_t. +typedef wchar_t wchar; +//! \brief unsigned integer type of the same size as a wchar_t +typedef uint16 uwchar; + +//! \brief enumeration to specify the byte ordering of a sequence. +enum Endianess +{ + //! \brief specifies little endian order, + //! the least significant byte comes first. + littleEndian, + //! \brief specifies big endian order, + //! the most significant byte comes first. + bigEndian +}; + +//! \brief This namespace is used to hold machine dependent definitions for +//! the target machine. +namespace Machine +{ + //! \brief Specifies the natural byte ordering of the target machine. + //! \todo detect endianess during compilation. + const Endianess endianess = littleEndian; // x86 + + inline bool SupportsMMX() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[3] & 0x00800000) != 0; + } + + inline bool SupportsSSE() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[3] & 0x02000000) != 0; + } + + inline bool SupportsSSE2() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[3] & 0x04000000) != 0; + } + + inline bool SupportsSSE3() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[2] & 0x00000001) != 0; + } + + inline bool SupportsSSSE3() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[2] & 0x00000200) != 0; + } + + inline bool SupportsSSE41() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[2] & 0x00080000) != 0; + } + + inline bool SupportsSSE42() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 1); + return (CPUInfo[2] & 0x00100000) != 0; + } + + inline bool SupportsSSE4A() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 0x80000000); + if (CPUInfo[0] >= 0x80000001) + { + __cpuid(CPUInfo, 0x80000001); + return (CPUInfo[2] & 0x00000040) != 0; + } + return false; + } + + inline bool SupportsSSE5() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 0x80000000); + if (CPUInfo[0] >= 0x80000001) + { + __cpuid(CPUInfo, 0x80000001); + return (CPUInfo[2] & 0x00000800) != 0; + } + return false; + } + + inline bool Supports3DNOW() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 0x80000000); + if (CPUInfo[0] >= 0x80000001) + { + __cpuid(CPUInfo, 0x80000001); + return (CPUInfo[3] & 0x80000000) != 0; + } + return false; + } + + inline bool Supports3DNOWEXT() + { + int CPUInfo[4] = {}; + __cpuid(CPUInfo, 0x80000000); + if (CPUInfo[0] >= 0x80000001) + { + __cpuid(CPUInfo, 0x80000001); + return (CPUInfo[3] & 0x40000000) != 0; + } + return false; + } +} + +//! \brief generic function to swap the byte ordering of a given type +//! +//! The byte ordering can be swapped meaningfully only for unsigned integer types +//! therefore specializations are provided only for those types. We use +//! template specialization in order to avoid automatic argument conversion. +template +struct SwapEndianess {}; + +template<> struct SwapEndianess< uint8 > +{ + uint8 operator()(uint8 value) const { return value; } +}; + template<> struct SwapEndianess< uint16 > + { + uint16 operator()(uint16 value) const + { + return _byteswap_ushort(value); + } + }; + + template<> struct SwapEndianess< uint32 > + { + uint32 operator()(uint32 value) const + { + return _byteswap_ulong(value); + } + }; + + template<> struct SwapEndianess< uint64 > + { + uint64 operator()(uint64 value) const + { + return _byteswap_uint64(value); + } + }; + + template + inline T swapEndianess(T value) + { + return SwapEndianess< T >()(value); + } + + //! \brief Generic function object to give its char serialization a given + //! specified byte ordering. + //! + //! The byte ordering of the argument is swapped unless it matches the byte + //! ordering of the target machine. + //! We use partial specialization to achieve this. + template struct TransformTo + { + T operator()(T value) const { return swapEndianess< T >(value); } + }; + template struct TransformTo< T, Machine::endianess > + { + T operator()(T value) const { return value; } + }; + + //! \brief Generic function object to reconstruct a value out of its serialized + //! form with a specified byte ordering. + //! + //! This function objects behaves the same as TransformTo does but its purpose + //! is different. Having both functions allows to make that purpose explicit in + //! code. + template struct TransformFrom + { + T operator()(T value) const { return TransformTo< T, endianPolicy >()(value); } + }; + + //! \brief Generic function to bring a given value into little endian order. + template inline T transformToLE(T value) + { + return TransformTo< T, littleEndian >()(value); + } + + //! \brief Generic function to bring a given value into big endian order. + template inline T transformToBE(T value) + { + return TransformTo< T, bigEndian >()(value); + } + + //! \brief Generic function to reconstruct a given value from little endian + //! order. + template inline T transformFromLE(T value) + { + return TransformFrom< T, littleEndian >()(value); + } + + //! \brief Generic function to reconstruct a given value from big endian + //! order. + template inline T transformFromBE(T value) + { + return TransformFrom< T, bigEndian >()(value); + } + + template struct StaticSwapEndianess; + template struct StaticSwapEndianess< uint8, v > + { + static const uint8 value = v; + }; + template struct StaticSwapEndianess< uint16, v > + { + static const uint16 value = (v << 8) | (v >> 8); + }; + template struct StaticSwapEndianess< uint32, v > + { + static const uint32 value = (v << 24) | ((v & 0xff00) << 8) + | ((v & 0xff0000) >> 8) | (v >> 24); + }; + template struct StaticSwapEndianess< uint64, v > + { + static const uint64 value + = StaticSwapEndianess< uint32, (v >> 32) >::value + | (uint64(StaticSwapEndianess< uint32, v >::value) << 32); + }; + + template struct StaticTransformTo + { + static const T value = StaticSwapEndianess< T, v >::value; + }; + template struct StaticTransformTo< T, v, Machine::endianess > + { + static const T value = v; + }; + + //! \brief for_each with predicate. + //! + //! A generalization of the for_each algorithm that takes a predicate that + //! must be fulfilled in order to apply the given function. This function + //! may mutate the input sequence, provided no iterators become invalid. + template + inline void for_each_if(InputIterator first, InputIterator last, + Predicate pred, Function f) + { + for (; first != last; ++first) + { + if (pred(*first)) + f(*first) + } + } + + //! Helper function to rotate the bits of a given unsigned value. + template inline T rotateLeft(T value, uint8 shift); + template<> inline uint8 rotateLeft(uint8 value, uint8 shift) + { + return uint8(value << shift | value >> (8 - shift)); + } + template<> inline uint16 rotateLeft(uint16 value, uint8 shift) + { + return uint16(value << shift | value >> (16 - shift)); + } + template<> inline uint32 rotateLeft(uint32 value, uint8 shift) + { + return uint32(value << shift | value >> (32 - shift)); + } + template<> inline uint64 rotateLeft(uint64 value, uint8 shift) + { + return uint64(value << shift | value >> (64 - shift)); + } \ No newline at end of file diff --git a/hasher/config.h b/hasher/config.h deleted file mode 100644 index 9d46a7f03..000000000 --- a/hasher/config.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2001-2005 Jacek Sieka, arnetheduck on gmail point com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#if !defined(CONFIG_H) -#define CONFIG_H - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifdef HAVE_CONFIG_H -#include "autoconf.h" -#endif - -// Changing this number will change the maximum number of simultaneous users -// we can handle (when using select)... -#define FD_SETSIZE 4096 - -// Remove this line if hashes are not available in your stl -#define HAVE_HASH 1 - -// This enables stlport's debug mode (and slows it down to a crawl...) -//# define _STLP_DEBUG 1 - -// --- Shouldn't have to change anything under here... - -#ifndef _REENTRANT -# define _REENTRANT 1 -#endif - -#ifdef HAVE_STLPORT -# define _STLP_DONT_USE_SHORT_STRING_OPTIM 1 // Lots of memory issues with this undefined...wonder what's up with that.. -# define _STLP_USE_PTR_SPECIALIZATIONS 1 -# define _STLP_USE_TEMPLATE_EXPRESSION 1 -# define _STLP_NO_ANACHRONISMS 1 -# define _STLP_NO_CUSTOM_IO 1 -# define _STLP_NO_IOSTREAMS 1 -# ifndef _DEBUG -# define _STLP_DONT_USE_EXCEPTIONS 1 -# endif -#endif - -#ifdef _MSC_VER -# pragma warning(disable: 4711) // function 'xxx' selected for automatic inline expansion -# pragma warning(disable: 4786) // identifier was truncated to '255' characters in the debug information -# pragma warning(disable: 4290) // C++ Exception Specification ignored -# pragma warning(disable: 4127) // constant expression -# pragma warning(disable: 4710) // function not inlined -# pragma warning(disable: 4503) // decorated name length exceeded, name was truncated -//# if _MSC_VER == 1200 || _MSC_VER == 1300 || _MSC_VER == 1310 - -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed long int32_t; -typedef signed __int64 int64_t; - -typedef unsigned char u_int8_t; -typedef unsigned short u_int16_t; -typedef unsigned long u_int32_t; -typedef unsigned __int64 u_int64_t; - -//# endif - -#endif - -#if defined(_MSC_VER) -#define _LL(x) x##ll -#define _ULL(x) x##ull -#define I64_FMT "%I64d" -#elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8 -#define _LL(x) x##l -#define _ULL(x) x##ul -#define I64_FMT "%ld" -#else -#define _LL(x) x##ll -#define _ULL(x) x##ull -#define I64_FMT "%lld" -#endif - -#ifdef _WIN32 - -# define PATH_SEPARATOR '\\' -# define PATH_SEPARATOR_STR "\\" - -#else - -# define PATH_SEPARATOR '/' -# define PATH_SEPARATOR_STR "/" - -#endif - -#ifdef _MSC_VER - -# ifndef CDECL -# define CDECL _cdecl -# endif - -#else // _MSC_VER - -# ifndef CDECL -# define CDECL -# endif - -#endif // _MSC_VER - -#define BZ_NO_STDIO - - - -#endif // !defined(CONFIG_H) - -/** - * @file - * $Id: config.h,v 1.35 2005/12/03 20:36:50 arnetheduck Exp $ - */ diff --git a/hasher/crc32x64.asm b/hasher/crc32x64.asm new file mode 100644 index 000000000..02fe36de4 --- /dev/null +++ b/hasher/crc32x64.asm @@ -0,0 +1,41 @@ +.code +crcCalc PROC PUBLIC USES rax rbx rcx rdx rdi rsi pdwCrc32:PTR DWORD, ptrCrc32Table:PTR DWORD,bufferAsm:PTR BYTE,dwBytesReadAsm:DWORD + + ;mov rax, pdwCrc32 ; Load the pointer to dwCrc32 + mov rsi, rcx + mov ecx, [rsi] ; Dereference the pointer to load dwCrc32 + + ;mov rdi, ptrCrc32Table ; Load the CRC32 table + + ;mov rsi, bufferAsm ; Load buffer + xor rbx, rbx + ;mov ebx, dwBytesReadAsm ; Load dwBytesRead + lea rdi, [r8 + r9] ; Calculate the end of the buffer + + crc32loop: + xor rax, rax ; Clear the eax register + mov bl, byte ptr [r8] ; Load the current source byte + + mov al, cl ; Copy crc value into eax + inc r8 ; Advance the source pointer + + xor al, bl ; Create the index into the CRC32 table + shr ecx, 8 + + mov ebx, [rdx + rax * 4] ; Get the value out of the table + xor ecx, ebx ; xor with the current byte + + cmp rdi, r8 ; Have we reached the end of the buffer? + jne crc32loop + + ; Restore the edi and esi registers + ;pop edi + ;pop esi + + ;mov rax, pdwCrc32 ; Load the pointer to dwCrc32 + mov [rsi], ecx ; Write the result + + ret + +crcCalc ENDP +END \ No newline at end of file diff --git a/hasher/crc32x86.asm b/hasher/crc32x86.asm new file mode 100644 index 000000000..44f9460fb --- /dev/null +++ b/hasher/crc32x86.asm @@ -0,0 +1,42 @@ +.586p +.model flat, C + +.code +crcCalc PROC PUBLIC USES eax ebx ecx edx edi esi pdwCrc32:PTR DWORD, ptrCrc32Table:PTR DWORD,bufferAsm:PTR BYTE,dwBytesReadAsm:DWORD + + mov eax, pdwCrc32 ; Load the pointer to dwCrc32 + mov ecx, [eax] ; Dereference the pointer to load dwCrc32 + + mov edi, ptrCrc32Table ; Load the CRC32 table + + mov esi, bufferAsm ; Load buffer + mov ebx, dwBytesReadAsm ; Load dwBytesRead + lea edx, [esi + ebx] ; Calculate the end of the buffer + + crc32loop: + xor eax, eax ; Clear the eax register + mov bl, byte ptr [esi] ; Load the current source byte + + mov al, cl ; Copy crc value into eax + inc esi ; Advance the source pointer + + xor al, bl ; Create the index into the CRC32 table + shr ecx, 8 + + mov ebx, [edi + eax * 4] ; Get the value out of the table + xor ecx, ebx ; xor with the current byte + + cmp edx, esi ; Have we reached the end of the buffer? + jne crc32loop + + ; Restore the edi and esi registers + ;pop edi + ;pop esi + + mov eax, pdwCrc32 ; Load the pointer to dwCrc32 + mov [eax], ecx ; Write the result + + ret + +crcCalc ENDP +END \ No newline at end of file diff --git a/hasher/hash_crc.cpp b/hasher/hash_crc.cpp index aeb27b4c6..d857d6e4a 100644 --- a/hasher/hash_crc.cpp +++ b/hasher/hash_crc.cpp @@ -20,63 +20,98 @@ #include #include +#ifdef _WIN64 +extern "C" void __fastcall crcCalc(DWORD *pdwCrc32, DWORD *ptrCrc32Table, BYTE *bufferAsm, DWORD dwBytesReadAsm); +#else +extern "C" void crcCalc(DWORD *pdwCrc32, DWORD *ptrCrc32Table, BYTE *bufferAsm, DWORD dwBytesReadAsm); +#endif /* Table of CRCs of all 8-bit messages. */ -unsigned long crc_table[256]; +static CONST DWORD arrdwCrc32Table[256] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, -/* Flag: has the table been computed? Initially false. */ -int crc_table_computed = 0; + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, -/* Make the table for a fast CRC. */ -void make_crc_table(void){ - unsigned long c; - int n, k; + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - for (n = 0; n < 256; n++) { - c = (unsigned long) n; - for (k = 0; k < 8; k++) { - if (c & 1) - c = 0xedb88320L ^ (c >> 1); - else - c = c >> 1; - } - crc_table[n] = c; - } - crc_table_computed = 1; -} + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +}; /* Update a running CRC with the bytes buf[0..len-1]--the CRC should be initialized to all 1's, and the transmitted value is the 1's complement of the final running CRC (see the crc() routine below)). */ -unsigned long update_crc(unsigned long crc, unsigned char *buf, int len) -{ - unsigned long c = crc; - int n; - - - for (n = 0; n < len; n++) { - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c; -} - -/* Return the CRC of the bytes buf[0..len-1]. */ -unsigned long crc(unsigned char *buf, int len) +DigestCRC::DigestCRC() { - return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; -} - -DigestCRC::DigestCRC(){ - if (!crc_table_computed) - make_crc_table(); crc_value = 0xffffffffL; } void DigestCRC::clean(){ } -void DigestCRC::update(char* s, int len){ - crc_value = update_crc(crc_value, (unsigned char *)s, len); +void DigestCRC::update(char* s, int len) +{ + crcCalc(&crc_value, (DWORD *)&arrdwCrc32Table,(BYTE *)s, (DWORD)len); } int DigestCRC::digest(char* sum, int len){ int val=crc_value^0xffffffffL; diff --git a/hasher/hash_md5.cpp b/hasher/hash_md5.cpp index 5b72ba534..3d03d4a82 100644 --- a/hasher/hash_md5.cpp +++ b/hasher/hash_md5.cpp @@ -14,221 +14,26 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -//#include - #include "stdafx.h" -#include "stdinc.h" #include "hash_wrapper.h" +#include "MD5.h" -// Code by: B-Con (http://b-con.us) -// Released under the GNU GPL -// MD5 Hash Digest implementation (little endian byte order) - - -// Bah, signed variables are for wimps -#define uchar unsigned char -#define uint unsigned int - -// DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it -#define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - c) ++b; a += c; -#define ROTLEFT(a,b) ((a << b) | (a >> (32-b))) - -#define F(x,y,z) ((x & y) | (~x & z)) -#define G(x,y,z) ((x & z) | (y & ~z)) -#define H(x,y,z) (x ^ y ^ z) -#define I(x,y,z) (y ^ (x | ~z)) - -#define FF(a,b,c,d,m,s,t) { a += F(b,c,d) + m + t; \ - a = b + ROTLEFT(a,s); } -#define GG(a,b,c,d,m,s,t) { a += G(b,c,d) + m + t; \ - a = b + ROTLEFT(a,s); } -#define HH(a,b,c,d,m,s,t) { a += H(b,c,d) + m + t; \ - a = b + ROTLEFT(a,s); } -#define II(a,b,c,d,m,s,t) { a += I(b,c,d) + m + t; \ - a = b + ROTLEFT(a,s); } - - -typedef struct { - uchar data[64]; - uint datalen; - uint bitlen[2]; - uint state[4]; -} MD5_CTX; - - -void md5_transform(MD5_CTX *ctx, uchar data[]) -{ - uint a,b,c,d,m[16],i,j; - - // MD5 specifies big endian byte order, but this implementation assumes a little - // endian byte order CPU. Reverse all the bytes upon input, and re-reverse them - // on output (in md5_final()). - for (i=0,j=0; i < 16; ++i, j += 4) - m[i] = (data[j]) + (data[j+1] << 8) + (data[j+2] << 16) + (data[j+3] << 24); - - a = ctx->state[0]; - b = ctx->state[1]; - c = ctx->state[2]; - d = ctx->state[3]; - - FF(a,b,c,d,m[0], 7,0xd76aa478); - FF(d,a,b,c,m[1], 12,0xe8c7b756); - FF(c,d,a,b,m[2], 17,0x242070db); - FF(b,c,d,a,m[3], 22,0xc1bdceee); - FF(a,b,c,d,m[4], 7,0xf57c0faf); - FF(d,a,b,c,m[5], 12,0x4787c62a); - FF(c,d,a,b,m[6], 17,0xa8304613); - FF(b,c,d,a,m[7], 22,0xfd469501); - FF(a,b,c,d,m[8], 7,0x698098d8); - FF(d,a,b,c,m[9], 12,0x8b44f7af); - FF(c,d,a,b,m[10],17,0xffff5bb1); - FF(b,c,d,a,m[11],22,0x895cd7be); - FF(a,b,c,d,m[12], 7,0x6b901122); - FF(d,a,b,c,m[13],12,0xfd987193); - FF(c,d,a,b,m[14],17,0xa679438e); - FF(b,c,d,a,m[15],22,0x49b40821); - - GG(a,b,c,d,m[1], 5,0xf61e2562); - GG(d,a,b,c,m[6], 9,0xc040b340); - GG(c,d,a,b,m[11],14,0x265e5a51); - GG(b,c,d,a,m[0], 20,0xe9b6c7aa); - GG(a,b,c,d,m[5], 5,0xd62f105d); - GG(d,a,b,c,m[10], 9,0x02441453); - GG(c,d,a,b,m[15],14,0xd8a1e681); - GG(b,c,d,a,m[4], 20,0xe7d3fbc8); - GG(a,b,c,d,m[9], 5,0x21e1cde6); - GG(d,a,b,c,m[14], 9,0xc33707d6); - GG(c,d,a,b,m[3], 14,0xf4d50d87); - GG(b,c,d,a,m[8], 20,0x455a14ed); - GG(a,b,c,d,m[13], 5,0xa9e3e905); - GG(d,a,b,c,m[2], 9,0xfcefa3f8); - GG(c,d,a,b,m[7], 14,0x676f02d9); - GG(b,c,d,a,m[12],20,0x8d2a4c8a); - - HH(a,b,c,d,m[5], 4,0xfffa3942); - HH(d,a,b,c,m[8], 11,0x8771f681); - HH(c,d,a,b,m[11],16,0x6d9d6122); - HH(b,c,d,a,m[14],23,0xfde5380c); - HH(a,b,c,d,m[1], 4,0xa4beea44); - HH(d,a,b,c,m[4], 11,0x4bdecfa9); - HH(c,d,a,b,m[7], 16,0xf6bb4b60); - HH(b,c,d,a,m[10],23,0xbebfbc70); - HH(a,b,c,d,m[13], 4,0x289b7ec6); - HH(d,a,b,c,m[0], 11,0xeaa127fa); - HH(c,d,a,b,m[3], 16,0xd4ef3085); - HH(b,c,d,a,m[6], 23,0x04881d05); - HH(a,b,c,d,m[9], 4,0xd9d4d039); - HH(d,a,b,c,m[12],11,0xe6db99e5); - HH(c,d,a,b,m[15],16,0x1fa27cf8); - HH(b,c,d,a,m[2], 23,0xc4ac5665); - - II(a,b,c,d,m[0], 6,0xf4292244); - II(d,a,b,c,m[7], 10,0x432aff97); - II(c,d,a,b,m[14],15,0xab9423a7); - II(b,c,d,a,m[5], 21,0xfc93a039); - II(a,b,c,d,m[12], 6,0x655b59c3); - II(d,a,b,c,m[3], 10,0x8f0ccc92); - II(c,d,a,b,m[10],15,0xffeff47d); - II(b,c,d,a,m[1], 21,0x85845dd1); - II(a,b,c,d,m[8], 6,0x6fa87e4f); - II(d,a,b,c,m[15],10,0xfe2ce6e0); - II(c,d,a,b,m[6], 15,0xa3014314); - II(b,c,d,a,m[13],21,0x4e0811a1); - II(a,b,c,d,m[4], 6,0xf7537e82); - II(d,a,b,c,m[11],10,0xbd3af235); - II(c,d,a,b,m[2], 15,0x2ad7d2bb); - II(b,c,d,a,m[9], 21,0xeb86d391); - - ctx->state[0] += a; - ctx->state[1] += b; - ctx->state[2] += c; - ctx->state[3] += d; -} - -void md5_init(MD5_CTX *ctx) -{ - ctx->datalen = 0; - ctx->bitlen[0] = 0; - ctx->bitlen[1] = 0; - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -void md5_update(MD5_CTX *ctx, uchar *data, uint len) -{ - uint i; - - for (i=0; i < len; ++i) { - ctx->data[ctx->datalen] = data[i]; - ctx->datalen++; - if (ctx->datalen == 64) { - md5_transform(ctx,ctx->data); - DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512); - ctx->datalen = 0; - } - } -} - -void md5_final(MD5_CTX *ctx, uchar hash[]) -{ - uint i; - - i = ctx->datalen; - - // Pad whatever data is left in the buffer. - if (ctx->datalen < 56) { - ctx->data[i++] = 0x80; - while (i < 56) - ctx->data[i++] = 0x00; - } - else if (ctx->datalen >= 56) { - ctx->data[i++] = 0x80; - while (i < 64) - ctx->data[i++] = 0x00; - md5_transform(ctx,ctx->data); - memset(ctx->data,0,56); - } - - // Append to the padding the total message's length in bits and transform. - DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],8 * ctx->datalen); - ctx->data[56] = ctx->bitlen[0]; - ctx->data[57] = ctx->bitlen[0] >> 8; - ctx->data[58] = ctx->bitlen[0] >> 16; - ctx->data[59] = ctx->bitlen[0] >> 24; - ctx->data[60] = ctx->bitlen[1]; - ctx->data[61] = ctx->bitlen[1] >> 8; - ctx->data[62] = ctx->bitlen[1] >> 16; - ctx->data[63] = ctx->bitlen[1] >> 24; - md5_transform(ctx,ctx->data); - - // Since this implementation uses little endian byte ordering and MD uses big endian, - // reverse all the bytes when copying the final state to the output hash. - for (i=0; i < 4; ++i) { - hash[i] = (ctx->state[0] >> (i*8)) & 0x000000ff; - hash[i+4] = (ctx->state[1] >> (i*8)) & 0x000000ff; - hash[i+8] = (ctx->state[2] >> (i*8)) & 0x000000ff; - hash[i+12] = (ctx->state[3] >> (i*8)) & 0x000000ff; - } -} DigestMD5::DigestMD5(){ - MD5_CTX* my = new MD5_CTX; - md5_init(my); - addr = (void*)my; + addr = (void*)new CMD5(); } void DigestMD5::clean(){ - delete (MD5_CTX*)addr; - //free((MD5_CTX*)addr); + CMD5* md5 = (CMD5*)addr; + delete md5; } -void DigestMD5::update(char* s, int len){ - md5_update((MD5_CTX*)addr,(uchar*)s,len); +void DigestMD5::update(char* buf, int len){ + CMD5* md5 = (CMD5*)addr; + md5->Add(buf, len); } int DigestMD5::digest(char* sum, int len){ - uchar hash[16]; - md5_final((MD5_CTX*)addr,hash); - memcpy(sum,hash,16); + CMD5* md5= (CMD5*)addr; + md5->Finish(); + md5->GetHash((uchar *)sum); return 16; -} \ No newline at end of file +} diff --git a/hasher/hash_sha.cpp b/hasher/hash_sha.cpp index be2c8b186..93dbdbbf1 100644 --- a/hasher/hash_sha.cpp +++ b/hasher/hash_sha.cpp @@ -33,8 +33,7 @@ void DigestSHA::update(char* buf, int len){ } int DigestSHA::digest(char* sum, int len){ CSHA* sha = (CSHA*)addr; - CAICHHash hash; - sha->Finish(hash); - memcpy(sum,hash.GetRawHash(), hash.GetHashSize()); - return hash.GetHashSize(); + sha->Finish(); + sha->GetHash((uchar *)sum); + return 20; } diff --git a/hasher/hash_wrapper.h b/hasher/hash_wrapper.h index f0aeea855..bccb23cfc 100644 --- a/hasher/hash_wrapper.h +++ b/hasher/hash_wrapper.h @@ -27,7 +27,7 @@ virtual void clean()=0; class DigestCRC : public Digest{ private: -unsigned long crc_value; +DWORD crc_value; public: DigestCRC(); void update(char* buf, int len); diff --git a/hasher/hasher.cpp b/hasher/hasher.cpp index 7b241e9f3..3dc1ff367 100644 --- a/hasher/hasher.cpp +++ b/hasher/hasher.cpp @@ -9,6 +9,8 @@ #include #include #include +#include + ///////////////////////////////////////////////////////////////////////////////// #define ED2K_CHUNK_SIZE 9728000 @@ -79,7 +81,7 @@ extern "C" __declspec(dllexport) int __cdecl CalculateHashes_SyncIO(const TCHAR } MD4Engine.Finish(); - MD4Engine.GetHash(&md4); + MD4Engine.GetHash((uchar *)&md4); BYTE * pData = (BYTE*)&md4; for (int n=0; n<16; n++) pTemp[nChunk*16+n] = pData[n]; @@ -113,7 +115,7 @@ extern "C" __declspec(dllexport) int __cdecl CalculateHashes_SyncIO(const TCHAR MD4Engine.Reset(); MD4Engine.Add(pTemp, nChunks*16); MD4Engine.Finish(); - MD4Engine.GetHash(&md4); + MD4Engine.GetHash((uchar *)&md4); BYTE * pData = (BYTE*)&md4; for (int n=0; n<16; n++) pResult[n] = pData[n]; @@ -269,7 +271,7 @@ extern "C" __declspec(dllexport) int __cdecl CalculateHashes_AsyncIO(const TCHAR if (getMD5) md5.update(blocks[iMaskedReaderPos], dwBytesChunkLeft); //calculate MD4 of chunk MD4Engine.Finish(); - MD4Engine.GetHash(&md4); + MD4Engine.GetHash((uchar *)&md4); BYTE * pData = (BYTE*)&md4; for (int n=0; n<16; n++) pTemp[nChunk*16+n] = pData[n]; @@ -326,7 +328,7 @@ extern "C" __declspec(dllexport) int __cdecl CalculateHashes_AsyncIO(const TCHAR MD4Engine.Reset(); MD4Engine.Add(pTemp, nChunks*16); MD4Engine.Finish(); - MD4Engine.GetHash(&md4); + MD4Engine.GetHash((uchar *)&md4); BYTE * pData = (BYTE*)&md4; for (int n=0; n<16; n++) pResult[n] = pData[n]; diff --git a/hasher/stdinc.h b/hasher/stdinc.h deleted file mode 100644 index 687d3d39b..000000000 --- a/hasher/stdinc.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2001-2005 Jacek Sieka, arnetheduck on gmail point com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#if !defined(STDINC_H) -#define STDINC_H - -#include "config.h" - -#ifdef _WIN32 - - -#define WIN32_LEAN_AND_MEAN -#define _WTL_NO_CSTRING -#define _ATL_NO_OPENGL -#define _ATL_NO_MSIMG -#define _ATL_NO_COM -#define _ATL_NO_HOSTING -#define _ATL_NO_OLD_NAMES - -#include - -#include -#include -#include - -#else -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Use maps if hash_maps aren't available -#ifdef HAVE_HASH -# ifdef HAVE_STLPORT -# define HASH_MAP_X(key, type, hfunc, eq, order) hash_map -# define HASH_MULTIMAP_X(key, type, hfunc, eq, order) hash_multimap -# elif defined(__GLIBCPP__) || defined(__GLIBCXX__) // Using GNU C++ library? -# define HASH_MAP_X(key, type, hfunc, eq, order) hash_map -# define HASH_MULTIMAP_X(key, type, hfunc, eq, order) hash_multimap -# elif defined(_MSC_VER) // Assume the msvc 7.x stl -# define HASH_MAP_X(key, type, hfunc, eq, order) hash_map -# define HASH_MULTIMAP_X(key, type, hfunc, eq, order) hash_multimap -# else -# error Unknown STL, hashes need to be configured -# endif - -# define HASH_SET hash_set -# define HASH_MAP hash_map -# define HASH_MULTIMAP hash_multimap - -#else // HAVE_HASH - -# define HASH_SET set -# define HASH_MAP map -# define HASH_MAP_X(key, type, hfunc, eq, order) map -# define HASH_MULTIMAP multimap -# define HASH_MULTIMAP_X(key, type, hfunc, eq, order) multimap - -#endif // HAVE_HASH - - -#ifdef HAVE_STLPORT -using namespace _STL; -#include -#include - -#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) // Using GNU C++ library? -#include -#include -#include -using namespace std; -using namespace __gnu_cxx; - -// GNU C++ library doesn't have hash(std::string) or hash(long long int) -namespace __gnu_cxx { - template<> struct hash { - size_t operator()(const std::string& x) const - { return hash()(x.c_str()); } - }; - template<> struct hash { - size_t operator()(long long int x) const { return x; } - }; -} -#else // __GLIBCPP__ - -#include -#include - -using namespace std; -using namespace stdext; - -#endif // __GLIBCPP__ - -#endif // !defined(STDINC_H) - -/** - * @file - * $Id: stdinc.h,v 1.20 2005/12/16 01:00:46 arnetheduck Exp $ - */