/src/blst_optimize_size/src/aggregate.c
Line | Count | Source (jump to first uncovered line) |
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 | | /* |
8 | | * Usage pattern on single-processor system is |
9 | | * |
10 | | * blst_pairing_init(ctx, hash_or_encode, DST); |
11 | | * blst_pairing_aggregate_pk_in_g1(ctx, PK[0], aggregated_signature, msg[0]); |
12 | | * blst_pairing_aggregate_pk_in_g1(ctx, PK[1], NULL, msg[1]); |
13 | | * ... |
14 | | * blst_pairing_commit(ctx); |
15 | | * blst_pairing_finalverify(ctx, NULL); |
16 | | * |
17 | | *********************************************************************** |
18 | | * Usage pattern on multi-processor system is |
19 | | * |
20 | | * blst_pairing_init(pk[0], hash_or_encode, DST); |
21 | | * blst_pairing_init(pk[1], hash_or_encode, DST); |
22 | | * ... |
23 | | * start threads each processing an N/nthreads slice of PKs and messages: |
24 | | * blst_pairing_aggregate_pk_in_g1(pk[i], PK[i*n+0], NULL, msg[i*n+0]); |
25 | | * blst_pairing_aggregate_pk_in_g1(pk[i], PK[i*n+1], NULL, msg[i*n+1]); |
26 | | * ... |
27 | | * blst_pairing_commit(pkx); |
28 | | * ... |
29 | | * meanwhile in main thread |
30 | | * blst_fp12 gtsig; |
31 | | * blst_aggregated_in_g2(>sig, aggregated_signature); |
32 | | * join threads and merge their contexts: |
33 | | * blst_pairing_merge(pk[0], pk[1]); |
34 | | * blst_pairing_merge(pk[0], pk[2]); |
35 | | * ... |
36 | | * blst_pairing_finalverify(pk[0], gtsig); |
37 | | */ |
38 | | |
39 | | #ifndef N_MAX |
40 | 669 | # define N_MAX 8 |
41 | | #endif |
42 | | |
43 | | typedef union { POINTonE1 e1; POINTonE2 e2; } AggregatedSignature; |
44 | | typedef struct { |
45 | | unsigned int ctrl; |
46 | | unsigned int nelems; |
47 | | const void *DST; |
48 | | size_t DST_len; |
49 | | vec384fp12 GT; |
50 | | AggregatedSignature AggrSign; |
51 | | POINTonE2_affine Q[N_MAX]; |
52 | | POINTonE1_affine P[N_MAX]; |
53 | | } PAIRING; |
54 | | |
55 | | enum { AGGR_UNDEFINED = 0, |
56 | | AGGR_MIN_SIG = 1, |
57 | | AGGR_MIN_PK = 2, |
58 | | AGGR_SIGN_SET = 0x10, |
59 | | AGGR_GT_SET = 0x20, |
60 | | AGGR_HASH_OR_ENCODE = 0x40 }; |
61 | 643 | #define MIN_SIG_OR_PK (AGGR_MIN_SIG | AGGR_MIN_PK) |
62 | | |
63 | | static const size_t sizeof_pairing = (sizeof(PAIRING) + 7) & ~(size_t)7; |
64 | | |
65 | | size_t blst_pairing_sizeof(void) |
66 | 0 | { return sizeof_pairing; } |
67 | | |
68 | | void blst_pairing_init(PAIRING *ctx, int hash_or_encode, |
69 | | const void *DST, size_t DST_len) |
70 | 0 | { |
71 | 0 | ctx->ctrl = AGGR_UNDEFINED | (hash_or_encode ? AGGR_HASH_OR_ENCODE : 0); |
72 | 0 | ctx->nelems = 0; |
73 | 0 | ctx->DST = (uptr_t)DST==(uptr_t)((byte *)ctx+sizeof_pairing) ? (void *)42 |
74 | 0 | : DST; |
75 | 0 | ctx->DST_len = DST_len; |
76 | 0 | } |
77 | | |
78 | | static const void *pairing_get_dst(const PAIRING *ctx) |
79 | 750 | { return (uptr_t)ctx->DST==(uptr_t)42 ? (const byte *)ctx+sizeof_pairing |
80 | 750 | : ctx->DST; |
81 | 750 | } |
82 | | |
83 | | const void *blst_pairing_get_dst(const PAIRING *ctx) |
84 | 0 | { return pairing_get_dst(ctx); } |
85 | | |
86 | 1.37k | #define FROM_AFFINE(out,in) do { \ |
87 | 1.37k | vec_copy((out)->X, in->X, 2*sizeof(in->X)), \ |
88 | 1.37k | vec_select((out)->Z, in->X, BLS12_381_Rx.p, sizeof(in->X), \ |
89 | 1.37k | vec_is_zero(in->X, 2*sizeof(in->X))); } while(0) |
90 | | |
91 | | /* |
92 | | * Optional |nbits|-wide |scalar| is used to facilitate multiple aggregated |
93 | | * signature verification as discussed at |
94 | | * https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407. |
95 | | * Usage pattern is not finalized yet, because (sig != NULL) is better and |
96 | | * will be handled separately... |
97 | | */ |
98 | | static BLST_ERROR PAIRING_Aggregate_PK_in_G2(PAIRING *ctx, |
99 | | const POINTonE2_affine *PK, |
100 | | size_t pk_groupcheck, |
101 | | const POINTonE1_affine *sig, |
102 | | size_t sig_groupcheck, |
103 | | const byte *scalar, size_t nbits, |
104 | | const void *msg, size_t msg_len, |
105 | | const void *aug, size_t aug_len) |
106 | 0 | { |
107 | 0 | if (ctx->ctrl & AGGR_MIN_PK) |
108 | 0 | return BLST_AGGR_TYPE_MISMATCH; |
109 | | |
110 | 0 | ctx->ctrl |= AGGR_MIN_SIG; |
111 | | |
112 | | /* |
113 | | * Since we don't know if the signature is individual or aggregated, |
114 | | * the only sensible thing to do is to skip over infinite one and |
115 | | * count on the corresponding infinite public key to be rejected, |
116 | | * in case the signature is non-aggregated that is. |
117 | | */ |
118 | 0 | if (sig != NULL && !vec_is_zero(sig, sizeof(*sig))) { |
119 | 0 | POINTonE1 *S = &ctx->AggrSign.e1; |
120 | 0 | POINTonE1 P[1]; |
121 | |
|
122 | 0 | FROM_AFFINE(P, sig); |
123 | |
|
124 | 0 | if (sig_groupcheck && !POINTonE1_in_G1(P)) |
125 | 0 | return BLST_POINT_NOT_IN_GROUP; |
126 | | |
127 | 0 | if (ctx->ctrl & AGGR_SIGN_SET) { |
128 | 0 | if (nbits != 0 && scalar != NULL) { |
129 | 0 | POINTonE1_mult_w5(P, P, scalar, nbits); |
130 | 0 | POINTonE1_dadd(S, S, P, NULL); |
131 | 0 | } else { |
132 | 0 | POINTonE1_dadd_affine(S, S, sig); |
133 | 0 | } |
134 | 0 | } else { |
135 | 0 | ctx->ctrl |= AGGR_SIGN_SET; |
136 | 0 | if (nbits != 0 && scalar != NULL) |
137 | 0 | POINTonE1_mult_w5(S, P, scalar, nbits); |
138 | 0 | else |
139 | 0 | vec_copy(S, P, sizeof(P)); |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | 0 | if (PK != NULL) { |
144 | 0 | unsigned int n; |
145 | 0 | POINTonE1 H[1]; |
146 | 0 | const void *DST = pairing_get_dst(ctx); |
147 | | |
148 | | /* |
149 | | * Reject infinite public keys. |
150 | | */ |
151 | 0 | if (vec_is_zero(PK, sizeof(*PK))) |
152 | 0 | return BLST_PK_IS_INFINITY; |
153 | | |
154 | 0 | if (pk_groupcheck) { |
155 | 0 | POINTonE2 P[1]; |
156 | |
|
157 | 0 | FROM_AFFINE(P, PK); |
158 | 0 | if (!POINTonE2_in_G2(P)) |
159 | 0 | return BLST_POINT_NOT_IN_GROUP; |
160 | 0 | } |
161 | | |
162 | 0 | if (ctx->ctrl & AGGR_HASH_OR_ENCODE) |
163 | 0 | Hash_to_G1(H, msg, msg_len, DST, ctx->DST_len, aug, aug_len); |
164 | 0 | else |
165 | 0 | Encode_to_G1(H, msg, msg_len, DST, ctx->DST_len, aug, aug_len); |
166 | |
|
167 | 0 | if (nbits != 0 && scalar != NULL) |
168 | 0 | POINTonE1_mult_w5(H, H, scalar, nbits); |
169 | |
|
170 | 0 | POINTonE1_from_Jacobian(H, H); |
171 | |
|
172 | 0 | n = ctx->nelems; |
173 | 0 | vec_copy(ctx->Q + n, PK, sizeof(POINTonE2_affine)); |
174 | 0 | vec_copy(ctx->P + n, H, sizeof(POINTonE1_affine)); |
175 | 0 | if (++n == N_MAX) { |
176 | 0 | if (ctx->ctrl & AGGR_GT_SET) { |
177 | 0 | vec384fp12 GT; |
178 | 0 | miller_loop_n(GT, ctx->Q, ctx->P, n); |
179 | 0 | mul_fp12(ctx->GT, ctx->GT, GT); |
180 | 0 | } else { |
181 | 0 | miller_loop_n(ctx->GT, ctx->Q, ctx->P, n); |
182 | 0 | ctx->ctrl |= AGGR_GT_SET; |
183 | 0 | } |
184 | 0 | n = 0; |
185 | 0 | } |
186 | 0 | ctx->nelems = n; |
187 | 0 | } |
188 | | |
189 | 0 | return BLST_SUCCESS; |
190 | 0 | } |
191 | | |
192 | | BLST_ERROR blst_pairing_aggregate_pk_in_g2(PAIRING *ctx, |
193 | | const POINTonE2_affine *PK, |
194 | | const POINTonE1_affine *signature, |
195 | | const void *msg, size_t msg_len, |
196 | | const void *aug, size_t aug_len) |
197 | 0 | { return PAIRING_Aggregate_PK_in_G2(ctx, PK, 0, signature, 1, NULL, 0, |
198 | 0 | msg, msg_len, aug, aug_len); |
199 | 0 | } |
200 | | |
201 | | BLST_ERROR blst_pairing_mul_n_aggregate_pk_in_g2(PAIRING *ctx, |
202 | | const POINTonE2_affine *PK, |
203 | | const POINTonE1_affine *sig, |
204 | | const byte *scalar, |
205 | | size_t nbits, |
206 | | const void *msg, |
207 | | size_t msg_len, |
208 | | const void *aug, |
209 | | size_t aug_len) |
210 | 0 | { return PAIRING_Aggregate_PK_in_G2(ctx, PK, 0, sig, 1, scalar, nbits, |
211 | 0 | msg, msg_len, aug, aug_len); |
212 | 0 | } |
213 | | |
214 | | BLST_ERROR blst_pairing_chk_n_aggr_pk_in_g2(PAIRING *ctx, |
215 | | const POINTonE2_affine *PK, |
216 | | size_t pk_grpchk, |
217 | | const POINTonE1_affine *signature, |
218 | | size_t sig_grpchk, |
219 | | const void *msg, size_t msg_len, |
220 | | const void *aug, size_t aug_len) |
221 | 0 | { return PAIRING_Aggregate_PK_in_G2(ctx, PK, pk_grpchk, signature, sig_grpchk, |
222 | 0 | NULL, 0, msg, msg_len, aug, aug_len); |
223 | 0 | } |
224 | | |
225 | | BLST_ERROR blst_pairing_chk_n_mul_n_aggr_pk_in_g2(PAIRING *ctx, |
226 | | const POINTonE2_affine *PK, |
227 | | size_t pk_grpchk, |
228 | | const POINTonE1_affine *sig, |
229 | | size_t sig_grpchk, |
230 | | const byte *scalar, |
231 | | size_t nbits, |
232 | | const void *msg, |
233 | | size_t msg_len, |
234 | | const void *aug, |
235 | | size_t aug_len) |
236 | 0 | { return PAIRING_Aggregate_PK_in_G2(ctx, PK, pk_grpchk, sig, sig_grpchk, |
237 | 0 | scalar, nbits, |
238 | 0 | msg, msg_len, aug, aug_len); |
239 | 0 | } |
240 | | |
241 | | static BLST_ERROR PAIRING_Aggregate_PK_in_G1(PAIRING *ctx, |
242 | | const POINTonE1_affine *PK, |
243 | | size_t pk_groupcheck, |
244 | | const POINTonE2_affine *sig, |
245 | | size_t sig_groupcheck, |
246 | | const byte *scalar, size_t nbits, |
247 | | const void *msg, size_t msg_len, |
248 | | const void *aug, size_t aug_len) |
249 | 783 | { |
250 | 783 | if (ctx->ctrl & AGGR_MIN_SIG) |
251 | 0 | return BLST_AGGR_TYPE_MISMATCH; |
252 | | |
253 | 783 | ctx->ctrl |= AGGR_MIN_PK; |
254 | | |
255 | | /* |
256 | | * Since we don't know if the signature is individual or aggregated, |
257 | | * the only sensible thing to do is to skip over infinite one and |
258 | | * count on the corresponding infinite public key to be rejected, |
259 | | * in case the signature is non-aggregated that is. |
260 | | */ |
261 | 783 | if (sig != NULL && !vec_is_zero(sig, sizeof(*sig))) { |
262 | 677 | POINTonE2 *S = &ctx->AggrSign.e2; |
263 | 677 | POINTonE2 P[1]; |
264 | | |
265 | 677 | FROM_AFFINE(P, sig); |
266 | | |
267 | 677 | if (sig_groupcheck && !POINTonE2_in_G2(P)) |
268 | 33 | return BLST_POINT_NOT_IN_GROUP; |
269 | | |
270 | 644 | if (ctx->ctrl & AGGR_SIGN_SET) { |
271 | 0 | if (nbits != 0 && scalar != NULL) { |
272 | |
|
273 | 0 | POINTonE2_mult_w5(P, P, scalar, nbits); |
274 | 0 | POINTonE2_dadd(S, S, P, NULL); |
275 | 0 | } else { |
276 | 0 | POINTonE2_dadd_affine(S, S, sig); |
277 | 0 | } |
278 | 644 | } else { |
279 | 644 | ctx->ctrl |= AGGR_SIGN_SET; |
280 | 644 | if (nbits != 0 && scalar != NULL) |
281 | 0 | POINTonE2_mult_w5(S, P, scalar, nbits); |
282 | 644 | else |
283 | 644 | vec_copy(S, P, sizeof(P)); |
284 | 644 | } |
285 | 644 | } |
286 | | |
287 | 750 | if (PK != NULL) { |
288 | 750 | unsigned int n; |
289 | 750 | POINTonE2 H[1]; |
290 | 750 | POINTonE1 pk[1]; |
291 | 750 | const void *DST = pairing_get_dst(ctx); |
292 | | |
293 | | /* |
294 | | * Reject infinite public keys. |
295 | | */ |
296 | 750 | if (vec_is_zero(PK, sizeof(*PK))) |
297 | 51 | return BLST_PK_IS_INFINITY; |
298 | | |
299 | 699 | if (pk_groupcheck) { |
300 | 699 | POINTonE1 P[1]; |
301 | | |
302 | 699 | FROM_AFFINE(P, PK); |
303 | 699 | if (!POINTonE1_in_G1(P)) |
304 | 30 | return BLST_POINT_NOT_IN_GROUP; |
305 | 699 | } |
306 | | |
307 | 669 | if (ctx->ctrl & AGGR_HASH_OR_ENCODE) |
308 | 669 | Hash_to_G2(H, msg, msg_len, DST, ctx->DST_len, aug, aug_len); |
309 | 0 | else |
310 | 0 | Encode_to_G2(H, msg, msg_len, DST, ctx->DST_len, aug, aug_len); |
311 | | |
312 | 669 | POINTonE2_from_Jacobian(H, H); |
313 | | |
314 | 669 | if (nbits != 0 && scalar != NULL) { |
315 | 0 | FROM_AFFINE(pk, PK); |
316 | 0 | POINTonE1_mult_w5(pk, pk, scalar, nbits); |
317 | 0 | POINTonE1_from_Jacobian(pk, pk); |
318 | 0 | PK = (const POINTonE1_affine *)pk; |
319 | 0 | } |
320 | | |
321 | 669 | n = ctx->nelems; |
322 | 669 | vec_copy(ctx->Q + n, H, sizeof(POINTonE2_affine)); |
323 | 669 | vec_copy(ctx->P + n, PK, sizeof(POINTonE1_affine)); |
324 | 669 | if (++n == N_MAX) { |
325 | 0 | if (ctx->ctrl & AGGR_GT_SET) { |
326 | 0 | vec384fp12 GT; |
327 | 0 | miller_loop_n(GT, ctx->Q, ctx->P, n); |
328 | 0 | mul_fp12(ctx->GT, ctx->GT, GT); |
329 | 0 | } else { |
330 | 0 | miller_loop_n(ctx->GT, ctx->Q, ctx->P, n); |
331 | 0 | ctx->ctrl |= AGGR_GT_SET; |
332 | 0 | } |
333 | 0 | n = 0; |
334 | 0 | } |
335 | 669 | ctx->nelems = n; |
336 | 669 | } |
337 | | |
338 | 669 | return BLST_SUCCESS; |
339 | 750 | } |
340 | | |
341 | | BLST_ERROR blst_pairing_aggregate_pk_in_g1(PAIRING *ctx, |
342 | | const POINTonE1_affine *PK, |
343 | | const POINTonE2_affine *signature, |
344 | | const void *msg, size_t msg_len, |
345 | | const void *aug, size_t aug_len) |
346 | 0 | { return PAIRING_Aggregate_PK_in_G1(ctx, PK, 0, signature, 1, NULL, 0, |
347 | 0 | msg, msg_len, aug, aug_len); |
348 | 0 | } |
349 | | |
350 | | BLST_ERROR blst_pairing_mul_n_aggregate_pk_in_g1(PAIRING *ctx, |
351 | | const POINTonE1_affine *PK, |
352 | | const POINTonE2_affine *sig, |
353 | | const byte *scalar, |
354 | | size_t nbits, |
355 | | const void *msg, |
356 | | size_t msg_len, |
357 | | const void *aug, |
358 | | size_t aug_len) |
359 | 0 | { return PAIRING_Aggregate_PK_in_G1(ctx, PK, 0, sig, 1, scalar, nbits, |
360 | 0 | msg, msg_len, aug, aug_len); |
361 | 0 | } |
362 | | |
363 | | BLST_ERROR blst_pairing_chk_n_aggr_pk_in_g1(PAIRING *ctx, |
364 | | const POINTonE1_affine *PK, |
365 | | size_t pk_grpchk, |
366 | | const POINTonE2_affine *signature, |
367 | | size_t sig_grpchk, |
368 | | const void *msg, size_t msg_len, |
369 | | const void *aug, size_t aug_len) |
370 | 0 | { return PAIRING_Aggregate_PK_in_G1(ctx, PK, pk_grpchk, signature, sig_grpchk, |
371 | 0 | NULL, 0, msg, msg_len, aug, aug_len); |
372 | 0 | } |
373 | | |
374 | | BLST_ERROR blst_pairing_chk_n_mul_n_aggr_pk_in_g1(PAIRING *ctx, |
375 | | const POINTonE1_affine *PK, |
376 | | size_t pk_grpchk, |
377 | | const POINTonE2_affine *sig, |
378 | | size_t sig_grpchk, |
379 | | const byte *scalar, |
380 | | size_t nbits, |
381 | | const void *msg, |
382 | | size_t msg_len, |
383 | | const void *aug, |
384 | | size_t aug_len) |
385 | 0 | { return PAIRING_Aggregate_PK_in_G1(ctx, PK, pk_grpchk, sig, sig_grpchk, |
386 | 0 | scalar, nbits, |
387 | 0 | msg, msg_len, aug, aug_len); |
388 | 0 | } |
389 | | |
390 | | static void PAIRING_Commit(PAIRING *ctx) |
391 | 669 | { |
392 | 669 | unsigned int n; |
393 | | |
394 | 669 | if ((n = ctx->nelems) != 0) { |
395 | 669 | if (ctx->ctrl & AGGR_GT_SET) { |
396 | 0 | vec384fp12 GT; |
397 | 0 | miller_loop_n(GT, ctx->Q, ctx->P, n); |
398 | 0 | mul_fp12(ctx->GT, ctx->GT, GT); |
399 | 669 | } else { |
400 | 669 | miller_loop_n(ctx->GT, ctx->Q, ctx->P, n); |
401 | 669 | ctx->ctrl |= AGGR_GT_SET; |
402 | 669 | } |
403 | 669 | ctx->nelems = 0; |
404 | 669 | } |
405 | 669 | } |
406 | | |
407 | | void blst_pairing_commit(PAIRING *ctx) |
408 | 0 | { PAIRING_Commit(ctx); } |
409 | | |
410 | | BLST_ERROR blst_pairing_merge(PAIRING *ctx, const PAIRING *ctx1) |
411 | 0 | { |
412 | 0 | if ((ctx->ctrl & MIN_SIG_OR_PK) != AGGR_UNDEFINED |
413 | 0 | && (ctx1->ctrl & MIN_SIG_OR_PK) != AGGR_UNDEFINED |
414 | 0 | && (ctx->ctrl & ctx1->ctrl & MIN_SIG_OR_PK) == 0) |
415 | 0 | return BLST_AGGR_TYPE_MISMATCH; |
416 | | |
417 | | /* context producers are expected to have called blst_pairing_commit */ |
418 | 0 | if (ctx->nelems || ctx1->nelems) |
419 | 0 | return BLST_AGGR_TYPE_MISMATCH; |
420 | | |
421 | 0 | ctx->ctrl |= ctx1->ctrl & MIN_SIG_OR_PK; |
422 | |
|
423 | 0 | switch (ctx->ctrl & MIN_SIG_OR_PK) { |
424 | 0 | case AGGR_MIN_SIG: |
425 | 0 | if (ctx->ctrl & ctx1->ctrl & AGGR_SIGN_SET) { |
426 | 0 | POINTonE1_dadd(&ctx->AggrSign.e1, &ctx->AggrSign.e1, |
427 | 0 | &ctx1->AggrSign.e1, NULL); |
428 | 0 | } else if (ctx1->ctrl & AGGR_SIGN_SET) { |
429 | 0 | ctx->ctrl |= AGGR_SIGN_SET; |
430 | 0 | vec_copy(&ctx->AggrSign.e1, &ctx1->AggrSign.e1, |
431 | 0 | sizeof(ctx->AggrSign.e1)); |
432 | 0 | } |
433 | 0 | break; |
434 | 0 | case AGGR_MIN_PK: |
435 | 0 | if (ctx->ctrl & ctx1->ctrl & AGGR_SIGN_SET) { |
436 | 0 | POINTonE2_dadd(&ctx->AggrSign.e2, &ctx->AggrSign.e2, |
437 | 0 | &ctx1->AggrSign.e2, NULL); |
438 | 0 | } else if (ctx1->ctrl & AGGR_SIGN_SET) { |
439 | 0 | ctx->ctrl |= AGGR_SIGN_SET; |
440 | 0 | vec_copy(&ctx->AggrSign.e2, &ctx1->AggrSign.e2, |
441 | 0 | sizeof(ctx->AggrSign.e2)); |
442 | 0 | } |
443 | 0 | break; |
444 | 0 | case AGGR_UNDEFINED: |
445 | 0 | break; |
446 | 0 | default: |
447 | 0 | return BLST_AGGR_TYPE_MISMATCH; |
448 | 0 | } |
449 | | |
450 | 0 | if (ctx->ctrl & ctx1->ctrl & AGGR_GT_SET) { |
451 | 0 | mul_fp12(ctx->GT, ctx->GT, ctx1->GT); |
452 | 0 | } else if (ctx1->ctrl & AGGR_GT_SET) { |
453 | 0 | ctx->ctrl |= AGGR_GT_SET; |
454 | 0 | vec_copy(ctx->GT, ctx1->GT, sizeof(ctx->GT)); |
455 | 0 | } |
456 | |
|
457 | 0 | return BLST_SUCCESS; |
458 | 0 | } |
459 | | |
460 | | static bool_t PAIRING_FinalVerify(const PAIRING *ctx, const vec384fp12 GTsig) |
461 | 669 | { |
462 | 669 | vec384fp12 GT; |
463 | | |
464 | 669 | if (!(ctx->ctrl & AGGR_GT_SET)) |
465 | 0 | return 0; |
466 | | |
467 | 669 | if (GTsig != NULL) { |
468 | 0 | vec_copy(GT, GTsig, sizeof(GT)); |
469 | 669 | } else if (ctx->ctrl & AGGR_SIGN_SET) { |
470 | 643 | AggregatedSignature AggrSign; |
471 | | |
472 | 643 | switch (ctx->ctrl & MIN_SIG_OR_PK) { |
473 | 0 | case AGGR_MIN_SIG: |
474 | 0 | POINTonE1_from_Jacobian(&AggrSign.e1, &ctx->AggrSign.e1); |
475 | 0 | miller_loop_n(GT, (const POINTonE2_affine *)&BLS12_381_G2, |
476 | 0 | (const POINTonE1_affine *)&AggrSign.e1, 1); |
477 | 0 | break; |
478 | 643 | case AGGR_MIN_PK: |
479 | 643 | POINTonE2_from_Jacobian(&AggrSign.e2, &ctx->AggrSign.e2); |
480 | 643 | miller_loop_n(GT, (const POINTonE2_affine *)&AggrSign.e2, |
481 | 643 | (const POINTonE1_affine *)&BLS12_381_G1, 1); |
482 | 643 | break; |
483 | 0 | default: |
484 | 0 | return 0; |
485 | 643 | } |
486 | 643 | } else { |
487 | | /* |
488 | | * The aggregated signature was infinite, relation between the |
489 | | * hashes and the public keys has to be VERY special... |
490 | | */ |
491 | 26 | vec_copy(GT, BLS12_381_Rx.p12, sizeof(GT)); |
492 | 26 | } |
493 | | |
494 | 669 | conjugate_fp12(GT); |
495 | 669 | mul_fp12(GT, GT, ctx->GT); |
496 | 669 | final_exp(GT, GT); |
497 | | |
498 | | /* return GT==1 */ |
499 | 669 | return vec_is_equal(GT[0][0], BLS12_381_Rx.p2, sizeof(GT[0][0])) & |
500 | 669 | vec_is_zero(GT[0][1], sizeof(GT) - sizeof(GT[0][0])); |
501 | 669 | } |
502 | | |
503 | | int blst_pairing_finalverify(const PAIRING *ctx, const vec384fp12 GTsig) |
504 | 0 | { return (int)PAIRING_FinalVerify(ctx, GTsig); } |
505 | | |
506 | | int blst_fp12_finalverify(const vec384fp12 GT1, const vec384fp12 GT2) |
507 | 0 | { |
508 | 0 | vec384fp12 GT; |
509 | |
|
510 | 0 | vec_copy(GT, GT1, sizeof(GT)); |
511 | 0 | conjugate_fp12(GT); |
512 | 0 | mul_fp12(GT, GT, GT2); |
513 | 0 | final_exp(GT, GT); |
514 | | |
515 | | /* return GT==1 */ |
516 | 0 | return (int)(vec_is_equal(GT[0][0], BLS12_381_Rx.p2, sizeof(GT[0][0])) & |
517 | 0 | vec_is_zero(GT[0][1], sizeof(GT) - sizeof(GT[0][0]))); |
518 | 0 | } |
519 | | |
520 | | void blst_pairing_raw_aggregate(PAIRING *ctx, const POINTonE2_affine *q, |
521 | | const POINTonE1_affine *p) |
522 | 0 | { |
523 | 0 | unsigned int n; |
524 | |
|
525 | 0 | if (vec_is_zero(q, sizeof(*q)) & vec_is_zero(p, sizeof(*p))) |
526 | 0 | return; |
527 | | |
528 | 0 | n = ctx->nelems; |
529 | 0 | vec_copy(ctx->Q + n, q, sizeof(*q)); |
530 | 0 | vec_copy(ctx->P + n, p, sizeof(*p)); |
531 | 0 | if (++n == N_MAX) { |
532 | 0 | if (ctx->ctrl & AGGR_GT_SET) { |
533 | 0 | vec384fp12 GT; |
534 | 0 | miller_loop_n(GT, ctx->Q, ctx->P, n); |
535 | 0 | mul_fp12(ctx->GT, ctx->GT, GT); |
536 | 0 | } else { |
537 | 0 | miller_loop_n(ctx->GT, ctx->Q, ctx->P, n); |
538 | 0 | ctx->ctrl |= AGGR_GT_SET; |
539 | 0 | } |
540 | 0 | n = 0; |
541 | 0 | } |
542 | 0 | ctx->nelems = n; |
543 | 0 | } |
544 | | |
545 | | vec384fp12 *blst_pairing_as_fp12(PAIRING *ctx) |
546 | 0 | { |
547 | 0 | PAIRING_Commit(ctx); |
548 | 0 | return (vec384fp12 *)ctx->GT; |
549 | 0 | } |
550 | | |
551 | | /* |
552 | | * PAIRING context-free entry points. |
553 | | * |
554 | | * To perform FastAggregateVerify, aggregate all public keys and |
555 | | * signatures with corresponding blst_aggregate_in_g{12}, convert |
556 | | * result to affine and call suitable blst_core_verify_pk_in_g{12} |
557 | | * or blst_aggregated_in_g{12}... |
558 | | */ |
559 | | BLST_ERROR blst_aggregate_in_g1(POINTonE1 *out, const POINTonE1 *in, |
560 | | const unsigned char *zwire) |
561 | 2.47k | { |
562 | 2.47k | POINTonE1 P[1]; |
563 | 2.47k | BLST_ERROR ret; |
564 | | |
565 | 2.47k | ret = POINTonE1_Deserialize_Z((POINTonE1_affine *)P, zwire); |
566 | | |
567 | 2.47k | if (ret != BLST_SUCCESS) |
568 | 52 | return ret; |
569 | | |
570 | 2.42k | if (vec_is_zero(P, sizeof(POINTonE1_affine))) { |
571 | 2.42k | if (in == NULL) |
572 | 148 | vec_zero(out, sizeof(*out)); |
573 | 2.42k | return BLST_SUCCESS; |
574 | 2.42k | } |
575 | | |
576 | 0 | vec_copy(P->Z, BLS12_381_Rx.p, sizeof(P->Z)); |
577 | |
|
578 | 0 | if (!POINTonE1_in_G1(P)) |
579 | 0 | return BLST_POINT_NOT_IN_GROUP; |
580 | | |
581 | 0 | if (in == NULL) |
582 | 0 | vec_copy(out, P, sizeof(P)); |
583 | 0 | else |
584 | 0 | POINTonE1_dadd_affine(out, in, (POINTonE1_affine *)P); |
585 | |
|
586 | 0 | return BLST_SUCCESS; |
587 | 0 | } |
588 | | |
589 | | BLST_ERROR blst_aggregate_in_g2(POINTonE2 *out, const POINTonE2 *in, |
590 | | const unsigned char *zwire) |
591 | 1.98k | { |
592 | 1.98k | POINTonE2 P[1]; |
593 | 1.98k | BLST_ERROR ret; |
594 | | |
595 | 1.98k | ret = POINTonE2_Deserialize_Z((POINTonE2_affine *)P, zwire); |
596 | | |
597 | 1.98k | if (ret != BLST_SUCCESS) |
598 | 61 | return ret; |
599 | | |
600 | 1.92k | if (vec_is_zero(P, sizeof(POINTonE2_affine))) { |
601 | 1.92k | if (in == NULL) |
602 | 187 | vec_zero(out, sizeof(*out)); |
603 | 1.92k | return BLST_SUCCESS; |
604 | 1.92k | } |
605 | | |
606 | 0 | vec_copy(P->Z, BLS12_381_Rx.p, sizeof(P->Z)); |
607 | |
|
608 | 0 | if (!POINTonE2_in_G2(P)) |
609 | 0 | return BLST_POINT_NOT_IN_GROUP; |
610 | | |
611 | 0 | if (in == NULL) { |
612 | 0 | vec_copy(out, P, sizeof(P)); |
613 | 0 | } else { |
614 | 0 | POINTonE2_dadd_affine(out, in, (POINTonE2_affine *)P); |
615 | 0 | } |
616 | 0 | return BLST_SUCCESS; |
617 | 0 | } |
618 | | |
619 | | void blst_aggregated_in_g1(vec384fp12 ret, const POINTonE1_affine *sig) |
620 | 0 | { miller_loop_n(ret, (const POINTonE2_affine *)&BLS12_381_G2, sig, 1); } |
621 | | |
622 | | void blst_aggregated_in_g2(vec384fp12 ret, const POINTonE2_affine *sig) |
623 | 0 | { miller_loop_n(ret, sig, (const POINTonE1_affine *)&BLS12_381_G1, 1); } |
624 | | |
625 | | BLST_ERROR blst_core_verify_pk_in_g1(const POINTonE1_affine *pk, |
626 | | const POINTonE2_affine *signature, |
627 | | int hash_or_encode, |
628 | | const void *msg, size_t msg_len, |
629 | | const void *DST, size_t DST_len, |
630 | | const void *aug, size_t aug_len) |
631 | 783 | { |
632 | 783 | PAIRING ctx; |
633 | 783 | BLST_ERROR ret; |
634 | | |
635 | 783 | ctx.ctrl = AGGR_UNDEFINED | (hash_or_encode ? AGGR_HASH_OR_ENCODE : 0); |
636 | 783 | ctx.nelems = 0; |
637 | 783 | ctx.DST = DST; |
638 | 783 | ctx.DST_len = DST_len; |
639 | | |
640 | 783 | ret = PAIRING_Aggregate_PK_in_G1(&ctx, pk, 1, signature, 1, NULL, 0, |
641 | 783 | msg, msg_len, aug, aug_len); |
642 | 783 | if (ret != BLST_SUCCESS) |
643 | 114 | return ret; |
644 | | |
645 | 669 | PAIRING_Commit(&ctx); |
646 | | |
647 | 669 | return PAIRING_FinalVerify(&ctx, NULL) ? BLST_SUCCESS : BLST_VERIFY_FAIL; |
648 | 783 | } |
649 | | |
650 | | BLST_ERROR blst_core_verify_pk_in_g2(const POINTonE2_affine *pk, |
651 | | const POINTonE1_affine *signature, |
652 | | int hash_or_encode, |
653 | | const void *msg, size_t msg_len, |
654 | | const void *DST, size_t DST_len, |
655 | | const void *aug, size_t aug_len) |
656 | 0 | { |
657 | 0 | PAIRING ctx; |
658 | 0 | BLST_ERROR ret; |
659 | |
|
660 | 0 | ctx.ctrl = AGGR_UNDEFINED | (hash_or_encode ? AGGR_HASH_OR_ENCODE : 0); |
661 | 0 | ctx.nelems = 0; |
662 | 0 | ctx.DST = DST; |
663 | 0 | ctx.DST_len = DST_len; |
664 | |
|
665 | 0 | ret = PAIRING_Aggregate_PK_in_G2(&ctx, pk, 1, signature, 1, NULL, 0, |
666 | 0 | msg, msg_len, aug, aug_len); |
667 | 0 | if (ret != BLST_SUCCESS) |
668 | 0 | return ret; |
669 | | |
670 | 0 | PAIRING_Commit(&ctx); |
671 | |
|
672 | 0 | return PAIRING_FinalVerify(&ctx, NULL) ? BLST_SUCCESS : BLST_VERIFY_FAIL; |
673 | 0 | } |