/src/trezor-firmware/crypto/blake2b.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | BLAKE2 reference source code package - reference C implementations |
3 | | |
4 | | Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the |
5 | | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at |
6 | | your option. The terms of these licenses can be found at: |
7 | | |
8 | | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 |
9 | | - OpenSSL license : https://www.openssl.org/source/license.html |
10 | | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 |
11 | | |
12 | | More information about the BLAKE2 hash function can be found at |
13 | | https://blake2.net. |
14 | | */ |
15 | | |
16 | | #include <string.h> |
17 | | |
18 | | #include "blake2b.h" |
19 | | #include "blake2_common.h" |
20 | | #include "memzero.h" |
21 | | |
22 | | typedef struct trezor_blake2b_param__ |
23 | | { |
24 | | uint8_t digest_length; /* 1 */ |
25 | | uint8_t key_length; /* 2 */ |
26 | | uint8_t fanout; /* 3 */ |
27 | | uint8_t depth; /* 4 */ |
28 | | uint32_t leaf_length; /* 8 */ |
29 | | uint32_t node_offset; /* 12 */ |
30 | | uint32_t xof_length; /* 16 */ |
31 | | uint8_t node_depth; /* 17 */ |
32 | | uint8_t inner_length; /* 18 */ |
33 | | uint8_t reserved[14]; /* 32 */ |
34 | | uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ |
35 | | uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ |
36 | | } __attribute__((packed)) trezor_blake2b_param; |
37 | | |
38 | | static const uint64_t trezor_blake2b_IV[8] = |
39 | | { |
40 | | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, |
41 | | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, |
42 | | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, |
43 | | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL |
44 | | }; |
45 | | |
46 | | static const uint8_t trezor_blake2b_sigma[12][16] = |
47 | | { |
48 | | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , |
49 | | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , |
50 | | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , |
51 | | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , |
52 | | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , |
53 | | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , |
54 | | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , |
55 | | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , |
56 | | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , |
57 | | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , |
58 | | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , |
59 | | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } |
60 | | }; |
61 | | |
62 | | |
63 | | static void trezor_blake2b_set_lastnode( trezor_blake2b_state *S ) |
64 | 0 | { |
65 | 0 | S->f[1] = (uint64_t)-1; |
66 | 0 | } |
67 | | |
68 | | /* Some helper functions, not necessarily useful */ |
69 | | static int trezor_blake2b_is_lastblock( const trezor_blake2b_state *S ) |
70 | 0 | { |
71 | 0 | return S->f[0] != 0; |
72 | 0 | } |
73 | | |
74 | | static void trezor_blake2b_set_lastblock( trezor_blake2b_state *S ) |
75 | 0 | { |
76 | 0 | if( S->last_node ) trezor_blake2b_set_lastnode( S ); |
77 | |
|
78 | 0 | S->f[0] = (uint64_t)-1; |
79 | 0 | } |
80 | | |
81 | | static void trezor_blake2b_increment_counter( trezor_blake2b_state *S, const uint64_t inc ) |
82 | 0 | { |
83 | 0 | S->t[0] += inc; |
84 | 0 | S->t[1] += ( S->t[0] < inc ); |
85 | 0 | } |
86 | | |
87 | | static void trezor_blake2b_init0( trezor_blake2b_state *S ) |
88 | 0 | { |
89 | 0 | size_t i = 0; |
90 | 0 | memzero( S, sizeof( trezor_blake2b_state ) ); |
91 | |
|
92 | 0 | for( i = 0; i < 8; ++i ) S->h[i] = trezor_blake2b_IV[i]; |
93 | 0 | } |
94 | | |
95 | | /* init xors IV with input parameter block */ |
96 | | int trezor_blake2b_init_param( trezor_blake2b_state *S, const trezor_blake2b_param *P ) |
97 | 0 | { |
98 | 0 | const uint8_t *p = ( const uint8_t * )( P ); |
99 | 0 | size_t i = 0; |
100 | |
|
101 | 0 | trezor_blake2b_init0( S ); |
102 | | |
103 | | /* IV XOR ParamBlock */ |
104 | 0 | for( i = 0; i < 8; ++i ) |
105 | 0 | S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); |
106 | |
|
107 | 0 | S->outlen = P->digest_length; |
108 | 0 | return 0; |
109 | 0 | } |
110 | | |
111 | | |
112 | | /* Sequential blake2b initialization */ |
113 | | int trezor_blake2b_Init( trezor_blake2b_state *S, size_t outlen ) |
114 | 0 | { |
115 | 0 | trezor_blake2b_param P[1] = {0}; |
116 | |
|
117 | 0 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; |
118 | | |
119 | 0 | P->digest_length = (uint8_t)outlen; |
120 | 0 | P->key_length = 0; |
121 | 0 | P->fanout = 1; |
122 | 0 | P->depth = 1; |
123 | 0 | store32( &P->leaf_length, 0 ); |
124 | 0 | store32( &P->node_offset, 0 ); |
125 | 0 | store32( &P->xof_length, 0 ); |
126 | 0 | P->node_depth = 0; |
127 | 0 | P->inner_length = 0; |
128 | 0 | memzero( P->reserved, sizeof( P->reserved ) ); |
129 | 0 | memzero( P->salt, sizeof( P->salt ) ); |
130 | 0 | memzero( P->personal, sizeof( P->personal ) ); |
131 | 0 | return trezor_blake2b_init_param( S, P ); |
132 | 0 | } |
133 | | |
134 | | int trezor_blake2b_InitPersonal( trezor_blake2b_state *S, size_t outlen, const void *personal, size_t personal_len) |
135 | 0 | { |
136 | 0 | trezor_blake2b_param P[1] = {0}; |
137 | |
|
138 | 0 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; |
139 | 0 | if ( ( !personal ) || ( personal_len != BLAKE2B_PERSONALBYTES ) ) return -1; |
140 | | |
141 | 0 | P->digest_length = (uint8_t)outlen; |
142 | 0 | P->key_length = 0; |
143 | 0 | P->fanout = 1; |
144 | 0 | P->depth = 1; |
145 | 0 | store32( &P->leaf_length, 0 ); |
146 | 0 | store32( &P->node_offset, 0 ); |
147 | 0 | store32( &P->xof_length, 0 ); |
148 | 0 | P->node_depth = 0; |
149 | 0 | P->inner_length = 0; |
150 | 0 | memzero( P->reserved, sizeof( P->reserved ) ); |
151 | 0 | memzero( P->salt, sizeof( P->salt ) ); |
152 | 0 | memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES ); |
153 | 0 | return trezor_blake2b_init_param( S, P ); |
154 | 0 | } |
155 | | |
156 | | int trezor_blake2b_InitKey( trezor_blake2b_state *S, size_t outlen, const void *key, size_t keylen ) |
157 | 0 | { |
158 | 0 | trezor_blake2b_param P[1] = {0}; |
159 | |
|
160 | 0 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; |
161 | | |
162 | 0 | if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; |
163 | | |
164 | 0 | P->digest_length = (uint8_t)outlen; |
165 | 0 | P->key_length = (uint8_t)keylen; |
166 | 0 | P->fanout = 1; |
167 | 0 | P->depth = 1; |
168 | 0 | store32( &P->leaf_length, 0 ); |
169 | 0 | store32( &P->node_offset, 0 ); |
170 | 0 | store32( &P->xof_length, 0 ); |
171 | 0 | P->node_depth = 0; |
172 | 0 | P->inner_length = 0; |
173 | 0 | memzero( P->reserved, sizeof( P->reserved ) ); |
174 | 0 | memzero( P->salt, sizeof( P->salt ) ); |
175 | 0 | memzero( P->personal, sizeof( P->personal ) ); |
176 | |
|
177 | 0 | if( trezor_blake2b_init_param( S, P ) < 0 ) return -1; |
178 | | |
179 | 0 | { |
180 | 0 | uint8_t block[BLAKE2B_BLOCKBYTES] = {0}; |
181 | 0 | memzero( block, BLAKE2B_BLOCKBYTES ); |
182 | 0 | memcpy( block, key, keylen ); |
183 | 0 | trezor_blake2b_Update( S, block, BLAKE2B_BLOCKBYTES ); |
184 | 0 | memzero( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ |
185 | 0 | } |
186 | 0 | return 0; |
187 | 0 | } |
188 | | |
189 | | #define G(r,i,a,b,c,d) \ |
190 | 0 | do { \ |
191 | 0 | a = a + b + m[trezor_blake2b_sigma[r][2*i+0]]; \ |
192 | 0 | d = rotr64(d ^ a, 32); \ |
193 | 0 | c = c + d; \ |
194 | 0 | b = rotr64(b ^ c, 24); \ |
195 | 0 | a = a + b + m[trezor_blake2b_sigma[r][2*i+1]]; \ |
196 | 0 | d = rotr64(d ^ a, 16); \ |
197 | 0 | c = c + d; \ |
198 | 0 | b = rotr64(b ^ c, 63); \ |
199 | 0 | } while(0) |
200 | | |
201 | | #define ROUND(r) \ |
202 | 0 | do { \ |
203 | 0 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ |
204 | 0 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ |
205 | 0 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ |
206 | 0 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ |
207 | 0 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ |
208 | 0 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ |
209 | 0 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ |
210 | 0 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ |
211 | 0 | } while(0) |
212 | | |
213 | | static void trezor_blake2b_compress( trezor_blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) |
214 | 0 | { |
215 | 0 | uint64_t m[16] = {0}; |
216 | 0 | uint64_t v[16] = {0}; |
217 | 0 | size_t i = 0; |
218 | |
|
219 | 0 | for( i = 0; i < 16; ++i ) { |
220 | 0 | m[i] = load64( block + i * sizeof( m[i] ) ); |
221 | 0 | } |
222 | |
|
223 | 0 | for( i = 0; i < 8; ++i ) { |
224 | 0 | v[i] = S->h[i]; |
225 | 0 | } |
226 | |
|
227 | 0 | v[ 8] = trezor_blake2b_IV[0]; |
228 | 0 | v[ 9] = trezor_blake2b_IV[1]; |
229 | 0 | v[10] = trezor_blake2b_IV[2]; |
230 | 0 | v[11] = trezor_blake2b_IV[3]; |
231 | 0 | v[12] = trezor_blake2b_IV[4] ^ S->t[0]; |
232 | 0 | v[13] = trezor_blake2b_IV[5] ^ S->t[1]; |
233 | 0 | v[14] = trezor_blake2b_IV[6] ^ S->f[0]; |
234 | 0 | v[15] = trezor_blake2b_IV[7] ^ S->f[1]; |
235 | |
|
236 | 0 | ROUND( 0 ); |
237 | 0 | ROUND( 1 ); |
238 | 0 | ROUND( 2 ); |
239 | 0 | ROUND( 3 ); |
240 | 0 | ROUND( 4 ); |
241 | 0 | ROUND( 5 ); |
242 | 0 | ROUND( 6 ); |
243 | 0 | ROUND( 7 ); |
244 | 0 | ROUND( 8 ); |
245 | 0 | ROUND( 9 ); |
246 | 0 | ROUND( 10 ); |
247 | 0 | ROUND( 11 ); |
248 | |
|
249 | 0 | for( i = 0; i < 8; ++i ) { |
250 | 0 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; |
251 | 0 | } |
252 | 0 | } |
253 | | |
254 | | #undef G |
255 | | #undef ROUND |
256 | | |
257 | | int trezor_blake2b_Update( trezor_blake2b_state *S, const void *pin, size_t inlen ) |
258 | 0 | { |
259 | 0 | const unsigned char * in = (const unsigned char *)pin; |
260 | 0 | if( inlen > 0 ) |
261 | 0 | { |
262 | 0 | size_t left = S->buflen; |
263 | 0 | size_t fill = BLAKE2B_BLOCKBYTES - left; |
264 | 0 | if( inlen > fill ) |
265 | 0 | { |
266 | 0 | S->buflen = 0; |
267 | 0 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ |
268 | 0 | trezor_blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); |
269 | 0 | trezor_blake2b_compress( S, S->buf ); /* Compress */ |
270 | 0 | in += fill; inlen -= fill; |
271 | 0 | while(inlen > BLAKE2B_BLOCKBYTES) { |
272 | 0 | trezor_blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); |
273 | 0 | trezor_blake2b_compress( S, in ); |
274 | 0 | in += BLAKE2B_BLOCKBYTES; |
275 | 0 | inlen -= BLAKE2B_BLOCKBYTES; |
276 | 0 | } |
277 | 0 | } |
278 | 0 | memcpy( S->buf + S->buflen, in, inlen ); |
279 | 0 | S->buflen += inlen; |
280 | 0 | } |
281 | 0 | return 0; |
282 | 0 | } |
283 | | |
284 | | int trezor_blake2b_Final( trezor_blake2b_state *S, void *out, size_t outlen ) |
285 | 0 | { |
286 | 0 | uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; |
287 | 0 | size_t i = 0; |
288 | |
|
289 | 0 | if( out == NULL || outlen < S->outlen ) |
290 | 0 | return -1; |
291 | | |
292 | 0 | if( trezor_blake2b_is_lastblock( S ) ) |
293 | 0 | return -1; |
294 | | |
295 | 0 | trezor_blake2b_increment_counter( S, S->buflen ); |
296 | 0 | trezor_blake2b_set_lastblock( S ); |
297 | 0 | memzero( S->buf + S->buflen, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ |
298 | 0 | trezor_blake2b_compress( S, S->buf ); |
299 | |
|
300 | 0 | for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ |
301 | 0 | store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); |
302 | |
|
303 | 0 | memcpy( out, buffer, S->outlen ); |
304 | 0 | memzero(buffer, sizeof(buffer)); |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | | int trezor_blake2b(const uint8_t *msg, uint32_t msg_len, void *out, size_t outlen) |
309 | 0 | { |
310 | 0 | BLAKE2B_CTX ctx; |
311 | 0 | if (0 != trezor_blake2b_Init(&ctx, outlen)) return -1; |
312 | 0 | if (0 != trezor_blake2b_Update(&ctx, msg, msg_len)) return -1; |
313 | 0 | if (0 != trezor_blake2b_Final(&ctx, out, outlen)) return -1; |
314 | 0 | return 0; |
315 | 0 | } |
316 | | |
317 | | int trezor_blake2b_Key(const uint8_t *msg, uint32_t msg_len, const void *key, size_t keylen, void *out, size_t outlen) |
318 | 0 | { |
319 | 0 | BLAKE2B_CTX ctx; |
320 | 0 | if (0 != trezor_blake2b_InitKey(&ctx, outlen, key, keylen)) return -1; |
321 | 0 | if (0 != trezor_blake2b_Update(&ctx, msg, msg_len)) return -1; |
322 | 0 | if (0 != trezor_blake2b_Final(&ctx, out, outlen)) return -1; |
323 | 0 | return 0; |
324 | 0 | } |