1 /* Sha1.c -- SHA-1 Hash
2 : Igor Pavlov : Public domain
3 This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
4
5 #include "Precomp.h"
6
7 #include <string.h>
8
9 #include "Sha1.h"
10 #include "RotateDefs.h"
11 #include "CpuArch.h"
12
13 #ifdef MY_CPU_X86_OR_AMD64
14 #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
15 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
16 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
17 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \
18 || defined(_MSC_VER) && (_MSC_VER >= 1200)
19 #define Z7_COMPILER_SHA1_SUPPORTED
20 #endif
21 #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) \
22 && (!defined(Z7_MSC_VER_ORIGINAL) || (_MSC_VER >= 1929) && (_MSC_FULL_VER >= 192930037))
23 #if defined(__ARM_FEATURE_SHA2) \
24 || defined(__ARM_FEATURE_CRYPTO)
25 #define Z7_COMPILER_SHA1_SUPPORTED
26 #else
27 #if defined(MY_CPU_ARM64) \
28 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
29 || defined(Z7_MSC_VER_ORIGINAL)
30 #if defined(__ARM_FP) && \
31 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
32 || defined(__GNUC__) && (__GNUC__ >= 6) \
33 ) \
34 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
35 #if defined(MY_CPU_ARM64) \
36 || !defined(Z7_CLANG_VERSION) \
37 || defined(__ARM_NEON) && \
38 (Z7_CLANG_VERSION < 170000 || \
39 Z7_CLANG_VERSION > 170001)
40 #define Z7_COMPILER_SHA1_SUPPORTED
41 #endif
42 #endif
43 #endif
44 #endif
45 #endif
46
47 void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks);
48
49 #ifdef Z7_COMPILER_SHA1_SUPPORTED
50 void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks);
51
52 static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS = Sha1_UpdateBlocks;
53 static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS_HW;
54
55 #define SHA1_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks
56 #else
57 #define SHA1_UPDATE_BLOCKS(p) Sha1_UpdateBlocks
58 #endif
59
60
Sha1_SetFunction(CSha1 * p,unsigned algo)61 BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo)
62 {
63 SHA1_FUNC_UPDATE_BLOCKS func = Sha1_UpdateBlocks;
64
65 #ifdef Z7_COMPILER_SHA1_SUPPORTED
66 if (algo != SHA1_ALGO_SW)
67 {
68 if (algo == SHA1_ALGO_DEFAULT)
69 func = g_SHA1_FUNC_UPDATE_BLOCKS;
70 else
71 {
72 if (algo != SHA1_ALGO_HW)
73 return False;
74 func = g_SHA1_FUNC_UPDATE_BLOCKS_HW;
75 if (!func)
76 return False;
77 }
78 }
79 #else
80 if (algo > 1)
81 return False;
82 #endif
83
84 p->v.vars.func_UpdateBlocks = func;
85 return True;
86 }
87
88
89 /* define it for speed optimization */
90 // #define Z7_SHA1_UNROLL
91
92 // allowed unroll steps: (1, 2, 4, 5, 20)
93
94 #undef Z7_SHA1_BIG_W
95 #ifdef Z7_SHA1_UNROLL
96 #define STEP_PRE 20
97 #define STEP_MAIN 20
98 #else
99 #define Z7_SHA1_BIG_W
100 #define STEP_PRE 5
101 #define STEP_MAIN 5
102 #endif
103
104
105 #ifdef Z7_SHA1_BIG_W
106 #define kNumW 80
107 #define w(i) W[i]
108 #else
109 #define kNumW 16
110 #define w(i) W[(i)&15]
111 #endif
112
113 #define w0(i) (W[i] = GetBe32(data + (size_t)(i) * 4))
114 #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))
115
116 #define f0(x,y,z) ( 0x5a827999 + (z^(x&(y^z))) )
117 #define f1(x,y,z) ( 0x6ed9eba1 + (x^y^z) )
118 #define f2(x,y,z) ( 0x8f1bbcdc + ((x&y)|(z&(x|y))) )
119 #define f3(x,y,z) ( 0xca62c1d6 + (x^y^z) )
120
121 /*
122 #define T1(fx, ww) \
123 tmp = e + fx(b,c,d) + ww + rotlFixed(a, 5); \
124 e = d; \
125 d = c; \
126 c = rotlFixed(b, 30); \
127 b = a; \
128 a = tmp; \
129 */
130
131 #define T5(a,b,c,d,e, fx, ww) \
132 e += fx(b,c,d) + ww + rotlFixed(a, 5); \
133 b = rotlFixed(b, 30); \
134
135
136 /*
137 #define R1(i, fx, wx) \
138 T1 ( fx, wx(i)); \
139
140 #define R2(i, fx, wx) \
141 R1 ( (i) , fx, wx); \
142 R1 ( (i) + 1, fx, wx); \
143
144 #define R4(i, fx, wx) \
145 R2 ( (i) , fx, wx); \
146 R2 ( (i) + 2, fx, wx); \
147 */
148
149 #define M5(i, fx, wx0, wx1) \
150 T5 ( a,b,c,d,e, fx, wx0((i) ) ) \
151 T5 ( e,a,b,c,d, fx, wx1((i)+1) ) \
152 T5 ( d,e,a,b,c, fx, wx1((i)+2) ) \
153 T5 ( c,d,e,a,b, fx, wx1((i)+3) ) \
154 T5 ( b,c,d,e,a, fx, wx1((i)+4) ) \
155
156 #define R5(i, fx, wx) \
157 M5 ( i, fx, wx, wx) \
158
159
160 #if STEP_PRE > 5
161
162 #define R20_START \
163 R5 ( 0, f0, w0) \
164 R5 ( 5, f0, w0) \
165 R5 ( 10, f0, w0) \
166 M5 ( 15, f0, w0, w1) \
167
168 #elif STEP_PRE == 5
169
170 #define R20_START \
171 { size_t i; for (i = 0; i < 15; i += STEP_PRE) \
172 { R5(i, f0, w0) } } \
173 M5 ( 15, f0, w0, w1) \
174
175 #else
176
177 #if STEP_PRE == 1
178 #define R_PRE R1
179 #elif STEP_PRE == 2
180 #define R_PRE R2
181 #elif STEP_PRE == 4
182 #define R_PRE R4
183 #endif
184
185 #define R20_START \
186 { size_t i; for (i = 0; i < 16; i += STEP_PRE) \
187 { R_PRE(i, f0, w0) } } \
188 R4 ( 16, f0, w1) \
189
190 #endif
191
192
193
194 #if STEP_MAIN > 5
195
196 #define R20(ii, fx) \
197 R5 ( (ii) , fx, w1) \
198 R5 ( (ii) + 5 , fx, w1) \
199 R5 ( (ii) + 10, fx, w1) \
200 R5 ( (ii) + 15, fx, w1) \
201
202 #else
203
204 #if STEP_MAIN == 1
205 #define R_MAIN R1
206 #elif STEP_MAIN == 2
207 #define R_MAIN R2
208 #elif STEP_MAIN == 4
209 #define R_MAIN R4
210 #elif STEP_MAIN == 5
211 #define R_MAIN R5
212 #endif
213
214 #define R20(ii, fx) \
215 { size_t i; for (i = (ii); i < (ii) + 20; i += STEP_MAIN) \
216 { R_MAIN(i, fx, w1) } } \
217
218 #endif
219
220
221
Sha1_InitState(CSha1 * p)222 void Sha1_InitState(CSha1 *p)
223 {
224 p->v.vars.count = 0;
225 p->state[0] = 0x67452301;
226 p->state[1] = 0xEFCDAB89;
227 p->state[2] = 0x98BADCFE;
228 p->state[3] = 0x10325476;
229 p->state[4] = 0xC3D2E1F0;
230 }
231
Sha1_Init(CSha1 * p)232 void Sha1_Init(CSha1 *p)
233 {
234 p->v.vars.func_UpdateBlocks =
235 #ifdef Z7_COMPILER_SHA1_SUPPORTED
236 g_SHA1_FUNC_UPDATE_BLOCKS;
237 #else
238 NULL;
239 #endif
240 Sha1_InitState(p);
241 }
242
243
244 Z7_NO_INLINE
Sha1_UpdateBlocks(UInt32 state[5],const Byte * data,size_t numBlocks)245 void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks)
246 {
247 UInt32 a, b, c, d, e;
248 UInt32 W[kNumW];
249
250 if (numBlocks == 0)
251 return;
252
253 a = state[0];
254 b = state[1];
255 c = state[2];
256 d = state[3];
257 e = state[4];
258
259 do
260 {
261 #if STEP_PRE < 5 || STEP_MAIN < 5
262 UInt32 tmp;
263 #endif
264
265 R20_START
266 R20(20, f1)
267 R20(40, f2)
268 R20(60, f3)
269
270 a += state[0];
271 b += state[1];
272 c += state[2];
273 d += state[3];
274 e += state[4];
275
276 state[0] = a;
277 state[1] = b;
278 state[2] = c;
279 state[3] = d;
280 state[4] = e;
281
282 data += SHA1_BLOCK_SIZE;
283 }
284 while (--numBlocks);
285 }
286
287
288 #define Sha1_UpdateBlock(p) SHA1_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
289
Sha1_Update(CSha1 * p,const Byte * data,size_t size)290 void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
291 {
292 if (size == 0)
293 return;
294 {
295 const unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1);
296 const unsigned num = SHA1_BLOCK_SIZE - pos;
297 p->v.vars.count += size;
298 if (num > size)
299 {
300 memcpy(p->buffer + pos, data, size);
301 return;
302 }
303 if (pos != 0)
304 {
305 size -= num;
306 memcpy(p->buffer + pos, data, num);
307 data += num;
308 Sha1_UpdateBlock(p);
309 }
310 }
311 {
312 const size_t numBlocks = size >> 6;
313 // if (numBlocks)
314 SHA1_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
315 size &= SHA1_BLOCK_SIZE - 1;
316 if (size == 0)
317 return;
318 data += (numBlocks << 6);
319 memcpy(p->buffer, data, size);
320 }
321 }
322
323
Sha1_Final(CSha1 * p,Byte * digest)324 void Sha1_Final(CSha1 *p, Byte *digest)
325 {
326 unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1);
327 p->buffer[pos++] = 0x80;
328 if (pos > (SHA1_BLOCK_SIZE - 4 * 2))
329 {
330 while (pos != SHA1_BLOCK_SIZE) { p->buffer[pos++] = 0; }
331 // memset(&p->buf.buffer[pos], 0, SHA1_BLOCK_SIZE - pos);
332 Sha1_UpdateBlock(p);
333 pos = 0;
334 }
335 memset(&p->buffer[pos], 0, (SHA1_BLOCK_SIZE - 4 * 2) - pos);
336 {
337 const UInt64 numBits = p->v.vars.count << 3;
338 SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32))
339 SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 1, (UInt32)(numBits))
340 }
341 Sha1_UpdateBlock(p);
342
343 SetBe32(digest, p->state[0])
344 SetBe32(digest + 4, p->state[1])
345 SetBe32(digest + 8, p->state[2])
346 SetBe32(digest + 12, p->state[3])
347 SetBe32(digest + 16, p->state[4])
348
349 Sha1_InitState(p);
350 }
351
352
Sha1_PrepareBlock(const CSha1 * p,Byte * block,unsigned size)353 void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size)
354 {
355 const UInt64 numBits = (p->v.vars.count + size) << 3;
356 SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 2], (UInt32)(numBits >> 32))
357 SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 1], (UInt32)(numBits))
358 // SetBe32((UInt32 *)(block + size), 0x80000000);
359 SetUi32((UInt32 *)(void *)(block + size), 0x80)
360 size += 4;
361 while (size != (SHA1_NUM_BLOCK_WORDS - 2) * 4)
362 {
363 *((UInt32 *)(void *)(block + size)) = 0;
364 size += 4;
365 }
366 }
367
Sha1_GetBlockDigest(const CSha1 * p,const Byte * data,Byte * destDigest)368 void Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest)
369 {
370 MY_ALIGN (16)
371 UInt32 st[SHA1_NUM_DIGEST_WORDS];
372
373 st[0] = p->state[0];
374 st[1] = p->state[1];
375 st[2] = p->state[2];
376 st[3] = p->state[3];
377 st[4] = p->state[4];
378
379 SHA1_UPDATE_BLOCKS(p)(st, data, 1);
380
381 SetBe32(destDigest + 0 , st[0])
382 SetBe32(destDigest + 1 * 4, st[1])
383 SetBe32(destDigest + 2 * 4, st[2])
384 SetBe32(destDigest + 3 * 4, st[3])
385 SetBe32(destDigest + 4 * 4, st[4])
386 }
387
388
Sha1Prepare(void)389 void Sha1Prepare(void)
390 {
391 #ifdef Z7_COMPILER_SHA1_SUPPORTED
392 SHA1_FUNC_UPDATE_BLOCKS f, f_hw;
393 f = Sha1_UpdateBlocks;
394 f_hw = NULL;
395 #ifdef MY_CPU_X86_OR_AMD64
396 if (CPU_IsSupported_SHA()
397 && CPU_IsSupported_SSSE3()
398 )
399 #else
400 if (CPU_IsSupported_SHA1())
401 #endif
402 {
403 // printf("\n========== HW SHA1 ======== \n");
404 #if 1 && defined(MY_CPU_ARM_OR_ARM64) && defined(Z7_MSC_VER_ORIGINAL) && (_MSC_FULL_VER < 192930037)
405 /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037).
406 It generated incorrect SHA-1 code. */
407 #pragma message("== SHA1 code can work incorrectly with this compiler")
408 #error Stop_Compiling_MSC_Compiler_BUG_SHA1
409 #endif
410 {
411 f = f_hw = Sha1_UpdateBlocks_HW;
412 }
413 }
414 g_SHA1_FUNC_UPDATE_BLOCKS = f;
415 g_SHA1_FUNC_UPDATE_BLOCKS_HW = f_hw;
416 #endif
417 }
418
419 #undef kNumW
420 #undef w
421 #undef w0
422 #undef w1
423 #undef f0
424 #undef f1
425 #undef f2
426 #undef f3
427 #undef T1
428 #undef T5
429 #undef M5
430 #undef R1
431 #undef R2
432 #undef R4
433 #undef R5
434 #undef R20_START
435 #undef R_PRE
436 #undef R_MAIN
437 #undef STEP_PRE
438 #undef STEP_MAIN
439 #undef Z7_SHA1_BIG_W
440 #undef Z7_SHA1_UNROLL
441 #undef Z7_COMPILER_SHA1_SUPPORTED
442