diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-01-20 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:49 +0300 |
commit | d9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch) | |
tree | c722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Crypto/Hash | |
parent | 804edc5756fede54dbb1aefda6d39d306111938d (diff) |
4.44 beta
Diffstat (limited to 'CPP/7zip/Crypto/Hash')
-rwxr-xr-x | CPP/7zip/Crypto/Hash/HmacSha1.cpp | 109 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/HmacSha1.h | 39 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.cpp | 83 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.h | 21 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/RandGen.cpp | 78 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/RandGen.h | 21 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/RotateDefs.h | 19 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Sha1.cpp | 210 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Sha1.h | 68 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Sha256.cpp | 210 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/Sha256.h | 30 | ||||
-rwxr-xr-x | CPP/7zip/Crypto/Hash/StdAfx.h | 8 |
12 files changed, 896 insertions, 0 deletions
diff --git a/CPP/7zip/Crypto/Hash/HmacSha1.cpp b/CPP/7zip/Crypto/Hash/HmacSha1.cpp new file mode 100755 index 00000000..a5c20a75 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/HmacSha1.cpp @@ -0,0 +1,109 @@ +// HmacSha1.cpp + +#include "StdAfx.h" + +#include "HmacSha1.h" + +namespace NCrypto { +namespace NSha1 { + +void CHmac::SetKey(const Byte *key, size_t keySize) +{ + Byte keyTemp[kBlockSize]; + size_t i; + for (i = 0; i < kBlockSize; i++) + keyTemp[i] = 0; + if(keySize > kBlockSize) + { + _sha.Init(); + _sha.Update(key, keySize); + _sha.Final(keyTemp); + keySize = kDigestSize; + } + else + for (i = 0; i < keySize; i++) + keyTemp[i] = key[i]; + for (i = 0; i < kBlockSize; i++) + keyTemp[i] ^= 0x36; + _sha.Init(); + _sha.Update(keyTemp, kBlockSize); + for (i = 0; i < kBlockSize; i++) + keyTemp[i] ^= 0x36 ^ 0x5C; + _sha2.Init(); + _sha2.Update(keyTemp, kBlockSize); +} + +void CHmac::Final(Byte *mac, size_t macSize) +{ + Byte digest[kDigestSize]; + _sha.Final(digest); + _sha2.Update(digest, kDigestSize); + _sha2.Final(digest); + for(size_t i = 0; i < macSize; i++) + mac[i] = digest[i]; +} + + +void CHmac32::SetKey(const Byte *key, size_t keySize) +{ + UInt32 keyTemp[kBlockSizeInWords]; + size_t i; + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] = 0; + if(keySize > kBlockSize) + { + CContext sha; + sha.Init(); + sha.Update(key, keySize); + Byte digest[kDigestSize]; + sha.Final(digest); + + for (int i = 0 ; i < kDigestSizeInWords; i++) + keyTemp[i] = + ((UInt32)(digest[i * 4 + 0]) << 24) | + ((UInt32)(digest[i * 4 + 1]) << 16) | + ((UInt32)(digest[i * 4 + 2]) << 8) | + ((UInt32)(digest[i * 4 + 3])); + keySize = kDigestSizeInWords; + } + else + for (size_t i = 0; i < keySize; i++) + keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3))); + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] ^= 0x36363636; + _sha.Init(); + _sha.Update(keyTemp, kBlockSizeInWords); + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C; + _sha2.Init(); + _sha2.Update(keyTemp, kBlockSizeInWords); +} + +void CHmac32::Final(UInt32 *mac, size_t macSize) +{ + UInt32 digest[kDigestSizeInWords]; + _sha.Final(digest); + _sha2.Update(digest, kDigestSizeInWords); + _sha2.Final(digest); + for(size_t i = 0; i < macSize; i++) + mac[i] = digest[i]; +} + +void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration) +{ + UInt32 block[kBlockSizeInWords]; + UInt32 block2[kBlockSizeInWords]; + _sha.PrepareBlock(block, kDigestSizeInWords); + _sha2.PrepareBlock(block2, kDigestSizeInWords); + for(unsigned int s = 0; s < kDigestSizeInWords; s++) + block[s] = mac[s]; + for(UInt32 i = 0; i < numIteration; i++) + { + _sha.GetBlockDigest(block, block2); + _sha2.GetBlockDigest(block2, block); + for (unsigned int s = 0; s < kDigestSizeInWords; s++) + mac[s] ^= block[s]; + } +} + +}} diff --git a/CPP/7zip/Crypto/Hash/HmacSha1.h b/CPP/7zip/Crypto/Hash/HmacSha1.h new file mode 100755 index 00000000..bca5bcf8 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/HmacSha1.h @@ -0,0 +1,39 @@ +// HmacSha1.h +// Implements HMAC-SHA-1 (RFC2104, FIPS-198) + +#ifndef _HMAC_H +#define _HMAC_H + +#include "Sha1.h" + +namespace NCrypto { +namespace NSha1 { + +// Use: SetKey(key, keySize); for () Update(data, size); Final(mac, macSize); + +class CHmac +{ + CContext _sha; + CContext _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); } + void Final(Byte *mac, size_t macSize = kDigestSize); +}; + +class CHmac32 +{ + CContext32 _sha; + CContext32 _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); } + void Final(UInt32 *mac, size_t macSize = kDigestSizeInWords); + + // It'sa for hmac function. in,out: mac[kDigestSizeInWords]. + void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.cpp new file mode 100755 index 00000000..b11881b7 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.cpp @@ -0,0 +1,83 @@ +// Pbkdf2HmacSha1.cpp + +#include "StdAfx.h" + +#include "HmacSha1.h" + +namespace NCrypto { +namespace NSha1 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, + UInt32 numIterations, Byte *key, size_t keySize) +{ + CHmac baseCtx; + baseCtx.SetKey(pwd, pwdSize); + for (UInt32 i = 1; keySize > 0; i++) + { + CHmac ctx = baseCtx; + ctx.Update(salt, saltSize); + Byte u[kDigestSize] = { (Byte)(i >> 24), (Byte)(i >> 16), (Byte)(i >> 8), (Byte)(i) }; + const unsigned int curSize = (keySize < kDigestSize) ? (unsigned int)keySize : kDigestSize; + ctx.Update(u, 4); + ctx.Final(u, kDigestSize); + + unsigned int s; + for (s = 0; s < curSize; s++) + key[s] = u[s]; + + for (UInt32 j = numIterations; j > 1; j--) + { + ctx = baseCtx; + ctx.Update(u, kDigestSize); + ctx.Final(u, kDigestSize); + for (s = 0; s < curSize; s++) + key[s] ^= u[s]; + } + + key += curSize; + keySize -= curSize; + } +} + +void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, + UInt32 numIterations, UInt32 *key, size_t keySize) +{ + CHmac32 baseCtx; + baseCtx.SetKey(pwd, pwdSize); + for (UInt32 i = 1; keySize > 0; i++) + { + CHmac32 ctx = baseCtx; + ctx.Update(salt, saltSize); + UInt32 u[kDigestSizeInWords] = { i }; + const unsigned int curSize = (keySize < kDigestSizeInWords) ? (unsigned int)keySize : kDigestSizeInWords; + ctx.Update(u, 1); + ctx.Final(u, kDigestSizeInWords); + + // Speed-optimized code start + ctx = baseCtx; + ctx.GetLoopXorDigest(u, numIterations - 1); + // Speed-optimized code end + + unsigned int s; + for (s = 0; s < curSize; s++) + key[s] = u[s]; + + /* + // Default code start + for (UInt32 j = numIterations; j > 1; j--) + { + ctx = baseCtx; + ctx.Update(u, kDigestSizeInWords); + ctx.Final(u, kDigestSizeInWords); + for (s = 0; s < curSize; s++) + key[s] ^= u[s]; + } + // Default code end + */ + + key += curSize; + keySize -= curSize; + } +} + +}} diff --git a/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.h new file mode 100755 index 00000000..00a5e009 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Pbkdf2HmacSha1.h @@ -0,0 +1,21 @@ +// Pbkdf2HmacSha1.h +// Password-Based Key Derivation Function (RFC 2898, PKCS #5) based on HMAC-SHA-1 + +#ifndef __PBKDF2HMACSHA1_H +#define __PBKDF2HMACSHA1_H + +#include <stddef.h> +#include "../../../Common/Types.h" + +namespace NCrypto { +namespace NSha1 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, + UInt32 numIterations, Byte *key, size_t keySize); + +void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, + UInt32 numIterations, UInt32 *key, size_t keySize); + +}} + +#endif diff --git a/CPP/7zip/Crypto/Hash/RandGen.cpp b/CPP/7zip/Crypto/Hash/RandGen.cpp new file mode 100755 index 00000000..480e04ca --- /dev/null +++ b/CPP/7zip/Crypto/Hash/RandGen.cpp @@ -0,0 +1,78 @@ +// RandGen.cpp + +#include "StdAfx.h" + +#include <stdio.h> + +#include "Windows/Synchronization.h" + +#include "RandGen.h" + +// This is not very good random number generator. +// Please use it only for salt. +// First genrated data block depends from timer. +// Other genrated data blocks depend from previous state +// Maybe it's possible to restore original timer vaue from generated value. + +void CRandomGenerator::Init() +{ + NCrypto::NSha1::CContext hash; + hash.Init(); + + #ifdef _WIN32 + DWORD w = ::GetCurrentProcessId(); + hash.Update((const Byte *)&w, sizeof(w)); + w = ::GetCurrentThreadId(); + hash.Update((const Byte *)&w, sizeof(w)); + #endif + + for (int i = 0; i < 1000; i++) + { + #ifdef _WIN32 + LARGE_INTEGER v; + if (::QueryPerformanceCounter(&v)) + hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart)); + #endif + + DWORD tickCount = ::GetTickCount(); + hash.Update((const Byte *)&tickCount, sizeof(tickCount)); + + for (int j = 0; j < 100; j++) + { + hash.Final(_buff); + hash.Init(); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + } + } + hash.Final(_buff); + _needInit = false; +} + +static NWindows::NSynchronization::CCriticalSection g_CriticalSection; + +void CRandomGenerator::Generate(Byte *data, unsigned int size) +{ + g_CriticalSection.Enter(); + if (_needInit) + Init(); + while (size > 0) + { + NCrypto::NSha1::CContext hash; + + hash.Init(); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + hash.Final(_buff); + + hash.Init(); + UInt32 salt = 0xF672ABD1; + hash.Update((const Byte *)&salt, sizeof(salt)); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + Byte buff[NCrypto::NSha1::kDigestSize]; + hash.Final(buff); + for (unsigned int i = 0; i < NCrypto::NSha1::kDigestSize && size > 0; i++, size--) + *data++ = buff[i]; + } + g_CriticalSection.Leave(); +} + +CRandomGenerator g_RandomGenerator; diff --git a/CPP/7zip/Crypto/Hash/RandGen.h b/CPP/7zip/Crypto/Hash/RandGen.h new file mode 100755 index 00000000..3b58a032 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/RandGen.h @@ -0,0 +1,21 @@ +// RandGen.h + +#ifndef __RANDGEN_H +#define __RANDGEN_H + +#include "Sha1.h" + +class CRandomGenerator +{ + Byte _buff[NCrypto::NSha1::kDigestSize]; + bool _needInit; + + void Init(); +public: + CRandomGenerator(): _needInit(true) {}; + void Generate(Byte *data, unsigned int size); +}; + +extern CRandomGenerator g_RandomGenerator; + +#endif diff --git a/CPP/7zip/Crypto/Hash/RotateDefs.h b/CPP/7zip/Crypto/Hash/RotateDefs.h new file mode 100755 index 00000000..832e7357 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/RotateDefs.h @@ -0,0 +1,19 @@ +// RotateDefs.h + +#ifndef __ROTATEDEFS_H +#define __ROTATEDEFS_H + +#ifdef _MSC_VER + +#include <stddef.h> +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#else + +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#endif + +#endif diff --git a/CPP/7zip/Crypto/Hash/Sha1.cpp b/CPP/7zip/Crypto/Hash/Sha1.cpp new file mode 100755 index 00000000..0e1d2ecf --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Sha1.cpp @@ -0,0 +1,210 @@ +// Sha1.cpp +// This file is based on public domain +// Steve Reid and Wei Dai's code from Crypto++ + +#include "StdAfx.h" + +#include "Sha1.h" +#include "RotateDefs.h" + +namespace NCrypto { +namespace NSha1 { + +// define it for speed optimization +// #define _SHA1_UNROLL + +static const unsigned int kNumW = + #ifdef _SHA1_UNROLL + 16; + #else + 80; + #endif + + +#define w0(i) (W[(i)] = data[(i)]) + +#ifdef _SHA1_UNROLL +#define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1)) +#else +#define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1)) +#endif + +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) + +#define RK1(a,b,c,d,e,i, f, w, k) e += f(b,c,d) + w(i) + k + rotlFixed(a,5); b = rotlFixed(b,30); + +#define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999) +#define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999) +#define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1) +#define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC) +#define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6) + +#define RX_1_4(rx1, rx4, i) rx1(a,b,c,d,e,i); rx4(e,a,b,c,d,i+1); rx4(d,e,a,b,c,i+2); rx4(c,d,e,a,b,i+3); rx4(b,c,d,e,a,i+4); +#define RX_5(rx, i) RX_1_4(rx, rx, i); + +void CContextBase::Init() +{ + _state[0] = 0x67452301; + _state[1] = 0xEFCDAB89; + _state[2] = 0x98BADCFE; + _state[3] = 0x10325476; + _state[4] = 0xC3D2E1F0; + _count = 0; +} + +void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes) +{ + UInt32 a, b, c, d, e; + UInt32 W[kNumW]; + + a = _state[0]; + b = _state[1]; + c = _state[2]; + d = _state[3]; + e = _state[4]; + #ifdef _SHA1_UNROLL + RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10); + #else + int i; + for (i = 0; i < 15; i += 5) { RX_5(R0, i); } + #endif + + RX_1_4(R0, R1, 15); + + + #ifdef _SHA1_UNROLL + RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35); + RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55); + RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75); + #else + i = 20; + for (; i < 40; i += 5) { RX_5(R2, i); } + for (; i < 60; i += 5) { RX_5(R3, i); } + for (; i < 80; i += 5) { RX_5(R4, i); } + #endif + + destDigest[0] = _state[0] + a; + destDigest[1] = _state[1] + b; + destDigest[2] = _state[2] + c; + destDigest[3] = _state[3] + d; + destDigest[4] = _state[4] + e; + + if (returnRes) + for (int i = 0 ; i < 16; i++) + data[i] = W[kNumW - 16 + i]; + + // Wipe variables + // a = b = c = d = e = 0; +} + +void CContextBase::PrepareBlock(UInt32 *block, unsigned int size) const +{ + unsigned int curBufferPos = size & 0xF; + block[curBufferPos++] = 0x80000000; + while (curBufferPos != (16 - 2)) + block[curBufferPos++] = 0; + const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5); + block[curBufferPos++] = (UInt32)(lenInBits >> 32); + block[curBufferPos++] = (UInt32)(lenInBits); +} + +void CContext::Update(Byte *data, size_t size, bool rar350Mode) +{ + bool returnRes = false; + unsigned int curBufferPos = _count2; + while (size-- > 0) + { + int pos = (int)(curBufferPos & 3); + if (pos == 0) + _buffer[curBufferPos >> 2] = 0; + _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); + if (++curBufferPos == kBlockSize) + { + curBufferPos = 0; + CContextBase::UpdateBlock(_buffer, returnRes); + if (returnRes) + for (int i = 0; i < kBlockSizeInWords; i++) + { + UInt32 d = _buffer[i]; + data[i * 4 + 0 - kBlockSize] = (Byte)(d); + data[i * 4 + 1 - kBlockSize] = (Byte)(d >> 8); + data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16); + data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24); + } + returnRes = rar350Mode; + } + } + _count2 = curBufferPos; +} + +void CContext::Final(Byte *digest) +{ + const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3); + unsigned int curBufferPos = _count2; + int pos = (int)(curBufferPos & 3); + curBufferPos >>= 2; + if (pos == 0) + _buffer[curBufferPos] = 0; + _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos)); + + while (curBufferPos != (16 - 2)) + { + curBufferPos &= 0xF; + if (curBufferPos == 0) + UpdateBlock(); + _buffer[curBufferPos++] = 0; + } + _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); + _buffer[curBufferPos++] = (UInt32)(lenInBits); + UpdateBlock(); + + int i; + for (i = 0; i < kDigestSizeInWords; i++) + { + UInt32 state = _state[i] & 0xFFFFFFFF; + *digest++ = (Byte)(state >> 24); + *digest++ = (Byte)(state >> 16); + *digest++ = (Byte)(state >> 8); + *digest++ = (Byte)(state); + } + Init(); +} + +/////////////////////////// +// Words version + +void CContext32::Update(const UInt32 *data, size_t size) +{ + while (size-- > 0) + { + _buffer[_count2++] = *data++; + if (_count2 == kBlockSizeInWords) + { + _count2 = 0; + UpdateBlock(); + } + } +} + +void CContext32::Final(UInt32 *digest) +{ + const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5); + unsigned int curBufferPos = _count2; + _buffer[curBufferPos++] = 0x80000000; + while (curBufferPos != (16 - 2)) + { + curBufferPos &= 0xF; + if (curBufferPos == 0) + UpdateBlock(); + _buffer[curBufferPos++] = 0; + } + _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); + _buffer[curBufferPos++] = (UInt32)(lenInBits); + GetBlockDigest(_buffer, digest); + Init(); +} + +}} diff --git a/CPP/7zip/Crypto/Hash/Sha1.h b/CPP/7zip/Crypto/Hash/Sha1.h new file mode 100755 index 00000000..ebb11142 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Sha1.h @@ -0,0 +1,68 @@ +// Sha1.h +// This file is based on public domain +// Steve Reid and Wei Dai's code from Crypto++ + +#ifndef __SHA1_H +#define __SHA1_H + +#include <stddef.h> +#include "../../../Common/Types.h" + +// Sha1 implementation in RAR before version 3.60 has bug: +// it changes data bytes in some cases. +// So this class supports both versions: normal_SHA and rar3Mode + +namespace NCrypto { +namespace NSha1 { + +const unsigned int kBlockSize = 64; +const unsigned int kDigestSize = 20; + +const unsigned int kBlockSizeInWords = (kBlockSize >> 2); +const unsigned int kDigestSizeInWords = (kDigestSize >> 2); + +class CContextBase +{ +protected: + UInt32 _state[5]; + UInt64 _count; + void UpdateBlock(UInt32 *data, bool returnRes = false) + { + GetBlockDigest(data, _state, returnRes); + _count++; + } +public: + void Init(); + void GetBlockDigest(UInt32 *blockData, UInt32 *destDigest, bool returnRes = false); + // PrepareBlock can be used only when size <= 13. size in Words + void PrepareBlock(UInt32 *block, unsigned int size) const; +}; + +class CContextBase2: public CContextBase +{ +protected: + unsigned int _count2; + UInt32 _buffer[kBlockSizeInWords]; + void UpdateBlock() { CContextBase::UpdateBlock(_buffer); } +public: + void Init() { CContextBase::Init(); _count2 = 0; } +}; + +class CContext: public CContextBase2 +{ +public: + void Update(Byte *data, size_t size, bool rar350Mode = false); + void Update(const Byte *data, size_t size) { Update((Byte *)data, size, false); } + void Final(Byte *digest); +}; + +class CContext32: public CContextBase2 +{ +public: + void Update(const UInt32 *data, size_t size); + void Final(UInt32 *digest); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Hash/Sha256.cpp b/CPP/7zip/Crypto/Hash/Sha256.cpp new file mode 100755 index 00000000..db236058 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Sha256.cpp @@ -0,0 +1,210 @@ +// Crypto/Sha256.cpp +// This code is based on code from Wei Dai's Crypto++ library. + +#include "StdAfx.h" + +#include "Sha256.h" +#include "RotateDefs.h" + +namespace NCrypto { +namespace NSha256 { + +// define it for speed optimization +// #define _SHA256_UNROLL +// #define _SHA256_UNROLL2 + +void CContext::Init() +{ + _state[0] = 0x6a09e667; + _state[1] = 0xbb67ae85; + _state[2] = 0x3c6ef372; + _state[3] = 0xa54ff53a; + _state[4] = 0x510e527f; + _state[5] = 0x9b05688c; + _state[6] = 0x1f83d9ab; + _state[7] = 0x5be0cd19; + + _count = 0; +} + +#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) +#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) +#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) +#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) + +#define blk0(i) (W[i] = data[i]) +#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#define a(i) T[(0-(i))&7] +#define b(i) T[(1-(i))&7] +#define c(i) T[(2-(i))&7] +#define d(i) T[(3-(i))&7] +#define e(i) T[(4-(i))&7] +#define f(i) T[(5-(i))&7] +#define g(i) T[(6-(i))&7] +#define h(i) T[(7-(i))&7] + + +#ifdef _SHA256_UNROLL2 + +#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\ + d += h; h += S0(a) + Maj(a, b, c) + +#define RX_8(i) \ + R(a,b,c,d,e,f,g,h, i); \ + R(h,a,b,c,d,e,f,g, i+1); \ + R(g,h,a,b,c,d,e,f, i+2); \ + R(f,g,h,a,b,c,d,e, i+3); \ + R(e,f,g,h,a,b,c,d, i+4); \ + R(d,e,f,g,h,a,b,c, i+5); \ + R(c,d,e,f,g,h,a,b, i+6); \ + R(b,c,d,e,f,g,h,a, i+7) + +#else + +#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ + d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) + +#ifdef _SHA256_UNROLL + +#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); + +#endif + +#endif + + +void CContext::Transform(UInt32 *state, const UInt32 *data) +{ + UInt32 W[16]; + + #ifdef _SHA256_UNROLL2 + UInt32 a,b,c,d,e,f,g,h; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + #else + UInt32 T[8]; + for (int s = 0; s < 8; s++) + T[s] = state[s]; + #endif + + for (unsigned int j = 0; j < 64; j += 16) + { + #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) + RX_8(0); RX_8(8); + #else + for (unsigned int i = 0; i < 16; i++) { R(i); } + #endif + } + + #ifdef _SHA256_UNROLL2 + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + #else + for (int i = 0; i < 8; i++) + state[i] += T[i]; + #endif + + // Wipe variables + // memset(W, 0, sizeof(W)); + // memset(T, 0, sizeof(T)); +} + +const UInt32 CContext::K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#undef S0 +#undef S1 +#undef s0 +#undef s1 + +void CContext::WriteByteBlock() +{ + UInt32 data32[16]; + for (int i = 0; i < 16; i++) + { + data32[i] = (UInt32(_buffer[i * 4]) << 24) + + (UInt32(_buffer[i * 4 + 1]) << 16) + + (UInt32(_buffer[i * 4 + 2]) << 8) + + UInt32(_buffer[i * 4 + 3]); + } + Transform(_state, data32); +} + +void CContext::Update(const Byte *data, size_t size) +{ + UInt32 curBufferPos = (UInt32)_count & 0x3F; + while (size > 0) + { + _buffer[curBufferPos++] = *data++; + _count++; + size--; + if (curBufferPos == 64) + { + curBufferPos = 0; + WriteByteBlock(); + } + } +} + +void CContext::Final(Byte *digest) +{ + UInt64 lenInBits = (_count << 3); + UInt32 curBufferPos = (UInt32)_count & 0x3F; + _buffer[curBufferPos++] = 0x80; + while (curBufferPos != (64 - 8)) + { + curBufferPos &= 0x3F; + if (curBufferPos == 0) + WriteByteBlock(); + _buffer[curBufferPos++] = 0; + } + for (int i = 0; i < 8; i++) + { + _buffer[curBufferPos++] = (Byte)(lenInBits >> 56); + lenInBits <<= 8; + } + WriteByteBlock(); + + for (int j = 0; j < 8; j++) + { + *digest++ = (Byte)(_state[j] >> 24); + *digest++ = (Byte)(_state[j] >> 16); + *digest++ = (Byte)(_state[j] >> 8); + *digest++ = (Byte)(_state[j]); + } + Init(); +} + +}} diff --git a/CPP/7zip/Crypto/Hash/Sha256.h b/CPP/7zip/Crypto/Hash/Sha256.h new file mode 100755 index 00000000..e4788f41 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/Sha256.h @@ -0,0 +1,30 @@ +// Crypto/Sha256.h + +#ifndef __CRYPTO_SHA256_H +#define __CRYPTO_SHA256_H + +#include "Common/Types.h" + +namespace NCrypto { +namespace NSha256 { + +class CContext +{ + static const UInt32 K[64]; + + UInt32 _state[8]; + UInt64 _count; + Byte _buffer[64]; + static void Transform(UInt32 *digest, const UInt32 *data); + void WriteByteBlock(); +public: + enum {DIGESTSIZE = 32}; + CContext() { Init(); } ; + void Init(); + void Update(const Byte *data, size_t size); + void Final(Byte *digest); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Hash/StdAfx.h b/CPP/7zip/Crypto/Hash/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/CPP/7zip/Crypto/Hash/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif |