Coverage Report

Created: 2025-05-12 07:03

/src/pycryptodome/src/hash_SHA2_template.c
Line
Count
Source (jump to first uncovered line)
1
/* ===================================================================
2
 *
3
 * Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in
14
 *    the documentation and/or other materials provided with the
15
 *    distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 * ===================================================================
30
 */
31
32
#include <stdio.h>
33
#include "common.h"
34
#include "endianess.h"
35
36
FAKE_INIT(MODULE_NAME)
37
38
0
#define FUNC_NAME(pf) _PASTE2(MODULE_NAME, pf)
39
40
/**
41
 * SHA-2 as defined in FIPS 180-4 http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
42
 */
43
44
20.1M
#define CH(x,y,z)       (((x) & (y)) ^ (~(x) & (z)))
45
20.1M
#define MAJ(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
46
47
181M
#define ROTR32(n, x)    (((x)>>(n)) | ((x)<<(32-(n))))
48
#define ROTR64(n, x)    (((x)>>(n)) | ((x)<<(64-(n))))
49
30.2M
#define SHR(n,x)        ((x)>>(n))
50
51
#if WORD_SIZE==4
52
53
/** SHA-224, SHA-256 **/
54
55
typedef uint32_t sha2_word_t;
56
57
15.4M
#define SCHEDULE_SIZE 64
58
947k
#define BLOCK_SIZE 64
59
60
20.1M
#define SIGMA_0_256(x)    (ROTR32(2,x)  ^ ROTR32(13,x) ^ ROTR32(22,x))
61
20.1M
#define SIGMA_1_256(x)    (ROTR32(6,x)  ^ ROTR32(11,x) ^ ROTR32(25,x))
62
15.1M
#define sigma_0_256(x)    (ROTR32(7,x)  ^ ROTR32(18,x) ^ SHR(3,x))
63
15.1M
#define sigma_1_256(x)    (ROTR32(17,x) ^ ROTR32(19,x) ^ SHR(10,x))
64
65
static const sha2_word_t K[SCHEDULE_SIZE] = {
66
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
67
    0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
68
    0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
69
    0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
70
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
71
    0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
72
    0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
73
    0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
74
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
75
    0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
76
    0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
77
    0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
78
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
79
};
80
81
15.1M
#define SCHEDULE(i) (sigma_1_256(W[i-2]) + W[i-7] + sigma_0_256(W[i-15]) + W[i-16])
82
83
#define CYCLE(a,b,c,d,e,f,g,h,t) \
84
20.1M
    h += SIGMA_1_256(e) + CH(e,f,g) + K[t]  + W[t]; \
85
20.1M
    d += h; \
86
20.1M
    h += SIGMA_0_256(a) + MAJ(a,b,c);
87
88
5.04M
#define LOAD_WORD_BIG(p)        LOAD_U32_BIG(p)
89
334
#define STORE_WORD_BIG(p, w)    STORE_U32_BIG(p, w)
90
91
#elif WORD_SIZE==8
92
93
/** SHA-384, SHA-512 **/
94
95
typedef uint64_t sha2_word_t;
96
97
#define SCHEDULE_SIZE 80
98
#define BLOCK_SIZE 128
99
100
#define SIGMA_0_512(x)    (ROTR64(28,x) ^ ROTR64(34,x) ^ ROTR64(39,x))
101
#define SIGMA_1_512(x)    (ROTR64(14,x) ^ ROTR64(18,x) ^ ROTR64(41,x))
102
#define sigma_0_512(x)    (ROTR64(1,x)  ^ ROTR64(8,x)  ^ SHR(7,x))
103
#define sigma_1_512(x)    (ROTR64(19,x) ^ ROTR64(61,x) ^ SHR(6,x))
104
105
static const sha2_word_t K[SCHEDULE_SIZE] = {
106
    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
107
    0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
108
    0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
109
    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
110
    0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
111
    0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
112
    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
113
    0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
114
    0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
115
    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
116
    0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
117
    0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
118
    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
119
    0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
120
    0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
121
    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
122
    0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
123
    0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
124
    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
125
    0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
126
};
127
128
#define SCHEDULE(i) (sigma_1_512(W[i-2]) + W[i-7] + sigma_0_512(W[i-15]) + W[i-16])
129
130
#define CYCLE(a,b,c,d,e,f,g,h,t) \
131
    h += SIGMA_1_512(e) + CH(e,f,g) + K[t]  + W[t]; \
132
    d += h; \
133
    h += SIGMA_0_512(a) + MAJ(a,b,c);
134
135
#define LOAD_WORD_BIG(p)        LOAD_U64_BIG(p)
136
#define STORE_WORD_BIG(p, w)    STORE_U64_BIG(p, w)
137
138
#else
139
#error Invalid WORD_SIZE
140
#endif
141
142
static inline void put_be(sha2_word_t number, uint8_t *p)
143
1.33k
{
144
1.33k
    int i;
145
146
6.68k
    for (i=0; i<WORD_SIZE; i++) {
147
5.34k
        p[WORD_SIZE-1-i] = (uint8_t)(number >> (i*8));
148
5.34k
    }
149
1.33k
}
150
151
typedef struct t_hash_state {
152
    sha2_word_t h[8];
153
    uint8_t buf[BLOCK_SIZE];    /** 16 words **/
154
    unsigned curlen;            /** Useful message bytes in buf[] (leftmost) **/
155
    sha2_word_t totbits[2];     /** Total message length in bits **/
156
    size_t digest_size;         /** Actual digest size in bytes **/
157
} hash_state;
158
159
static int add_bits(hash_state *hs, sha2_word_t bits)
160
315k
{
161
315k
    hs->totbits[0] += bits;
162
315k
    if (hs->totbits[0] >= bits) {
163
315k
        return 0;
164
315k
    }
165
166
    /** Overflow **/
167
0
    hs->totbits[1] += 1;
168
0
    if (hs->totbits[1] > 0) {
169
0
        return 0;
170
0
    }
171
172
0
    return ERR_MAX_DATA;
173
0
}
174
175
static void sha_compress(hash_state * hs)
176
315k
{
177
315k
    sha2_word_t a, b, c, d, e, f, g, h;
178
315k
    sha2_word_t W[SCHEDULE_SIZE];
179
315k
    int i;
180
181
    /** Words flow in in big-endian mode **/
182
5.35M
    for (i=0; i<16; i++) {
183
5.04M
        W[i] = LOAD_WORD_BIG(&hs->buf[i*WORD_SIZE]);
184
5.04M
    }
185
15.4M
    for (;i<SCHEDULE_SIZE; i++) {
186
15.1M
        W[i] = SCHEDULE(i);
187
15.1M
    }
188
189
315k
    a = hs->h[0];
190
315k
    b = hs->h[1];
191
315k
    c = hs->h[2];
192
315k
    d = hs->h[3];
193
315k
    e = hs->h[4];
194
315k
    f = hs->h[5];
195
315k
    g = hs->h[6];
196
315k
    h = hs->h[7];
197
198
315k
    CYCLE(a,b,c,d,e,f,g,h, 0);
199
315k
    CYCLE(h,a,b,c,d,e,f,g, 1);
200
315k
    CYCLE(g,h,a,b,c,d,e,f, 2);
201
315k
    CYCLE(f,g,h,a,b,c,d,e, 3);
202
315k
    CYCLE(e,f,g,h,a,b,c,d, 4);
203
315k
    CYCLE(d,e,f,g,h,a,b,c, 5);
204
315k
    CYCLE(c,d,e,f,g,h,a,b, 6);
205
315k
    CYCLE(b,c,d,e,f,g,h,a, 7);
206
315k
    CYCLE(a,b,c,d,e,f,g,h, 8);
207
315k
    CYCLE(h,a,b,c,d,e,f,g, 9);
208
315k
    CYCLE(g,h,a,b,c,d,e,f, 10);
209
315k
    CYCLE(f,g,h,a,b,c,d,e, 11);
210
315k
    CYCLE(e,f,g,h,a,b,c,d, 12);
211
315k
    CYCLE(d,e,f,g,h,a,b,c, 13);
212
315k
    CYCLE(c,d,e,f,g,h,a,b, 14);
213
315k
    CYCLE(b,c,d,e,f,g,h,a, 15);
214
315k
    CYCLE(a,b,c,d,e,f,g,h, 16);
215
315k
    CYCLE(h,a,b,c,d,e,f,g, 17);
216
315k
    CYCLE(g,h,a,b,c,d,e,f, 18);
217
315k
    CYCLE(f,g,h,a,b,c,d,e, 19);
218
315k
    CYCLE(e,f,g,h,a,b,c,d, 20);
219
315k
    CYCLE(d,e,f,g,h,a,b,c, 21);
220
315k
    CYCLE(c,d,e,f,g,h,a,b, 22);
221
315k
    CYCLE(b,c,d,e,f,g,h,a, 23);
222
315k
    CYCLE(a,b,c,d,e,f,g,h, 24);
223
315k
    CYCLE(h,a,b,c,d,e,f,g, 25);
224
315k
    CYCLE(g,h,a,b,c,d,e,f, 26);
225
315k
    CYCLE(f,g,h,a,b,c,d,e, 27);
226
315k
    CYCLE(e,f,g,h,a,b,c,d, 28);
227
315k
    CYCLE(d,e,f,g,h,a,b,c, 29);
228
315k
    CYCLE(c,d,e,f,g,h,a,b, 30);
229
315k
    CYCLE(b,c,d,e,f,g,h,a, 31);
230
315k
    CYCLE(a,b,c,d,e,f,g,h, 32);
231
315k
    CYCLE(h,a,b,c,d,e,f,g, 33);
232
315k
    CYCLE(g,h,a,b,c,d,e,f, 34);
233
315k
    CYCLE(f,g,h,a,b,c,d,e, 35);
234
315k
    CYCLE(e,f,g,h,a,b,c,d, 36);
235
315k
    CYCLE(d,e,f,g,h,a,b,c, 37);
236
315k
    CYCLE(c,d,e,f,g,h,a,b, 38);
237
315k
    CYCLE(b,c,d,e,f,g,h,a, 39);
238
315k
    CYCLE(a,b,c,d,e,f,g,h, 40);
239
315k
    CYCLE(h,a,b,c,d,e,f,g, 41);
240
315k
    CYCLE(g,h,a,b,c,d,e,f, 42);
241
315k
    CYCLE(f,g,h,a,b,c,d,e, 43);
242
315k
    CYCLE(e,f,g,h,a,b,c,d, 44);
243
315k
    CYCLE(d,e,f,g,h,a,b,c, 45);
244
315k
    CYCLE(c,d,e,f,g,h,a,b, 46);
245
315k
    CYCLE(b,c,d,e,f,g,h,a, 47);
246
315k
    CYCLE(a,b,c,d,e,f,g,h, 48);
247
315k
    CYCLE(h,a,b,c,d,e,f,g, 49);
248
315k
    CYCLE(g,h,a,b,c,d,e,f, 50);
249
315k
    CYCLE(f,g,h,a,b,c,d,e, 51);
250
315k
    CYCLE(e,f,g,h,a,b,c,d, 52);
251
315k
    CYCLE(d,e,f,g,h,a,b,c, 53);
252
315k
    CYCLE(c,d,e,f,g,h,a,b, 54);
253
315k
    CYCLE(b,c,d,e,f,g,h,a, 55);
254
315k
    CYCLE(a,b,c,d,e,f,g,h, 56);
255
315k
    CYCLE(h,a,b,c,d,e,f,g, 57);
256
315k
    CYCLE(g,h,a,b,c,d,e,f, 58);
257
315k
    CYCLE(f,g,h,a,b,c,d,e, 59);
258
315k
    CYCLE(e,f,g,h,a,b,c,d, 60);
259
315k
    CYCLE(d,e,f,g,h,a,b,c, 61);
260
315k
    CYCLE(c,d,e,f,g,h,a,b, 62);
261
315k
    CYCLE(b,c,d,e,f,g,h,a, 63);
262
263
#if SCHEDULE_SIZE==80
264
    CYCLE(a,b,c,d,e,f,g,h, 64);
265
    CYCLE(h,a,b,c,d,e,f,g, 65);
266
    CYCLE(g,h,a,b,c,d,e,f, 66);
267
    CYCLE(f,g,h,a,b,c,d,e, 67);
268
    CYCLE(e,f,g,h,a,b,c,d, 68);
269
    CYCLE(d,e,f,g,h,a,b,c, 69);
270
    CYCLE(c,d,e,f,g,h,a,b, 70);
271
    CYCLE(b,c,d,e,f,g,h,a, 71);
272
    CYCLE(a,b,c,d,e,f,g,h, 72);
273
    CYCLE(h,a,b,c,d,e,f,g, 73);
274
    CYCLE(g,h,a,b,c,d,e,f, 74);
275
    CYCLE(f,g,h,a,b,c,d,e, 75);
276
    CYCLE(e,f,g,h,a,b,c,d, 76);
277
    CYCLE(d,e,f,g,h,a,b,c, 77);
278
    CYCLE(c,d,e,f,g,h,a,b, 78);
279
    CYCLE(b,c,d,e,f,g,h,a, 79);
280
#endif
281
282
    /** compute new intermediate hash **/
283
315k
    hs->h[0] += a;
284
315k
    hs->h[1] += b;
285
315k
    hs->h[2] += c;
286
315k
    hs->h[3] += d;
287
315k
    hs->h[4] += e;
288
315k
    hs->h[5] += f;
289
315k
    hs->h[6] += g;
290
315k
    hs->h[7] += h;
291
315k
}
292
293
EXPORT_SYM int FUNC_NAME(_init)(hash_state **shaState
294
#if DIGEST_SIZE == (512/8)
295
        , size_t digest_size
296
#endif
297
        )
298
328
{
299
328
    hash_state *hs;
300
328
    int i;
301
#if DIGEST_SIZE == (512/8)
302
    size_t variant;
303
#endif
304
305
328
    if (NULL == shaState) {
306
0
        return ERR_NULL;
307
0
    }
308
309
328
    *shaState = hs = (hash_state*) calloc(1, sizeof(hash_state));
310
328
    if (NULL == hs)
311
0
        return ERR_MEMORY;
312
313
328
    hs->curlen = 0;
314
328
    hs->totbits[0] = hs->totbits[1] = 0;
315
316
    /** Digest size and initial intermediate hash value **/
317
#if DIGEST_SIZE == (512/8)
318
    hs->digest_size = digest_size;
319
320
    switch (digest_size) {
321
        case 28: variant = 1;   /** SHA-512/224 **/
322
                 break;
323
        case 32: variant = 2;   /** SHA-512/256 **/
324
                 break;
325
        default: variant = 0;   /** Vanilla SHA-512 **/
326
    }
327
    
328
    for (i=0; i<8; i++) {
329
        hs->h[i] = H_SHA_512[variant][i];
330
    }
331
#else
332
328
    hs->digest_size = DIGEST_SIZE;
333
2.95k
    for (i=0; i<8; i++) {
334
2.62k
        hs->h[i] = H[i];
335
2.62k
    }
336
328
#endif
337
338
328
    return 0;
339
328
}
340
341
EXPORT_SYM int FUNC_NAME(_destroy)(hash_state *shaState)
342
328
{
343
328
    free(shaState);
344
328
    return 0;
345
328
}
346
347
EXPORT_SYM int FUNC_NAME(_update)(hash_state *hs, const uint8_t *buf, size_t len)
348
1.44k
{
349
1.44k
    if (NULL == hs || NULL == buf) {
350
161
        return ERR_NULL;
351
161
    }
352
353
1.28k
    assert(hs->curlen < BLOCK_SIZE);
354
355
317k
    while (len>0) {
356
316k
        unsigned btc, left;
357
358
316k
        left = BLOCK_SIZE - hs->curlen;
359
316k
        btc = (unsigned)MIN(left, len);
360
316k
        memcpy(&hs->buf[hs->curlen], buf, btc);
361
316k
        buf += btc;
362
316k
        hs->curlen += btc;
363
316k
        len -= btc;
364
365
316k
        if (hs->curlen == BLOCK_SIZE) {
366
314k
            sha_compress(hs);
367
314k
            hs->curlen = 0;
368
314k
            if (add_bits(hs, BLOCK_SIZE*8)) {
369
0
                return ERR_MAX_DATA;
370
0
            }
371
314k
        }
372
316k
    }
373
374
1.28k
    return 0;
375
1.28k
}
376
377
static int sha_finalize(hash_state *hs, uint8_t *hash, size_t digest_size)
378
167
{
379
167
    unsigned left, i;
380
167
    uint8_t hash_tmp[WORD_SIZE*8];
381
382
167
    if (digest_size != hs->digest_size) {
383
0
        return ERR_DIGEST_SIZE;
384
0
    }
385
386
    /* remaining length of the message */
387
167
    if (add_bits(hs, hs->curlen*8)) {
388
0
        return ERR_MAX_DATA;
389
0
    }
390
391
    /* append the '1' bit */
392
    /* buf[] is guaranteed to have at least 1 byte free */
393
167
    hs->buf[hs->curlen++] = 0x80;
394
395
    /** if there are less then 64/128 bits left, just pad with zeroes and compress **/
396
167
    left = BLOCK_SIZE - hs->curlen;
397
167
    if (left < WORD_SIZE*2) {
398
63
        memset(&hs->buf[hs->curlen], 0, left);
399
63
        sha_compress(hs);
400
63
        hs->curlen = 0;
401
63
    }
402
403
    /**
404
     * pad with zeroes and close the block with the bit length
405
     * encoded as 64-bit integer big endian.
406
     **/
407
167
    left = BLOCK_SIZE - hs->curlen;
408
167
    memset(&hs->buf[hs->curlen], 0, left);
409
167
    STORE_WORD_BIG(&hs->buf[BLOCK_SIZE-(2*WORD_SIZE)], hs->totbits[1]);
410
167
    STORE_WORD_BIG(&hs->buf[BLOCK_SIZE-(  WORD_SIZE)], hs->totbits[0]);
411
412
    /** compress one last time **/
413
167
    sha_compress(hs);
414
415
    /** create final hash **/
416
1.50k
    for (i=0; i<8; i++) {
417
1.33k
        put_be(hs->h[i], &hash_tmp[i*WORD_SIZE]);
418
1.33k
    }
419
167
    memcpy(hash, hash_tmp, hs->digest_size);
420
421
167
    return 0;
422
167
}
423
424
EXPORT_SYM int FUNC_NAME(_digest)(const hash_state *shaState, uint8_t *digest, size_t digest_size)
425
167
{
426
167
    hash_state temp;
427
428
167
    if (NULL == shaState) {
429
0
        return ERR_NULL;
430
0
    }
431
432
167
    if (digest_size != shaState->digest_size) {
433
0
        return ERR_DIGEST_SIZE;
434
0
    }
435
436
167
    temp = *shaState;
437
167
    sha_finalize(&temp, digest, digest_size);
438
167
    return 0;
439
167
}
440
441
EXPORT_SYM int FUNC_NAME(_copy)(const hash_state *src, hash_state *dst)
442
0
{
443
0
    if (NULL == src || NULL == dst) {
444
0
        return ERR_NULL;
445
0
    }
446
447
0
    *dst = *src;
448
0
    return 0;
449
0
}
450
451
/**
452
 * This is a specialized function to efficiently perform the inner loop of PBKDF2-HMAC.
453
 *
454
 * - inner, the hash after the inner padded secret has been absorbed
455
 * - outer, the hash after the outer padded secret has been absorbed
456
 * - first_hmac, the output of the first HMAC iteration (with salt and counter)
457
 * - result, the XOR of the HMACs from all iterations
458
 * - iterations, the total number of PBKDF2 iterations (>0)
459
 *
460
 * This function does not change the state of either hash.
461
 */
462
EXPORT_SYM int FUNC_NAME(_pbkdf2_hmac_assist)(const hash_state *inner, const hash_state *outer,
463
                                             const uint8_t *first_hmac,
464
                                             uint8_t *result,
465
                                             size_t iterations,
466
                                             size_t digest_size)
467
0
{
468
0
    hash_state inner_temp, outer_temp;
469
0
    size_t i;
470
0
    uint8_t last_hmac[DIGEST_SIZE]; /** MAX DIGEST SIZE **/
471
472
0
    if (NULL == inner || NULL == outer || NULL == first_hmac || NULL == result) {
473
0
        return ERR_NULL;
474
0
    }
475
476
0
    if (iterations == 0) {
477
0
        return ERR_NR_ROUNDS;
478
0
    }
479
480
0
    if (digest_size != inner->digest_size || digest_size != outer->digest_size) {
481
0
        return ERR_DIGEST_SIZE;
482
0
    }
483
    
484
0
    memcpy(result, first_hmac, digest_size);
485
0
    memcpy(last_hmac, first_hmac, digest_size);
486
487
0
    for (i=1; i<iterations; i++) {
488
0
        unsigned j;
489
490
0
        inner_temp = *inner;
491
0
        outer_temp = *outer;
492
493
0
        FUNC_NAME(_update)(&inner_temp, last_hmac, digest_size);
494
0
        sha_finalize(&inner_temp, last_hmac, digest_size);
495
496
        /** last_hmac is now the intermediate digest **/
497
498
0
        FUNC_NAME(_update)(&outer_temp, last_hmac, digest_size);
499
0
        sha_finalize(&outer_temp, last_hmac, digest_size);
500
501
0
        for (j=0; j<digest_size; j++) {
502
0
            result[j] ^= last_hmac[j];
503
0
        }
504
0
    }
505
506
0
    return 0;
507
0
}
508
509
#ifdef MAIN
510
511
void initialize(hash_state **hs)
512
{
513
#if DIGEST_SIZE == (512/8)
514
    FUNC_NAME(_init)(hs, 512);
515
#else
516
    FUNC_NAME(_init)(hs);
517
#endif
518
 
519
}
520
521
int main(void)
522
{
523
    hash_state *hs;
524
    const uint8_t tv[] = "The quick brown fox jumps over the lazy dog";
525
    uint8_t result[DIGEST_SIZE];
526
    int i;
527
528
    initialize(&hs);
529
    FUNC_NAME(_update)(hs, tv, sizeof tv - 1);
530
    FUNC_NAME(_digest)(hs, result);
531
    FUNC_NAME(_destroy)(hs);
532
533
    for (i=0; i < hs->digest_size; i++) {
534
        printf("%02X", result[i]);
535
    }
536
    printf("\n");
537
538
    initialize(&hs);
539
    FUNC_NAME(_digest)(hs, result);
540
    FUNC_NAME(_destroy)(hs);
541
542
    for (i=0; i< hs->digest_size; i++) {
543
        printf("%02X", result[i]);
544
    }
545
    printf("\n");
546
547
    initialize(&hs);
548
    for (i=0; i<10000000; i++) {
549
        FUNC_NAME(_update)(hs, tv, sizeof tv - 1);
550
    }
551
    FUNC_NAME(_destroy)(hs);
552
553
    printf("\n");
554
}
555
#endif