Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
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
34const 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
45cx_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
50cx_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
80err:
81 return CX_INVALID_PARAMETER;
82}
83
84cx_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
96cx_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
102size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx)
103{
104 return ctx->output_size;
105}
106
107cx_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)
170static 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
182static 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}
193static 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
206static 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
213static 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
226static 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}
238static 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
252static 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)
270static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c)
271{
272 return (w >> c) | (w << (32 - c));
273}
274#endif
275
276static 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() */
282static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
283{
284 memset(v, 0, n);
285}
286
287/*
288endof inline
289*** */
290
291static const uint64_t blake2b_IV[8] = {0x6a09e667f3bcc908ULL,
292 0xbb67ae8584caa73bULL,
293 0x3c6ef372fe94f82bULL,
294 0xa54ff53a5f1d36f1ULL,
295 0x510e527fade682d1ULL,
296 0x9b05688c2b3e6c1fULL,
297 0x1f83d9abfb41bd6bULL,
298 0x5be0cd19137e2179ULL};
299
300static 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
315static void blake2b_set_lastnode(blake2b_state *S)
316{
317 S->f[1] = (uint64_t) -1;
318}
319
320/* Some helper functions, not necessarily useful */
321static int blake2b_is_lastblock(const blake2b_state *S)
322{
323 return S->f[0] != 0;
324}
325
326static 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
335static 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
341static 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 */
352int 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
368int 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
402int 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
455static void blake2b_compress(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
456{
457/*
458uint64_t m[16];
459uint64_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
503void 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
528int 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. */
564int 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
604int 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"
612int 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;
667fail:
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