/src/cryptofuzz/crypto.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include <cryptofuzz/crypto.h> |
2 | | #include <stdint.h> |
3 | | #include <stdlib.h> |
4 | | #include <string.h> |
5 | | |
6 | | namespace cryptofuzz { |
7 | | namespace crypto { |
8 | | namespace impl { |
9 | | |
10 | | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ |
11 | | /* SPDX-License-Identifier: Unlicense */ |
12 | | |
13 | 0 | #define ROR(x,n) __builtin_rotateright32(x,n) |
14 | 0 | #define ROL(x,n) __builtin_rotateleft32(x,n) |
15 | 0 | #define ROLc(x,n) ROL(x,n) |
16 | 0 | #define RORc(x,n) ROR(x,n) |
17 | | |
18 | 0 | #define XMEMCPY memcpy |
19 | | |
20 | | #define LTC_ARGCHK(...) |
21 | | |
22 | 0 | #define MIN(x, y) ( ((x)<(y))?(x):(y) ) |
23 | | |
24 | 0 | #define STORE32H(x, y) \ |
25 | 0 | do { ulong32 ttt = __builtin_bswap32 ((x)); \ |
26 | 0 | XMEMCPY ((y), &ttt, 4); } while(0) |
27 | | |
28 | 0 | #define LOAD32H(x, y) \ |
29 | 0 | do { XMEMCPY (&(x), (y), 4); \ |
30 | 0 | (x) = __builtin_bswap32 ((x)); } while(0) |
31 | | |
32 | 0 | #define STORE64H(x, y) \ |
33 | 0 | do { ulong64 ttt = __builtin_bswap64 ((x)); \ |
34 | 0 | XMEMCPY ((y), &ttt, 8); } while(0) |
35 | | |
36 | | #define LOAD64H(x, y) \ |
37 | | do { XMEMCPY (&(x), (y), 8); \ |
38 | | (x) = __builtin_bswap64 ((x)); } while(0) |
39 | | |
40 | | typedef uint64_t ulong64; |
41 | | typedef uint32_t ulong32; |
42 | | |
43 | | /* error codes [will be expanded in future releases] */ |
44 | | enum { |
45 | | CRYPT_OK=0, /* Result OK */ |
46 | | CRYPT_ERROR, /* Generic Error */ |
47 | | CRYPT_NOP, /* Not a failure but no operation was performed */ |
48 | | |
49 | | CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ |
50 | | CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ |
51 | | CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ |
52 | | |
53 | | CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ |
54 | | CRYPT_INVALID_PACKET, /* Invalid input packet given */ |
55 | | |
56 | | CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ |
57 | | CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ |
58 | | |
59 | | CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ |
60 | | CRYPT_INVALID_HASH, /* Invalid hash specified */ |
61 | | CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ |
62 | | |
63 | | CRYPT_MEM, /* Out of memory */ |
64 | | |
65 | | CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ |
66 | | CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ |
67 | | |
68 | | CRYPT_INVALID_ARG, /* Generic invalid argument */ |
69 | | CRYPT_FILE_NOTFOUND, /* File Not Found */ |
70 | | |
71 | | CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ |
72 | | |
73 | | CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ |
74 | | |
75 | | CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ |
76 | | |
77 | | CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ |
78 | | |
79 | | CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ |
80 | | |
81 | | CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ |
82 | | CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ |
83 | | |
84 | | CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ |
85 | | }; |
86 | | |
87 | | #define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ |
88 | 0 | int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ |
89 | 0 | { \ |
90 | 0 | unsigned long n; \ |
91 | 0 | int err; \ |
92 | 0 | LTC_ARGCHK(md != NULL); \ |
93 | 0 | LTC_ARGCHK(in != NULL); \ |
94 | 0 | if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ |
95 | 0 | return CRYPT_INVALID_ARG; \ |
96 | 0 | } \ |
97 | 0 | if ((md-> state_var .length + inlen * 8) < md-> state_var .length) { \ |
98 | 0 | return CRYPT_HASH_OVERFLOW; \ |
99 | 0 | } \ |
100 | 0 | while (inlen > 0) { \ |
101 | 0 | if (md-> state_var .curlen == 0 && inlen >= block_size) { \ |
102 | 0 | if ((err = compress_name (md, in)) != CRYPT_OK) { \ |
103 | 0 | return err; \ |
104 | 0 | } \ |
105 | 0 | md-> state_var .length += block_size * 8; \ |
106 | 0 | in += block_size; \ |
107 | 0 | inlen -= block_size; \ |
108 | 0 | } else { \ |
109 | 0 | n = MIN(inlen, (block_size - md-> state_var .curlen)); \ |
110 | 0 | XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ |
111 | 0 | md-> state_var .curlen += n; \ |
112 | 0 | in += n; \ |
113 | 0 | inlen -= n; \ |
114 | 0 | if (md-> state_var .curlen == block_size) { \ |
115 | 0 | if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ |
116 | 0 | return err; \ |
117 | 0 | } \ |
118 | 0 | md-> state_var .length += 8*block_size; \ |
119 | 0 | md-> state_var .curlen = 0; \ |
120 | 0 | } \ |
121 | 0 | } \ |
122 | 0 | } \ |
123 | 0 | return CRYPT_OK; \ |
124 | 0 | } Unexecuted instantiation: cryptofuzz::crypto::impl::sha1_process(cryptofuzz::crypto::impl::Hash_state*, unsigned char const*, unsigned long) Unexecuted instantiation: cryptofuzz::crypto::impl::sha256_process(cryptofuzz::crypto::impl::Hash_state*, unsigned char const*, unsigned long) |
125 | | |
126 | | struct sha1_state { |
127 | | ulong64 length; |
128 | | ulong32 state[5], curlen; |
129 | | unsigned char buf[64]; |
130 | | }; |
131 | | |
132 | | struct sha256_state { |
133 | | ulong64 length; |
134 | | ulong32 state[8], curlen; |
135 | | unsigned char buf[64]; |
136 | | }; |
137 | | |
138 | | typedef union Hash_state { |
139 | | char dummy[1]; |
140 | | struct sha1_state sha1; |
141 | | struct sha256_state sha256; |
142 | | void *data; |
143 | | } hash_state; |
144 | | |
145 | | /** |
146 | | @file sha1.c |
147 | | LTC_SHA1 code by Tom St Denis |
148 | | */ |
149 | | |
150 | | |
151 | 0 | #define F0(x,y,z) (z ^ (x & (y ^ z))) |
152 | 0 | #define F1(x,y,z) (x ^ y ^ z) |
153 | 0 | #define F2(x,y,z) ((x & y) | (z & (x | y))) |
154 | 0 | #define F3(x,y,z) (x ^ y ^ z) |
155 | | |
156 | | #ifdef LTC_CLEAN_STACK |
157 | | static int ss_sha1_compress(hash_state *md, const unsigned char *buf) |
158 | | #else |
159 | | static int s_sha1_compress(hash_state *md, const unsigned char *buf) |
160 | | #endif |
161 | 0 | { |
162 | 0 | ulong32 a,b,c,d,e,W[80],i; |
163 | | #ifdef LTC_SMALL_CODE |
164 | | ulong32 t; |
165 | | #endif |
166 | | |
167 | | /* copy the state into 512-bits into W[0..15] */ |
168 | 0 | for (i = 0; i < 16; i++) { |
169 | 0 | LOAD32H(W[i], buf + (4*i)); |
170 | 0 | } |
171 | | |
172 | | /* copy state */ |
173 | 0 | a = md->sha1.state[0]; |
174 | 0 | b = md->sha1.state[1]; |
175 | 0 | c = md->sha1.state[2]; |
176 | 0 | d = md->sha1.state[3]; |
177 | 0 | e = md->sha1.state[4]; |
178 | | |
179 | | /* expand it */ |
180 | 0 | for (i = 16; i < 80; i++) { |
181 | 0 | W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); |
182 | 0 | } |
183 | | |
184 | | /* compress */ |
185 | | /* round one */ |
186 | 0 | #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); |
187 | 0 | #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); |
188 | 0 | #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); |
189 | 0 | #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); |
190 | |
|
191 | | #ifdef LTC_SMALL_CODE |
192 | | |
193 | | for (i = 0; i < 20; ) { |
194 | | FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; |
195 | | } |
196 | | |
197 | | for (; i < 40; ) { |
198 | | FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; |
199 | | } |
200 | | |
201 | | for (; i < 60; ) { |
202 | | FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; |
203 | | } |
204 | | |
205 | | for (; i < 80; ) { |
206 | | FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; |
207 | | } |
208 | | |
209 | | #else |
210 | |
|
211 | 0 | for (i = 0; i < 20; ) { |
212 | 0 | FF0(a,b,c,d,e,i++); |
213 | 0 | FF0(e,a,b,c,d,i++); |
214 | 0 | FF0(d,e,a,b,c,i++); |
215 | 0 | FF0(c,d,e,a,b,i++); |
216 | 0 | FF0(b,c,d,e,a,i++); |
217 | 0 | } |
218 | | |
219 | | /* round two */ |
220 | 0 | for (; i < 40; ) { |
221 | 0 | FF1(a,b,c,d,e,i++); |
222 | 0 | FF1(e,a,b,c,d,i++); |
223 | 0 | FF1(d,e,a,b,c,i++); |
224 | 0 | FF1(c,d,e,a,b,i++); |
225 | 0 | FF1(b,c,d,e,a,i++); |
226 | 0 | } |
227 | | |
228 | | /* round three */ |
229 | 0 | for (; i < 60; ) { |
230 | 0 | FF2(a,b,c,d,e,i++); |
231 | 0 | FF2(e,a,b,c,d,i++); |
232 | 0 | FF2(d,e,a,b,c,i++); |
233 | 0 | FF2(c,d,e,a,b,i++); |
234 | 0 | FF2(b,c,d,e,a,i++); |
235 | 0 | } |
236 | | |
237 | | /* round four */ |
238 | 0 | for (; i < 80; ) { |
239 | 0 | FF3(a,b,c,d,e,i++); |
240 | 0 | FF3(e,a,b,c,d,i++); |
241 | 0 | FF3(d,e,a,b,c,i++); |
242 | 0 | FF3(c,d,e,a,b,i++); |
243 | 0 | FF3(b,c,d,e,a,i++); |
244 | 0 | } |
245 | 0 | #endif |
246 | |
|
247 | 0 | #undef FF0 |
248 | 0 | #undef FF1 |
249 | 0 | #undef FF2 |
250 | 0 | #undef FF3 |
251 | | |
252 | | /* store */ |
253 | 0 | md->sha1.state[0] = md->sha1.state[0] + a; |
254 | 0 | md->sha1.state[1] = md->sha1.state[1] + b; |
255 | 0 | md->sha1.state[2] = md->sha1.state[2] + c; |
256 | 0 | md->sha1.state[3] = md->sha1.state[3] + d; |
257 | 0 | md->sha1.state[4] = md->sha1.state[4] + e; |
258 | |
|
259 | 0 | return CRYPT_OK; |
260 | 0 | } |
261 | | |
262 | | #ifdef LTC_CLEAN_STACK |
263 | | static int s_sha1_compress(hash_state *md, const unsigned char *buf) |
264 | | { |
265 | | int err; |
266 | | err = ss_sha1_compress(md, buf); |
267 | | burn_stack(sizeof(ulong32) * 87); |
268 | | return err; |
269 | | } |
270 | | #endif |
271 | | |
272 | | /** |
273 | | Initialize the hash state |
274 | | @param md The hash state you wish to initialize |
275 | | @return CRYPT_OK if successful |
276 | | */ |
277 | | int sha1_init(hash_state * md) |
278 | 0 | { |
279 | 0 | LTC_ARGCHK(md != NULL); |
280 | 0 | md->sha1.state[0] = 0x67452301UL; |
281 | 0 | md->sha1.state[1] = 0xefcdab89UL; |
282 | 0 | md->sha1.state[2] = 0x98badcfeUL; |
283 | 0 | md->sha1.state[3] = 0x10325476UL; |
284 | 0 | md->sha1.state[4] = 0xc3d2e1f0UL; |
285 | 0 | md->sha1.curlen = 0; |
286 | 0 | md->sha1.length = 0; |
287 | 0 | return CRYPT_OK; |
288 | 0 | } |
289 | | |
290 | | /** |
291 | | Process a block of memory though the hash |
292 | | @param md The hash state |
293 | | @param in The data to hash |
294 | | @param inlen The length of the data (octets) |
295 | | @return CRYPT_OK if successful |
296 | | */ |
297 | | HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64) |
298 | | |
299 | | /** |
300 | | Terminate the hash to get the digest |
301 | | @param md The hash state |
302 | | @param out [out] The destination of the hash (20 bytes) |
303 | | @return CRYPT_OK if successful |
304 | | */ |
305 | | int sha1_done(hash_state * md, unsigned char *out) |
306 | 0 | { |
307 | 0 | int i; |
308 | |
|
309 | 0 | LTC_ARGCHK(md != NULL); |
310 | 0 | LTC_ARGCHK(out != NULL); |
311 | |
|
312 | 0 | if (md->sha1.curlen >= sizeof(md->sha1.buf)) { |
313 | 0 | return CRYPT_INVALID_ARG; |
314 | 0 | } |
315 | | |
316 | | /* increase the length of the message */ |
317 | 0 | md->sha1.length += md->sha1.curlen * 8; |
318 | | |
319 | | /* append the '1' bit */ |
320 | 0 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; |
321 | | |
322 | | /* if the length is currently above 56 bytes we append zeros |
323 | | * then compress. Then we can fall back to padding zeros and length |
324 | | * encoding like normal. |
325 | | */ |
326 | 0 | if (md->sha1.curlen > 56) { |
327 | 0 | while (md->sha1.curlen < 64) { |
328 | 0 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; |
329 | 0 | } |
330 | 0 | s_sha1_compress(md, md->sha1.buf); |
331 | 0 | md->sha1.curlen = 0; |
332 | 0 | } |
333 | | |
334 | | /* pad upto 56 bytes of zeroes */ |
335 | 0 | while (md->sha1.curlen < 56) { |
336 | 0 | md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; |
337 | 0 | } |
338 | | |
339 | | /* store length */ |
340 | 0 | STORE64H(md->sha1.length, md->sha1.buf+56); |
341 | 0 | s_sha1_compress(md, md->sha1.buf); |
342 | | |
343 | | /* copy output */ |
344 | 0 | for (i = 0; i < 5; i++) { |
345 | 0 | STORE32H(md->sha1.state[i], out+(4*i)); |
346 | 0 | } |
347 | | #ifdef LTC_CLEAN_STACK |
348 | | zeromem(md, sizeof(hash_state)); |
349 | | #endif |
350 | 0 | return CRYPT_OK; |
351 | 0 | } |
352 | | |
353 | | #ifdef LTC_SMALL_CODE |
354 | | /* the K array */ |
355 | | static const ulong32 K[64] = { |
356 | | 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, |
357 | | 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, |
358 | | 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, |
359 | | 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, |
360 | | 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, |
361 | | 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, |
362 | | 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, |
363 | | 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, |
364 | | 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, |
365 | | 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, |
366 | | 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, |
367 | | 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, |
368 | | 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL |
369 | | }; |
370 | | #endif |
371 | | |
372 | | /* Various logical functions */ |
373 | 0 | #define Ch(x,y,z) (z ^ (x & (y ^ z))) |
374 | 0 | #define Maj(x,y,z) (((x | y) & z) | (x & y)) |
375 | 0 | #define S(x, n) RORc((x),(n)) |
376 | 0 | #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) |
377 | 0 | #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) |
378 | 0 | #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) |
379 | 0 | #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) |
380 | 0 | #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) |
381 | | |
382 | | /* compress 512-bits */ |
383 | | #ifdef LTC_CLEAN_STACK |
384 | | static int ss_sha256_compress(hash_state * md, const unsigned char *buf) |
385 | | #else |
386 | | static int s_sha256_compress(hash_state * md, const unsigned char *buf) |
387 | | #endif |
388 | 0 | { |
389 | 0 | ulong32 S[8], W[64], t0, t1; |
390 | | #ifdef LTC_SMALL_CODE |
391 | | ulong32 t; |
392 | | #endif |
393 | 0 | int i; |
394 | | |
395 | | /* copy state into S */ |
396 | 0 | for (i = 0; i < 8; i++) { |
397 | 0 | S[i] = md->sha256.state[i]; |
398 | 0 | } |
399 | | |
400 | | /* copy the state into 512-bits into W[0..15] */ |
401 | 0 | for (i = 0; i < 16; i++) { |
402 | 0 | LOAD32H(W[i], buf + (4*i)); |
403 | 0 | } |
404 | | |
405 | | /* fill W[16..63] */ |
406 | 0 | for (i = 16; i < 64; i++) { |
407 | 0 | W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; |
408 | 0 | } |
409 | | |
410 | | /* Compress */ |
411 | | #ifdef LTC_SMALL_CODE |
412 | | #define RND(a,b,c,d,e,f,g,h,i) \ |
413 | | t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ |
414 | | t1 = Sigma0(a) + Maj(a, b, c); \ |
415 | | d += t0; \ |
416 | | h = t0 + t1; |
417 | | |
418 | | for (i = 0; i < 64; ++i) { |
419 | | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); |
420 | | t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; |
421 | | S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; |
422 | | } |
423 | | #else |
424 | 0 | #define RND(a,b,c,d,e,f,g,h,i,ki) \ |
425 | 0 | t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ |
426 | 0 | t1 = Sigma0(a) + Maj(a, b, c); \ |
427 | 0 | d += t0; \ |
428 | 0 | h = t0 + t1; |
429 | |
|
430 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); |
431 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); |
432 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); |
433 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); |
434 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); |
435 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); |
436 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); |
437 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); |
438 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); |
439 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); |
440 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); |
441 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); |
442 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); |
443 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); |
444 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); |
445 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); |
446 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); |
447 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); |
448 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); |
449 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); |
450 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); |
451 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); |
452 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); |
453 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); |
454 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); |
455 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); |
456 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); |
457 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); |
458 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); |
459 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); |
460 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); |
461 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); |
462 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); |
463 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); |
464 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); |
465 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); |
466 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); |
467 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); |
468 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); |
469 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); |
470 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); |
471 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); |
472 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); |
473 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); |
474 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); |
475 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); |
476 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); |
477 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); |
478 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); |
479 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); |
480 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); |
481 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); |
482 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); |
483 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); |
484 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); |
485 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); |
486 | 0 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); |
487 | 0 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); |
488 | 0 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); |
489 | 0 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); |
490 | 0 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); |
491 | 0 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); |
492 | 0 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); |
493 | 0 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); |
494 | 0 | #endif |
495 | 0 | #undef RND |
496 | | |
497 | | /* feedback */ |
498 | 0 | for (i = 0; i < 8; i++) { |
499 | 0 | md->sha256.state[i] = md->sha256.state[i] + S[i]; |
500 | 0 | } |
501 | 0 | return CRYPT_OK; |
502 | 0 | } |
503 | | |
504 | | #ifdef LTC_CLEAN_STACK |
505 | | static int s_sha256_compress(hash_state * md, const unsigned char *buf) |
506 | | { |
507 | | int err; |
508 | | err = ss_sha256_compress(md, buf); |
509 | | burn_stack(sizeof(ulong32) * 74); |
510 | | return err; |
511 | | } |
512 | | #endif |
513 | | |
514 | | /** |
515 | | Initialize the hash state |
516 | | @param md The hash state you wish to initialize |
517 | | @return CRYPT_OK if successful |
518 | | */ |
519 | | int sha256_init(hash_state * md) |
520 | 0 | { |
521 | 0 | LTC_ARGCHK(md != NULL); |
522 | |
|
523 | 0 | md->sha256.curlen = 0; |
524 | 0 | md->sha256.length = 0; |
525 | 0 | md->sha256.state[0] = 0x6A09E667UL; |
526 | 0 | md->sha256.state[1] = 0xBB67AE85UL; |
527 | 0 | md->sha256.state[2] = 0x3C6EF372UL; |
528 | 0 | md->sha256.state[3] = 0xA54FF53AUL; |
529 | 0 | md->sha256.state[4] = 0x510E527FUL; |
530 | 0 | md->sha256.state[5] = 0x9B05688CUL; |
531 | 0 | md->sha256.state[6] = 0x1F83D9ABUL; |
532 | 0 | md->sha256.state[7] = 0x5BE0CD19UL; |
533 | 0 | return CRYPT_OK; |
534 | 0 | } |
535 | | |
536 | | /** |
537 | | Process a block of memory though the hash |
538 | | @param md The hash state |
539 | | @param in The data to hash |
540 | | @param inlen The length of the data (octets) |
541 | | @return CRYPT_OK if successful |
542 | | */ |
543 | | HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64) |
544 | | |
545 | | /** |
546 | | Terminate the hash to get the digest |
547 | | @param md The hash state |
548 | | @param out [out] The destination of the hash (32 bytes) |
549 | | @return CRYPT_OK if successful |
550 | | */ |
551 | | int sha256_done(hash_state * md, unsigned char *out) |
552 | 0 | { |
553 | 0 | int i; |
554 | |
|
555 | 0 | LTC_ARGCHK(md != NULL); |
556 | 0 | LTC_ARGCHK(out != NULL); |
557 | |
|
558 | 0 | if (md->sha256.curlen >= sizeof(md->sha256.buf)) { |
559 | 0 | return CRYPT_INVALID_ARG; |
560 | 0 | } |
561 | | |
562 | | |
563 | | /* increase the length of the message */ |
564 | 0 | md->sha256.length += md->sha256.curlen * 8; |
565 | | |
566 | | /* append the '1' bit */ |
567 | 0 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; |
568 | | |
569 | | /* if the length is currently above 56 bytes we append zeros |
570 | | * then compress. Then we can fall back to padding zeros and length |
571 | | * encoding like normal. |
572 | | */ |
573 | 0 | if (md->sha256.curlen > 56) { |
574 | 0 | while (md->sha256.curlen < 64) { |
575 | 0 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; |
576 | 0 | } |
577 | 0 | s_sha256_compress(md, md->sha256.buf); |
578 | 0 | md->sha256.curlen = 0; |
579 | 0 | } |
580 | | |
581 | | /* pad upto 56 bytes of zeroes */ |
582 | 0 | while (md->sha256.curlen < 56) { |
583 | 0 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; |
584 | 0 | } |
585 | | |
586 | | /* store length */ |
587 | 0 | STORE64H(md->sha256.length, md->sha256.buf+56); |
588 | 0 | s_sha256_compress(md, md->sha256.buf); |
589 | | |
590 | | /* copy output */ |
591 | 0 | for (i = 0; i < 8; i++) { |
592 | 0 | STORE32H(md->sha256.state[i], out+(4*i)); |
593 | 0 | } |
594 | | #ifdef LTC_CLEAN_STACK |
595 | | zeromem(md, sizeof(hash_state)); |
596 | | #endif |
597 | 0 | return CRYPT_OK; |
598 | 0 | } |
599 | | |
600 | | } /* namespace impl */ |
601 | | |
602 | 0 | std::vector<uint8_t> sha1(const uint8_t* data, const size_t size) { |
603 | 0 | uint8_t out[20]; |
604 | |
|
605 | 0 | impl::hash_state md; |
606 | 0 | impl::sha1_init(&md); |
607 | 0 | impl::sha1_process(&md, data, size); |
608 | 0 | impl::sha1_done(&md, out); |
609 | |
|
610 | 0 | return std::vector<uint8_t>(out, out + sizeof(out)); |
611 | 0 | } |
612 | | |
613 | 0 | std::vector<uint8_t> sha1(const std::vector<uint8_t> data) { |
614 | 0 | return sha1(data.data(), data.size()); |
615 | 0 | } |
616 | | |
617 | 0 | std::vector<uint8_t> sha256(const uint8_t* data, const size_t size) { |
618 | 0 | uint8_t out[32]; |
619 | |
|
620 | 0 | impl::hash_state md; |
621 | 0 | impl::sha256_init(&md); |
622 | 0 | impl::sha256_process(&md, data, size); |
623 | 0 | impl::sha256_done(&md, out); |
624 | |
|
625 | 0 | return std::vector<uint8_t>(out, out + sizeof(out)); |
626 | 0 | } |
627 | | |
628 | 0 | std::vector<uint8_t> sha256(const std::vector<uint8_t> data) { |
629 | 0 | return sha256(data.data(), data.size()); |
630 | 0 | } |
631 | | |
632 | 0 | std::vector<uint8_t> hmac_sha256(const uint8_t* data, const size_t size, const uint8_t* key, const size_t key_size) { |
633 | 0 | uint8_t _key[64]; |
634 | 0 | uint8_t out[32]; |
635 | 0 | impl::hash_state inner, outer; |
636 | |
|
637 | 0 | impl::sha256_init(&inner); |
638 | 0 | impl::sha256_init(&outer); |
639 | |
|
640 | 0 | if ( key_size <= 64 ) { |
641 | 0 | if ( key_size ) { |
642 | 0 | memcpy(_key, key, key_size); |
643 | 0 | } |
644 | 0 | memset(_key + key_size, 0, 64 - key_size); |
645 | 0 | } else { |
646 | 0 | const auto key_hash = sha256(key, key_size); |
647 | 0 | memcpy(_key, key_hash.data(), key_hash.size()); |
648 | 0 | memset(_key + 32, 0, 32); |
649 | 0 | } |
650 | |
|
651 | 0 | for (size_t i = 0; i < 64; i++) { |
652 | 0 | _key[i] ^= 0x5C; |
653 | 0 | } |
654 | 0 | impl::sha256_process(&outer, _key, 64); |
655 | |
|
656 | 0 | for (int i = 0; i < 64; i++) { |
657 | 0 | _key[i] ^= 0x5C ^ 0x36; |
658 | 0 | } |
659 | 0 | impl::sha256_process(&inner, _key, 64); |
660 | |
|
661 | 0 | impl::sha256_process(&inner, data, size); |
662 | |
|
663 | 0 | impl::sha256_done(&inner, out); |
664 | 0 | impl::sha256_process(&outer, out, 32); |
665 | 0 | impl::sha256_done(&outer, out); |
666 | |
|
667 | 0 | return {out, out + 32}; |
668 | 0 | } |
669 | | |
670 | 0 | std::vector<uint8_t> hmac_sha256(const std::vector<uint8_t> data, const std::vector<uint8_t> key) { |
671 | 0 | return hmac_sha256(data.data(), data.size(), key.data(), key.size()); |
672 | 0 | } |
673 | | |
674 | | |
675 | | } /* namespace crypto */ |
676 | | } /* namespace cryptofuzz */ |