diff options
Diffstat (limited to 'multiarc/src/formats/7z/C/Sha1.c')
-rwxr-xr-x[-rw-r--r--] | multiarc/src/formats/7z/C/Sha1.c | 623 |
1 files changed, 378 insertions, 245 deletions
diff --git a/multiarc/src/formats/7z/C/Sha1.c b/multiarc/src/formats/7z/C/Sha1.c index 96b5e787..9665b5b5 100644..100755 --- a/multiarc/src/formats/7z/C/Sha1.c +++ b/multiarc/src/formats/7z/C/Sha1.c @@ -1,5 +1,5 @@ /* Sha1.c -- SHA-1 Hash -2017-04-03 : Igor Pavlov : Public domain +2021-07-13 : Igor Pavlov : Public domain This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ #include "Precomp.h" @@ -10,331 +10,464 @@ This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ l #include "RotateDefs.h" #include "Sha1.h" -// define it for speed optimization +#if defined(_MSC_VER) && (_MSC_VER < 1900) +// #define USE_MY_MM +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + #ifdef _MSC_VER + #if _MSC_VER >= 1200 + #define _SHA_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1800) // fix that check + #define _SHA_SUPPORTED + #endif + #endif +#elif defined(MY_CPU_ARM_OR_ARM64) + #ifdef _MSC_VER + #if _MSC_VER >= 1910 && _MSC_VER >= 1929 && _MSC_FULL_VER >= 192930037 + #define _SHA_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define _SHA_SUPPORTED + #endif + #endif +#endif + +void MY_FAST_CALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks); + +#ifdef _SHA_SUPPORTED + void MY_FAST_CALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks); + + static SHA1_FUNC_UPDATE_BLOCKS g_FUNC_UPDATE_BLOCKS = Sha1_UpdateBlocks; + static SHA1_FUNC_UPDATE_BLOCKS g_FUNC_UPDATE_BLOCKS_HW; + + #define UPDATE_BLOCKS(p) p->func_UpdateBlocks +#else + #define UPDATE_BLOCKS(p) Sha1_UpdateBlocks +#endif + + +BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo) +{ + SHA1_FUNC_UPDATE_BLOCKS func = Sha1_UpdateBlocks; + + #ifdef _SHA_SUPPORTED + if (algo != SHA1_ALGO_SW) + { + if (algo == SHA1_ALGO_DEFAULT) + func = g_FUNC_UPDATE_BLOCKS; + else + { + if (algo != SHA1_ALGO_HW) + return False; + func = g_FUNC_UPDATE_BLOCKS_HW; + if (!func) + return False; + } + } + #else + if (algo > 1) + return False; + #endif + + p->func_UpdateBlocks = func; + return True; +} + + +/* define it for speed optimization */ // #define _SHA1_UNROLL +// allowed unroll steps: (1, 2, 4, 5, 20) + #ifdef _SHA1_UNROLL - #define kNumW 16 - #define WW(i) W[(i)&15] + #define STEP_PRE 20 + #define STEP_MAIN 20 #else + #define _SHA1_BIG_W + #define STEP_PRE 5 + #define STEP_MAIN 5 +#endif + + +#ifdef _SHA1_BIG_W #define kNumW 80 - #define WW(i) W[i] + #define w(i) W[i] +#else + #define kNumW 16 + #define w(i) W[(i)&15] #endif -#define w0(i) (W[i] = data[i]) +#define w0(i) (W[i] = GetBe32(data + (size_t)(i) * 4)) +#define w1(i) (w(i) = rotlFixed(w((size_t)(i)-3) ^ w((size_t)(i)-8) ^ w((size_t)(i)-14) ^ w((size_t)(i)-16), 1)) -#define w1(i) (WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1)) +#define f0(x,y,z) ( 0x5a827999 + (z^(x&(y^z))) ) +#define f1(x,y,z) ( 0x6ed9eba1 + (x^y^z) ) +#define f2(x,y,z) ( 0x8f1bbcdc + ((x&y)|(z&(x|y))) ) +#define f3(x,y,z) ( 0xca62c1d6 + (x^y^z) ) -#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 T1(fx, ww) \ + tmp = e + fx(b,c,d) + ww + rotlFixed(a, 5); \ + e = d; \ + d = c; \ + c = rotlFixed(b, 30); \ + b = a; \ + a = tmp; \ +*/ -#define RK(a,b,c,d,e, fx, w, k) e += fx(b,c,d) + w + k + rotlFixed(a,5); b = rotlFixed(b,30); +#define T5(a,b,c,d,e, fx, ww) \ + e += fx(b,c,d) + ww + rotlFixed(a, 5); \ + b = rotlFixed(b, 30); \ -#define R0(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w0(i), 0x5A827999) -#define R1(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w1(i), 0x5A827999) -#define R2(a,b,c,d,e, i) RK(a,b,c,d,e, f2, w1(i), 0x6ED9EBA1) -#define R3(a,b,c,d,e, i) RK(a,b,c,d,e, f3, w1(i), 0x8F1BBCDC) -#define R4(a,b,c,d,e, i) RK(a,b,c,d,e, f4, w1(i), 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 R1(i, fx, wx) \ + T1 ( fx, wx(i)); \ -#define RX_5(rx, i) RX_1_4(rx, rx, i); +#define R2(i, fx, wx) \ + R1 ( (i) , fx, wx); \ + R1 ( (i) + 1, fx, wx); \ -#ifdef _SHA1_UNROLL +#define R4(i, fx, wx) \ + R2 ( (i) , fx, wx); \ + R2 ( (i) + 2, fx, wx); \ +*/ + +#define M5(i, fx, wx0, wx1) \ + T5 ( a,b,c,d,e, fx, wx0((i) ) ); \ + T5 ( e,a,b,c,d, fx, wx1((i)+1) ); \ + T5 ( d,e,a,b,c, fx, wx1((i)+2) ); \ + T5 ( c,d,e,a,b, fx, wx1((i)+3) ); \ + T5 ( b,c,d,e,a, fx, wx1((i)+4) ); \ - #define RX_15 \ - RX_5(R0, 0); \ - RX_5(R0, 5); \ - RX_5(R0, 10); +#define R5(i, fx, wx) \ + M5 ( i, fx, wx, wx) \ + + +#if STEP_PRE > 5 + + #define R20_START \ + R5 ( 0, f0, w0); \ + R5 ( 5, f0, w0); \ + R5 ( 10, f0, w0); \ + M5 ( 15, f0, w0, w1); \ + + #elif STEP_PRE == 5 - #define RX_20(rx, i) \ - RX_5(rx, i); \ - RX_5(rx, i + 5); \ - RX_5(rx, i + 10); \ - RX_5(rx, i + 15); + #define R20_START \ + { size_t i; for (i = 0; i < 15; i += STEP_PRE) \ + { R5(i, f0, w0); } } \ + M5 ( 15, f0, w0, w1); \ #else - -#define RX_15 { size_t i; for (i = 0; i < 15; i += 5) { RX_5(R0, i); } } -#define RX_20(rx, ii) { size_t i; i = ii; for (; i < ii + 20; i += 5) { RX_5(rx, i); } } + + #if STEP_PRE == 1 + #define R_PRE R1 + #elif STEP_PRE == 2 + #define R_PRE R2 + #elif STEP_PRE == 4 + #define R_PRE R4 + #endif + + #define R20_START \ + { size_t i; for (i = 0; i < 16; i += STEP_PRE) \ + { R_PRE(i, f0, w0); } } \ + R4 ( 16, f0, w1); \ #endif -void Sha1_Init(CSha1 *p) + +#if STEP_MAIN > 5 + + #define R20(ii, fx) \ + R5 ( (ii) , fx, w1); \ + R5 ( (ii) + 5 , fx, w1); \ + R5 ( (ii) + 10, fx, w1); \ + R5 ( (ii) + 15, fx, w1); \ + +#else + + #if STEP_MAIN == 1 + #define R_MAIN R1 + #elif STEP_MAIN == 2 + #define R_MAIN R2 + #elif STEP_MAIN == 4 + #define R_MAIN R4 + #elif STEP_MAIN == 5 + #define R_MAIN R5 + #endif + + #define R20(ii, fx) \ + { size_t i; for (i = (ii); i < (ii) + 20; i += STEP_MAIN) \ + { R_MAIN(i, fx, w1); } } \ + +#endif + + + +void Sha1_InitState(CSha1 *p) { + p->count = 0; p->state[0] = 0x67452301; p->state[1] = 0xEFCDAB89; p->state[2] = 0x98BADCFE; p->state[3] = 0x10325476; p->state[4] = 0xC3D2E1F0; - p->count = 0; } -void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest) +void Sha1_Init(CSha1 *p) { - UInt32 a, b, c, d, e; - UInt32 W[kNumW]; - - a = p->state[0]; - b = p->state[1]; - c = p->state[2]; - d = p->state[3]; - e = p->state[4]; - - RX_15 - - RX_1_4(R0, R1, 15); - - RX_20(R2, 20); - RX_20(R3, 40); - RX_20(R4, 60); - - destDigest[0] = p->state[0] + a; - destDigest[1] = p->state[1] + b; - destDigest[2] = p->state[2] + c; - destDigest[3] = p->state[3] + d; - destDigest[4] = p->state[4] + e; + p->func_UpdateBlocks = + #ifdef _SHA_SUPPORTED + g_FUNC_UPDATE_BLOCKS; + #else + NULL; + #endif + Sha1_InitState(p); } -void Sha1_UpdateBlock_Rar(CSha1 *p, UInt32 *data, int returnRes) + +MY_NO_INLINE +void MY_FAST_CALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks) { UInt32 a, b, c, d, e; UInt32 W[kNumW]; + // if (numBlocks != 0x1264378347) return; + if (numBlocks == 0) + return; - a = p->state[0]; - b = p->state[1]; - c = p->state[2]; - d = p->state[3]; - e = p->state[4]; - - RX_15 - - RX_1_4(R0, R1, 15); - - RX_20(R2, 20); - RX_20(R3, 40); - RX_20(R4, 60); - - p->state[0] += a; - p->state[1] += b; - p->state[2] += c; - p->state[3] += d; - p->state[4] += e; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; - if (returnRes) + do { - size_t i; - for (i = 0 ; i < SHA1_NUM_BLOCK_WORDS; i++) - data[i] = W[kNumW - SHA1_NUM_BLOCK_WORDS + i]; + #if STEP_PRE < 5 || STEP_MAIN < 5 + UInt32 tmp; + #endif + + R20_START + R20(20, f1); + R20(40, f2); + R20(60, f3); + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + + data += 64; } + while (--numBlocks); } -#define Sha1_UpdateBlock(p) Sha1_GetBlockDigest(p, p->buffer, p->state) + +#define Sha1_UpdateBlock(p) UPDATE_BLOCKS(p)(p->state, p->buffer, 1) void Sha1_Update(CSha1 *p, const Byte *data, size_t size) { - unsigned pos, pos2; if (size == 0) return; - pos = (unsigned)p->count & 0x3F; - p->count += size; - pos2 = pos & 3; - pos >>= 2; - - if (pos2 != 0) - { - UInt32 w; - pos2 = (3 - pos2) * 8; - w = ((UInt32)*data++) << pos2; - if (--size && pos2) - { - pos2 -= 8; - w |= ((UInt32)*data++) << pos2; - if (--size && pos2) - { - pos2 -= 8; - w |= ((UInt32)*data++) << pos2; - size--; - } - } - p->buffer[pos] |= w; - if (pos2 == 0) - pos++; - } - for (;;) { - if (pos == SHA1_NUM_BLOCK_WORDS) + unsigned pos = (unsigned)p->count & 0x3F; + unsigned num; + + p->count += size; + + num = 64 - pos; + if (num > size) { - for (;;) - { - size_t i; - Sha1_UpdateBlock(p); - if (size < SHA1_BLOCK_SIZE) - break; - size -= SHA1_BLOCK_SIZE; - for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i += 2) - { - p->buffer[i ] = GetBe32(data); - p->buffer[i + 1] = GetBe32(data + 4); - data += 8; - } - } - pos = 0; + memcpy(p->buffer + pos, data, size); + return; } - if (size < 4) - break; - - p->buffer[pos] = GetBe32(data); - data += 4; - size -= 4; - pos++; - } - - if (size != 0) - { - UInt32 w = ((UInt32)data[0]) << 24; - if (size > 1) + + if (pos != 0) { - w |= ((UInt32)data[1]) << 16; - if (size > 2) - w |= ((UInt32)data[2]) << 8; + size -= num; + memcpy(p->buffer + pos, data, num); + data += num; + Sha1_UpdateBlock(p); } - p->buffer[pos] = w; } -} - -void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size /* , int rar350Mode */) -{ - int returnRes = False; - - unsigned pos = (unsigned)p->count & 0x3F; - p->count += size; - - while (size--) { - unsigned pos2 = (pos & 3); - UInt32 v = ((UInt32)*data++) << (8 * (3 - pos2)); - UInt32 *ref = &(p->buffer[pos >> 2]); - pos++; - if (pos2 == 0) - { - *ref = v; - continue; - } - *ref |= v; - - if (pos == SHA1_BLOCK_SIZE) - { - pos = 0; - Sha1_UpdateBlock_Rar(p, p->buffer, returnRes); - if (returnRes) - { - size_t i; - for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) - { - UInt32 d = p->buffer[i]; - Byte *prev = data + i * 4 - SHA1_BLOCK_SIZE; - SetUi32(prev, d); - } - } - // returnRes = rar350Mode; - returnRes = True; - } + size_t numBlocks = size >> 6; + UPDATE_BLOCKS(p)(p->state, data, numBlocks); + size &= 0x3F; + if (size == 0) + return; + data += (numBlocks << 6); + memcpy(p->buffer, data, size); } } + void Sha1_Final(CSha1 *p, Byte *digest) { unsigned pos = (unsigned)p->count & 0x3F; - unsigned pos2 = (pos & 3); - UInt64 numBits; - UInt32 w; - unsigned i; - pos >>= 2; + + p->buffer[pos++] = 0x80; - w = 0; - if (pos2 != 0) - w = p->buffer[pos]; - p->buffer[pos++] = w | (((UInt32)0x80000000) >> (8 * pos2)); + if (pos > (64 - 8)) + { + while (pos != 64) { p->buffer[pos++] = 0; } + // memset(&p->buf.buffer[pos], 0, 64 - pos); + Sha1_UpdateBlock(p); + pos = 0; + } - while (pos != (SHA1_NUM_BLOCK_WORDS - 2)) + /* + if (pos & 3) { - pos &= 0xF; - if (pos == 0) - Sha1_UpdateBlock(p); - p->buffer[pos++] = 0; + p->buffer[pos] = 0; + p->buffer[pos + 1] = 0; + p->buffer[pos + 2] = 0; + pos += 3; + pos &= ~3; } - - numBits = (p->count << 3); - p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32); - p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits); - Sha1_UpdateBlock(p); + { + for (; pos < 64 - 8; pos += 4) + *(UInt32 *)(&p->buffer[pos]) = 0; + } + */ + + memset(&p->buffer[pos], 0, (64 - 8) - pos); - for (i = 0; i < SHA1_NUM_DIGEST_WORDS; i++) { - UInt32 v = p->state[i]; - SetBe32(digest, v); - digest += 4; + UInt64 numBits = (p->count << 3); + SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)); + SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)); } + + Sha1_UpdateBlock(p); - Sha1_Init(p); -} + SetBe32(digest, p->state[0]); + SetBe32(digest + 4, p->state[1]); + SetBe32(digest + 8, p->state[2]); + SetBe32(digest + 12, p->state[3]); + SetBe32(digest + 16, p->state[4]); + -void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size) -{ - const UInt64 numBits = (p->count + size) << 5; - block[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32); - block[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits); - block[size++] = 0x80000000; - while (size != (SHA1_NUM_BLOCK_WORDS - 2)) - block[size++] = 0; + + Sha1_InitState(p); } -void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size) + +void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size) { - unsigned pos = (unsigned)p->count & 0xF; - p->count += size; - while (size--) + const UInt64 numBits = (p->count + size) << 3; + SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 2], (UInt32)(numBits >> 32)); + SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 1], (UInt32)(numBits)); + // SetBe32((UInt32 *)(block + size), 0x80000000); + SetUi32((UInt32 *)(void *)(block + size), 0x80); + size += 4; + while (size != (SHA1_NUM_BLOCK_WORDS - 2) * 4) { - p->buffer[pos++] = *data++; - if (pos == SHA1_NUM_BLOCK_WORDS) - { - pos = 0; - Sha1_UpdateBlock(p); - } + *((UInt32 *)(void *)(block + size)) = 0; + size += 4; } } -void Sha1_32_Final(CSha1 *p, UInt32 *digest) +void Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest) { - UInt64 numBits; - unsigned pos = (unsigned)p->count & 0xF; - p->buffer[pos++] = 0x80000000; + MY_ALIGN (16) + UInt32 st[SHA1_NUM_DIGEST_WORDS]; + + st[0] = p->state[0]; + st[1] = p->state[1]; + st[2] = p->state[2]; + st[3] = p->state[3]; + st[4] = p->state[4]; + + UPDATE_BLOCKS(p)(st, data, 1); - while (pos != (SHA1_NUM_BLOCK_WORDS - 2)) + SetBe32(destDigest + 0 , st[0]); + SetBe32(destDigest + 1 * 4, st[1]); + SetBe32(destDigest + 2 * 4, st[2]); + SetBe32(destDigest + 3 * 4, st[3]); + SetBe32(destDigest + 4 * 4, st[4]); +} + + +void Sha1Prepare() +{ + #ifdef _SHA_SUPPORTED + SHA1_FUNC_UPDATE_BLOCKS f, f_hw; + f = Sha1_UpdateBlocks; + f_hw = NULL; + #ifdef MY_CPU_X86_OR_AMD64 + #ifndef USE_MY_MM + if (CPU_IsSupported_SHA() + && CPU_IsSupported_SSSE3() + // && CPU_IsSupported_SSE41() + ) + #endif + #else + if (CPU_IsSupported_SHA1()) + #endif { - pos &= 0xF; - if (pos == 0) - Sha1_UpdateBlock(p); - p->buffer[pos++] = 0; - } - - numBits = (p->count << 5); - p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32); - p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits); + // printf("\n========== HW SHA1 ======== \n"); + #if defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER) + /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037). + It generated incorrect SHA-1 code. + 21.03 : we test sha1-hardware code at runtime initialization */ + + #pragma message("== SHA1 code: MSC compiler : failure-check code was inserted") + + UInt32 state[5] = { 0, 1, 2, 3, 4 } ; + Byte data[64]; + unsigned i; + for (i = 0; i < sizeof(data); i += 2) + { + data[i ] = (Byte)(i); + data[i + 1] = (Byte)(i + 1); + } - Sha1_GetBlockDigest(p, p->buffer, digest); - - Sha1_Init(p); + Sha1_UpdateBlocks_HW(state, data, sizeof(data) / 64); + + if ( state[0] != 0x9acd7297 + || state[1] != 0x4624d898 + || state[2] != 0x0bf079f0 + || state[3] != 0x031e61b3 + || state[4] != 0x8323fe20) + { + // printf("\n========== SHA-1 hardware version failure ======== \n"); + } + else + #endif + { + f = f_hw = Sha1_UpdateBlocks_HW; + } + } + g_FUNC_UPDATE_BLOCKS = f; + g_FUNC_UPDATE_BLOCKS_HW = f_hw; + #endif } |