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 | | * Why this file? Overall goal is to ensure that all internal calls |
8 | | * remain internal after linking application. This is to both |
9 | | * |
10 | | * a) minimize possibility of external name conflicts (since all |
11 | | * non-blst-prefixed and [assembly subroutines] remain static); |
12 | | * b) preclude possibility of unintentional internal reference |
13 | | * overload in shared library context (one can achieve same |
14 | | * effect with -Bsymbolic, but we don't want to rely on end-user |
15 | | * to remember to use it); |
16 | | */ |
17 | | |
18 | | #include "fields.h" |
19 | | #include "bytes.h" |
20 | | |
21 | | /* |
22 | | * BLS12-381-specific Fr shortcuts to assembly. |
23 | | */ |
24 | | void blst_fr_add(vec256 ret, const vec256 a, const vec256 b) |
25 | 21 | { add_mod_256(ret, a, b, BLS12_381_r); } |
26 | | |
27 | | void blst_fr_sub(vec256 ret, const vec256 a, const vec256 b) |
28 | 142 | { sub_mod_256(ret, a, b, BLS12_381_r); } |
29 | | |
30 | | void blst_fr_mul_by_3(vec256 ret, const vec256 a) |
31 | 3 | { mul_by_3_mod_256(ret, a, BLS12_381_r); } |
32 | | |
33 | | void blst_fr_lshift(vec256 ret, const vec256 a, size_t count) |
34 | 23 | { lshift_mod_256(ret, a, count, BLS12_381_r); } |
35 | | |
36 | | void blst_fr_rshift(vec256 ret, const vec256 a, size_t count) |
37 | 130 | { rshift_mod_256(ret, a, count, BLS12_381_r); } |
38 | | |
39 | | void blst_fr_mul(vec256 ret, const vec256 a, const vec256 b) |
40 | 91 | { mul_mont_sparse_256(ret, a, b, BLS12_381_r, r0); } |
41 | | |
42 | | void blst_fr_ct_bfly(vec256 x0, vec256 x1, const vec256 twiddle) |
43 | 0 | { |
44 | 0 | vec256 x2; |
45 | |
|
46 | 0 | mul_mont_sparse_256(x2, x1, twiddle, BLS12_381_r, r0); |
47 | 0 | sub_mod_256(x1, x0, x2, BLS12_381_r); |
48 | 0 | add_mod_256(x0, x0, x2, BLS12_381_r); |
49 | 0 | } |
50 | | |
51 | | void blst_fr_gs_bfly(vec256 x0, vec256 x1, const vec256 twiddle) |
52 | 0 | { |
53 | 0 | vec256 x2; |
54 | |
|
55 | 0 | sub_mod_256(x2, x0, x1, BLS12_381_r); |
56 | 0 | add_mod_256(x0, x0, x1, BLS12_381_r); |
57 | 0 | mul_mont_sparse_256(x1, x2, twiddle, BLS12_381_r, r0); |
58 | 0 | } |
59 | | |
60 | | void blst_fr_sqr(vec256 ret, const vec256 a) |
61 | 38 | { sqr_mont_sparse_256(ret, a, BLS12_381_r, r0); } |
62 | | |
63 | | void blst_fr_cneg(vec256 ret, const vec256 a, int flag) |
64 | 8 | { cneg_mod_256(ret, a, is_zero(flag) ^ 1, BLS12_381_r); } |
65 | | |
66 | | void blst_fr_to(vec256 ret, const vec256 a) |
67 | 0 | { mul_mont_sparse_256(ret, BLS12_381_rRR, a, BLS12_381_r, r0); } |
68 | | |
69 | | void blst_fr_from(vec256 ret, const vec256 a) |
70 | 0 | { from_mont_256(ret, a, BLS12_381_r, r0); } |
71 | | |
72 | | void blst_fr_from_scalar(vec256 ret, const pow256 a) |
73 | 0 | { |
74 | 0 | const union { |
75 | 0 | long one; |
76 | 0 | char little; |
77 | 0 | } is_endian = { 1 }; |
78 | |
|
79 | 0 | if ((uptr_t)ret == (uptr_t)a && is_endian.little) { |
80 | 0 | mul_mont_sparse_256(ret, BLS12_381_rRR, (const limb_t *)a, |
81 | 0 | BLS12_381_r, r0); |
82 | 0 | } else { |
83 | 0 | vec256 out; |
84 | 0 | limbs_from_le_bytes(out, a, 32); |
85 | 0 | mul_mont_sparse_256(ret, BLS12_381_rRR, out, BLS12_381_r, r0); |
86 | 0 | vec_zero(out, sizeof(out)); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | void blst_scalar_from_fr(pow256 ret, const vec256 a) |
91 | 0 | { |
92 | 0 | const union { |
93 | 0 | long one; |
94 | 0 | char little; |
95 | 0 | } is_endian = { 1 }; |
96 | |
|
97 | 0 | if ((uptr_t)ret == (uptr_t)a && is_endian.little) { |
98 | 0 | from_mont_256((limb_t *)ret, a, BLS12_381_r, r0); |
99 | 0 | } else { |
100 | 0 | vec256 out; |
101 | 0 | from_mont_256(out, a, BLS12_381_r, r0); |
102 | 0 | le_bytes_from_limbs(ret, out, 32); |
103 | 0 | vec_zero(out, sizeof(out)); |
104 | 0 | } |
105 | 0 | } |
106 | | |
107 | | int blst_scalar_fr_check(const pow256 a) |
108 | 0 | { return (int)(check_mod_256(a, BLS12_381_r) | |
109 | 0 | bytes_are_zero(a, sizeof(pow256))); |
110 | 0 | } |
111 | | |
112 | | int blst_sk_check(const pow256 a) |
113 | 336 | { return (int)check_mod_256(a, BLS12_381_r); } |
114 | | |
115 | | int blst_sk_add_n_check(pow256 ret, const pow256 a, const pow256 b) |
116 | 0 | { return (int)add_n_check_mod_256(ret, a, b, BLS12_381_r); } |
117 | | |
118 | | int blst_sk_sub_n_check(pow256 ret, const pow256 a, const pow256 b) |
119 | 0 | { return (int)sub_n_check_mod_256(ret, a, b, BLS12_381_r); } |
120 | | |
121 | | int blst_sk_mul_n_check(pow256 ret, const pow256 a, const pow256 b) |
122 | 0 | { |
123 | 0 | vec256 t[2]; |
124 | 0 | const union { |
125 | 0 | long one; |
126 | 0 | char little; |
127 | 0 | } is_endian = { 1 }; |
128 | 0 | bool_t is_zero; |
129 | |
|
130 | 0 | if (((size_t)a|(size_t)b)%sizeof(limb_t) != 0 || !is_endian.little) { |
131 | 0 | limbs_from_le_bytes(t[0], a, sizeof(pow256)); |
132 | 0 | limbs_from_le_bytes(t[1], b, sizeof(pow256)); |
133 | 0 | a = (const byte *)t[0]; |
134 | 0 | b = (const byte *)t[1]; |
135 | 0 | } |
136 | 0 | mul_mont_sparse_256(t[0], BLS12_381_rRR, (const limb_t *)a, BLS12_381_r, r0); |
137 | 0 | mul_mont_sparse_256(t[0], t[0], (const limb_t *)b, BLS12_381_r, r0); |
138 | 0 | le_bytes_from_limbs(ret, t[0], sizeof(pow256)); |
139 | 0 | is_zero = vec_is_zero(t[0], sizeof(vec256)); |
140 | 0 | vec_zero(t, sizeof(t)); |
141 | |
|
142 | 0 | return (int)(is_zero^1); |
143 | 0 | } |
144 | | |
145 | | void blst_sk_inverse(pow256 ret, const pow256 a) |
146 | 0 | { |
147 | 0 | const union { |
148 | 0 | long one; |
149 | 0 | char little; |
150 | 0 | } is_endian = { 1 }; |
151 | |
|
152 | 0 | if (((size_t)a|(size_t)ret)%sizeof(limb_t) == 0 && is_endian.little) { |
153 | 0 | limb_t *out = (limb_t *)ret; |
154 | 0 | mul_mont_sparse_256(out, BLS12_381_rRR, (const limb_t *)a, |
155 | 0 | BLS12_381_r, r0); |
156 | 0 | reciprocal_fr(out, out); |
157 | 0 | from_mont_256(out, out, BLS12_381_r, r0); |
158 | 0 | } else { |
159 | 0 | vec256 out; |
160 | 0 | limbs_from_le_bytes(out, a, 32); |
161 | 0 | mul_mont_sparse_256(out, BLS12_381_rRR, out, BLS12_381_r, r0); |
162 | 0 | reciprocal_fr(out, out); |
163 | 0 | from_mont_256(out, out, BLS12_381_r, r0); |
164 | 0 | le_bytes_from_limbs(ret, out, 32); |
165 | 0 | vec_zero(out, sizeof(out)); |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | | /* |
170 | | * BLS12-381-specific Fp shortcuts to assembly. |
171 | | */ |
172 | | void blst_fp_add(vec384 ret, const vec384 a, const vec384 b) |
173 | 7 | { add_fp(ret, a, b); } |
174 | | |
175 | | void blst_fp_sub(vec384 ret, const vec384 a, const vec384 b) |
176 | 28 | { sub_fp(ret, a, b); } |
177 | | |
178 | | void blst_fp_mul_by_3(vec384 ret, const vec384 a) |
179 | 3 | { mul_by_3_fp(ret, a); } |
180 | | |
181 | | void blst_fp_mul_by_8(vec384 ret, const vec384 a) |
182 | 4 | { mul_by_8_fp(ret, a); } |
183 | | |
184 | | void blst_fp_lshift(vec384 ret, const vec384 a, size_t count) |
185 | 20 | { lshift_fp(ret, a, count); } |
186 | | |
187 | | void blst_fp_mul(vec384 ret, const vec384 a, const vec384 b) |
188 | 210 | { mul_fp(ret, a, b); } |
189 | | |
190 | | void blst_fp_sqr(vec384 ret, const vec384 a) |
191 | 209 | { sqr_fp(ret, a); } |
192 | | |
193 | | void blst_fp_cneg(vec384 ret, const vec384 a, int flag) |
194 | 112 | { cneg_fp(ret, a, is_zero(flag) ^ 1); } |
195 | | |
196 | | void blst_fp_to(vec384 ret, const vec384 a) |
197 | 0 | { mul_fp(ret, a, BLS12_381_RR); } |
198 | | |
199 | | void blst_fp_from(vec384 ret, const vec384 a) |
200 | 0 | { from_fp(ret, a); } |
201 | | |
202 | | /* |
203 | | * Fp serialization/deserialization. |
204 | | */ |
205 | | void blst_fp_from_uint32(vec384 ret, const unsigned int a[12]) |
206 | 0 | { |
207 | 0 | if (sizeof(limb_t) == 8) { |
208 | 0 | int i; |
209 | 0 | for (i = 0; i < 6; i++) |
210 | 0 | ret[i] = a[2*i] | ((limb_t)a[2*i+1] << (32 & (8*sizeof(limb_t)-1))); |
211 | 0 | a = (const unsigned int *)ret; |
212 | 0 | } |
213 | 0 | mul_fp(ret, (const limb_t *)a, BLS12_381_RR); |
214 | 0 | } |
215 | | |
216 | | void blst_uint32_from_fp(unsigned int ret[12], const vec384 a) |
217 | 0 | { |
218 | 0 | if (sizeof(limb_t) == 4) { |
219 | 0 | from_fp((limb_t *)ret, a); |
220 | 0 | } else { |
221 | 0 | vec384 out; |
222 | 0 | int i; |
223 | |
|
224 | 0 | from_fp(out, a); |
225 | 0 | for (i = 0; i < 6; i++) { |
226 | 0 | limb_t limb = out[i]; |
227 | 0 | ret[2*i] = (unsigned int)limb; |
228 | 0 | ret[2*i+1] = (unsigned int)(limb >> (32 & (8*sizeof(limb_t)-1))); |
229 | 0 | } |
230 | 0 | } |
231 | 0 | } |
232 | | |
233 | | void blst_fp_from_uint64(vec384 ret, const unsigned long long a[6]) |
234 | 9.23k | { |
235 | 9.23k | const union { |
236 | 9.23k | long one; |
237 | 9.23k | char little; |
238 | 9.23k | } is_endian = { 1 }; |
239 | | |
240 | 9.23k | if (sizeof(limb_t) == 4 && !is_endian.little) { |
241 | 0 | int i; |
242 | 0 | for (i = 0; i < 6; i++) { |
243 | 0 | unsigned long long limb = a[i]; |
244 | 0 | ret[2*i] = (limb_t)limb; |
245 | 0 | ret[2*i+1] = (limb_t)(limb >> 32); |
246 | 0 | } |
247 | 0 | a = (const unsigned long long *)ret; |
248 | 0 | } |
249 | 9.23k | mul_fp(ret, (const limb_t *)a, BLS12_381_RR); |
250 | 9.23k | } |
251 | | |
252 | | void blst_uint64_from_fp(unsigned long long ret[6], const vec384 a) |
253 | 5.17k | { |
254 | 5.17k | const union { |
255 | 5.17k | long one; |
256 | 5.17k | char little; |
257 | 5.17k | } is_endian = { 1 }; |
258 | | |
259 | 5.17k | if (sizeof(limb_t) == 8 || is_endian.little) { |
260 | 5.17k | from_fp((limb_t *)ret, a); |
261 | 5.17k | } else { |
262 | 0 | vec384 out; |
263 | 0 | int i; |
264 | |
|
265 | 0 | from_fp(out, a); |
266 | 0 | for (i = 0; i < 6; i++) |
267 | 0 | ret[i] = out[2*i] | ((unsigned long long)out[2*i+1] << 32); |
268 | 0 | } |
269 | 5.17k | } |
270 | | |
271 | | void blst_fp_from_bendian(vec384 ret, const unsigned char a[48]) |
272 | 0 | { |
273 | 0 | vec384 out; |
274 | |
|
275 | 0 | limbs_from_be_bytes(out, a, sizeof(vec384)); |
276 | 0 | mul_fp(ret, out, BLS12_381_RR); |
277 | 0 | } |
278 | | |
279 | | void blst_bendian_from_fp(unsigned char ret[48], const vec384 a) |
280 | 0 | { |
281 | 0 | vec384 out; |
282 | |
|
283 | 0 | from_fp(out, a); |
284 | 0 | be_bytes_from_limbs(ret, out, sizeof(vec384)); |
285 | 0 | } |
286 | | |
287 | | void blst_fp_from_lendian(vec384 ret, const unsigned char a[48]) |
288 | 0 | { |
289 | 0 | vec384 out; |
290 | |
|
291 | 0 | limbs_from_le_bytes(out, a, sizeof(vec384)); |
292 | 0 | mul_fp(ret, out, BLS12_381_RR); |
293 | 0 | } |
294 | | |
295 | | void blst_lendian_from_fp(unsigned char ret[48], const vec384 a) |
296 | 0 | { |
297 | 0 | vec384 out; |
298 | |
|
299 | 0 | from_fp(out, a); |
300 | 0 | le_bytes_from_limbs(ret, out, sizeof(vec384)); |
301 | 0 | } |
302 | | |
303 | | /* |
304 | | * BLS12-381-specific Fp2 shortcuts to assembly. |
305 | | */ |
306 | | void blst_fp2_add(vec384x ret, const vec384x a, const vec384x b) |
307 | 0 | { add_fp2(ret, a, b); } |
308 | | |
309 | | void blst_fp2_sub(vec384x ret, const vec384x a, const vec384x b) |
310 | 0 | { sub_fp2(ret, a, b); } |
311 | | |
312 | | void blst_fp2_mul_by_3(vec384x ret, const vec384x a) |
313 | 0 | { mul_by_3_fp2(ret, a); } |
314 | | |
315 | | void blst_fp2_mul_by_8(vec384x ret, const vec384x a) |
316 | 0 | { mul_by_8_fp2(ret, a); } |
317 | | |
318 | | void blst_fp2_lshift(vec384x ret, const vec384x a, size_t count) |
319 | 0 | { lshift_fp2(ret, a, count); } |
320 | | |
321 | | void blst_fp2_mul(vec384x ret, const vec384x a, const vec384x b) |
322 | 0 | { mul_fp2(ret, a, b); } |
323 | | |
324 | | void blst_fp2_sqr(vec384x ret, const vec384x a) |
325 | 0 | { sqr_fp2(ret, a); } |
326 | | |
327 | | void blst_fp2_cneg(vec384x ret, const vec384x a, int flag) |
328 | 0 | { cneg_fp2(ret, a, is_zero(flag) ^ 1); } |
329 | | |
330 | | /* |
331 | | * Scalar serialization/deserialization. |
332 | | */ |
333 | | void blst_scalar_from_uint32(pow256 ret, const unsigned int a[8]) |
334 | 0 | { |
335 | 0 | const union { |
336 | 0 | long one; |
337 | 0 | char little; |
338 | 0 | } is_endian = { 1 }; |
339 | 0 | size_t i; |
340 | |
|
341 | 0 | if ((uptr_t)ret==(uptr_t)a && is_endian.little) |
342 | 0 | return; |
343 | | |
344 | 0 | for(i = 0; i < 8; i++) { |
345 | 0 | unsigned int w = a[i]; |
346 | 0 | *ret++ = (byte)w; |
347 | 0 | *ret++ = (byte)(w >> 8); |
348 | 0 | *ret++ = (byte)(w >> 16); |
349 | 0 | *ret++ = (byte)(w >> 24); |
350 | 0 | } |
351 | 0 | } |
352 | | |
353 | | void blst_uint32_from_scalar(unsigned int ret[8], const pow256 a) |
354 | 0 | { |
355 | 0 | const union { |
356 | 0 | long one; |
357 | 0 | char little; |
358 | 0 | } is_endian = { 1 }; |
359 | 0 | size_t i; |
360 | |
|
361 | 0 | if ((uptr_t)ret==(uptr_t)a && is_endian.little) |
362 | 0 | return; |
363 | | |
364 | 0 | for(i = 0; i < 8; i++) { |
365 | 0 | unsigned int w = (unsigned int)(*a++); |
366 | 0 | w |= (unsigned int)(*a++) << 8; |
367 | 0 | w |= (unsigned int)(*a++) << 16; |
368 | 0 | w |= (unsigned int)(*a++) << 24; |
369 | 0 | ret[i] = w; |
370 | 0 | } |
371 | 0 | } |
372 | | |
373 | | void blst_scalar_from_uint64(pow256 ret, const unsigned long long a[4]) |
374 | 336 | { |
375 | 336 | const union { |
376 | 336 | long one; |
377 | 336 | char little; |
378 | 336 | } is_endian = { 1 }; |
379 | 336 | size_t i; |
380 | | |
381 | 336 | if ((uptr_t)ret==(uptr_t)a && is_endian.little) |
382 | 0 | return; |
383 | | |
384 | 1.68k | for(i = 0; i < 4; i++) { |
385 | 1.34k | unsigned long long w = a[i]; |
386 | 1.34k | *ret++ = (byte)w; |
387 | 1.34k | *ret++ = (byte)(w >> 8); |
388 | 1.34k | *ret++ = (byte)(w >> 16); |
389 | 1.34k | *ret++ = (byte)(w >> 24); |
390 | 1.34k | *ret++ = (byte)(w >> 32); |
391 | 1.34k | *ret++ = (byte)(w >> 40); |
392 | 1.34k | *ret++ = (byte)(w >> 48); |
393 | 1.34k | *ret++ = (byte)(w >> 56); |
394 | 1.34k | } |
395 | 336 | } |
396 | | |
397 | | void blst_uint64_from_scalar(unsigned long long ret[4], const pow256 a) |
398 | 0 | { |
399 | 0 | const union { |
400 | 0 | long one; |
401 | 0 | char little; |
402 | 0 | } is_endian = { 1 }; |
403 | 0 | size_t i; |
404 | |
|
405 | 0 | if ((uptr_t)ret==(uptr_t)a && is_endian.little) |
406 | 0 | return; |
407 | | |
408 | 0 | for(i = 0; i < 4; i++) { |
409 | 0 | unsigned long long w = (unsigned long long)(*a++); |
410 | 0 | w |= (unsigned long long)(*a++) << 8; |
411 | 0 | w |= (unsigned long long)(*a++) << 16; |
412 | 0 | w |= (unsigned long long)(*a++) << 24; |
413 | 0 | w |= (unsigned long long)(*a++) << 32; |
414 | 0 | w |= (unsigned long long)(*a++) << 40; |
415 | 0 | w |= (unsigned long long)(*a++) << 48; |
416 | 0 | w |= (unsigned long long)(*a++) << 56; |
417 | 0 | ret[i] = w; |
418 | 0 | } |
419 | 0 | } |
420 | | |
421 | | void blst_scalar_from_bendian(pow256 ret, const unsigned char a[32]) |
422 | 0 | { |
423 | 0 | vec256 out; |
424 | 0 | limbs_from_be_bytes(out, a, sizeof(out)); |
425 | 0 | le_bytes_from_limbs(ret, out, sizeof(out)); |
426 | 0 | vec_zero(out, sizeof(out)); |
427 | 0 | } |
428 | | |
429 | | void blst_bendian_from_scalar(unsigned char ret[32], const pow256 a) |
430 | 0 | { |
431 | 0 | vec256 out; |
432 | 0 | limbs_from_le_bytes(out, a, sizeof(out)); |
433 | 0 | be_bytes_from_limbs(ret, out, sizeof(out)); |
434 | 0 | vec_zero(out, sizeof(out)); |
435 | 0 | } |
436 | | |
437 | | void blst_scalar_from_lendian(pow256 ret, const unsigned char a[32]) |
438 | 0 | { |
439 | 0 | size_t i; |
440 | |
|
441 | 0 | if ((uptr_t)ret==(uptr_t)a) |
442 | 0 | return; |
443 | | |
444 | 0 | for (i = 0; i < 32; i++) |
445 | 0 | ret[i] = a[i]; |
446 | 0 | } |
447 | | |
448 | | void blst_lendian_from_scalar(unsigned char ret[32], const pow256 a) |
449 | 0 | { |
450 | 0 | size_t i; |
451 | |
|
452 | 0 | if ((uptr_t)ret==(uptr_t)a) |
453 | 0 | return; |
454 | | |
455 | 0 | for (i = 0; i < 32; i++) |
456 | 0 | ret[i] = a[i]; |
457 | 0 | } |
458 | | |
459 | | void blst_fr_from_uint64(vec256 ret, const unsigned long long a[4]) |
460 | 1.50k | { |
461 | 1.50k | const union { |
462 | 1.50k | long one; |
463 | 1.50k | char little; |
464 | 1.50k | } is_endian = { 1 }; |
465 | | |
466 | 1.50k | if (sizeof(limb_t) == 4 && !is_endian.little) { |
467 | 0 | int i; |
468 | 0 | for (i = 0; i < 4; i++) { |
469 | 0 | unsigned long long limb = a[i]; |
470 | 0 | ret[2*i] = (limb_t)limb; |
471 | 0 | ret[2*i+1] = (limb_t)(limb >> 32); |
472 | 0 | } |
473 | 0 | a = (const unsigned long long *)ret; |
474 | 0 | } |
475 | 1.50k | mul_mont_sparse_256(ret, BLS12_381_rRR, (const limb_t *)a, BLS12_381_r, r0); |
476 | 1.50k | } |
477 | | |
478 | | void blst_uint64_from_fr(unsigned long long ret[4], const vec256 a) |
479 | 360 | { |
480 | 360 | const union { |
481 | 360 | long one; |
482 | 360 | char little; |
483 | 360 | } is_endian = { 1 }; |
484 | | |
485 | 360 | if (sizeof(limb_t) == 8 || is_endian.little) { |
486 | 360 | from_mont_256((limb_t *)ret, a, BLS12_381_r, r0); |
487 | 360 | } else { |
488 | 0 | vec256 out; |
489 | 0 | int i; |
490 | |
|
491 | 0 | from_mont_256(out, a, BLS12_381_r, r0); |
492 | 0 | for (i = 0; i < 4; i++) |
493 | 0 | ret[i] = out[2*i] | ((unsigned long long)out[2*i+1] << 32); |
494 | 0 | vec_zero(out, sizeof(out)); |
495 | 0 | } |
496 | 360 | } |
497 | | |
498 | | int blst_scalar_from_le_bytes(pow256 out, const unsigned char *bytes, size_t n) |
499 | 0 | { |
500 | 0 | size_t rem = n ? ((n - 1) % 32 + 1) : 0; |
501 | 0 | struct { vec256 out, digit; } t; |
502 | 0 | limb_t ret; |
503 | |
|
504 | 0 | vec_zero(t.out, sizeof(t.out)); |
505 | |
|
506 | 0 | n -= rem; |
507 | 0 | limbs_from_le_bytes(t.out, bytes += n, rem); |
508 | 0 | mul_mont_sparse_256(t.out, BLS12_381_rRR, t.out, BLS12_381_r, r0); |
509 | |
|
510 | 0 | while (n) { |
511 | 0 | limbs_from_le_bytes(t.digit, bytes -= 32, 32); |
512 | 0 | add_mod_256(t.out, t.out, t.digit, BLS12_381_r); |
513 | 0 | mul_mont_sparse_256(t.out, BLS12_381_rRR, t.out, BLS12_381_r, r0); |
514 | 0 | n -= 32; |
515 | 0 | } |
516 | |
|
517 | 0 | from_mont_256(t.out, t.out, BLS12_381_r, r0); |
518 | |
|
519 | 0 | ret = vec_is_zero(t.out, sizeof(t.out)); |
520 | 0 | le_bytes_from_limbs(out, t.out, 32); |
521 | 0 | vec_zero(&t, sizeof(t)); |
522 | |
|
523 | 0 | return (int)(ret^1); |
524 | 0 | } |
525 | | |
526 | | int blst_scalar_from_be_bytes(pow256 out, const unsigned char *bytes, size_t n) |
527 | 0 | { |
528 | 0 | size_t rem = n ? ((n - 1) % 32 + 1) : 0; |
529 | 0 | struct { vec256 out, digit; } t; |
530 | 0 | limb_t ret; |
531 | |
|
532 | 0 | vec_zero(t.out, sizeof(t.out)); |
533 | |
|
534 | 0 | limbs_from_be_bytes(t.out, bytes, rem); |
535 | 0 | mul_mont_sparse_256(t.out, BLS12_381_rRR, t.out, BLS12_381_r, r0); |
536 | |
|
537 | 0 | while (n -= rem) { |
538 | 0 | limbs_from_be_bytes(t.digit, bytes += rem, 32); |
539 | 0 | add_mod_256(t.out, t.out, t.digit, BLS12_381_r); |
540 | 0 | mul_mont_sparse_256(t.out, BLS12_381_rRR, t.out, BLS12_381_r, r0); |
541 | 0 | rem = 32; |
542 | 0 | } |
543 | |
|
544 | 0 | from_mont_256(t.out, t.out, BLS12_381_r, r0); |
545 | |
|
546 | 0 | ret = vec_is_zero(t.out, sizeof(t.out)); |
547 | 0 | le_bytes_from_limbs(out, t.out, 32); |
548 | 0 | vec_zero(&t, sizeof(t)); |
549 | |
|
550 | 0 | return (int)(ret^1); |
551 | 0 | } |
552 | | |
553 | | void blst_fp_from_le_bytes(vec384 out, const unsigned char *bytes, size_t n) |
554 | 0 | { |
555 | 0 | size_t rem = n ? ((n - 1) % 48 + 1) : 0; |
556 | 0 | vec384 digit; |
557 | |
|
558 | 0 | vec_zero(out, sizeof(vec384)); |
559 | |
|
560 | 0 | n -= rem; |
561 | 0 | limbs_from_le_bytes(out, bytes += n, rem); |
562 | 0 | mul_mont_384(out, BLS12_381_RR, out, BLS12_381_P, p0); |
563 | |
|
564 | 0 | while (n) { |
565 | 0 | limbs_from_le_bytes(digit, bytes -= 48, 48); |
566 | 0 | add_mod_384(out, out, digit, BLS12_381_P); |
567 | 0 | mul_mont_384(out, BLS12_381_RR, out, BLS12_381_P, p0); |
568 | 0 | n -= 48; |
569 | 0 | } |
570 | 0 | } |
571 | | |
572 | | void blst_fp_from_be_bytes(vec384 out, const unsigned char *bytes, size_t n) |
573 | 0 | { |
574 | 0 | size_t rem = n ? ((n - 1) % 48 + 1) : 0; |
575 | 0 | vec384 digit; |
576 | |
|
577 | 0 | vec_zero(out, sizeof(vec384)); |
578 | |
|
579 | 0 | limbs_from_be_bytes(out, bytes, rem); |
580 | 0 | mul_mont_384(out, BLS12_381_RR, out, BLS12_381_P, p0); |
581 | |
|
582 | 0 | while (n -= rem) { |
583 | 0 | limbs_from_be_bytes(digit, bytes += rem, 48); |
584 | 0 | add_mod_384(out, out, digit, BLS12_381_P); |
585 | 0 | mul_mont_384(out, BLS12_381_RR, out, BLS12_381_P, p0); |
586 | 0 | rem = 48; |
587 | 0 | } |
588 | 0 | } |
589 | | |
590 | | /* |
591 | | * Single-short SHA-256 hash function. |
592 | | */ |
593 | | #include "sha256.h" |
594 | | |
595 | | void blst_sha256(unsigned char md[32], const void *msg, size_t len) |
596 | 0 | { |
597 | 0 | SHA256_CTX ctx; |
598 | |
|
599 | 0 | sha256_init(&ctx); |
600 | 0 | sha256_update(&ctx, msg, len); |
601 | 0 | sha256_final(md, &ctx); |
602 | 0 | } |
603 | | |
604 | | /* |
605 | | * Test facilitator. |
606 | | */ |
607 | | void blst_scalar_from_hexascii(pow256 ret, const char *hex) |
608 | 0 | { bytes_from_hexascii(ret, sizeof(pow256), hex); } |
609 | | |
610 | | void blst_fr_from_hexascii(vec256 ret, const char *hex) |
611 | 0 | { |
612 | 0 | limbs_from_hexascii(ret, sizeof(vec256), hex); |
613 | 0 | mul_mont_sparse_256(ret, BLS12_381_rRR, ret, BLS12_381_r, r0); |
614 | 0 | } |
615 | | |
616 | | void blst_fp_from_hexascii(vec384 ret, const char *hex) |
617 | 0 | { |
618 | 0 | limbs_from_hexascii(ret, sizeof(vec384), hex); |
619 | 0 | mul_fp(ret, ret, BLS12_381_RR); |
620 | 0 | } |