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