xref: /aosp_15_r20/external/lzma/C/Sha3.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 /* Sha3.c -- SHA-3 Hash
2 : Igor Pavlov : Public domain
3 This code is based on public domain code from Wei Dai's Crypto++ library. */
4 
5 #include "Precomp.h"
6 
7 #include <string.h>
8 
9 #include "Sha3.h"
10 #include "RotateDefs.h"
11 #include "CpuArch.h"
12 
13 #define U64C(x) UINT64_CONST(x)
14 
15 static
16 MY_ALIGN(64)
17 const UInt64 SHA3_K_ARRAY[24] =
18 {
19   U64C(0x0000000000000001), U64C(0x0000000000008082),
20   U64C(0x800000000000808a), U64C(0x8000000080008000),
21   U64C(0x000000000000808b), U64C(0x0000000080000001),
22   U64C(0x8000000080008081), U64C(0x8000000000008009),
23   U64C(0x000000000000008a), U64C(0x0000000000000088),
24   U64C(0x0000000080008009), U64C(0x000000008000000a),
25   U64C(0x000000008000808b), U64C(0x800000000000008b),
26   U64C(0x8000000000008089), U64C(0x8000000000008003),
27   U64C(0x8000000000008002), U64C(0x8000000000000080),
28   U64C(0x000000000000800a), U64C(0x800000008000000a),
29   U64C(0x8000000080008081), U64C(0x8000000000008080),
30   U64C(0x0000000080000001), U64C(0x8000000080008008)
31 };
32 
Sha3_Init(CSha3 * p)33 void Sha3_Init(CSha3 *p)
34 {
35   p->count = 0;
36   memset(p->state, 0, sizeof(p->state));
37 }
38 
39 #define GET_state(i, a)   UInt64 a = state[i];
40 #define SET_state(i, a)   state[i] = a;
41 
42 #define LS_5(M, i, a0,a1,a2,a3,a4) \
43         M ((i) * 5    , a0) \
44         M ((i) * 5 + 1, a1) \
45         M ((i) * 5 + 2, a2) \
46         M ((i) * 5 + 3, a3) \
47         M ((i) * 5 + 4, a4) \
48 
49 #define LS_25(M) \
50         LS_5 (M, 0, a50, a51, a52, a53, a54) \
51         LS_5 (M, 1, a60, a61, a62, a63, a64) \
52         LS_5 (M, 2, a70, a71, a72, a73, a74) \
53         LS_5 (M, 3, a80, a81, a82, a83, a84) \
54         LS_5 (M, 4, a90, a91, a92, a93, a94) \
55 
56 
57 #define XOR_1(i, a0) \
58         a0 ^= GetUi64(data + (i) * 8); \
59 
60 #define XOR_4(i, a0,a1,a2,a3) \
61         XOR_1 ((i)    , a0); \
62         XOR_1 ((i) + 1, a1); \
63         XOR_1 ((i) + 2, a2); \
64         XOR_1 ((i) + 3, a3); \
65 
66 #define D(d,b1,b2) \
67         d = b1 ^ Z7_ROTL64(b2, 1);
68 
69 #define D5 \
70         D (d0, c4, c1) \
71         D (d1, c0, c2) \
72         D (d2, c1, c3) \
73         D (d3, c2, c4) \
74         D (d4, c3, c0) \
75 
76 #define C0(c,a,d) \
77         c = a ^ d; \
78 
79 #define C(c,a,d,k) \
80         c = a ^ d; \
81         c = Z7_ROTL64(c, k); \
82 
83 #define E4(e1,e2,e3,e4) \
84         e1 = c1 ^ (~c2 & c3); \
85         e2 = c2 ^ (~c3 & c4); \
86         e3 = c3 ^ (~c4 & c0); \
87         e4 = c4 ^ (~c0 & c1); \
88 
89 #define CK(   v0,w0,    \
90               v1,w1,k1, \
91               v2,w2,k2, \
92               v3,w3,k3, \
93               v4,w4,k4, e0,e1,e2,e3,e4, keccak_c) \
94         C0(c0,v0,w0)    \
95         C (c1,v1,w1,k1) \
96         C (c2,v2,w2,k2) \
97         C (c3,v3,w3,k3) \
98         C (c4,v4,w4,k4) \
99         e0 = c0 ^ (~c1 & c2) ^ keccak_c; \
100         E4(e1,e2,e3,e4) \
101 
102 #define CE(   v0,w0,k0, \
103               v1,w1,k1, \
104               v2,w2,k2, \
105               v3,w3,k3, \
106               v4,w4,k4, e0,e1,e2,e3,e4) \
107         C (c0,v0,w0,k0) \
108         C (c1,v1,w1,k1) \
109         C (c2,v2,w2,k2) \
110         C (c3,v3,w3,k3) \
111         C (c4,v4,w4,k4) \
112         e0 = c0 ^ (~c1 & c2); \
113         E4(e1,e2,e3,e4) \
114 
115 // numBlocks != 0
116 static
117 Z7_NO_INLINE
Sha3_UpdateBlocks(UInt64 state[SHA3_NUM_STATE_WORDS],const Byte * data,size_t numBlocks,size_t blockSize)118 void Z7_FASTCALL Sha3_UpdateBlocks(UInt64 state[SHA3_NUM_STATE_WORDS],
119     const Byte *data, size_t numBlocks, size_t blockSize)
120 {
121   LS_25 (GET_state)
122 
123   do
124   {
125     unsigned round;
126                               XOR_4 ( 0, a50, a51, a52, a53)
127                               XOR_4 ( 4, a54, a60, a61, a62)
128                               XOR_1 ( 8, a63)
129     if (blockSize > 8 *  9) { XOR_4 ( 9, a64, a70, a71, a72)  // sha3-384
130     if (blockSize > 8 * 13) { XOR_4 (13, a73, a74, a80, a81)  // sha3-256
131     if (blockSize > 8 * 17) { XOR_1 (17, a82)                 // sha3-224
132     if (blockSize > 8 * 18) { XOR_1 (18, a83)                 // shake128
133                               XOR_1 (19, a84)
134                               XOR_1 (20, a90) }}}}
135     data += blockSize;
136 
137     for (round = 0; round < 24; round += 2)
138     {
139       UInt64 c0, c1, c2, c3, c4;
140       UInt64 d0, d1, d2, d3, d4;
141       UInt64 e50, e51, e52, e53, e54;
142       UInt64 e60, e61, e62, e63, e64;
143       UInt64 e70, e71, e72, e73, e74;
144       UInt64 e80, e81, e82, e83, e84;
145       UInt64 e90, e91, e92, e93, e94;
146 
147       c0 = a50^a60^a70^a80^a90;
148       c1 = a51^a61^a71^a81^a91;
149       c2 = a52^a62^a72^a82^a92;
150       c3 = a53^a63^a73^a83^a93;
151       c4 = a54^a64^a74^a84^a94;
152       D5
153       CK( a50, d0,
154           a61, d1, 44,
155           a72, d2, 43,
156           a83, d3, 21,
157           a94, d4, 14, e50, e51, e52, e53, e54, SHA3_K_ARRAY[round])
158       CE( a53, d3, 28,
159           a64, d4, 20,
160           a70, d0,  3,
161           a81, d1, 45,
162           a92, d2, 61, e60, e61, e62, e63, e64)
163       CE( a51, d1,  1,
164           a62, d2,  6,
165           a73, d3, 25,
166           a84, d4,  8,
167           a90, d0, 18, e70, e71, e72, e73, e74)
168       CE( a54, d4, 27,
169           a60, d0, 36,
170           a71, d1, 10,
171           a82, d2, 15,
172           a93, d3, 56, e80, e81, e82, e83, e84)
173       CE( a52, d2, 62,
174           a63, d3, 55,
175           a74, d4, 39,
176           a80, d0, 41,
177           a91, d1,  2, e90, e91, e92, e93, e94)
178 
179       // ---------- ROUND + 1 ----------
180 
181       c0 = e50^e60^e70^e80^e90;
182       c1 = e51^e61^e71^e81^e91;
183       c2 = e52^e62^e72^e82^e92;
184       c3 = e53^e63^e73^e83^e93;
185       c4 = e54^e64^e74^e84^e94;
186       D5
187       CK( e50, d0,
188           e61, d1, 44,
189           e72, d2, 43,
190           e83, d3, 21,
191           e94, d4, 14, a50, a51, a52, a53, a54, SHA3_K_ARRAY[(size_t)round + 1])
192       CE( e53, d3, 28,
193           e64, d4, 20,
194           e70, d0,  3,
195           e81, d1, 45,
196           e92, d2, 61, a60, a61, a62, a63, a64)
197       CE( e51, d1,  1,
198           e62, d2,  6,
199           e73, d3, 25,
200           e84, d4,  8,
201           e90, d0, 18, a70, a71, a72, a73, a74)
202       CE (e54, d4, 27,
203           e60, d0, 36,
204           e71, d1, 10,
205           e82, d2, 15,
206           e93, d3, 56, a80, a81, a82, a83, a84)
207       CE (e52, d2, 62,
208           e63, d3, 55,
209           e74, d4, 39,
210           e80, d0, 41,
211           e91, d1,  2, a90, a91, a92, a93, a94)
212     }
213   }
214   while (--numBlocks);
215 
216   LS_25 (SET_state)
217 }
218 
219 
220 #define Sha3_UpdateBlock(p) \
221         Sha3_UpdateBlocks(p->state, p->buffer, 1, p->blockSize)
222 
Sha3_Update(CSha3 * p,const Byte * data,size_t size)223 void Sha3_Update(CSha3 *p, const Byte *data, size_t size)
224 {
225 /*
226   for (;;)
227   {
228     if (size == 0)
229       return;
230     unsigned cur = p->blockSize - p->count;
231     if (cur > size)
232       cur = (unsigned)size;
233     size -= cur;
234     unsigned pos = p->count;
235     p->count = pos + cur;
236     while (pos & 7)
237     {
238       if (cur == 0)
239         return;
240       Byte *pb = &(((Byte *)p->state)[pos]);
241       *pb = (Byte)(*pb ^ *data++);
242       cur--;
243       pos++;
244     }
245     if (cur >= 8)
246     {
247       do
248       {
249         *(UInt64 *)(void *)&(((Byte *)p->state)[pos]) ^= GetUi64(data);
250         data += 8;
251         pos += 8;
252         cur -= 8;
253       }
254       while (cur >= 8);
255     }
256     if (pos != p->blockSize)
257     {
258       if (cur)
259       {
260         Byte *pb = &(((Byte *)p->state)[pos]);
261         do
262         {
263           *pb = (Byte)(*pb ^ *data++);
264           pb++;
265         }
266         while (--cur);
267       }
268       return;
269     }
270     Sha3_UpdateBlock(p->state);
271     p->count = 0;
272   }
273 */
274   if (size == 0)
275     return;
276   {
277     const unsigned pos = p->count;
278     const unsigned num = p->blockSize - pos;
279     if (num > size)
280     {
281       p->count = pos + (unsigned)size;
282       memcpy(p->buffer + pos, data, size);
283       return;
284     }
285     if (pos != 0)
286     {
287       size -= num;
288       memcpy(p->buffer + pos, data, num);
289       data += num;
290       Sha3_UpdateBlock(p);
291     }
292   }
293   if (size >= p->blockSize)
294   {
295     const size_t numBlocks = size / p->blockSize;
296     const Byte *dataOld = data;
297     data += numBlocks * p->blockSize;
298     size = (size_t)(dataOld + size - data);
299     Sha3_UpdateBlocks(p->state, dataOld, numBlocks, p->blockSize);
300   }
301   p->count = (unsigned)size;
302   if (size)
303     memcpy(p->buffer, data, size);
304 }
305 
306 
307 // we support only (digestSize % 4 == 0) cases
Sha3_Final(CSha3 * p,Byte * digest,unsigned digestSize,unsigned shake)308 void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake)
309 {
310   memset(p->buffer + p->count, 0, p->blockSize - p->count);
311   // we write bits markers from low to higher in current byte:
312   //   - if sha-3 : 2 bits : 0,1
313   //   - if shake : 4 bits : 1111
314   // then we write bit 1 to same byte.
315   // And we write bit 1 to highest bit of last byte of block.
316   p->buffer[p->count] = (Byte)(shake ? 0x1f : 0x06);
317   // we need xor operation (^= 0x80) here because we must write 0x80 bit
318   // to same byte as (0x1f : 0x06), if (p->count == p->blockSize - 1) !!!
319   p->buffer[p->blockSize - 1] ^= 0x80;
320 /*
321   ((Byte *)p->state)[p->count] ^= (Byte)(shake ? 0x1f : 0x06);
322   ((Byte *)p->state)[p->blockSize - 1] ^= 0x80;
323 */
324   Sha3_UpdateBlock(p);
325 #if 1 && defined(MY_CPU_LE)
326   memcpy(digest, p->state, digestSize);
327 #else
328   {
329     const unsigned numWords = digestSize >> 3;
330     unsigned i;
331     for (i = 0; i < numWords; i++)
332     {
333       const UInt64 v = p->state[i];
334       SetUi64(digest, v)
335       digest += 8;
336     }
337     if (digestSize & 4) // for SHA3-224
338     {
339       const UInt32 v = (UInt32)p->state[numWords];
340       SetUi32(digest, v)
341     }
342   }
343 #endif
344   Sha3_Init(p);
345 }
346 
347 #undef GET_state
348 #undef SET_state
349 #undef LS_5
350 #undef LS_25
351 #undef XOR_1
352 #undef XOR_4
353 #undef D
354 #undef D5
355 #undef C0
356 #undef C
357 #undef E4
358 #undef CK
359 #undef CE
360