/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 "blake2_common.h" |
19 | | #include "blake2b.h" |
20 | | #include "memzero.h" |
21 | | #include "options.h" |
22 | | |
23 | | typedef struct trezor_blake2b_param__ { |
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 | | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, |
40 | | 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, |
41 | | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; |
42 | | |
43 | | static const uint8_t trezor_blake2b_sigma[12][16] = { |
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 | | {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, |
47 | | {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, |
48 | | {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, |
49 | | {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, |
50 | | {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, |
51 | | {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, |
52 | | {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, |
53 | | {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, |
54 | | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, |
55 | | {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}}; |
56 | | |
57 | 0 | static void trezor_blake2b_set_lastnode(trezor_blake2b_state *S) { S->f[1] = (uint64_t)-1; } |
58 | | |
59 | | /* Some helper functions, not necessarily useful */ |
60 | 42 | static int trezor_blake2b_is_lastblock(const trezor_blake2b_state *S) { return S->f[0] != 0; } |
61 | | |
62 | 42 | static void trezor_blake2b_set_lastblock(trezor_blake2b_state *S) { |
63 | 42 | if (S->last_node) trezor_blake2b_set_lastnode(S); |
64 | | |
65 | 42 | S->f[0] = (uint64_t)-1; |
66 | 42 | } |
67 | | |
68 | 10.6k | static void trezor_blake2b_increment_counter(trezor_blake2b_state *S, const uint64_t inc) { |
69 | 10.6k | S->t[0] += inc; |
70 | 10.6k | S->t[1] += (S->t[0] < inc); |
71 | 10.6k | } |
72 | | |
73 | 42 | static void trezor_blake2b_init0(trezor_blake2b_state *S) { |
74 | 42 | size_t i = 0; |
75 | 42 | memzero(S, sizeof(trezor_blake2b_state)); |
76 | | |
77 | 378 | for (i = 0; i < 8; ++i) S->h[i] = trezor_blake2b_IV[i]; |
78 | 42 | } |
79 | | |
80 | | /* init xors IV with input parameter block */ |
81 | 42 | int trezor_blake2b_init_param(trezor_blake2b_state *S, const trezor_blake2b_param *P) { |
82 | 42 | const uint8_t *p = (const uint8_t *)(P); |
83 | 42 | size_t i = 0; |
84 | | |
85 | 42 | trezor_blake2b_init0(S); |
86 | | |
87 | | /* IV XOR ParamBlock */ |
88 | 378 | for (i = 0; i < 8; ++i) S->h[i] ^= load64(p + sizeof(S->h[i]) * i); |
89 | | |
90 | 42 | S->outlen = P->digest_length; |
91 | 42 | return 0; |
92 | 42 | } |
93 | | |
94 | | /* Sequential blake2b initialization */ |
95 | 42 | int trezor_blake2b_Init(trezor_blake2b_state *S, size_t outlen) { |
96 | 42 | trezor_blake2b_param P[1] = {0}; |
97 | | |
98 | 42 | if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; |
99 | | |
100 | 42 | P->digest_length = (uint8_t)outlen; |
101 | 42 | P->key_length = 0; |
102 | 42 | P->fanout = 1; |
103 | 42 | P->depth = 1; |
104 | 42 | store32(&P->leaf_length, 0); |
105 | 42 | store32(&P->node_offset, 0); |
106 | 42 | store32(&P->xof_length, 0); |
107 | 42 | P->node_depth = 0; |
108 | 42 | P->inner_length = 0; |
109 | 42 | memzero(P->reserved, sizeof(P->reserved)); |
110 | 42 | memzero(P->salt, sizeof(P->salt)); |
111 | 42 | memzero(P->personal, sizeof(P->personal)); |
112 | 42 | return trezor_blake2b_init_param(S, P); |
113 | 42 | } |
114 | | |
115 | | int trezor_blake2b_InitPersonal(trezor_blake2b_state *S, size_t outlen, const void *personal, |
116 | 0 | size_t personal_len) { |
117 | 0 | trezor_blake2b_param P[1] = {0}; |
118 | |
|
119 | 0 | if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; |
120 | 0 | if ((!personal) || (personal_len != BLAKE2B_PERSONALBYTES)) return -1; |
121 | | |
122 | 0 | P->digest_length = (uint8_t)outlen; |
123 | 0 | P->key_length = 0; |
124 | 0 | P->fanout = 1; |
125 | 0 | P->depth = 1; |
126 | 0 | store32(&P->leaf_length, 0); |
127 | 0 | store32(&P->node_offset, 0); |
128 | 0 | store32(&P->xof_length, 0); |
129 | 0 | P->node_depth = 0; |
130 | 0 | P->inner_length = 0; |
131 | 0 | memzero(P->reserved, sizeof(P->reserved)); |
132 | 0 | memzero(P->salt, sizeof(P->salt)); |
133 | 0 | memcpy(P->personal, personal, BLAKE2B_PERSONALBYTES); |
134 | 0 | return trezor_blake2b_init_param(S, P); |
135 | 0 | } |
136 | | |
137 | | int trezor_blake2b_InitKey(trezor_blake2b_state *S, size_t outlen, const void *key, |
138 | 0 | size_t keylen) { |
139 | 0 | trezor_blake2b_param P[1] = {0}; |
140 | |
|
141 | 0 | if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; |
142 | | |
143 | 0 | if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) return -1; |
144 | | |
145 | 0 | P->digest_length = (uint8_t)outlen; |
146 | 0 | P->key_length = (uint8_t)keylen; |
147 | 0 | P->fanout = 1; |
148 | 0 | P->depth = 1; |
149 | 0 | store32(&P->leaf_length, 0); |
150 | 0 | store32(&P->node_offset, 0); |
151 | 0 | store32(&P->xof_length, 0); |
152 | 0 | P->node_depth = 0; |
153 | 0 | P->inner_length = 0; |
154 | 0 | memzero(P->reserved, sizeof(P->reserved)); |
155 | 0 | memzero(P->salt, sizeof(P->salt)); |
156 | 0 | memzero(P->personal, sizeof(P->personal)); |
157 | |
|
158 | 0 | if (trezor_blake2b_init_param(S, P) < 0) return -1; |
159 | | |
160 | 0 | { |
161 | 0 | uint8_t block[BLAKE2B_BLOCKBYTES] = {0}; |
162 | 0 | memzero(block, BLAKE2B_BLOCKBYTES); |
163 | 0 | memcpy(block, key, keylen); |
164 | 0 | trezor_blake2b_Update(S, block, BLAKE2B_BLOCKBYTES); |
165 | 0 | memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ |
166 | 0 | } |
167 | 0 | return 0; |
168 | 0 | } |
169 | | |
170 | | #define G(m, r, i, a, b, c, d) \ |
171 | 1.02M | do { \ |
172 | 1.02M | *(a) = *(a) + *(b) + m[trezor_blake2b_sigma[r][2 * i + 0]]; \ |
173 | 1.02M | *(d) = rotr64(*(d) ^ *(a), 32); \ |
174 | 1.02M | *(c) = *(c) + *(d); \ |
175 | 1.02M | *(b) = rotr64(*(b) ^ *(c), 24); \ |
176 | 1.02M | *(a) = *(a) + *(b) + m[trezor_blake2b_sigma[r][2 * i + 1]]; \ |
177 | 1.02M | *(d) = rotr64(*(d) ^ *(a), 16); \ |
178 | 1.02M | *(c) = *(c) + *(d); \ |
179 | 1.02M | *(b) = rotr64(*(b) ^ *(c), 63); \ |
180 | 1.02M | } while (0) |
181 | | |
182 | | #if OPTIMIZE_SIZE_BLAKE2B |
183 | | static void g(uint64_t *m, int r, int i, uint64_t *a, uint64_t *b, uint64_t *c, |
184 | 1.02M | uint64_t *d) { |
185 | 1.02M | G(m, r, i, a, b, c, d); |
186 | 1.02M | } |
187 | | #else |
188 | | #define g(m, r, i, a, b, c, d) G(m, r, i, a, b, c, d) |
189 | | #endif |
190 | | |
191 | | #define ROUND(m, v, r) \ |
192 | 128k | do { \ |
193 | 128k | g(m, r, 0, v + 0, v + 4, v + 8, v + 12); \ |
194 | 128k | g(m, r, 1, v + 1, v + 5, v + 9, v + 13); \ |
195 | 128k | g(m, r, 2, v + 2, v + 6, v + 10, v + 14); \ |
196 | 128k | g(m, r, 3, v + 3, v + 7, v + 11, v + 15); \ |
197 | 128k | g(m, r, 4, v + 0, v + 5, v + 10, v + 15); \ |
198 | 128k | g(m, r, 5, v + 1, v + 6, v + 11, v + 12); \ |
199 | 128k | g(m, r, 6, v + 2, v + 7, v + 8, v + 13); \ |
200 | 128k | g(m, r, 7, v + 3, v + 4, v + 9, v + 14); \ |
201 | 128k | } while (0) |
202 | | |
203 | | static void trezor_blake2b_compress(trezor_blake2b_state *S, |
204 | 10.6k | const uint8_t block[BLAKE2B_BLOCKBYTES]) { |
205 | 10.6k | uint64_t m[16] = {0}; |
206 | 10.6k | uint64_t v[16] = {0}; |
207 | 10.6k | size_t i = 0; |
208 | | |
209 | 181k | for (i = 0; i < 16; ++i) { |
210 | 170k | m[i] = load64(block + i * sizeof(m[i])); |
211 | 170k | } |
212 | | |
213 | 96.1k | for (i = 0; i < 8; ++i) { |
214 | 85.4k | v[i] = S->h[i]; |
215 | 85.4k | } |
216 | | |
217 | 10.6k | v[8] = trezor_blake2b_IV[0]; |
218 | 10.6k | v[9] = trezor_blake2b_IV[1]; |
219 | 10.6k | v[10] = trezor_blake2b_IV[2]; |
220 | 10.6k | v[11] = trezor_blake2b_IV[3]; |
221 | 10.6k | v[12] = trezor_blake2b_IV[4] ^ S->t[0]; |
222 | 10.6k | v[13] = trezor_blake2b_IV[5] ^ S->t[1]; |
223 | 10.6k | v[14] = trezor_blake2b_IV[6] ^ S->f[0]; |
224 | 10.6k | v[15] = trezor_blake2b_IV[7] ^ S->f[1]; |
225 | | |
226 | 10.6k | #if OPTIMIZE_SIZE_BLAKE2B |
227 | 138k | for (int r = 0; r < 12; r++) { |
228 | 128k | ROUND(m, v, r); |
229 | 128k | } |
230 | | #else |
231 | | ROUND(m, v, 0); |
232 | | ROUND(m, v, 1); |
233 | | ROUND(m, v, 2); |
234 | | ROUND(m, v, 3); |
235 | | ROUND(m, v, 4); |
236 | | ROUND(m, v, 5); |
237 | | ROUND(m, v, 6); |
238 | | ROUND(m, v, 7); |
239 | | ROUND(m, v, 8); |
240 | | ROUND(m, v, 9); |
241 | | ROUND(m, v, 10); |
242 | | ROUND(m, v, 11); |
243 | | #endif |
244 | | |
245 | 96.1k | for (i = 0; i < 8; ++i) { |
246 | 85.4k | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; |
247 | 85.4k | } |
248 | 10.6k | } |
249 | | |
250 | | #undef G |
251 | | #undef ROUND |
252 | | |
253 | 12.8k | int trezor_blake2b_Update(trezor_blake2b_state *S, const void *pin, size_t inlen) { |
254 | 12.8k | const unsigned char *in = (const unsigned char *)pin; |
255 | 12.8k | if (inlen > 0) { |
256 | 383 | size_t left = S->buflen; |
257 | 383 | size_t fill = BLAKE2B_BLOCKBYTES - left; |
258 | 383 | if (inlen > fill) { |
259 | 201 | S->buflen = 0; |
260 | 201 | memcpy(S->buf + left, in, fill); /* Fill buffer */ |
261 | 201 | trezor_blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); |
262 | 201 | trezor_blake2b_compress(S, S->buf); /* Compress */ |
263 | 201 | in += fill; |
264 | 201 | inlen -= fill; |
265 | 10.6k | while (inlen > BLAKE2B_BLOCKBYTES) { |
266 | 10.4k | trezor_blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); |
267 | 10.4k | trezor_blake2b_compress(S, in); |
268 | 10.4k | in += BLAKE2B_BLOCKBYTES; |
269 | 10.4k | inlen -= BLAKE2B_BLOCKBYTES; |
270 | 10.4k | } |
271 | 201 | } |
272 | 383 | memcpy(S->buf + S->buflen, in, inlen); |
273 | 383 | S->buflen += inlen; |
274 | 383 | } |
275 | 12.8k | return 0; |
276 | 12.8k | } |
277 | | |
278 | 42 | int trezor_blake2b_Final(trezor_blake2b_state *S, void *out, size_t outlen) { |
279 | 42 | uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; |
280 | 42 | size_t i = 0; |
281 | | |
282 | 42 | if (out == NULL || outlen < S->outlen) return -1; |
283 | | |
284 | 42 | if (trezor_blake2b_is_lastblock(S)) return -1; |
285 | | |
286 | 42 | trezor_blake2b_increment_counter(S, S->buflen); |
287 | 42 | trezor_blake2b_set_lastblock(S); |
288 | 42 | memzero(S->buf + S->buflen, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ |
289 | 42 | trezor_blake2b_compress(S, S->buf); |
290 | | |
291 | 378 | for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */ |
292 | 336 | store64(buffer + sizeof(S->h[i]) * i, S->h[i]); |
293 | | |
294 | 42 | memcpy(out, buffer, S->outlen); |
295 | 42 | memzero(buffer, sizeof(buffer)); |
296 | 42 | return 0; |
297 | 42 | } |
298 | | |
299 | 0 | int trezor_blake2b(const uint8_t *msg, uint32_t msg_len, void *out, size_t outlen) { |
300 | 0 | BLAKE2B_CTX ctx; |
301 | 0 | if (0 != trezor_blake2b_Init(&ctx, outlen)) return -1; |
302 | 0 | if (0 != trezor_blake2b_Update(&ctx, msg, msg_len)) return -1; |
303 | 0 | if (0 != trezor_blake2b_Final(&ctx, out, outlen)) return -1; |
304 | 0 | return 0; |
305 | 0 | } |
306 | | |
307 | | int trezor_blake2b_Key(const uint8_t *msg, uint32_t msg_len, const void *key, |
308 | 0 | size_t keylen, void *out, size_t outlen) { |
309 | 0 | BLAKE2B_CTX ctx; |
310 | 0 | if (0 != trezor_blake2b_InitKey(&ctx, outlen, key, keylen)) return -1; |
311 | 0 | if (0 != trezor_blake2b_Update(&ctx, msg, msg_len)) return -1; |
312 | 0 | if (0 != trezor_blake2b_Final(&ctx, out, outlen)) return -1; |
313 | 0 | return 0; |
314 | 0 | } |