rlm@1: // Crypto/Sha1.cpp rlm@1: // This file is based on public domain rlm@1: // Steve Reid and Wei Dai's code from Crypto++ rlm@1: rlm@1: #include "StdAfx.h" rlm@1: rlm@1: #include "Sha1.h" rlm@1: extern "C" rlm@1: { rlm@1: #include "../../../C/RotateDefs.h" rlm@1: } rlm@1: rlm@1: namespace NCrypto { rlm@1: namespace NSha1 { rlm@1: rlm@1: // define it for speed optimization rlm@1: // #define _SHA1_UNROLL rlm@1: rlm@1: static const unsigned kNumW = rlm@1: #ifdef _SHA1_UNROLL rlm@1: 16; rlm@1: #else rlm@1: 80; rlm@1: #endif rlm@1: rlm@1: rlm@1: #define w0(i) (W[(i)] = data[(i)]) rlm@1: rlm@1: #ifdef _SHA1_UNROLL rlm@1: #define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1)) rlm@1: #else rlm@1: #define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1)) rlm@1: #endif rlm@1: rlm@1: #define f1(x,y,z) (z^(x&(y^z))) rlm@1: #define f2(x,y,z) (x^y^z) rlm@1: #define f3(x,y,z) ((x&y)|(z&(x|y))) rlm@1: #define f4(x,y,z) (x^y^z) rlm@1: rlm@1: #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); rlm@1: rlm@1: #define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999) rlm@1: #define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999) rlm@1: #define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1) rlm@1: #define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC) rlm@1: #define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6) rlm@1: rlm@1: #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); rlm@1: #define RX_5(rx, i) RX_1_4(rx, rx, i); rlm@1: rlm@1: void CContextBase::Init() rlm@1: { rlm@1: _state[0] = 0x67452301; rlm@1: _state[1] = 0xEFCDAB89; rlm@1: _state[2] = 0x98BADCFE; rlm@1: _state[3] = 0x10325476; rlm@1: _state[4] = 0xC3D2E1F0; rlm@1: _count = 0; rlm@1: } rlm@1: rlm@1: void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes) rlm@1: { rlm@1: UInt32 a, b, c, d, e; rlm@1: UInt32 W[kNumW]; rlm@1: rlm@1: a = _state[0]; rlm@1: b = _state[1]; rlm@1: c = _state[2]; rlm@1: d = _state[3]; rlm@1: e = _state[4]; rlm@1: #ifdef _SHA1_UNROLL rlm@1: RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10); rlm@1: #else rlm@1: int i; rlm@1: for (i = 0; i < 15; i += 5) { RX_5(R0, i); } rlm@1: #endif rlm@1: rlm@1: RX_1_4(R0, R1, 15); rlm@1: rlm@1: rlm@1: #ifdef _SHA1_UNROLL rlm@1: RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35); rlm@1: RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55); rlm@1: RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75); rlm@1: #else rlm@1: i = 20; rlm@1: for (; i < 40; i += 5) { RX_5(R2, i); } rlm@1: for (; i < 60; i += 5) { RX_5(R3, i); } rlm@1: for (; i < 80; i += 5) { RX_5(R4, i); } rlm@1: #endif rlm@1: rlm@1: destDigest[0] = _state[0] + a; rlm@1: destDigest[1] = _state[1] + b; rlm@1: destDigest[2] = _state[2] + c; rlm@1: destDigest[3] = _state[3] + d; rlm@1: destDigest[4] = _state[4] + e; rlm@1: rlm@1: if (returnRes) rlm@1: for (int i = 0 ; i < 16; i++) rlm@1: data[i] = W[kNumW - 16 + i]; rlm@1: rlm@1: // Wipe variables rlm@1: // a = b = c = d = e = 0; rlm@1: } rlm@1: rlm@1: void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const rlm@1: { rlm@1: unsigned curBufferPos = size & 0xF; rlm@1: block[curBufferPos++] = 0x80000000; rlm@1: while (curBufferPos != (16 - 2)) rlm@1: block[curBufferPos++] = 0; rlm@1: const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5); rlm@1: block[curBufferPos++] = (UInt32)(lenInBits >> 32); rlm@1: block[curBufferPos++] = (UInt32)(lenInBits); rlm@1: } rlm@1: rlm@1: void CContext::Update(Byte *data, size_t size, bool rar350Mode) rlm@1: { rlm@1: bool returnRes = false; rlm@1: unsigned curBufferPos = _count2; rlm@1: while (size-- > 0) rlm@1: { rlm@1: int pos = (int)(curBufferPos & 3); rlm@1: if (pos == 0) rlm@1: _buffer[curBufferPos >> 2] = 0; rlm@1: _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); rlm@1: if (++curBufferPos == kBlockSize) rlm@1: { rlm@1: curBufferPos = 0; rlm@1: CContextBase::UpdateBlock(_buffer, returnRes); rlm@1: if (returnRes) rlm@1: for (int i = 0; i < kBlockSizeInWords; i++) rlm@1: { rlm@1: UInt32 d = _buffer[i]; rlm@1: data[i * 4 + 0 - kBlockSize] = (Byte)(d); rlm@1: data[i * 4 + 1 - kBlockSize] = (Byte)(d >> 8); rlm@1: data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16); rlm@1: data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24); rlm@1: } rlm@1: returnRes = rar350Mode; rlm@1: } rlm@1: } rlm@1: _count2 = curBufferPos; rlm@1: } rlm@1: rlm@1: void CContext::Final(Byte *digest) rlm@1: { rlm@1: const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3); rlm@1: unsigned curBufferPos = _count2; rlm@1: int pos = (int)(curBufferPos & 3); rlm@1: curBufferPos >>= 2; rlm@1: if (pos == 0) rlm@1: _buffer[curBufferPos] = 0; rlm@1: _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos)); rlm@1: rlm@1: while (curBufferPos != (16 - 2)) rlm@1: { rlm@1: curBufferPos &= 0xF; rlm@1: if (curBufferPos == 0) rlm@1: UpdateBlock(); rlm@1: _buffer[curBufferPos++] = 0; rlm@1: } rlm@1: _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); rlm@1: _buffer[curBufferPos++] = (UInt32)(lenInBits); rlm@1: UpdateBlock(); rlm@1: rlm@1: int i; rlm@1: for (i = 0; i < kDigestSizeInWords; i++) rlm@1: { rlm@1: UInt32 state = _state[i] & 0xFFFFFFFF; rlm@1: *digest++ = (Byte)(state >> 24); rlm@1: *digest++ = (Byte)(state >> 16); rlm@1: *digest++ = (Byte)(state >> 8); rlm@1: *digest++ = (Byte)(state); rlm@1: } rlm@1: Init(); rlm@1: } rlm@1: rlm@1: /////////////////////////// rlm@1: // Words version rlm@1: rlm@1: void CContext32::Update(const UInt32 *data, size_t size) rlm@1: { rlm@1: while (size-- > 0) rlm@1: { rlm@1: _buffer[_count2++] = *data++; rlm@1: if (_count2 == kBlockSizeInWords) rlm@1: { rlm@1: _count2 = 0; rlm@1: UpdateBlock(); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void CContext32::Final(UInt32 *digest) rlm@1: { rlm@1: const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5); rlm@1: unsigned curBufferPos = _count2; rlm@1: _buffer[curBufferPos++] = 0x80000000; rlm@1: while (curBufferPos != (16 - 2)) rlm@1: { rlm@1: curBufferPos &= 0xF; rlm@1: if (curBufferPos == 0) rlm@1: UpdateBlock(); rlm@1: _buffer[curBufferPos++] = 0; rlm@1: } rlm@1: _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); rlm@1: _buffer[curBufferPos++] = (UInt32)(lenInBits); rlm@1: GetBlockDigest(_buffer, digest); rlm@1: Init(); rlm@1: } rlm@1: rlm@1: }}