Project Alice
Loading...
Searching...
No Matches
blake2.c
Go to the documentation of this file.
1
2/*
3 BLAKE2 reference source code package - reference C implementations
4
5 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
6 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
7 your option. The terms of these licenses can be found at:
8
9 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
10 - OpenSSL license : https://www.openssl.org/source/license.html
11 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
12
13 More information about the BLAKE2 hash function can be found at
14 https://blake2.net.
15*/
16
17#include <stdint.h>
18#include <string.h>
19#include <stdio.h>
20
21#include "blake2.h"
22#include "blake2-impl.h"
23
24static const uint64_t blake2b_IV[8] =
25{
26 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
27 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
28 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
29 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
30};
31
32static const uint8_t blake2b_sigma[12][16] =
33{
34 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
35 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
36 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
37 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
38 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
39 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
40 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
41 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
42 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
43 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
44 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
45 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
46};
47
48
49static void blake2b_set_lastnode(blake2b_state* S) {
50 S->f[1] = (uint64_t)-1;
51}
52
53/* Some helper functions, not necessarily useful */
54static int blake2b_is_lastblock(const blake2b_state* S) {
55 return S->f[0] != 0;
56}
57
58static void blake2b_set_lastblock(blake2b_state* S) {
59 if(S->last_node) blake2b_set_lastnode(S);
60
61 S->f[0] = (uint64_t)-1;
62}
63
64static void blake2b_increment_counter(blake2b_state* S, const uint64_t inc) {
65 S->t[0] += inc;
66 S->t[1] += (S->t[0] < inc);
67}
68
69static void blake2b_init0(blake2b_state* S) {
70 size_t i;
71 memset(S, 0, sizeof(blake2b_state));
72
73 for(i = 0; i < 8; ++i) S->h[i] = blake2b_IV[i];
74}
75
76/* init xors IV with input parameter block */
78 const uint8_t* p = (const uint8_t*)(P);
79 size_t i;
80
81 blake2b_init0(S);
82
83 /* IV XOR ParamBlock */
84 for(i = 0; i < 8; ++i)
85 S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
86
87 S->outlen = P->digest_length;
88 return 0;
89}
90
91int blake2b_init(blake2b_state* S, size_t outlen) {
92 blake2b_param P[1];
93
94 if((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1;
95
96 P->digest_length = (uint8_t)outlen;
97 P->key_length = 0;
98 P->fanout = 1;
99 P->depth = 1;
100 store32(&P->leaf_length, 0);
101 store32(&P->node_offset, 0);
102 store32(&P->xof_length, 0);
103 P->node_depth = 0;
104 P->inner_length = 0;
105 memset(P->reserved, 0, sizeof(P->reserved));
106 memset(P->salt, 0, sizeof(P->salt));
107 memset(P->personal, 0, sizeof(P->personal));
108 return blake2b_init_param(S, P);
109}
110
111
112int blake2b_init_key(blake2b_state* S, size_t outlen, const void* key, size_t keylen) {
113 blake2b_param P[1];
114
115 if((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1;
116
117 if(!key || !keylen || keylen > BLAKE2B_KEYBYTES) return -1;
118
119 P->digest_length = (uint8_t)outlen;
120 P->key_length = (uint8_t)keylen;
121 P->fanout = 1;
122 P->depth = 1;
123 store32(&P->leaf_length, 0);
124 store32(&P->node_offset, 0);
125 store32(&P->xof_length, 0);
126 P->node_depth = 0;
127 P->inner_length = 0;
128 memset(P->reserved, 0, sizeof(P->reserved));
129 memset(P->salt, 0, sizeof(P->salt));
130 memset(P->personal, 0, sizeof(P->personal));
131
132 if(blake2b_init_param(S, P) < 0) return -1;
133
134 {
136 memset(block, 0, BLAKE2B_BLOCKBYTES);
137 memcpy(block, key, keylen);
139 secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
140 }
141 return 0;
142}
143
144#define G(r,i,a,b,c,d) \
145 do { \
146 a = a + b + m[blake2b_sigma[r][2*i+0]]; \
147 d = rotr64(d ^ a, 32); \
148 c = c + d; \
149 b = rotr64(b ^ c, 24); \
150 a = a + b + m[blake2b_sigma[r][2*i+1]]; \
151 d = rotr64(d ^ a, 16); \
152 c = c + d; \
153 b = rotr64(b ^ c, 63); \
154 } while(0)
155
156#define ROUND(r) \
157 do { \
158 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
159 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
160 G(r,2,v[ 2],v[ 6],v[10],v[14]); \
161 G(r,3,v[ 3],v[ 7],v[11],v[15]); \
162 G(r,4,v[ 0],v[ 5],v[10],v[15]); \
163 G(r,5,v[ 1],v[ 6],v[11],v[12]); \
164 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
165 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
166 } while(0)
167
168static void blake2b_compress(blake2b_state* S, const uint8_t block[BLAKE2B_BLOCKBYTES]) {
169 uint64_t m[16];
170 uint64_t v[16];
171 size_t i;
172
173 for(i = 0; i < 16; ++i) {
174 m[i] = load64(block + i * sizeof(m[i]));
175 }
176
177 for(i = 0; i < 8; ++i) {
178 v[i] = S->h[i];
179 }
180
181 v[8] = blake2b_IV[0];
182 v[9] = blake2b_IV[1];
183 v[10] = blake2b_IV[2];
184 v[11] = blake2b_IV[3];
185 v[12] = blake2b_IV[4] ^ S->t[0];
186 v[13] = blake2b_IV[5] ^ S->t[1];
187 v[14] = blake2b_IV[6] ^ S->f[0];
188 v[15] = blake2b_IV[7] ^ S->f[1];
189
190 ROUND(0);
191 ROUND(1);
192 ROUND(2);
193 ROUND(3);
194 ROUND(4);
195 ROUND(5);
196 ROUND(6);
197 ROUND(7);
198 ROUND(8);
199 ROUND(9);
200 ROUND(10);
201 ROUND(11);
202
203 for(i = 0; i < 8; ++i) {
204 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
205 }
206}
207
208#undef G
209#undef ROUND
210
211int blake2b_update(blake2b_state* S, const void* pin, size_t inlen) {
212 const unsigned char* in = (const unsigned char*)pin;
213 if(inlen > 0) {
214 size_t left = S->buflen;
215 size_t fill = BLAKE2B_BLOCKBYTES - left;
216 if(inlen > fill) {
217 S->buflen = 0;
218 memcpy(S->buf + left, in, fill); /* Fill buffer */
219 blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
220 blake2b_compress(S, S->buf); /* Compress */
221 in += fill; inlen -= fill;
222 while(inlen > BLAKE2B_BLOCKBYTES) {
223 blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
224 blake2b_compress(S, in);
225 in += BLAKE2B_BLOCKBYTES;
226 inlen -= BLAKE2B_BLOCKBYTES;
227 }
228 }
229 memcpy(S->buf + S->buflen, in, inlen);
230 S->buflen += inlen;
231 }
232 return 0;
233}
234
235int blake2b_final(blake2b_state* S, void* out, size_t outlen) {
236 uint8_t buffer[BLAKE2B_OUTBYTES] = { 0 };
237 size_t i;
238
239 if(out == NULL || outlen < S->outlen)
240 return -1;
241
242 if(blake2b_is_lastblock(S))
243 return -1;
244
245 blake2b_increment_counter(S, S->buflen);
246 blake2b_set_lastblock(S);
247 memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
248 blake2b_compress(S, S->buf);
249
250 for(i = 0; i < 8; ++i) /* Output full hash to temp buffer */
251 store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
252
253 memcpy(out, buffer, S->outlen);
254 secure_zero_memory(buffer, sizeof(buffer));
255 return 0;
256}
257
258/* inlen, at least, should be uint64_t. Others can be size_t. */
259int blake2b(void* out, size_t outlen, const void* in, size_t inlen, const void* key, size_t keylen) {
260 blake2b_state S[1];
261
262 /* Verify parameters */
263 if(NULL == in && inlen > 0) return -1;
264
265 if(NULL == out) return -1;
266
267 if(NULL == key && keylen > 0) return -1;
268
269 if(!outlen || outlen > BLAKE2B_OUTBYTES) return -1;
270
271 if(keylen > BLAKE2B_KEYBYTES) return -1;
272
273 if(keylen > 0) {
274 if(blake2b_init_key(S, outlen, key, keylen) < 0) return -1;
275 } else {
276 if(blake2b_init(S, outlen) < 0) return -1;
277 }
278
279 blake2b_update(S, (const uint8_t*)in, inlen);
280 blake2b_final(S, out, outlen);
281 return 0;
282}
283
284int blake2(void* out, size_t outlen, const void* in, size_t inlen, const void* key, size_t keylen) {
285 return blake2b(out, outlen, in, inlen, key, keylen);
286}
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen)
Definition: blake2.c:112
int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
Definition: blake2.c:259
int blake2b_update(blake2b_state *S, const void *pin, size_t inlen)
Definition: blake2.c:211
int blake2b_init(blake2b_state *S, size_t outlen)
Definition: blake2.c:91
int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
Definition: blake2.c:284
#define ROUND(r)
Definition: blake2.c:156
int blake2b_final(blake2b_state *S, void *out, size_t outlen)
Definition: blake2.c:235
int blake2b_init_param(blake2b_state *S, const blake2b_param *P)
Definition: blake2.c:77
struct blake2b_param__ blake2b_param
Definition: blake2.h:116
@ BLAKE2B_KEYBYTES
Definition: blake2.h:42
@ BLAKE2B_OUTBYTES
Definition: blake2.h:41
@ BLAKE2B_BLOCKBYTES
Definition: blake2.h:40
ulong uint64_t
uchar uint8_t