• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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