Embedded SDK
Embedded SDK
cx_blake2b.c
Go to the documentation of this file.
1 
2 
3 /*******************************************************************************
4  * Ledger Nano S - Secure firmware
5  * (c) 2022 Ledger
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  ********************************************************************************/
19 
20 #ifdef HAVE_BLAKE2
21 
22 #include "cx_blake2.h"
23 #include "cx_utils.h"
24 #include "cx_ram.h"
25 
26 #include <string.h>
27 
28 #ifdef ARCH_LITTLE_ENDIAN
29 #ifndef NATIVE_LITTLE_ENDIAN
30 #define NATIVE_LITTLE_ENDIAN
31 #endif
32 #endif
33 
34 const cx_hash_info_t cx_blake2b_info
35  = {CX_BLAKE2B,
36  0,
37  BLAKE2B_BLOCKBYTES,
38  sizeof(cx_blake2b_t),
39  NULL,
40  (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_blake2b_update,
41  (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_blake2b_final,
42  (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_blake2b_init_no_throw,
43  (size_t(*)(const cx_hash_t *ctx)) cx_blake2b_get_output_size};
44 
45 cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t size)
46 {
47  return cx_blake2b_init2_no_throw(hash, size, NULL, 0, NULL, 0);
48 }
49 
50 cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash,
51  size_t size,
52  uint8_t *salt,
53  size_t salt_len,
54  uint8_t *perso,
55  size_t perso_len)
56 {
57  if (salt == NULL && salt_len != 0) {
58  goto err;
59  }
60  if (perso == NULL && perso_len != 0) {
61  goto err;
62  }
63  if (salt_len > 16 || perso_len > 16) {
64  goto err;
65  }
66  if (size % 8 != 0 || size < 8 || size > 512) {
67  goto err;
68  }
69  memset(hash, 0, sizeof(cx_blake2b_t));
70 
71  size = size / 8;
72  hash->output_size = size;
73  hash->header.info = &cx_blake2b_info;
74 
75  if (blake2b_init(&hash->ctx, size, salt, salt_len, perso, perso_len) < 0) {
76  goto err;
77  }
78  return CX_OK;
79 
80 err:
81  return CX_INVALID_PARAMETER;
82 }
83 
84 cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len)
85 {
86  if (ctx == NULL) {
87  return CX_INVALID_PARAMETER;
88  }
89  if (data == NULL && len != 0) {
90  return CX_INVALID_PARAMETER;
91  }
92  blake2b_update(&ctx->ctx, data, len);
93  return CX_OK;
94 }
95 
96 cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest)
97 {
98  (void) blake2b_final(&ctx->ctx, digest, ctx->output_size);
99  return CX_OK;
100 }
101 
102 size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx)
103 {
104  return ctx->output_size;
105 }
106 
107 cx_err_t cx_blake2b(cx_hash_t *hash,
108  uint32_t mode,
109  const uint8_t *in,
110  size_t len,
111  uint8_t *out,
112  size_t out_len)
113 {
114  size_t sz = 0;
115  blake2b_update(&((cx_blake2b_t *) hash)->ctx, in, len);
116  if (mode & CX_LAST) {
117  sz = ((cx_blake2b_t *) hash)->output_size;
118  if (out && (out_len < sz)) {
119  return INVALID_PARAMETER;
120  }
121  if ((size_t) blake2b_final(&((cx_blake2b_t *) hash)->ctx, out, out_len) != sz) {
122  return INVALID_PARAMETER;
123  }
124  }
125  return CX_OK;
126 }
127 
128 /*
129  BLAKE2 reference source code package - reference C implementations
130 
131  Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
132  terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
133  your option. The terms of these licenses can be found at:
134 
135  - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
136  - OpenSSL license : https://www.openssl.org/source/license.html
137  - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
138 
139  More information about the BLAKE2 hash function can be found at
140  https://blake2.net.
141 */
142 
143 // #include <stdint.h>
144 // #include <string.h>
145 // #include <stdio.h>
146 
147 // #include "cx_blake2.h" //moved on top
148 
149 #include <stddef.h>
150 #include <string.h>
151 
152 /* ***
153 #include "cx_blake2-impl.h"
154 //inline here:
155 */
156 
157 #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
158 #if defined(_MSC_VER)
159 #define BLAKE2_INLINE __inline
160 #elif defined(__GNUC__)
161 #define BLAKE2_INLINE __inline__
162 #else
163 #define BLAKE2_INLINE
164 #endif
165 #else
166 #define BLAKE2_INLINE inline
167 #endif
168 
169 #if defined(BLAKE2_UNUSED)
170 static BLAKE2_INLINE uint16_t load16(const void *src)
171 {
172 #if defined(NATIVE_LITTLE_ENDIAN)
173  uint16_t w;
174  memcpy(&w, src, sizeof w);
175  return w;
176 #else
177  const uint8_t *p = (const uint8_t *) src;
178  return ((uint16_t) (p[0]) << 0) | ((uint16_t) (p[1]) << 8);
179 #endif
180 }
181 
182 static BLAKE2_INLINE void store16(void *dst, uint16_t w)
183 {
184 #if defined(NATIVE_LITTLE_ENDIAN)
185  memcpy(dst, &w, sizeof w);
186 #else
187  uint8_t *p = (uint8_t *) dst;
188  *p++ = (uint8_t) w;
189  w >>= 8;
190  *p++ = (uint8_t) w;
191 #endif
192 }
193 static BLAKE2_INLINE uint32_t load32(const void *src)
194 {
195 #if defined(NATIVE_LITTLE_ENDIAN)
196  uint32_t w;
197  memcpy(&w, src, sizeof w);
198  return w;
199 #else
200  const uint8_t *p = (const uint8_t *) src;
201  return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16)
202  | ((uint32_t) (p[3]) << 24);
203 #endif
204 }
205 
206 static BLAKE2_INLINE uint64_t load48(const void *src)
207 {
208  const uint8_t *p = (const uint8_t *) src;
209  return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16)
210  | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40);
211 }
212 
213 static BLAKE2_INLINE void store48(void *dst, uint64_t w)
214 {
215  uint8_t *p = (uint8_t *) dst;
216  p[0] = (uint8_t) (w >> 0);
217  p[1] = (uint8_t) (w >> 8);
218  p[2] = (uint8_t) (w >> 16);
219  p[3] = (uint8_t) (w >> 24);
220  p[4] = (uint8_t) (w >> 32);
221  p[5] = (uint8_t) (w >> 40);
222 }
223 
224 #endif
225 
226 static BLAKE2_INLINE void store32(void *dst, uint32_t w)
227 {
228 #if defined(NATIVE_LITTLE_ENDIAN)
229  memcpy(dst, &w, sizeof w);
230 #else
231  uint8_t *p = (uint8_t *) dst;
232  p[0] = (uint8_t) (w >> 0);
233  p[1] = (uint8_t) (w >> 8);
234  p[2] = (uint8_t) (w >> 16);
235  p[3] = (uint8_t) (w >> 24);
236 #endif
237 }
238 static BLAKE2_INLINE uint64_t load64(const void *src)
239 {
240 #if defined(NATIVE_LITTLE_ENDIAN)
241  uint64_t w;
242  memcpy(&w, src, sizeof w);
243  return w;
244 #else
245  const uint8_t *p = (const uint8_t *) src;
246  return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16)
247  | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40)
248  | ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56);
249 #endif
250 }
251 
252 static BLAKE2_INLINE void store64(void *dst, uint64_t w)
253 {
254 #if defined(NATIVE_LITTLE_ENDIAN)
255  memcpy(dst, &w, sizeof w);
256 #else
257  uint8_t *p = (uint8_t *) dst;
258  p[0] = (uint8_t) (w >> 0);
259  p[1] = (uint8_t) (w >> 8);
260  p[2] = (uint8_t) (w >> 16);
261  p[3] = (uint8_t) (w >> 24);
262  p[4] = (uint8_t) (w >> 32);
263  p[5] = (uint8_t) (w >> 40);
264  p[6] = (uint8_t) (w >> 48);
265  p[7] = (uint8_t) (w >> 56);
266 #endif
267 }
268 
269 #if defined(BLAKE2_UNUSED)
270 static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c)
271 {
272  return (w >> c) | (w << (32 - c));
273 }
274 #endif
275 
276 static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c)
277 {
278  return (w >> c) | (w << (64 - c));
279 }
280 
281 /* prevents compiler optimizing out memset() */
282 static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
283 {
284  memset(v, 0, n);
285 }
286 
287 /*
288 endof inline
289 *** */
290 
291 static const uint64_t blake2b_IV[8] = {0x6a09e667f3bcc908ULL,
292  0xbb67ae8584caa73bULL,
293  0x3c6ef372fe94f82bULL,
294  0xa54ff53a5f1d36f1ULL,
295  0x510e527fade682d1ULL,
296  0x9b05688c2b3e6c1fULL,
297  0x1f83d9abfb41bd6bULL,
298  0x5be0cd19137e2179ULL};
299 
300 static const uint8_t blake2b_sigma[12][16] = {
301  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
302  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
303  {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
304  {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
305  {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
306  {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
307  {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
308  {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
309  {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
310  {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
311  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
312  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
313 };
314 
315 static void blake2b_set_lastnode(blake2b_state *S)
316 {
317  S->f[1] = (uint64_t) -1;
318 }
319 
320 /* Some helper functions, not necessarily useful */
321 static int blake2b_is_lastblock(const blake2b_state *S)
322 {
323  return S->f[0] != 0;
324 }
325 
326 static void blake2b_set_lastblock(blake2b_state *S)
327 {
328  if (S->last_node) {
329  blake2b_set_lastnode(S);
330  }
331 
332  S->f[0] = (uint64_t) -1;
333 }
334 
335 static void blake2b_increment_counter(blake2b_state *S, const uint64_t inc)
336 {
337  S->t[0] += inc;
338  S->t[1] += (S->t[0] < inc);
339 }
340 
341 static void blake2b_init0(blake2b_state *S)
342 {
343  size_t i;
344  memset(S, 0, sizeof(blake2b_state));
345 
346  for (i = 0; i < 8; ++i) {
347  S->h[i] = blake2b_IV[i];
348  }
349 }
350 
351 /* init xors IV with input parameter block */
352 int blake2b_init_param(blake2b_state *S, const blake2b_param *P)
353 {
354  const uint8_t *p = (const uint8_t *) (P);
355  size_t i;
356 
357  blake2b_init0(S);
358 
359  /* IV XOR ParamBlock */
360  for (i = 0; i < 8; ++i) {
361  S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
362  }
363 
364  S->outlen = P->digest_length;
365  return 0;
366 }
367 
368 int blake2b_init(blake2b_state *S,
369  size_t outlen,
370  uint8_t *salt,
371  size_t salt_len,
372  uint8_t *personal,
373  size_t personal_len)
374 {
375  blake2b_param P[1];
376 
377  if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
378  return CX_INVALID_PARAMETER;
379  }
380 
381  P->digest_length = (uint8_t) outlen;
382  P->key_length = 0;
383  P->fanout = 1;
384  P->depth = 1;
385  store32(&P->leaf_length, 0);
386  store32(&P->node_offset, 0);
387  store32(&P->xof_length, 0);
388  P->node_depth = 0;
389  P->inner_length = 0;
390  memset(P->reserved, 0, sizeof(P->reserved));
391  memset(P->salt, 0, sizeof(P->salt));
392  memset(P->personal, 0, sizeof(P->personal));
393  if (salt) {
394  memcpy(P->salt, salt, salt_len);
395  }
396  if (personal) {
397  memcpy(P->personal, personal, personal_len);
398  }
399  return blake2b_init_param(S, P);
400 }
401 
402 int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen)
403 {
404  blake2b_param P[1];
405 
406  if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
407  return -1;
408  }
409 
410  if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
411  return -1;
412  }
413 
414  P->digest_length = (uint8_t) outlen;
415  P->key_length = (uint8_t) keylen;
416  P->fanout = 1;
417  P->depth = 1;
418  store32(&P->leaf_length, 0);
419  store32(&P->node_offset, 0);
420  store32(&P->xof_length, 0);
421  P->node_depth = 0;
422  P->inner_length = 0;
423  memset(P->reserved, 0, sizeof(P->reserved));
424  memset(P->salt, 0, sizeof(P->salt));
425  memset(P->personal, 0, sizeof(P->personal));
426 
427  if (blake2b_init_param(S, P) < 0) {
428  return -1;
429  }
430 
431  {
432 // uint8_t block[BLAKE2B_BLOCKBYTES];
433 #define block G_cx.blake.block1
434  memset(block, 0, BLAKE2B_BLOCKBYTES);
435  memcpy(block, key, keylen);
436  blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
437  secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
438 #undef block
439  }
440  return 0;
441 }
442 
443 #define G(r, i, a, b, c, d) \
444  do { \
445  a = a + b + m[blake2b_sigma[r][2 * (i) + 0]]; \
446  d = rotr64(d ^ a, 32); \
447  c = c + d; \
448  b = rotr64(b ^ c, 24); \
449  a = a + b + m[blake2b_sigma[r][2 * (i) + 1]]; \
450  d = rotr64(d ^ a, 16); \
451  c = c + d; \
452  b = rotr64(b ^ c, 63); \
453  } while (0)
454 
455 static void blake2b_compress(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
456 {
457 /*
458 uint64_t m[16];
459 uint64_t v[16];
460 */
461 #define m G_cx.blake.m
462 #define v G_cx.blake.v
463 
464  size_t i;
465 
466  for (i = 0; i < 16; ++i) {
467  m[i] = load64(block + i * sizeof(m[i]));
468  }
469 
470  for (i = 0; i < 8; ++i) {
471  v[i] = S->h[i];
472  }
473 
474  v[8] = blake2b_IV[0];
475  v[9] = blake2b_IV[1];
476  v[10] = blake2b_IV[2];
477  v[11] = blake2b_IV[3];
478  v[12] = blake2b_IV[4] ^ S->t[0];
479  v[13] = blake2b_IV[5] ^ S->t[1];
480  v[14] = blake2b_IV[6] ^ S->f[0];
481  v[15] = blake2b_IV[7] ^ S->f[1];
482 
483  for (int r = 0; r < 12; r++) {
484  for (i = 0; i < 4; i++) {
485  G(r, i, v[i], v[4 + i], v[8 + i], v[12 + i]);
486  }
487 
488  for (i = 0; i < 4; i++) {
489  G(r, 4 + i, v[i], v[4 + ((i + 1) & 3)], v[8 + ((i + 2) & 3)], v[12 + ((i + 3) & 3)]);
490  }
491  }
492 
493  for (i = 0; i < 8; ++i) {
494  S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
495  }
496 #undef m
497 #undef v
498 }
499 
500 #undef G
501 #undef ROUND
502 
503 void blake2b_update(blake2b_state *S, const void *pin, size_t inlen)
504 {
505  const uint8_t *in = (const uint8_t *) pin;
506  if (inlen > 0) {
507  size_t left = S->buflen;
508  size_t fill = BLAKE2B_BLOCKBYTES - left;
509  if (inlen > fill) {
510  S->buflen = 0;
511  memcpy(S->buf + left, in, fill); /* Fill buffer */
512  blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
513  blake2b_compress(S, S->buf); /* Compress */
514  in += fill;
515  inlen -= fill;
516  while (inlen > BLAKE2B_BLOCKBYTES) {
517  blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
518  blake2b_compress(S, in);
519  in += BLAKE2B_BLOCKBYTES;
520  inlen -= BLAKE2B_BLOCKBYTES;
521  }
522  }
523  memcpy(S->buf + S->buflen, in, inlen);
524  S->buflen += inlen;
525  }
526 }
527 
528 int blake2b_final(blake2b_state *S, void *out, size_t outlen)
529 {
530  size_t i;
531 // uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
532 #define buffer G_cx.blake.buffer
533  memset(buffer, 0, BLAKE2B_OUTBYTES);
534 
535  if ((out != NULL) && (outlen < S->outlen)) {
536  return -1;
537  }
538 
539  if (blake2b_is_lastblock(S)) {
540  return -1;
541  }
542 
543  blake2b_increment_counter(S, S->buflen);
544  blake2b_set_lastblock(S);
545  memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
546  blake2b_compress(S, S->buf);
547 
548  for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
549  store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
550  }
551  memcpy(S->buf, buffer, S->outlen); //.acc destination
552  if (out) {
553  memcpy(out, buffer, S->outlen);
554  }
555  secure_zero_memory(buffer, sizeof(buffer));
556  return S->outlen;
557 #undef buffer
558 }
559 
560 /* =============================== UNUSED =============================== */
561 // Following code is not used
562 #if defined(BLAKE2_UNUSED)
563 /* inlen, at least, should be uint64_t. Others can be size_t. */
564 int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
565 {
566  blake2b_state S[1];
567 
568  /* Verify parameters */
569  if (NULL == in && inlen > 0) {
570  return -1;
571  }
572 
573  if (NULL == out) {
574  return -1;
575  }
576 
577  if (NULL == key && keylen > 0) {
578  return -1;
579  }
580 
581  if (!outlen || outlen > BLAKE2B_OUTBYTES) {
582  return -1;
583  }
584 
585  if (keylen > BLAKE2B_KEYBYTES) {
586  return -1;
587  }
588 
589  if (keylen > 0) {
590  if (blake2b_init_key(S, outlen, key, keylen) < 0) {
591  return -1;
592  }
593  }
594  else {
595  if (blake2b_init(S, outlen) < 0) {
596  return -1;
597  }
598  }
599 
600  blake2b_update(S, (const uint8_t *) in, inlen);
601  return blake2b_final(S, out, outlen);
602 }
603 
604 int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
605 {
606  return blake2b(out, outlen, in, inlen, key, keylen);
607 }
608 
609 #if defined(BLAKE2B_SELFTEST)
610 #include <string.h>
611 #include "blake2-kat.h"
612 int main(void)
613 {
614  uint8_t key[BLAKE2B_KEYBYTES];
615  uint8_t buf[BLAKE2_KAT_LENGTH];
616  size_t i, step;
617 
618  for (i = 0; i < BLAKE2B_KEYBYTES; ++i) {
619  key[i] = (uint8_t) i;
620  }
621 
622  for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
623  buf[i] = (uint8_t) i;
624  }
625 
626  /* Test simple API */
627  for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
628  uint8_t hash[BLAKE2B_OUTBYTES];
629  blake2b(hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES);
630 
631  if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
632  goto fail;
633  }
634  }
635 
636  /* Test streaming API */
637  for (step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
638  for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
639  uint8_t hash[BLAKE2B_OUTBYTES];
640  blake2b_state S;
641  uint8_t *p = buf;
642  size_t mlen = i;
643  int err = 0;
644 
645  if ((err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0) {
646  goto fail;
647  }
648 
649  while (mlen >= step) {
650  blake2b_update(&S, p, step);
651  mlen -= step;
652  p += step;
653  }
654  blake2b_update(&S, p, mlen);
655  if ((err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
656  goto fail;
657  }
658 
659  if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
660  goto fail;
661  }
662  }
663  }
664 
665  puts("ok");
666  return 0;
667 fail:
668  puts("error");
669  return -1;
670 }
671 #endif
672 
673 #endif // BLAKE2_UNUSED
674 
675 #endif // HAVE_BLAKE2
#define CX_LAST
Definition: lcx_common.h:115
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53