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