Coverage Report

Created: 2024-11-21 07:03

/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
}