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