Coverage Report

Created: 2022-08-24 06:31

/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 */