28#ifdef ARCH_LITTLE_ENDIAN
29#ifndef NATIVE_LITTLE_ENDIAN
30#define NATIVE_LITTLE_ENDIAN
34const cx_hash_info_t cx_blake2b_info
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};
45cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash,
size_t size)
47 return cx_blake2b_init2_no_throw(hash, size, NULL, 0, NULL, 0);
50cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash,
57 if (salt == NULL && salt_len != 0) {
60 if (perso == NULL && perso_len != 0) {
63 if (salt_len > 16 || perso_len > 16) {
66 if (size % 8 != 0 || size < 8 || size > 512) {
69 memset(hash, 0,
sizeof(cx_blake2b_t));
72 hash->output_size = size;
73 hash->header.info = &cx_blake2b_info;
75 if (blake2b_init(&hash->ctx, size, salt, salt_len, perso, perso_len) < 0) {
81 return CX_INVALID_PARAMETER;
84cx_err_t cx_blake2b_update(cx_blake2b_t *ctx,
const uint8_t *data,
size_t len)
87 return CX_INVALID_PARAMETER;
89 if (data == NULL && len != 0) {
90 return CX_INVALID_PARAMETER;
92 blake2b_update(&ctx->ctx, data, len);
96cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest)
98 (void) blake2b_final(&ctx->ctx, digest, ctx->output_size);
102size_t cx_blake2b_get_output_size(
const cx_blake2b_t *ctx)
104 return ctx->output_size;
107cx_err_t cx_blake2b(cx_hash_t *hash,
115 blake2b_update(&((cx_blake2b_t *) hash)->ctx, in, len);
117 sz = ((cx_blake2b_t *) hash)->output_size;
118 if (out && (out_len < sz)) {
119 return INVALID_PARAMETER;
121 if ((
size_t) blake2b_final(&((cx_blake2b_t *) hash)->ctx, out, out_len) != sz) {
122 return INVALID_PARAMETER;
150#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
152#define BLAKE2_INLINE __inline
153#elif defined(__GNUC__)
154#define BLAKE2_INLINE __inline__
159#define BLAKE2_INLINE inline
162#if defined(BLAKE2_UNUSED)
163static BLAKE2_INLINE uint16_t load16(
const void *src)
165#if defined(NATIVE_LITTLE_ENDIAN)
167 memcpy(&w, src,
sizeof w);
170 const uint8_t *p = (
const uint8_t *) src;
171 return ((uint16_t) (p[0]) << 0) | ((uint16_t) (p[1]) << 8);
175static BLAKE2_INLINE
void store16(
void *dst, uint16_t w)
177#if defined(NATIVE_LITTLE_ENDIAN)
178 memcpy(dst, &w,
sizeof w);
180 uint8_t *p = (uint8_t *) dst;
186static BLAKE2_INLINE uint32_t load32(
const void *src)
188#if defined(NATIVE_LITTLE_ENDIAN)
190 memcpy(&w, src,
sizeof w);
193 const uint8_t *p = (
const uint8_t *) src;
194 return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16)
195 | ((uint32_t) (p[3]) << 24);
199static BLAKE2_INLINE uint64_t load48(
const void *src)
201 const uint8_t *p = (
const uint8_t *) src;
202 return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16)
203 | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40);
206static BLAKE2_INLINE
void store48(
void *dst, uint64_t w)
208 uint8_t *p = (uint8_t *) dst;
209 p[0] = (uint8_t) (w >> 0);
210 p[1] = (uint8_t) (w >> 8);
211 p[2] = (uint8_t) (w >> 16);
212 p[3] = (uint8_t) (w >> 24);
213 p[4] = (uint8_t) (w >> 32);
214 p[5] = (uint8_t) (w >> 40);
219static BLAKE2_INLINE
void store32(
void *dst, uint32_t w)
221#if defined(NATIVE_LITTLE_ENDIAN)
222 memcpy(dst, &w,
sizeof w);
224 uint8_t *p = (uint8_t *) dst;
225 p[0] = (uint8_t) (w >> 0);
226 p[1] = (uint8_t) (w >> 8);
227 p[2] = (uint8_t) (w >> 16);
228 p[3] = (uint8_t) (w >> 24);
231static BLAKE2_INLINE uint64_t load64(
const void *src)
233#if defined(NATIVE_LITTLE_ENDIAN)
235 memcpy(&w, src,
sizeof w);
238 const uint8_t *p = (
const uint8_t *) src;
239 return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16)
240 | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40)
241 | ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56);
245static BLAKE2_INLINE
void store64(
void *dst, uint64_t w)
247#if defined(NATIVE_LITTLE_ENDIAN)
248 memcpy(dst, &w,
sizeof w);
250 uint8_t *p = (uint8_t *) dst;
251 p[0] = (uint8_t) (w >> 0);
252 p[1] = (uint8_t) (w >> 8);
253 p[2] = (uint8_t) (w >> 16);
254 p[3] = (uint8_t) (w >> 24);
255 p[4] = (uint8_t) (w >> 32);
256 p[5] = (uint8_t) (w >> 40);
257 p[6] = (uint8_t) (w >> 48);
258 p[7] = (uint8_t) (w >> 56);
262#if defined(BLAKE2_UNUSED)
263static BLAKE2_INLINE uint32_t rotr32(
const uint32_t w,
const unsigned c)
265 return (w >> c) | (w << (32 - c));
269static BLAKE2_INLINE uint64_t rotr64(
const uint64_t w,
const unsigned c)
271 return (w >> c) | (w << (64 - c));
275static BLAKE2_INLINE
void secure_zero_memory(
void *v,
size_t n)
284static const uint64_t blake2b_IV[8] = {0x6a09e667f3bcc908ULL,
285 0xbb67ae8584caa73bULL,
286 0x3c6ef372fe94f82bULL,
287 0xa54ff53a5f1d36f1ULL,
288 0x510e527fade682d1ULL,
289 0x9b05688c2b3e6c1fULL,
290 0x1f83d9abfb41bd6bULL,
291 0x5be0cd19137e2179ULL};
293static const uint8_t blake2b_sigma[12][16] = {
294 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
295 {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
296 {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
297 {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
298 {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
299 {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
300 {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
301 {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
302 {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
303 {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
304 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
305 {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
308static void blake2b_set_lastnode(blake2b_state *S)
310 S->f[1] = (uint64_t) -1;
314static int blake2b_is_lastblock(
const blake2b_state *S)
319static void blake2b_set_lastblock(blake2b_state *S)
322 blake2b_set_lastnode(S);
325 S->f[0] = (uint64_t) -1;
328static void blake2b_increment_counter(blake2b_state *S,
const uint64_t inc)
331 S->t[1] += (S->t[0] < inc);
334static void blake2b_init0(blake2b_state *S)
337 memset(S, 0,
sizeof(blake2b_state));
339 for (i = 0; i < 8; ++i) {
340 S->h[i] = blake2b_IV[i];
345int blake2b_init_param(blake2b_state *S,
const blake2b_param *P)
347 const uint8_t *p = (
const uint8_t *) (P);
353 for (i = 0; i < 8; ++i) {
354 S->h[i] ^= load64(p +
sizeof(S->h[i]) * i);
357 S->outlen = P->digest_length;
361int blake2b_init(blake2b_state *S,
370 if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
371 return CX_INVALID_PARAMETER;
374 P->digest_length = (uint8_t) outlen;
378 store32(&P->leaf_length, 0);
379 store32(&P->node_offset, 0);
380 store32(&P->xof_length, 0);
383 memset(P->reserved, 0,
sizeof(P->reserved));
384 memset(P->salt, 0,
sizeof(P->salt));
385 memset(P->personal, 0,
sizeof(P->personal));
387 memcpy(P->salt, salt, salt_len);
390 memcpy(P->personal, personal, personal_len);
392 return blake2b_init_param(S, P);
395int blake2b_init_key(blake2b_state *S,
size_t outlen,
const void *key,
size_t keylen)
399 if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
403 if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
407 P->digest_length = (uint8_t) outlen;
408 P->key_length = (uint8_t) keylen;
411 store32(&P->leaf_length, 0);
412 store32(&P->node_offset, 0);
413 store32(&P->xof_length, 0);
416 memset(P->reserved, 0,
sizeof(P->reserved));
417 memset(P->salt, 0,
sizeof(P->salt));
418 memset(P->personal, 0,
sizeof(P->personal));
420 if (blake2b_init_param(S, P) < 0) {
426#define block G_cx.blake.block1
427 memset(block, 0, BLAKE2B_BLOCKBYTES);
428 memcpy(block, key, keylen);
429 blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
430 secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
436#define G(r, i, a, b, c, d) \
438 a = a + b + m[blake2b_sigma[r][2 * (i) + 0]]; \
439 d = rotr64(d ^ a, 32); \
441 b = rotr64(b ^ c, 24); \
442 a = a + b + m[blake2b_sigma[r][2 * (i) + 1]]; \
443 d = rotr64(d ^ a, 16); \
445 b = rotr64(b ^ c, 63); \
448static void blake2b_compress(blake2b_state *S,
const uint8_t block[BLAKE2B_BLOCKBYTES])
454#define m G_cx.blake.m
455#define v G_cx.blake.v
459 for (i = 0; i < 16; ++i) {
460 m[i] = load64(block + i *
sizeof(m[i]));
463 for (i = 0; i < 8; ++i) {
467 v[8] = blake2b_IV[0];
468 v[9] = blake2b_IV[1];
469 v[10] = blake2b_IV[2];
470 v[11] = blake2b_IV[3];
471 v[12] = blake2b_IV[4] ^ S->t[0];
472 v[13] = blake2b_IV[5] ^ S->t[1];
473 v[14] = blake2b_IV[6] ^ S->f[0];
474 v[15] = blake2b_IV[7] ^ S->f[1];
476 for (
int r = 0; r < 12; r++) {
477 for (i = 0; i < 4; i++) {
478 G(r, i, v[i], v[4 + i], v[8 + i], v[12 + i]);
481 for (i = 0; i < 4; i++) {
482 G(r, 4 + i, v[i], v[4 + ((i + 1) & 3)], v[8 + ((i + 2) & 3)], v[12 + ((i + 3) & 3)]);
486 for (i = 0; i < 8; ++i) {
487 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
496void blake2b_update(blake2b_state *S,
const void *pin,
size_t inlen)
498 const uint8_t *in = (
const uint8_t *) pin;
500 size_t left = S->buflen;
501 size_t fill = BLAKE2B_BLOCKBYTES - left;
504 memcpy(S->buf + left, in, fill);
505 blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
506 blake2b_compress(S, S->buf);
509 while (inlen > BLAKE2B_BLOCKBYTES) {
510 blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
511 blake2b_compress(S, in);
512 in += BLAKE2B_BLOCKBYTES;
513 inlen -= BLAKE2B_BLOCKBYTES;
516 memcpy(S->buf + S->buflen, in, inlen);
521int blake2b_final(blake2b_state *S,
void *out,
size_t outlen)
525#define buffer G_cx.blake.buffer
526 memset(buffer, 0, BLAKE2B_OUTBYTES);
528 if ((out != NULL) && (outlen < S->outlen)) {
532 if (blake2b_is_lastblock(S)) {
536 blake2b_increment_counter(S, S->buflen);
537 blake2b_set_lastblock(S);
538 memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen);
539 blake2b_compress(S, S->buf);
541 for (i = 0; i < 8; ++i) {
542 store64(buffer +
sizeof(S->h[i]) * i, S->h[i]);
544 memcpy(S->buf, buffer, S->outlen);
546 memcpy(out, buffer, S->outlen);
548 secure_zero_memory(buffer,
sizeof(buffer));
555#if defined(BLAKE2_UNUSED)
557int blake2b(
void *out,
size_t outlen,
const void *in,
size_t inlen,
const void *key,
size_t keylen)
562 if (NULL == in && inlen > 0) {
570 if (NULL == key && keylen > 0) {
574 if (!outlen || outlen > BLAKE2B_OUTBYTES) {
578 if (keylen > BLAKE2B_KEYBYTES) {
583 if (blake2b_init_key(S, outlen, key, keylen) < 0) {
588 if (blake2b_init(S, outlen) < 0) {
593 blake2b_update(S, (
const uint8_t *) in, inlen);
594 return blake2b_final(S, out, outlen);
597int blake2(
void *out,
size_t outlen,
const void *in,
size_t inlen,
const void *key,
size_t keylen)
599 return blake2b(out, outlen, in, inlen, key, keylen);
602#if defined(BLAKE2B_SELFTEST)
604#include "blake2-kat.h"
607 uint8_t key[BLAKE2B_KEYBYTES];
608 uint8_t buf[BLAKE2_KAT_LENGTH];
611 for (i = 0; i < BLAKE2B_KEYBYTES; ++i) {
612 key[i] = (uint8_t) i;
615 for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
616 buf[i] = (uint8_t) i;
620 for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
621 uint8_t hash[BLAKE2B_OUTBYTES];
622 blake2b(hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES);
624 if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
630 for (step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
631 for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
632 uint8_t hash[BLAKE2B_OUTBYTES];
638 if ((err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0) {
642 while (mlen >= step) {
643 blake2b_update(&S, p, step);
647 blake2b_update(&S, p, mlen);
648 if ((err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
652 if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {