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
23.2M
#define CH(x,y,z)       (((x) & (y)) ^ (~(x) & (z)))
45
23.2M
#define MAJ(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
46
47
209M
#define ROTR32(n, x)    (((x)>>(n)) | ((x)<<(32-(n))))
48
#define ROTR64(n, x)    (((x)>>(n)) | ((x)<<(64-(n))))
49
34.8M
#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
17.8M
#define SCHEDULE_SIZE 64
58
1.09M
#define BLOCK_SIZE 64
59
60
23.2M
#define SIGMA_0_256(x)    (ROTR32(2,x)  ^ ROTR32(13,x) ^ ROTR32(22,x))
61
23.2M
#define SIGMA_1_256(x)    (ROTR32(6,x)  ^ ROTR32(11,x) ^ ROTR32(25,x))
62
17.4M
#define sigma_0_256(x)    (ROTR32(7,x)  ^ ROTR32(18,x) ^ SHR(3,x))
63
17.4M
#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
17.4M
#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
23.2M
    h += SIGMA_1_256(e) + CH(e,f,g) + K[t]  + W[t]; \
85
23.2M
    d += h; \
86
23.2M
    h += SIGMA_0_256(a) + MAJ(a,b,c);
87
88
5.81M
#define LOAD_WORD_BIG(p)        LOAD_U32_BIG(p)
89
342
#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.36k
{
144
1.36k
    int i;
145
146
6.84k
    for (i=0; i<WORD_SIZE; i++) {
147
5.47k
        p[WORD_SIZE-1-i] = (uint8_t)(number >> (i*8));
148
5.47k
    }
149
1.36k
}
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
363k
{
161
363k
    hs->totbits[0] += bits;
162
363k
    if (hs->totbits[0] >= bits) {
163
363k
        return 0;
164
363k
    }
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
363k
{
177
363k
    sha2_word_t a, b, c, d, e, f, g, h;
178
363k
    sha2_word_t W[SCHEDULE_SIZE];
179
363k
    int i;
180
181
    /** Words flow in in big-endian mode **/
182
6.17M
    for (i=0; i<16; i++) {
183
5.81M
        W[i] = LOAD_WORD_BIG(&hs->buf[i*WORD_SIZE]);
184
5.81M
    }
185
17.8M
    for (;i<SCHEDULE_SIZE; i++) {
186
17.4M
        W[i] = SCHEDULE(i);
187
17.4M
    }
188
189
363k
    a = hs->h[0];
190
363k
    b = hs->h[1];
191
363k
    c = hs->h[2];
192
363k
    d = hs->h[3];
193
363k
    e = hs->h[4];
194
363k
    f = hs->h[5];
195
363k
    g = hs->h[6];
196
363k
    h = hs->h[7];
197
198
363k
    CYCLE(a,b,c,d,e,f,g,h, 0);
199
363k
    CYCLE(h,a,b,c,d,e,f,g, 1);
200
363k
    CYCLE(g,h,a,b,c,d,e,f, 2);
201
363k
    CYCLE(f,g,h,a,b,c,d,e, 3);
202
363k
    CYCLE(e,f,g,h,a,b,c,d, 4);
203
363k
    CYCLE(d,e,f,g,h,a,b,c, 5);
204
363k
    CYCLE(c,d,e,f,g,h,a,b, 6);
205
363k
    CYCLE(b,c,d,e,f,g,h,a, 7);
206
363k
    CYCLE(a,b,c,d,e,f,g,h, 8);
207
363k
    CYCLE(h,a,b,c,d,e,f,g, 9);
208
363k
    CYCLE(g,h,a,b,c,d,e,f, 10);
209
363k
    CYCLE(f,g,h,a,b,c,d,e, 11);
210
363k
    CYCLE(e,f,g,h,a,b,c,d, 12);
211
363k
    CYCLE(d,e,f,g,h,a,b,c, 13);
212
363k
    CYCLE(c,d,e,f,g,h,a,b, 14);
213
363k
    CYCLE(b,c,d,e,f,g,h,a, 15);
214
363k
    CYCLE(a,b,c,d,e,f,g,h, 16);
215
363k
    CYCLE(h,a,b,c,d,e,f,g, 17);
216
363k
    CYCLE(g,h,a,b,c,d,e,f, 18);
217
363k
    CYCLE(f,g,h,a,b,c,d,e, 19);
218
363k
    CYCLE(e,f,g,h,a,b,c,d, 20);
219
363k
    CYCLE(d,e,f,g,h,a,b,c, 21);
220
363k
    CYCLE(c,d,e,f,g,h,a,b, 22);
221
363k
    CYCLE(b,c,d,e,f,g,h,a, 23);
222
363k
    CYCLE(a,b,c,d,e,f,g,h, 24);
223
363k
    CYCLE(h,a,b,c,d,e,f,g, 25);
224
363k
    CYCLE(g,h,a,b,c,d,e,f, 26);
225
363k
    CYCLE(f,g,h,a,b,c,d,e, 27);
226
363k
    CYCLE(e,f,g,h,a,b,c,d, 28);
227
363k
    CYCLE(d,e,f,g,h,a,b,c, 29);
228
363k
    CYCLE(c,d,e,f,g,h,a,b, 30);
229
363k
    CYCLE(b,c,d,e,f,g,h,a, 31);
230
363k
    CYCLE(a,b,c,d,e,f,g,h, 32);
231
363k
    CYCLE(h,a,b,c,d,e,f,g, 33);
232
363k
    CYCLE(g,h,a,b,c,d,e,f, 34);
233
363k
    CYCLE(f,g,h,a,b,c,d,e, 35);
234
363k
    CYCLE(e,f,g,h,a,b,c,d, 36);
235
363k
    CYCLE(d,e,f,g,h,a,b,c, 37);
236
363k
    CYCLE(c,d,e,f,g,h,a,b, 38);
237
363k
    CYCLE(b,c,d,e,f,g,h,a, 39);
238
363k
    CYCLE(a,b,c,d,e,f,g,h, 40);
239
363k
    CYCLE(h,a,b,c,d,e,f,g, 41);
240
363k
    CYCLE(g,h,a,b,c,d,e,f, 42);
241
363k
    CYCLE(f,g,h,a,b,c,d,e, 43);
242
363k
    CYCLE(e,f,g,h,a,b,c,d, 44);
243
363k
    CYCLE(d,e,f,g,h,a,b,c, 45);
244
363k
    CYCLE(c,d,e,f,g,h,a,b, 46);
245
363k
    CYCLE(b,c,d,e,f,g,h,a, 47);
246
363k
    CYCLE(a,b,c,d,e,f,g,h, 48);
247
363k
    CYCLE(h,a,b,c,d,e,f,g, 49);
248
363k
    CYCLE(g,h,a,b,c,d,e,f, 50);
249
363k
    CYCLE(f,g,h,a,b,c,d,e, 51);
250
363k
    CYCLE(e,f,g,h,a,b,c,d, 52);
251
363k
    CYCLE(d,e,f,g,h,a,b,c, 53);
252
363k
    CYCLE(c,d,e,f,g,h,a,b, 54);
253
363k
    CYCLE(b,c,d,e,f,g,h,a, 55);
254
363k
    CYCLE(a,b,c,d,e,f,g,h, 56);
255
363k
    CYCLE(h,a,b,c,d,e,f,g, 57);
256
363k
    CYCLE(g,h,a,b,c,d,e,f, 58);
257
363k
    CYCLE(f,g,h,a,b,c,d,e, 59);
258
363k
    CYCLE(e,f,g,h,a,b,c,d, 60);
259
363k
    CYCLE(d,e,f,g,h,a,b,c, 61);
260
363k
    CYCLE(c,d,e,f,g,h,a,b, 62);
261
363k
    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
363k
    hs->h[0] += a;
284
363k
    hs->h[1] += b;
285
363k
    hs->h[2] += c;
286
363k
    hs->h[3] += d;
287
363k
    hs->h[4] += e;
288
363k
    hs->h[5] += f;
289
363k
    hs->h[6] += g;
290
363k
    hs->h[7] += h;
291
363k
}
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
337
{
299
337
    hash_state *hs;
300
337
    int i;
301
#if DIGEST_SIZE == (512/8)
302
    size_t variant;
303
#endif
304
305
337
    if (NULL == shaState) {
306
0
        return ERR_NULL;
307
0
    }
308
309
337
    *shaState = hs = (hash_state*) calloc(1, sizeof(hash_state));
310
337
    if (NULL == hs)
311
0
        return ERR_MEMORY;
312
313
337
    hs->curlen = 0;
314
337
    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
337
    hs->digest_size = DIGEST_SIZE;
333
3.03k
    for (i=0; i<8; i++) {
334
2.69k
        hs->h[i] = H[i];
335
2.69k
    }
336
337
#endif
337
338
337
    return 0;
339
337
}
340
341
EXPORT_SYM int FUNC_NAME(_destroy)(hash_state *shaState)
342
337
{
343
337
    free(shaState);
344
337
    return 0;
345
337
}
346
347
EXPORT_SYM int FUNC_NAME(_update)(hash_state *hs, const uint8_t *buf, size_t len)
348
1.53k
{
349
1.53k
    if (NULL == hs || NULL == buf) {
350
166
        return ERR_NULL;
351
166
    }
352
353
1.36k
    assert(hs->curlen < BLOCK_SIZE);
354
355
365k
    while (len>0) {
356
364k
        unsigned btc, left;
357
358
364k
        left = BLOCK_SIZE - hs->curlen;
359
364k
        btc = (unsigned)MIN(left, len);
360
364k
        memcpy(&hs->buf[hs->curlen], buf, btc);
361
364k
        buf += btc;
362
364k
        hs->curlen += btc;
363
364k
        len -= btc;
364
365
364k
        if (hs->curlen == BLOCK_SIZE) {
366
363k
            sha_compress(hs);
367
363k
            hs->curlen = 0;
368
363k
            if (add_bits(hs, BLOCK_SIZE*8)) {
369
0
                return ERR_MAX_DATA;
370
0
            }
371
363k
        }
372
364k
    }
373
374
1.36k
    return 0;
375
1.36k
}
376
377
static int sha_finalize(hash_state *hs, uint8_t *hash, size_t digest_size)
378
171
{
379
171
    unsigned left, i;
380
171
    uint8_t hash_tmp[WORD_SIZE*8];
381
382
171
    if (digest_size != hs->digest_size) {
383
0
        return ERR_DIGEST_SIZE;
384
0
    }
385
386
    /* remaining length of the message */
387
171
    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
171
    hs->buf[hs->curlen++] = 0x80;
394
395
    /** if there are less then 64/128 bits left, just pad with zeroes and compress **/
396
171
    left = BLOCK_SIZE - hs->curlen;
397
171
    if (left < WORD_SIZE*2) {
398
65
        memset(&hs->buf[hs->curlen], 0, left);
399
65
        sha_compress(hs);
400
65
        hs->curlen = 0;
401
65
    }
402
403
    /**
404
     * pad with zeroes and close the block with the bit length
405
     * encoded as 64-bit integer big endian.
406
     **/
407
171
    left = BLOCK_SIZE - hs->curlen;
408
171
    memset(&hs->buf[hs->curlen], 0, left);
409
171
    STORE_WORD_BIG(&hs->buf[BLOCK_SIZE-(2*WORD_SIZE)], hs->totbits[1]);
410
171
    STORE_WORD_BIG(&hs->buf[BLOCK_SIZE-(  WORD_SIZE)], hs->totbits[0]);
411
412
    /** compress one last time **/
413
171
    sha_compress(hs);
414
415
    /** create final hash **/
416
1.53k
    for (i=0; i<8; i++) {
417
1.36k
        put_be(hs->h[i], &hash_tmp[i*WORD_SIZE]);
418
1.36k
    }
419
171
    memcpy(hash, hash_tmp, hs->digest_size);
420
421
171
    return 0;
422
171
}
423
424
EXPORT_SYM int FUNC_NAME(_digest)(const hash_state *shaState, uint8_t *digest, size_t digest_size)
425
171
{
426
171
    hash_state temp;
427
428
171
    if (NULL == shaState) {
429
0
        return ERR_NULL;
430
0
    }
431
432
171
    if (digest_size != shaState->digest_size) {
433
0
        return ERR_DIGEST_SIZE;
434
0
    }
435
436
171
    temp = *shaState;
437
171
    sha_finalize(&temp, digest, digest_size);
438
171
    return 0;
439
171
}
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