]> pd.if.org Git - zpackage/blob - lib/blake2b.c
reindent blake2 files
[zpackage] / lib / blake2b.c
1 /*
2  * public domain blake2 implementation adapted from the reference
3  * implementation by Samuel Neves
4  * More information about the BLAKE2 hash function can be found at
5  * https://blake2.net.
6  */
7
8 #include <stdint.h>
9 #include <string.h>
10 #include <stdio.h>
11
12 #include "blake2.h"
13
14 static uint64_t load64(const void *src) {
15 #if defined(NATIVE_LITTLE_ENDIAN)
16         uint64_t w;
17         memcpy(&w, src, sizeof w);
18         return w;
19 #else
20         const uint8_t *p = (const uint8_t *) src;
21         return ((uint64_t) (p[0]) << 0) |
22             ((uint64_t) (p[1]) << 8) |
23             ((uint64_t) (p[2]) << 16) |
24             ((uint64_t) (p[3]) << 24) |
25             ((uint64_t) (p[4]) << 32) |
26             ((uint64_t) (p[5]) << 40) |
27             ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56);
28 #endif
29 }
30
31 static void store32(void *dst, uint32_t w) {
32 #if defined(NATIVE_LITTLE_ENDIAN)
33         memcpy(dst, &w, sizeof w);
34 #else
35         uint8_t *p = (uint8_t *) dst;
36         p[0] = (uint8_t) (w >> 0);
37         p[1] = (uint8_t) (w >> 8);
38         p[2] = (uint8_t) (w >> 16);
39         p[3] = (uint8_t) (w >> 24);
40 #endif
41 }
42
43 static void store64(void *dst, uint64_t w) {
44 #if defined(NATIVE_LITTLE_ENDIAN)
45         memcpy(dst, &w, sizeof w);
46 #else
47         uint8_t *p = (uint8_t *) dst;
48         p[0] = (uint8_t) (w >> 0);
49         p[1] = (uint8_t) (w >> 8);
50         p[2] = (uint8_t) (w >> 16);
51         p[3] = (uint8_t) (w >> 24);
52         p[4] = (uint8_t) (w >> 32);
53         p[5] = (uint8_t) (w >> 40);
54         p[6] = (uint8_t) (w >> 48);
55         p[7] = (uint8_t) (w >> 56);
56 #endif
57 }
58
59 static uint64_t rotr64(const uint64_t w, const unsigned c) {
60         return (w >> c) | (w << (64 - c));
61 }
62
63 /* prevents compiler optimizing out memset() */
64 static void secure_zero_memory(void *v, size_t n) {
65         static void *(*const volatile memset_v)(void *, int, size_t) =
66             &memset;
67         memset_v(v, 0, n);
68 }
69
70 static const uint64_t blake2b_IV[8] = {
71         0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
72         0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
73         0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
74         0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
75 };
76
77 static const uint8_t blake2b_sigma[12][16] = {
78         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
79         { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
80         { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
81         { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
82         { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
83         { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
84         { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
85         { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
86         { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
87         { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
88         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
89         { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
90 };
91
92
93 static void blake2b_set_lastnode(blake2b_state * S) {
94         S->f[1] = (uint64_t) - 1;
95 }
96
97 /* Some helper functions, not necessarily useful */
98 static int blake2b_is_lastblock(const blake2b_state * S) {
99         return S->f[0] != 0;
100 }
101
102 static void blake2b_set_lastblock(blake2b_state * S) {
103         if (S->last_node)
104                 blake2b_set_lastnode(S);
105
106         S->f[0] = (uint64_t) - 1;
107 }
108
109 static void blake2b_increment_counter(blake2b_state * S,
110                                       const uint64_t inc) {
111         S->t[0] += inc;
112         S->t[1] += (S->t[0] < inc);
113 }
114
115 static void blake2b_init0(blake2b_state * S) {
116         size_t i;
117         memset(S, 0, sizeof(blake2b_state));
118
119         for (i = 0; i < 8; ++i)
120                 S->h[i] = blake2b_IV[i];
121 }
122
123 /* init xors IV with input parameter block */
124 int blake2b_init_param(blake2b_state * S, const blake2b_param * P) {
125         const uint8_t *p = (const uint8_t *) (P);
126         size_t i;
127
128         blake2b_init0(S);
129
130         /* IV XOR ParamBlock */
131         for (i = 0; i < 8; ++i)
132                 S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
133
134         S->outlen = P->digest_length;
135         return 0;
136 }
137
138 int blake2b_init(blake2b_state * S, size_t outlen) {
139         blake2b_param P[1];
140
141         if ((!outlen) || (outlen > BLAKE2B_OUTBYTES))
142                 return -1;
143
144         P->digest_length = (uint8_t) outlen;
145         P->key_length = 0;
146         P->fanout = 1;
147         P->depth = 1;
148         store32(&P->leaf_length, 0);
149         store32(&P->node_offset, 0);
150         store32(&P->xof_length, 0);
151         P->node_depth = 0;
152         P->inner_length = 0;
153         memset(P->reserved, 0, sizeof(P->reserved));
154         memset(P->salt, 0, sizeof(P->salt));
155         memset(P->personal, 0, sizeof(P->personal));
156         return blake2b_init_param(S, P);
157 }
158
159 int blake2b_init_key(blake2b_state * S, size_t outlen, const void *key,
160                      size_t keylen) {
161         blake2b_param P[1];
162
163         if ((!outlen) || (outlen > BLAKE2B_OUTBYTES))
164                 return -1;
165
166         if (!key || !keylen || keylen > BLAKE2B_KEYBYTES)
167                 return -1;
168
169         P->digest_length = (uint8_t) outlen;
170         P->key_length = (uint8_t) keylen;
171         P->fanout = 1;
172         P->depth = 1;
173         store32(&P->leaf_length, 0);
174         store32(&P->node_offset, 0);
175         store32(&P->xof_length, 0);
176         P->node_depth = 0;
177         P->inner_length = 0;
178         memset(P->reserved, 0, sizeof(P->reserved));
179         memset(P->salt, 0, sizeof(P->salt));
180         memset(P->personal, 0, sizeof(P->personal));
181
182         if (blake2b_init_param(S, P) < 0)
183                 return -1;
184
185         {
186                 uint8_t block[BLAKE2B_BLOCKBYTES];
187                 memset(block, 0, BLAKE2B_BLOCKBYTES);
188                 memcpy(block, key, keylen);
189                 blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
190                 secure_zero_memory(block, BLAKE2B_BLOCKBYTES);  /* Burn the key from stack */
191         }
192         return 0;
193 }
194
195 #define G(r,i,a,b,c,d)                      \
196   do {                                      \
197     a = a + b + m[blake2b_sigma[r][2*i+0]]; \
198     d = rotr64(d ^ a, 32);                  \
199     c = c + d;                              \
200     b = rotr64(b ^ c, 24);                  \
201     a = a + b + m[blake2b_sigma[r][2*i+1]]; \
202     d = rotr64(d ^ a, 16);                  \
203     c = c + d;                              \
204     b = rotr64(b ^ c, 63);                  \
205   } while(0)
206
207 #define ROUND(r)                    \
208   do {                              \
209     G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
210     G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
211     G(r,2,v[ 2],v[ 6],v[10],v[14]); \
212     G(r,3,v[ 3],v[ 7],v[11],v[15]); \
213     G(r,4,v[ 0],v[ 5],v[10],v[15]); \
214     G(r,5,v[ 1],v[ 6],v[11],v[12]); \
215     G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
216     G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
217   } while(0)
218
219 static void blake2b_compress(blake2b_state * S,
220                              const uint8_t block[BLAKE2B_BLOCKBYTES]) {
221         uint64_t m[16];
222         uint64_t v[16];
223         size_t i;
224
225         for (i = 0; i < 16; ++i) {
226                 m[i] = load64(block + i * sizeof(m[i]));
227         }
228
229         for (i = 0; i < 8; ++i) {
230                 v[i] = S->h[i];
231         }
232
233         v[8] = blake2b_IV[0];
234         v[9] = blake2b_IV[1];
235         v[10] = blake2b_IV[2];
236         v[11] = blake2b_IV[3];
237         v[12] = blake2b_IV[4] ^ S->t[0];
238         v[13] = blake2b_IV[5] ^ S->t[1];
239         v[14] = blake2b_IV[6] ^ S->f[0];
240         v[15] = blake2b_IV[7] ^ S->f[1];
241
242         ROUND(0);
243         ROUND(1);
244         ROUND(2);
245         ROUND(3);
246         ROUND(4);
247         ROUND(5);
248         ROUND(6);
249         ROUND(7);
250         ROUND(8);
251         ROUND(9);
252         ROUND(10);
253         ROUND(11);
254
255         for (i = 0; i < 8; ++i) {
256                 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
257         }
258 }
259
260 #undef G
261 #undef ROUND
262
263 int blake2b_update(blake2b_state * S, const void *pin, size_t inlen) {
264         const unsigned char *in = (const unsigned char *) pin;
265         if (inlen > 0) {
266                 size_t left = S->buflen;
267                 size_t fill = BLAKE2B_BLOCKBYTES - left;
268                 if (inlen > fill) {
269                         S->buflen = 0;
270                         memcpy(S->buf + left, in, fill);        /* Fill buffer */
271                         blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
272                         blake2b_compress(S, S->buf);    /* Compress */
273                         in += fill;
274                         inlen -= fill;
275                         while (inlen > BLAKE2B_BLOCKBYTES) {
276                                 blake2b_increment_counter(S,
277                                                           BLAKE2B_BLOCKBYTES);
278                                 blake2b_compress(S, in);
279                                 in += BLAKE2B_BLOCKBYTES;
280                                 inlen -= BLAKE2B_BLOCKBYTES;
281                         }
282                 }
283                 memcpy(S->buf + S->buflen, in, inlen);
284                 S->buflen += inlen;
285         }
286         return 0;
287 }
288
289 int blake2b_final(blake2b_state * S, void *out, size_t outlen) {
290         uint8_t buffer[BLAKE2B_OUTBYTES] = { 0 };
291         size_t i;
292
293         if (out == NULL || outlen < S->outlen)
294                 return -1;
295
296         if (blake2b_is_lastblock(S))
297                 return -1;
298
299         blake2b_increment_counter(S, S->buflen);
300         blake2b_set_lastblock(S);
301         memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen);  /* Padding */
302         blake2b_compress(S, S->buf);
303
304         for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */
305                 store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
306
307         memcpy(out, buffer, S->outlen);
308         secure_zero_memory(buffer, sizeof(buffer));
309         return 0;
310 }
311
312 /* inlen, at least, should be uint64_t. Others can be size_t. */
313 int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
314             const void *key, size_t keylen) {
315         blake2b_state S[1];
316
317         /* Verify parameters */
318         if (NULL == in && inlen > 0)
319                 return -1;
320
321         if (NULL == out)
322                 return -1;
323
324         if (NULL == key && keylen > 0)
325                 return -1;
326
327         if (!outlen || outlen > BLAKE2B_OUTBYTES)
328                 return -1;
329
330         if (keylen > BLAKE2B_KEYBYTES)
331                 return -1;
332
333         if (keylen > 0) {
334                 if (blake2b_init_key(S, outlen, key, keylen) < 0)
335                         return -1;
336         } else {
337                 if (blake2b_init(S, outlen) < 0)
338                         return -1;
339         }
340
341         blake2b_update(S, (const uint8_t *) in, inlen);
342         blake2b_final(S, out, outlen);
343         return 0;
344 }
345
346 int blake2(void *out, size_t outlen, const void *in, size_t inlen,
347            const void *key, size_t keylen) {
348         return blake2b(out, outlen, in, inlen, key, keylen);
349 }