Line data Source code
1 : /*
2 : * Copyright (c) 2020 Doc.ai and/or its affiliates.
3 : * Copyright (c) 2012 Samuel Neves <sneves@dei.uc.pt>.
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 : /*
17 : More information about the BLAKE2 hash function can be found at
18 : https://blake2.net.
19 : */
20 :
21 : #include <stdint.h>
22 : #include <string.h>
23 : #include <stdio.h>
24 :
25 : #include <wireguard/blake/blake2s.h>
26 : #include "blake2-impl.h"
27 :
28 : static const uint32_t blake2s_IV[8] = {
29 : 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
30 : 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
31 : };
32 :
33 : static const uint8_t blake2s_sigma[10][16] = {
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 : };
45 :
46 : static void
47 0 : blake2s_set_lastnode (blake2s_state_t * S)
48 : {
49 0 : S->f[1] = (uint32_t) - 1;
50 0 : }
51 :
52 : /* Some helper functions, not necessarily useful */
53 : static int
54 6855 : blake2s_is_lastblock (const blake2s_state_t * S)
55 : {
56 6855 : return S->f[0] != 0;
57 : }
58 :
59 : static void
60 6855 : blake2s_set_lastblock (blake2s_state_t * S)
61 : {
62 6855 : if (S->last_node)
63 0 : blake2s_set_lastnode (S);
64 :
65 6855 : S->f[0] = (uint32_t) - 1;
66 6855 : }
67 :
68 : static void
69 10989 : blake2s_increment_counter (blake2s_state_t * S, const uint32_t inc)
70 : {
71 10989 : S->t[0] += inc;
72 10989 : S->t[1] += (S->t[0] < inc);
73 10989 : }
74 :
75 : static void
76 6855 : blake2s_init0 (blake2s_state_t * S)
77 : {
78 : size_t i;
79 6855 : memset (S, 0, sizeof (blake2s_state_t));
80 :
81 61695 : for (i = 0; i < 8; ++i)
82 54840 : S->h[i] = blake2s_IV[i];
83 6855 : }
84 :
85 : /* init2 xors IV with input parameter block */
86 : int
87 6855 : blake2s_init_param (blake2s_state_t * S, const blake2s_param_t * P)
88 : {
89 6855 : const unsigned char *p = (const unsigned char *) (P);
90 : size_t i;
91 :
92 6855 : blake2s_init0 (S);
93 :
94 : /* IV XOR ParamBlock */
95 61695 : for (i = 0; i < 8; ++i)
96 54840 : S->h[i] ^= load32 (&p[i * 4]);
97 :
98 6855 : S->outlen = P->digest_length;
99 6855 : return 0;
100 : }
101 :
102 :
103 : /* Sequential blake2s initialization */
104 : int
105 5432 : blake2s_init (blake2s_state_t * S, size_t outlen)
106 : {
107 : blake2s_param_t P[1];
108 :
109 : /* Move interval verification here? */
110 5432 : if ((!outlen) || (outlen > BLAKE2S_OUT_BYTES))
111 0 : return -1;
112 :
113 5432 : P->digest_length = (uint8_t) outlen;
114 5432 : P->key_length = 0;
115 5432 : P->fanout = 1;
116 5432 : P->depth = 1;
117 5432 : store32 (&P->leaf_length, 0);
118 5432 : store32 (&P->node_offset, 0);
119 5432 : store16 (&P->xof_length, 0);
120 5432 : P->node_depth = 0;
121 5432 : P->inner_length = 0;
122 : /* memset(P->reserved, 0, sizeof(P->reserved) ); */
123 5432 : memset (P->salt, 0, sizeof (P->salt));
124 5432 : memset (P->personal, 0, sizeof (P->personal));
125 5432 : return blake2s_init_param (S, P);
126 : }
127 :
128 : int
129 1423 : blake2s_init_key (blake2s_state_t * S, size_t outlen, const void *key,
130 : size_t keylen)
131 : {
132 : blake2s_param_t P[1];
133 :
134 1423 : if ((!outlen) || (outlen > BLAKE2S_OUT_BYTES))
135 0 : return -1;
136 :
137 1423 : if (!key || !keylen || keylen > BLAKE2S_KEY_BYTES)
138 0 : return -1;
139 :
140 1423 : P->digest_length = (uint8_t) outlen;
141 1423 : P->key_length = (uint8_t) keylen;
142 1423 : P->fanout = 1;
143 1423 : P->depth = 1;
144 1423 : store32 (&P->leaf_length, 0);
145 1423 : store32 (&P->node_offset, 0);
146 1423 : store16 (&P->xof_length, 0);
147 1423 : P->node_depth = 0;
148 1423 : P->inner_length = 0;
149 : /* memset(P->reserved, 0, sizeof(P->reserved) ); */
150 1423 : memset (P->salt, 0, sizeof (P->salt));
151 1423 : memset (P->personal, 0, sizeof (P->personal));
152 :
153 1423 : if (blake2s_init_param (S, P) < 0)
154 0 : return -1;
155 :
156 : {
157 : uint8_t block[BLAKE2S_BLOCK_BYTES];
158 1423 : memset (block, 0, BLAKE2S_BLOCK_BYTES);
159 1423 : memcpy (block, key, keylen);
160 1423 : blake2s_update (S, block, BLAKE2S_BLOCK_BYTES);
161 1423 : secure_zero_memory (block, BLAKE2S_BLOCK_BYTES); /* Burn the key from stack */
162 : }
163 1423 : return 0;
164 : }
165 :
166 : #define G(r,i,a,b,c,d) \
167 : do { \
168 : a = a + b + m[blake2s_sigma[r][2*i+0]]; \
169 : d = rotr32(d ^ a, 16); \
170 : c = c + d; \
171 : b = rotr32(b ^ c, 12); \
172 : a = a + b + m[blake2s_sigma[r][2*i+1]]; \
173 : d = rotr32(d ^ a, 8); \
174 : c = c + d; \
175 : b = rotr32(b ^ c, 7); \
176 : } while(0)
177 :
178 : #define ROUND(r) \
179 : do { \
180 : G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
181 : G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
182 : G(r,2,v[ 2],v[ 6],v[10],v[14]); \
183 : G(r,3,v[ 3],v[ 7],v[11],v[15]); \
184 : G(r,4,v[ 0],v[ 5],v[10],v[15]); \
185 : G(r,5,v[ 1],v[ 6],v[11],v[12]); \
186 : G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
187 : G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
188 : } while(0)
189 :
190 : static void
191 10989 : blake2s_compress (blake2s_state_t * S, const uint8_t in[BLAKE2S_BLOCK_BYTES])
192 : {
193 : uint32_t m[16];
194 : uint32_t v[16];
195 : size_t i;
196 :
197 186813 : for (i = 0; i < 16; ++i)
198 : {
199 175824 : m[i] = load32 (in + i * sizeof (m[i]));
200 : }
201 :
202 98901 : for (i = 0; i < 8; ++i)
203 : {
204 87912 : v[i] = S->h[i];
205 : }
206 :
207 10989 : v[8] = blake2s_IV[0];
208 10989 : v[9] = blake2s_IV[1];
209 10989 : v[10] = blake2s_IV[2];
210 10989 : v[11] = blake2s_IV[3];
211 10989 : v[12] = S->t[0] ^ blake2s_IV[4];
212 10989 : v[13] = S->t[1] ^ blake2s_IV[5];
213 10989 : v[14] = S->f[0] ^ blake2s_IV[6];
214 10989 : v[15] = S->f[1] ^ blake2s_IV[7];
215 :
216 10989 : ROUND (0);
217 10989 : ROUND (1);
218 10989 : ROUND (2);
219 10989 : ROUND (3);
220 10989 : ROUND (4);
221 10989 : ROUND (5);
222 10989 : ROUND (6);
223 10989 : ROUND (7);
224 10989 : ROUND (8);
225 10989 : ROUND (9);
226 :
227 98901 : for (i = 0; i < 8; ++i)
228 : {
229 87912 : S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
230 : }
231 10989 : }
232 :
233 : #undef G
234 : #undef ROUND
235 :
236 : int
237 13221 : blake2s_update (blake2s_state_t * S, const void *pin, size_t inlen)
238 : {
239 13221 : const unsigned char *in = (const unsigned char *) pin;
240 13221 : if (inlen > 0)
241 : {
242 13221 : size_t left = S->buflen;
243 13221 : size_t fill = BLAKE2S_BLOCK_BYTES - left;
244 13221 : if (inlen > fill)
245 : {
246 3123 : S->buflen = 0;
247 3123 : memcpy (S->buf + left, in, fill); /* Fill buffer */
248 3123 : blake2s_increment_counter (S, BLAKE2S_BLOCK_BYTES);
249 3123 : blake2s_compress (S, S->buf); /* Compress */
250 3123 : in += fill;
251 3123 : inlen -= fill;
252 4134 : while (inlen > BLAKE2S_BLOCK_BYTES)
253 : {
254 1011 : blake2s_increment_counter (S, BLAKE2S_BLOCK_BYTES);
255 1011 : blake2s_compress (S, in);
256 1011 : in += BLAKE2S_BLOCK_BYTES;
257 1011 : inlen -= BLAKE2S_BLOCK_BYTES;
258 : }
259 : }
260 13221 : memcpy (S->buf + S->buflen, in, inlen);
261 13221 : S->buflen += inlen;
262 : }
263 13221 : return 0;
264 : }
265 :
266 : int
267 6855 : blake2s_final (blake2s_state_t * S, void *out, size_t outlen)
268 : {
269 6855 : uint8_t buffer[BLAKE2S_OUT_BYTES] = { 0 };
270 : size_t i;
271 :
272 6855 : if (out == NULL || outlen < S->outlen)
273 0 : return -1;
274 :
275 6855 : if (blake2s_is_lastblock (S))
276 0 : return -1;
277 :
278 6855 : blake2s_increment_counter (S, (uint32_t) S->buflen);
279 6855 : blake2s_set_lastblock (S);
280 6855 : memset (S->buf + S->buflen, 0, BLAKE2S_BLOCK_BYTES - S->buflen); /* Padding */
281 6855 : blake2s_compress (S, S->buf);
282 :
283 61695 : for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */
284 54840 : store32 (buffer + sizeof (S->h[i]) * i, S->h[i]);
285 :
286 6855 : memcpy (out, buffer, outlen);
287 6855 : secure_zero_memory (buffer, sizeof (buffer));
288 6855 : return 0;
289 : }
290 :
291 : int
292 785 : blake2s (void *out, size_t outlen, const void *in, size_t inlen,
293 : const void *key, size_t keylen)
294 : {
295 : blake2s_state_t S[1];
296 :
297 : /* Verify parameters */
298 785 : if (NULL == in && inlen > 0)
299 0 : return -1;
300 :
301 785 : if (NULL == out)
302 0 : return -1;
303 :
304 785 : if (NULL == key && keylen > 0)
305 0 : return -1;
306 :
307 785 : if (!outlen || outlen > BLAKE2S_OUT_BYTES)
308 0 : return -1;
309 :
310 785 : if (keylen > BLAKE2S_KEY_BYTES)
311 0 : return -1;
312 :
313 785 : if (keylen > 0)
314 : {
315 0 : if (blake2s_init_key (S, outlen, key, keylen) < 0)
316 0 : return -1;
317 : }
318 : else
319 : {
320 785 : if (blake2s_init (S, outlen) < 0)
321 0 : return -1;
322 : }
323 :
324 785 : blake2s_update (S, (const uint8_t *) in, inlen);
325 785 : blake2s_final (S, out, outlen);
326 785 : return 0;
327 : }
328 :
329 : /*
330 : * fd.io coding-style-patch-verification: ON
331 : *
332 : * Local Variables:
333 : * eval: (c-set-style "gnu")
334 : * End:
335 : */
|