1 /* ===================================================================
2 *
3 * Copyright (c) 2014, Legrandin <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 #define WORDS_IN_BLOCK 16
37 #define WORDS_IN_STATE 8
38 #define BLOCK_SIZE (WORDS_IN_BLOCK*BLAKE2_WORD_SIZE/8)
39
40 typedef struct {
41 blake2_word h[WORDS_IN_STATE];
42 blake2_word off_counter_low;
43 blake2_word off_counter_high;
44 unsigned buf_occ;
45 uint8_t buf[BLOCK_SIZE];
46 } hash_state;
47
48 typedef enum { NON_FINAL_BLOCK, FINAL_BLOCK } block_type;
49
blake2_init(hash_state ** state,const uint8_t * key,size_t key_size,size_t digest_size)50 EXPORT_SYM int blake2_init (hash_state **state,
51 const uint8_t *key,
52 size_t key_size,
53 size_t digest_size)
54 {
55 hash_state *hs;
56 unsigned i;
57
58 if (NULL == state)
59 return ERR_NULL;
60
61 if (NULL == key || key_size > MAX_KEY_BYTES)
62 return ERR_KEY_SIZE;
63
64 if (0 == digest_size || digest_size > MAX_DIGEST_BYTES)
65 return ERR_DIGEST_SIZE;
66
67 *state = hs = (hash_state*) calloc(1, sizeof(hash_state));
68 if (NULL == hs)
69 return ERR_MEMORY;
70
71 for (i=0; i<WORDS_IN_STATE; i++) {
72 hs->h[i] = iv[i];
73 }
74 hs->h[0] = (blake2_word)(hs->h[0] ^ 0x01010000 ^ (key_size << 8) ^ digest_size);
75
76 /** If the key is present, the first block is the key padded with zeroes **/
77 if (key_size>0) {
78 memcpy(hs->buf, key, key_size);
79 hs->buf_occ = BLOCK_SIZE;
80 }
81
82 return 0;
83 }
84
blake2_destroy(hash_state * hs)85 EXPORT_SYM int blake2_destroy(hash_state *hs)
86 {
87 free(hs);
88 return 0;
89 }
90
blake2_copy(const hash_state * src,hash_state * dst)91 EXPORT_SYM int blake2_copy(const hash_state *src, hash_state *dst)
92 {
93 if (NULL == src || NULL == dst) {
94 return ERR_NULL;
95 }
96
97 *dst = *src;
98 return 0;
99 }
100
101 #define ROTR(x,n) (((x) >> (n)) ^ ((x) << (BLAKE2_WORD_SIZE - (n))))
102
103 #define G(v,a,b,c,d,x,y) \
104 { \
105 v[a] = v[a] + v[b] + x; \
106 v[d] = ROTR(v[d] ^ v[a], G_R1); \
107 v[c] = v[c] + v[d]; \
108 v[b] = ROTR(v[b] ^ v[c], G_R2); \
109 v[a] = v[a] + v[b] + y; \
110 v[d] = ROTR(v[d] ^ v[a], G_R3); \
111 v[c] = v[c] + v[d]; \
112 v[b] = ROTR(v[b] ^ v[c], G_R4); \
113 }
114
blake2b_compress(blake2_word state[8],const blake2_word m[WORDS_IN_BLOCK],blake2_word off_counter_low,blake2_word off_counter_high,block_type bt)115 static void blake2b_compress(blake2_word state[8],
116 const blake2_word m[WORDS_IN_BLOCK],
117 blake2_word off_counter_low,
118 blake2_word off_counter_high,
119 block_type bt
120 )
121 {
122 static const uint8_t sigma[12][16] = {
123 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
124 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
125 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
126 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
127 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
128 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
129 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
130 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
131 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
132 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
133 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
134 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
135 };
136 blake2_word work[WORDS_IN_BLOCK];
137 unsigned i;
138
139 for (i=0; i<WORDS_IN_STATE; i++) {
140 work[i] = state[i];
141 work[i+WORDS_IN_STATE] = iv[i];
142 }
143
144 work[12] ^= off_counter_low;
145 work[13] ^= off_counter_high;
146
147 if (bt == FINAL_BLOCK)
148 work[14] = ~work[14];
149
150 for (i=0; i<F_ROUNDS; i++) {
151 const uint8_t *s;
152
153 s = &sigma[i][0];
154 G(work, 0, 4, 8, 12, m[s[ 0]], m[s[ 1]]);
155 G(work, 1, 5, 9, 13, m[s[ 2]], m[s[ 3]]);
156 G(work, 2, 6, 10, 14, m[s[ 4]], m[s[ 5]]);
157 G(work, 3, 7, 11, 15, m[s[ 6]], m[s[ 7]]);
158 G(work, 0, 5, 10, 15, m[s[ 8]], m[s[ 9]]);
159 G(work, 1, 6, 11, 12, m[s[10]], m[s[11]]);
160 G(work, 2, 7, 8, 13, m[s[12]], m[s[13]]);
161 G(work, 3, 4, 9, 14, m[s[14]], m[s[15]]);
162 }
163
164 for (i=0; i<WORDS_IN_STATE; i++)
165 state[i] ^= work[i] ^ work[i+WORDS_IN_STATE];
166 }
167
blake2b_process_buffer(hash_state * hs,size_t new_data_added,block_type bt)168 static int blake2b_process_buffer(hash_state *hs,
169 size_t new_data_added,
170 block_type bt)
171 {
172 blake2_word bufw[WORDS_IN_BLOCK];
173 const uint8_t *buf;
174 unsigned i;
175
176 buf = hs->buf;
177 for (i=0; i<WORDS_IN_BLOCK; i++) {
178 bufw[i] = LOAD_WORD_LITTLE(buf);
179 buf += sizeof(blake2_word);
180 }
181
182 hs->off_counter_low = (blake2_word)(hs->off_counter_low + new_data_added);
183 if (hs->off_counter_low < new_data_added) {
184 if (0 == ++hs->off_counter_high)
185 return ERR_MAX_DATA;
186 }
187
188 blake2b_compress(hs->h,
189 bufw,
190 hs->off_counter_low,
191 hs->off_counter_high,
192 bt);
193
194 hs->buf_occ = 0;
195 return 0;
196 }
197
blake2_update(hash_state * hs,const uint8_t * in,size_t len)198 EXPORT_SYM int blake2_update(hash_state *hs,
199 const uint8_t *in,
200 size_t len)
201 {
202 if (NULL == hs)
203 return ERR_NULL;
204
205 if (len > 0 && NULL == in)
206 return ERR_NULL;
207
208
209 while (len > 0) {
210 unsigned tc, left;
211
212 /** Consume input **/
213 left = (unsigned)(BLOCK_SIZE - hs->buf_occ);
214 tc = (unsigned)MIN(len, left);
215 memcpy(&hs->buf[hs->buf_occ], in, tc);
216 len -= tc;
217 in += tc;
218 hs->buf_occ += tc;
219
220 /* Flush buffer if full. However, we must leave at least
221 * one byte in the buffer at the end, because we don't
222 * know if we are processing the last block.
223 */
224 if (hs->buf_occ == BLOCK_SIZE && len>0) {
225 int result;
226
227 result = blake2b_process_buffer(hs, BLOCK_SIZE, NON_FINAL_BLOCK);
228 if (result)
229 return result;
230 }
231 }
232
233 return 0;
234 }
235
blake2_digest(const hash_state * hs,uint8_t digest[MAX_DIGEST_BYTES])236 EXPORT_SYM int blake2_digest(const hash_state *hs,
237 uint8_t digest[MAX_DIGEST_BYTES])
238 {
239 hash_state temp_hs;
240 unsigned i;
241 int result;
242
243 if (NULL==hs || NULL==digest)
244 return ERR_NULL;
245
246 temp_hs = *hs;
247
248 /** Pad buffer with zeroes, if needed. In the special case
249 * of no key and no data, we must process an all zero block.
250 */
251 for (i=temp_hs.buf_occ; i<BLOCK_SIZE; i++) {
252 temp_hs.buf[i] = 0;
253 }
254
255 result = blake2b_process_buffer(&temp_hs,
256 temp_hs.buf_occ,
257 FINAL_BLOCK);
258 if (result)
259 return result;
260
261 assert(sizeof temp_hs.h == MAX_DIGEST_BYTES);
262 for (i=0; i<WORDS_IN_STATE; i++) {
263 STORE_WORD_LITTLE(digest, temp_hs.h[i]);
264 digest += sizeof(blake2_word);
265 }
266
267 return 0;
268 }
269