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