Line | Count | Source |
1 | | /* |
2 | | * Copyright Supranational LLC |
3 | | * Licensed under the Apache License, Version 2.0, see LICENSE for details. |
4 | | * SPDX-License-Identifier: Apache-2.0 |
5 | | */ |
6 | | |
7 | | #include "consts.h" |
8 | | #include "bytes.h" |
9 | | #include "sha256.h" |
10 | | |
11 | | typedef struct { |
12 | | SHA256_CTX ctx; |
13 | | unsigned int h_ipad[8]; |
14 | | unsigned int h_opad[8]; |
15 | | union { limb_t l[64/sizeof(limb_t)]; unsigned char c[64]; } tail; |
16 | | } HMAC_SHA256_CTX; |
17 | | |
18 | | static void HMAC_init(HMAC_SHA256_CTX *ctx, const void *K, size_t K_len) |
19 | 0 | { |
20 | 0 | size_t i; |
21 | |
|
22 | 0 | if (K == NULL) { /* reuse h_ipad and h_opad */ |
23 | 0 | sha256_hcopy(ctx->ctx.h, ctx->h_ipad); |
24 | 0 | ctx->ctx.N = 64; |
25 | 0 | vec_zero(ctx->ctx.buf, sizeof(ctx->ctx.buf)); |
26 | 0 | ctx->ctx.off = 0; |
27 | |
|
28 | 0 | return; |
29 | 0 | } |
30 | | |
31 | 0 | vec_zero(ctx->tail.c, sizeof(ctx->tail)); |
32 | 0 | if (K_len > 64) { |
33 | 0 | sha256_init(&ctx->ctx); |
34 | 0 | sha256_update(&ctx->ctx, K, K_len); |
35 | 0 | sha256_final(ctx->tail.c, &ctx->ctx); |
36 | 0 | } else { |
37 | 0 | sha256_bcopy(ctx->tail.c, K, K_len); |
38 | 0 | } |
39 | |
|
40 | 0 | for (i = 0; i < 64/sizeof(limb_t); i++) |
41 | 0 | ctx->tail.l[i] ^= (limb_t)0x3636363636363636; |
42 | |
|
43 | 0 | sha256_init(&ctx->ctx); |
44 | 0 | sha256_update(&ctx->ctx, ctx->tail.c, 64); |
45 | 0 | sha256_hcopy(ctx->h_ipad, ctx->ctx.h); |
46 | |
|
47 | 0 | for (i = 0; i < 64/sizeof(limb_t); i++) |
48 | 0 | ctx->tail.l[i] ^= (limb_t)(0x3636363636363636 ^ 0x5c5c5c5c5c5c5c5c); |
49 | |
|
50 | 0 | sha256_init_h(ctx->h_opad); |
51 | 0 | sha256_block_data_order(ctx->h_opad, ctx->tail.c, 1); |
52 | |
|
53 | 0 | vec_zero(ctx->tail.c, sizeof(ctx->tail)); |
54 | 0 | ctx->tail.c[32] = 0x80; |
55 | 0 | ctx->tail.c[62] = 3; /* (64+32)*8 in big endian */ |
56 | 0 | ctx->tail.c[63] = 0; |
57 | 0 | } |
58 | | |
59 | | static void HMAC_update(HMAC_SHA256_CTX *ctx, const unsigned char *inp, |
60 | | size_t len) |
61 | 0 | { sha256_update(&ctx->ctx, inp, len); } |
62 | | |
63 | | static void HMAC_final(unsigned char md[32], HMAC_SHA256_CTX *ctx) |
64 | 0 | { |
65 | 0 | sha256_final(ctx->tail.c, &ctx->ctx); |
66 | 0 | sha256_hcopy(ctx->ctx.h, ctx->h_opad); |
67 | 0 | sha256_block_data_order(ctx->ctx.h, ctx->tail.c, 1); |
68 | 0 | sha256_emit(md, ctx->ctx.h); |
69 | 0 | } |
70 | | |
71 | | static void HKDF_Extract(unsigned char PRK[32], |
72 | | const void *salt, size_t salt_len, |
73 | | const void *IKM, size_t IKM_len, |
74 | | #ifndef __BLST_HKDF_TESTMODE__ |
75 | | int IKM_fixup, |
76 | | #endif |
77 | | HMAC_SHA256_CTX *ctx) |
78 | 0 | { |
79 | 0 | unsigned char zero[1] = { 0 }; |
80 | |
|
81 | 0 | HMAC_init(ctx, salt != NULL ? salt : zero, salt_len); |
82 | 0 | HMAC_update(ctx, IKM, IKM_len); |
83 | 0 | #ifndef __BLST_HKDF_TESTMODE__ |
84 | 0 | if (IKM_fixup) { |
85 | | /* Section 2.3 KeyGen in BLS-signature draft */ |
86 | 0 | HMAC_update(ctx, zero, 1); |
87 | 0 | } |
88 | 0 | #endif |
89 | 0 | HMAC_final(PRK, ctx); |
90 | 0 | } |
91 | | |
92 | | static void HKDF_Expand(unsigned char *OKM, size_t L, |
93 | | const unsigned char PRK[32], |
94 | | const void *info, size_t info_len, |
95 | | #ifndef __BLST_HKDF_TESTMODE__ |
96 | | int info_fixup, |
97 | | #endif |
98 | | HMAC_SHA256_CTX *ctx) |
99 | 0 | { |
100 | | #if !defined(__STDC_VERSION__) || __STDC_VERSION__<199901 \ |
101 | | || defined(__STDC_NO_VLA__) |
102 | | unsigned char *info_prime = alloca(info_len + 2 + 1); |
103 | | #else |
104 | 0 | unsigned char info_prime[info_len + 2 + 1]; |
105 | 0 | #endif |
106 | |
|
107 | 0 | HMAC_init(ctx, PRK, 32); |
108 | |
|
109 | 0 | if (info_len != 0) |
110 | 0 | sha256_bcopy(info_prime, info, info_len); |
111 | 0 | #ifndef __BLST_HKDF_TESTMODE__ |
112 | 0 | if (info_fixup) { |
113 | | /* Section 2.3 KeyGen in BLS-signature draft */ |
114 | 0 | info_prime[info_len + 0] = (unsigned char)(L >> 8); |
115 | 0 | info_prime[info_len + 1] = (unsigned char)(L); |
116 | 0 | info_len += 2; |
117 | 0 | } |
118 | 0 | #endif |
119 | 0 | info_prime[info_len] = 1; /* counter */ |
120 | 0 | HMAC_update(ctx, info_prime, info_len + 1); |
121 | 0 | HMAC_final(ctx->tail.c, ctx); |
122 | 0 | while (L > 32) { |
123 | 0 | sha256_hcopy((unsigned int *)OKM, (const unsigned int *)ctx->tail.c); |
124 | 0 | OKM += 32; L -= 32; |
125 | 0 | ++info_prime[info_len]; /* counter */ |
126 | 0 | HMAC_init(ctx, NULL, 0); |
127 | 0 | HMAC_update(ctx, ctx->tail.c, 32); |
128 | 0 | HMAC_update(ctx, info_prime, info_len + 1); |
129 | 0 | HMAC_final(ctx->tail.c, ctx); |
130 | 0 | } |
131 | 0 | sha256_bcopy(OKM, ctx->tail.c, L); |
132 | 0 | } |
133 | | |
134 | | #ifndef __BLST_HKDF_TESTMODE__ |
135 | | static void keygen(pow256 SK, const void *IKM, size_t IKM_len, |
136 | | const void *salt, size_t salt_len, |
137 | | const void *info, size_t info_len, |
138 | | int version) |
139 | 0 | { |
140 | 0 | struct { |
141 | 0 | HMAC_SHA256_CTX ctx; |
142 | 0 | unsigned char PRK[32], OKM[48]; |
143 | 0 | vec512 key; |
144 | 0 | } scratch; |
145 | 0 | unsigned char salt_prime[32] = "BLS-SIG-KEYGEN-SALT-"; |
146 | |
|
147 | 0 | if (IKM_len < 32 || (version > 4 && salt == NULL)) { |
148 | 0 | vec_zero(SK, sizeof(pow256)); |
149 | 0 | return; |
150 | 0 | } |
151 | | |
152 | | /* |
153 | | * Vet |info| since some callers were caught to be sloppy, e.g. |
154 | | * SWIG-4.0-generated Python wrapper... |
155 | | */ |
156 | 0 | info_len = info==NULL ? 0 : info_len; |
157 | |
|
158 | 0 | if (salt == NULL) { |
159 | 0 | salt = salt_prime; |
160 | 0 | salt_len = 20; |
161 | 0 | } |
162 | |
|
163 | 0 | if (version == 4) { |
164 | | /* salt = H(salt) */ |
165 | 0 | sha256_init(&scratch.ctx.ctx); |
166 | 0 | sha256_update(&scratch.ctx.ctx, salt, salt_len); |
167 | 0 | sha256_final(salt_prime, &scratch.ctx.ctx); |
168 | 0 | salt = salt_prime; |
169 | 0 | salt_len = sizeof(salt_prime); |
170 | 0 | } |
171 | |
|
172 | 0 | while (1) { |
173 | | /* PRK = HKDF-Extract(salt, IKM || I2OSP(0, 1)) */ |
174 | 0 | HKDF_Extract(scratch.PRK, salt, salt_len, |
175 | 0 | IKM, IKM_len, 1, &scratch.ctx); |
176 | | |
177 | | /* OKM = HKDF-Expand(PRK, key_info || I2OSP(L, 2), L) */ |
178 | 0 | HKDF_Expand(scratch.OKM, sizeof(scratch.OKM), scratch.PRK, |
179 | 0 | info, info_len, 1, &scratch.ctx); |
180 | | |
181 | | /* SK = OS2IP(OKM) mod r */ |
182 | 0 | vec_zero(scratch.key, sizeof(scratch.key)); |
183 | 0 | limbs_from_be_bytes(scratch.key, scratch.OKM, sizeof(scratch.OKM)); |
184 | 0 | redc_mont_256(scratch.key, scratch.key, BLS12_381_r, r0); |
185 | | /* |
186 | | * Given that mul_mont_sparse_256 has special boundary conditions |
187 | | * it's appropriate to mention that redc_mont_256 output is fully |
188 | | * reduced at this point. Because we started with 384-bit input, |
189 | | * one with most significant half smaller than the modulus. |
190 | | */ |
191 | 0 | mul_mont_sparse_256(scratch.key, scratch.key, BLS12_381_rRR, |
192 | 0 | BLS12_381_r, r0); |
193 | |
|
194 | 0 | if (version < 4 || !vec_is_zero(scratch.key, sizeof(vec256))) |
195 | 0 | break; |
196 | | |
197 | | /* salt = H(salt) */ |
198 | 0 | sha256_init(&scratch.ctx.ctx); |
199 | 0 | sha256_update(&scratch.ctx.ctx, salt, salt_len); |
200 | 0 | sha256_final(salt_prime, &scratch.ctx.ctx); |
201 | 0 | salt = salt_prime; |
202 | 0 | salt_len = sizeof(salt_prime); |
203 | 0 | } |
204 | |
|
205 | 0 | le_bytes_from_limbs(SK, scratch.key, sizeof(pow256)); |
206 | | |
207 | | /* |
208 | | * scrub the stack just in case next callee inadvertently flashes |
209 | | * a fragment across application boundary... |
210 | | */ |
211 | 0 | vec_zero(&scratch, sizeof(scratch)); |
212 | 0 | } |
213 | | |
214 | | void blst_keygen(pow256 SK, const void *IKM, size_t IKM_len, |
215 | | const void *info, size_t info_len) |
216 | 0 | { keygen(SK, IKM, IKM_len, NULL, 0, info, info_len, 4); } |
217 | | |
218 | | void blst_keygen_v3(pow256 SK, const void *IKM, size_t IKM_len, |
219 | | const void *info, size_t info_len) |
220 | 0 | { keygen(SK, IKM, IKM_len, NULL, 0, info, info_len, 3); } |
221 | | |
222 | | void blst_keygen_v4_5(pow256 SK, const void *IKM, size_t IKM_len, |
223 | | const void *salt, size_t salt_len, |
224 | | const void *info, size_t info_len) |
225 | 0 | { keygen(SK, IKM, IKM_len, salt, salt_len, info, info_len, 4); } |
226 | | |
227 | | void blst_keygen_v5(pow256 SK, const void *IKM, size_t IKM_len, |
228 | | const void *salt, size_t salt_len, |
229 | | const void *info, size_t info_len) |
230 | 0 | { keygen(SK, IKM, IKM_len, salt, salt_len, info, info_len, 5); } |
231 | | |
232 | | /* |
233 | | * https://eips.ethereum.org/EIPS/eip-2333 |
234 | | */ |
235 | | void blst_derive_master_eip2333(pow256 SK, const void *seed, size_t seed_len) |
236 | 0 | { keygen(SK, seed, seed_len, NULL, 0, NULL, 0, 4); } |
237 | | |
238 | | static void parent_SK_to_lamport_PK(pow256 PK, const pow256 parent_SK, |
239 | | unsigned int index) |
240 | 0 | { |
241 | 0 | size_t i; |
242 | 0 | struct { |
243 | 0 | HMAC_SHA256_CTX ctx; |
244 | 0 | SHA256_CTX ret; |
245 | 0 | unsigned char PRK[32], IKM[32]; |
246 | 0 | unsigned char lamport[255][32]; |
247 | 0 | } scratch; |
248 | | |
249 | | /* salt = I2OSP(index, 4) */ |
250 | 0 | unsigned char salt[4] = { (unsigned char)(index>>24), |
251 | 0 | (unsigned char)(index>>16), |
252 | 0 | (unsigned char)(index>>8), |
253 | 0 | (unsigned char)(index) }; |
254 | | |
255 | | /* IKM = I2OSP(parent_SK, 32) */ |
256 | 0 | for (i = 0; i < 32; i++) |
257 | 0 | scratch.IKM[i] = parent_SK[31-i]; |
258 | | |
259 | | /* lamport_0 = IKM_to_lamport_SK(IKM, salt) */ |
260 | 0 | HKDF_Extract(scratch.PRK, salt, sizeof(salt), scratch.IKM, 32, 0, |
261 | 0 | &scratch.ctx); |
262 | 0 | HKDF_Expand(scratch.lamport[0], sizeof(scratch.lamport), |
263 | 0 | scratch.PRK, NULL, 0, 0, &scratch.ctx); |
264 | |
|
265 | 0 | vec_zero(scratch.ctx.ctx.buf, sizeof(scratch.ctx.ctx.buf)); |
266 | 0 | scratch.ctx.ctx.buf[32] = 0x80; |
267 | 0 | scratch.ctx.ctx.buf[62] = 1; /* 32*8 in big endian */ |
268 | 0 | scratch.ctx.ctx.buf[63] = 0; |
269 | 0 | for (i = 0; i < 255; i++) { |
270 | | /* lamport_PK = lamport_PK | SHA256(lamport_0[i]) */ |
271 | 0 | sha256_init_h(scratch.ctx.ctx.h); |
272 | 0 | sha256_bcopy(scratch.ctx.ctx.buf, scratch.lamport[i], 32); |
273 | 0 | sha256_block_data_order(scratch.ctx.ctx.h, scratch.ctx.ctx.buf, 1); |
274 | 0 | sha256_emit(scratch.lamport[i], scratch.ctx.ctx.h); |
275 | 0 | } |
276 | | |
277 | | /* compressed_lamport_PK = SHA256(lamport_PK) */ |
278 | 0 | sha256_init(&scratch.ret); |
279 | 0 | sha256_update(&scratch.ret, scratch.lamport, sizeof(scratch.lamport)); |
280 | | |
281 | | /* not_IKM = flip_bits(IKM) */ |
282 | 0 | for (i = 0; i< 32; i++) |
283 | 0 | scratch.IKM[i] = ~scratch.IKM[i]; |
284 | | |
285 | | /* lamport_1 = IKM_to_lamport_SK(not_IKM, salt) */ |
286 | 0 | HKDF_Extract(scratch.PRK, salt, sizeof(salt), scratch.IKM, 32, 0, |
287 | 0 | &scratch.ctx); |
288 | 0 | HKDF_Expand(scratch.lamport[0], sizeof(scratch.lamport), |
289 | 0 | scratch.PRK, NULL, 0, 0, &scratch.ctx); |
290 | |
|
291 | 0 | vec_zero(scratch.ctx.ctx.buf, sizeof(scratch.ctx.ctx.buf)); |
292 | 0 | scratch.ctx.ctx.buf[32] = 0x80; |
293 | 0 | scratch.ctx.ctx.buf[62] = 1; |
294 | 0 | for (i = 0; i < 255; i++) { |
295 | | /* lamport_PK = lamport_PK | SHA256(lamport_1[i]) */ |
296 | 0 | sha256_init_h(scratch.ctx.ctx.h); |
297 | 0 | sha256_bcopy(scratch.ctx.ctx.buf, scratch.lamport[i], 32); |
298 | 0 | sha256_block_data_order(scratch.ctx.ctx.h, scratch.ctx.ctx.buf, 1); |
299 | 0 | sha256_emit(scratch.lamport[i], scratch.ctx.ctx.h); |
300 | 0 | } |
301 | | |
302 | | /* compressed_lamport_PK = SHA256(lamport_PK) */ |
303 | 0 | sha256_update(&scratch.ret, scratch.lamport, sizeof(scratch.lamport)); |
304 | 0 | sha256_final(PK, &scratch.ret); |
305 | | |
306 | | /* |
307 | | * scrub the stack just in case next callee inadvertently flashes |
308 | | * a fragment across application boundary... |
309 | | */ |
310 | 0 | vec_zero(&scratch, sizeof(scratch)); |
311 | 0 | } |
312 | | |
313 | | void blst_derive_child_eip2333(pow256 SK, const pow256 parent_SK, |
314 | | unsigned int child_index) |
315 | 0 | { |
316 | 0 | parent_SK_to_lamport_PK(SK, parent_SK, child_index); |
317 | 0 | keygen(SK, SK, sizeof(pow256), NULL, 0, NULL, 0, 4); |
318 | 0 | } |
319 | | #endif |