1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2021, Google Inc.
2*8fb009dcSAndroid Build Coastguard Worker *
3*8fb009dcSAndroid Build Coastguard Worker * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker *
7*8fb009dcSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker #include <openssl/blake2.h>
16*8fb009dcSAndroid Build Coastguard Worker
17*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
18*8fb009dcSAndroid Build Coastguard Worker
19*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
20*8fb009dcSAndroid Build Coastguard Worker
21*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7693#section-2.6
22*8fb009dcSAndroid Build Coastguard Worker static const uint64_t kIV[8] = {
23*8fb009dcSAndroid Build Coastguard Worker UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
24*8fb009dcSAndroid Build Coastguard Worker UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
25*8fb009dcSAndroid Build Coastguard Worker UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
26*8fb009dcSAndroid Build Coastguard Worker UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179),
27*8fb009dcSAndroid Build Coastguard Worker };
28*8fb009dcSAndroid Build Coastguard Worker
29*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7693#section-2.7
30*8fb009dcSAndroid Build Coastguard Worker static const uint8_t kSigma[10 * 16] = {
31*8fb009dcSAndroid Build Coastguard Worker // clang-format off
32*8fb009dcSAndroid Build Coastguard Worker 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
33*8fb009dcSAndroid Build Coastguard Worker 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
34*8fb009dcSAndroid Build Coastguard Worker 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
35*8fb009dcSAndroid Build Coastguard Worker 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
36*8fb009dcSAndroid Build Coastguard Worker 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
37*8fb009dcSAndroid Build Coastguard Worker 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
38*8fb009dcSAndroid Build Coastguard Worker 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
39*8fb009dcSAndroid Build Coastguard Worker 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
40*8fb009dcSAndroid Build Coastguard Worker 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
41*8fb009dcSAndroid Build Coastguard Worker 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
42*8fb009dcSAndroid Build Coastguard Worker // clang-format on
43*8fb009dcSAndroid Build Coastguard Worker };
44*8fb009dcSAndroid Build Coastguard Worker
45*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7693#section-3.1
blake2b_mix(uint64_t v[16],int a,int b,int c,int d,uint64_t x,uint64_t y)46*8fb009dcSAndroid Build Coastguard Worker static void blake2b_mix(uint64_t v[16], int a, int b, int c, int d, uint64_t x,
47*8fb009dcSAndroid Build Coastguard Worker uint64_t y) {
48*8fb009dcSAndroid Build Coastguard Worker v[a] = v[a] + v[b] + x;
49*8fb009dcSAndroid Build Coastguard Worker v[d] = CRYPTO_rotr_u64(v[d] ^ v[a], 32);
50*8fb009dcSAndroid Build Coastguard Worker v[c] = v[c] + v[d];
51*8fb009dcSAndroid Build Coastguard Worker v[b] = CRYPTO_rotr_u64(v[b] ^ v[c], 24);
52*8fb009dcSAndroid Build Coastguard Worker v[a] = v[a] + v[b] + y;
53*8fb009dcSAndroid Build Coastguard Worker v[d] = CRYPTO_rotr_u64(v[d] ^ v[a], 16);
54*8fb009dcSAndroid Build Coastguard Worker v[c] = v[c] + v[d];
55*8fb009dcSAndroid Build Coastguard Worker v[b] = CRYPTO_rotr_u64(v[b] ^ v[c], 63);
56*8fb009dcSAndroid Build Coastguard Worker }
57*8fb009dcSAndroid Build Coastguard Worker
blake2b_load(const uint8_t block[BLAKE2B_CBLOCK],size_t i)58*8fb009dcSAndroid Build Coastguard Worker static uint64_t blake2b_load(const uint8_t block[BLAKE2B_CBLOCK], size_t i) {
59*8fb009dcSAndroid Build Coastguard Worker return CRYPTO_load_u64_le(block + 8 * i);
60*8fb009dcSAndroid Build Coastguard Worker }
61*8fb009dcSAndroid Build Coastguard Worker
blake2b_transform(BLAKE2B_CTX * b2b,const uint8_t block[BLAKE2B_CBLOCK],size_t num_bytes,int is_final_block)62*8fb009dcSAndroid Build Coastguard Worker static void blake2b_transform(BLAKE2B_CTX *b2b,
63*8fb009dcSAndroid Build Coastguard Worker const uint8_t block[BLAKE2B_CBLOCK],
64*8fb009dcSAndroid Build Coastguard Worker size_t num_bytes, int is_final_block) {
65*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7693#section-3.2
66*8fb009dcSAndroid Build Coastguard Worker uint64_t v[16];
67*8fb009dcSAndroid Build Coastguard Worker static_assert(sizeof(v) == sizeof(b2b->h) + sizeof(kIV), "");
68*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(v, b2b->h, sizeof(b2b->h));
69*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&v[8], kIV, sizeof(kIV));
70*8fb009dcSAndroid Build Coastguard Worker
71*8fb009dcSAndroid Build Coastguard Worker b2b->t_low += num_bytes;
72*8fb009dcSAndroid Build Coastguard Worker if (b2b->t_low < num_bytes) {
73*8fb009dcSAndroid Build Coastguard Worker b2b->t_high++;
74*8fb009dcSAndroid Build Coastguard Worker }
75*8fb009dcSAndroid Build Coastguard Worker v[12] ^= b2b->t_low;
76*8fb009dcSAndroid Build Coastguard Worker v[13] ^= b2b->t_high;
77*8fb009dcSAndroid Build Coastguard Worker
78*8fb009dcSAndroid Build Coastguard Worker if (is_final_block) {
79*8fb009dcSAndroid Build Coastguard Worker v[14] = ~v[14];
80*8fb009dcSAndroid Build Coastguard Worker }
81*8fb009dcSAndroid Build Coastguard Worker
82*8fb009dcSAndroid Build Coastguard Worker for (int round = 0; round < 12; round++) {
83*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const s = &kSigma[16 * (round % 10)];
84*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 0, 4, 8, 12, blake2b_load(block, s[0]),
85*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[1]));
86*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 1, 5, 9, 13, blake2b_load(block, s[2]),
87*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[3]));
88*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 2, 6, 10, 14, blake2b_load(block, s[4]),
89*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[5]));
90*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 3, 7, 11, 15, blake2b_load(block, s[6]),
91*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[7]));
92*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 0, 5, 10, 15, blake2b_load(block, s[8]),
93*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[9]));
94*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 1, 6, 11, 12, blake2b_load(block, s[10]),
95*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[11]));
96*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 2, 7, 8, 13, blake2b_load(block, s[12]),
97*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[13]));
98*8fb009dcSAndroid Build Coastguard Worker blake2b_mix(v, 3, 4, 9, 14, blake2b_load(block, s[14]),
99*8fb009dcSAndroid Build Coastguard Worker blake2b_load(block, s[15]));
100*8fb009dcSAndroid Build Coastguard Worker }
101*8fb009dcSAndroid Build Coastguard Worker
102*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(b2b->h); i++) {
103*8fb009dcSAndroid Build Coastguard Worker b2b->h[i] ^= v[i];
104*8fb009dcSAndroid Build Coastguard Worker b2b->h[i] ^= v[i + 8];
105*8fb009dcSAndroid Build Coastguard Worker }
106*8fb009dcSAndroid Build Coastguard Worker }
107*8fb009dcSAndroid Build Coastguard Worker
BLAKE2B256_Init(BLAKE2B_CTX * b2b)108*8fb009dcSAndroid Build Coastguard Worker void BLAKE2B256_Init(BLAKE2B_CTX *b2b) {
109*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(b2b, 0, sizeof(BLAKE2B_CTX));
110*8fb009dcSAndroid Build Coastguard Worker
111*8fb009dcSAndroid Build Coastguard Worker static_assert(sizeof(kIV) == sizeof(b2b->h), "");
112*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&b2b->h, kIV, sizeof(kIV));
113*8fb009dcSAndroid Build Coastguard Worker
114*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7693#section-2.5
115*8fb009dcSAndroid Build Coastguard Worker b2b->h[0] ^= 0x01010000 | BLAKE2B256_DIGEST_LENGTH;
116*8fb009dcSAndroid Build Coastguard Worker }
117*8fb009dcSAndroid Build Coastguard Worker
BLAKE2B256_Update(BLAKE2B_CTX * b2b,const void * in_data,size_t len)118*8fb009dcSAndroid Build Coastguard Worker void BLAKE2B256_Update(BLAKE2B_CTX *b2b, const void *in_data, size_t len) {
119*8fb009dcSAndroid Build Coastguard Worker if (len == 0) {
120*8fb009dcSAndroid Build Coastguard Worker // Work around a C language bug. See https://crbug.com/1019588.
121*8fb009dcSAndroid Build Coastguard Worker return;
122*8fb009dcSAndroid Build Coastguard Worker }
123*8fb009dcSAndroid Build Coastguard Worker
124*8fb009dcSAndroid Build Coastguard Worker const uint8_t *data = in_data;
125*8fb009dcSAndroid Build Coastguard Worker size_t todo = sizeof(b2b->block) - b2b->block_used;
126*8fb009dcSAndroid Build Coastguard Worker if (todo > len) {
127*8fb009dcSAndroid Build Coastguard Worker todo = len;
128*8fb009dcSAndroid Build Coastguard Worker }
129*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&b2b->block[b2b->block_used], data, todo);
130*8fb009dcSAndroid Build Coastguard Worker b2b->block_used += todo;
131*8fb009dcSAndroid Build Coastguard Worker data += todo;
132*8fb009dcSAndroid Build Coastguard Worker len -= todo;
133*8fb009dcSAndroid Build Coastguard Worker
134*8fb009dcSAndroid Build Coastguard Worker if (!len) {
135*8fb009dcSAndroid Build Coastguard Worker return;
136*8fb009dcSAndroid Build Coastguard Worker }
137*8fb009dcSAndroid Build Coastguard Worker
138*8fb009dcSAndroid Build Coastguard Worker // More input remains therefore we must have filled |b2b->block|.
139*8fb009dcSAndroid Build Coastguard Worker assert(b2b->block_used == BLAKE2B_CBLOCK);
140*8fb009dcSAndroid Build Coastguard Worker blake2b_transform(b2b, b2b->block, BLAKE2B_CBLOCK,
141*8fb009dcSAndroid Build Coastguard Worker /*is_final_block=*/0);
142*8fb009dcSAndroid Build Coastguard Worker b2b->block_used = 0;
143*8fb009dcSAndroid Build Coastguard Worker
144*8fb009dcSAndroid Build Coastguard Worker while (len > BLAKE2B_CBLOCK) {
145*8fb009dcSAndroid Build Coastguard Worker blake2b_transform(b2b, data, BLAKE2B_CBLOCK, /*is_final_block=*/0);
146*8fb009dcSAndroid Build Coastguard Worker data += BLAKE2B_CBLOCK;
147*8fb009dcSAndroid Build Coastguard Worker len -= BLAKE2B_CBLOCK;
148*8fb009dcSAndroid Build Coastguard Worker }
149*8fb009dcSAndroid Build Coastguard Worker
150*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(b2b->block, data, len);
151*8fb009dcSAndroid Build Coastguard Worker b2b->block_used = len;
152*8fb009dcSAndroid Build Coastguard Worker }
153*8fb009dcSAndroid Build Coastguard Worker
BLAKE2B256_Final(uint8_t out[BLAKE2B256_DIGEST_LENGTH],BLAKE2B_CTX * b2b)154*8fb009dcSAndroid Build Coastguard Worker void BLAKE2B256_Final(uint8_t out[BLAKE2B256_DIGEST_LENGTH], BLAKE2B_CTX *b2b) {
155*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(&b2b->block[b2b->block_used], 0,
156*8fb009dcSAndroid Build Coastguard Worker sizeof(b2b->block) - b2b->block_used);
157*8fb009dcSAndroid Build Coastguard Worker blake2b_transform(b2b, b2b->block, b2b->block_used,
158*8fb009dcSAndroid Build Coastguard Worker /*is_final_block=*/1);
159*8fb009dcSAndroid Build Coastguard Worker static_assert(BLAKE2B256_DIGEST_LENGTH <= sizeof(b2b->h), "");
160*8fb009dcSAndroid Build Coastguard Worker memcpy(out, b2b->h, BLAKE2B256_DIGEST_LENGTH);
161*8fb009dcSAndroid Build Coastguard Worker }
162*8fb009dcSAndroid Build Coastguard Worker
BLAKE2B256(const uint8_t * data,size_t len,uint8_t out[BLAKE2B256_DIGEST_LENGTH])163*8fb009dcSAndroid Build Coastguard Worker void BLAKE2B256(const uint8_t *data, size_t len,
164*8fb009dcSAndroid Build Coastguard Worker uint8_t out[BLAKE2B256_DIGEST_LENGTH]) {
165*8fb009dcSAndroid Build Coastguard Worker BLAKE2B_CTX ctx;
166*8fb009dcSAndroid Build Coastguard Worker BLAKE2B256_Init(&ctx);
167*8fb009dcSAndroid Build Coastguard Worker BLAKE2B256_Update(&ctx, data, len);
168*8fb009dcSAndroid Build Coastguard Worker BLAKE2B256_Final(out, &ctx);
169*8fb009dcSAndroid Build Coastguard Worker }
170