github.com/onflow/flow-go/crypto@v0.24.8/bls12381_utils.c (about) 1 // +build relic 2 3 // this file contains utility functions for the curve BLS 12-381 4 // these tools are shared by the BLS signature scheme, the BLS based threshold signature 5 // and the BLS distributed key generation protocols 6 7 #include "bls12381_utils.h" 8 #include "bls_include.h" 9 #include "assert.h" 10 11 // The functions are tested for ALLOC=AUTO (not for ALLOC=DYNAMIC) 12 13 // return macro values to the upper Go Layer 14 int get_valid() { 15 return VALID; 16 } 17 18 int get_invalid() { 19 return INVALID; 20 } 21 22 void bn_new_wrapper(bn_t a) { 23 bn_new(a); 24 } 25 26 // global variable of the pre-computed data 27 prec_st bls_prec_st; 28 prec_st* bls_prec = NULL; 29 30 // required constants for the optimized SWU hash to curve 31 #if (hashToPoint == LOCAL_SSWU) 32 extern const uint64_t iso_Nx_data[ELLP_Nx_LEN][Fp_DIGITS]; 33 extern const uint64_t iso_Ny_data[ELLP_Ny_LEN][Fp_DIGITS]; 34 #endif 35 36 #if (MEMBERSHIP_CHECK_G1 == BOWE) 37 extern const uint64_t beta_data[Fp_DIGITS]; 38 extern const uint64_t z2_1_by3_data[2]; 39 #endif 40 41 // sets the global variable to input 42 void precomputed_data_set(const prec_st* p) { 43 bls_prec = (prec_st*)p; 44 } 45 46 // Reads a prime field element from a digit vector in big endian format. 47 // There is no conversion to Montgomery domain in this function. 48 #define fp_read_raw(a, data_pointer) dv_copy((a), (data_pointer), Fp_DIGITS) 49 50 // pre-compute some data required for curve BLS12-381 51 prec_st* init_precomputed_data_BLS12_381() { 52 bls_prec = &bls_prec_st; 53 ctx_t* ctx = core_get(); 54 55 // (p-1)/2 56 bn_div_dig(&bls_prec->p_1div2, &ctx->prime, 2); 57 #if (hashToPoint == LOCAL_SSWU) 58 // (p-3)/4 59 bn_div_dig(&bls_prec->p_3div4, &bls_prec->p_1div2, 2); 60 // sqrt(-z) 61 fp_neg(bls_prec->sqrt_z, ctx->ep_map_u); 62 fp_srt(bls_prec->sqrt_z, bls_prec->sqrt_z); 63 // -a1 and a1*z 64 fp_neg(bls_prec->minus_a1, ctx->ep_iso.a); 65 fp_mul(bls_prec->a1z, ctx->ep_iso.a, ctx->ep_map_u); 66 67 for (int i=0; i<ELLP_Nx_LEN; i++) 68 fp_read_raw(bls_prec->iso_Nx[i], iso_Nx_data[i]); 69 for (int i=0; i<ELLP_Ny_LEN; i++) 70 fp_read_raw(bls_prec->iso_Ny[i], iso_Ny_data[i]); 71 #endif 72 73 #if (MEMBERSHIP_CHECK_G1 == BOWE) 74 bn_new(&bls_prec->beta); 75 bn_read_raw(&bls_prec->beta, beta_data, Fp_DIGITS); 76 bn_new(&bls_prec->z2_1_by3); 77 bn_read_raw(&bls_prec->z2_1_by3, z2_1_by3_data, 2); 78 #endif 79 80 // Montgomery constant R 81 fp_set_dig(bls_prec->r, 1); 82 return bls_prec; 83 } 84 85 // Initializes Relic context with BLS12-381 parameters 86 ctx_t* relic_init_BLS12_381() { 87 // check Relic was compiled with the right conf 88 assert(ALLOC == AUTO); 89 90 // sanity check of Relic constants the package is relying on 91 assert(RLC_OK == RLC_EQ); 92 93 // initialize relic core with a new context 94 ctx_t* bls_ctx = (ctx_t*) calloc(1, sizeof(ctx_t)); 95 if (!bls_ctx) return NULL; 96 core_set(bls_ctx); 97 if (core_init() != RLC_OK) return NULL; 98 99 // init BLS curve 100 int ret = RLC_OK; 101 #if (FP_PRIME == 381) 102 ret = ep_param_set_any_pairf(); // sets B12_P381 if FP_PRIME = 381 in relic config 103 #else 104 ep_param_set(B12_P381); 105 ep2_curve_set_twist(EP_MTYPE); // Multiplicative twist 106 #endif 107 108 if (ret != RLC_OK) return NULL; 109 return core_get(); 110 } 111 112 // seeds relic PRG 113 void seed_relic(byte* seed, int len) { 114 #if RAND == HASHD 115 // instantiate a new DRBG 116 ctx_t *ctx = core_get(); 117 ctx->seeded = 0; 118 #endif 119 rand_seed(seed, len); 120 } 121 122 // Exponentiation of a generic point p in G1 123 void ep_mult(ep_t res, const ep_t p, const bn_t expo) { 124 // Using window NAF of size 2 125 ep_mul_lwnaf(res, p, expo); 126 } 127 128 // Exponentiation of generator g1 in G1 129 // These two function are here for bench purposes only 130 void ep_mult_gen_bench(ep_t res, const bn_t expo) { 131 // Using precomputed table of size 4 132 ep_mul_gen(res, (bn_st *)expo); 133 } 134 135 void ep_mult_generic_bench(ep_t res, const bn_t expo) { 136 // generic point multiplication 137 ep_mult(res, &core_get()->ep_g, expo); 138 } 139 140 // Exponentiation of a generic point p in G2 141 void ep2_mult(ep2_t res, ep2_t p, bn_t expo) { 142 // Using window NAF of size 2 143 ep2_mul_lwnaf(res, p, expo); 144 } 145 146 // Exponentiation of fixed g2 in G2 147 void ep2_mult_gen(ep2_t res, const bn_t expo) { 148 // Using precomputed table of size 4 149 g2_mul_gen(res, (bn_st*)expo); 150 } 151 152 // DEBUG printing functions 153 void bytes_print_(char* s, byte* data, int len) { 154 printf("[%s]:\n", s); 155 for (int i=0; i<len; i++) 156 printf("%02x,", data[i]); 157 printf("\n"); 158 } 159 160 // DEBUG printing functions 161 void fp_print_(char* s, fp_st a) { 162 char* str = malloc(sizeof(char) * fp_size_str(a, 16)); 163 fp_write_str(str, 100, a, 16); 164 printf("[%s]:\n%s\n", s, str); 165 free(str); 166 } 167 168 void bn_print_(char* s, bn_st *a) { 169 char* str = malloc(sizeof(char) * bn_size_str(a, 16)); 170 bn_write_str(str, 128, a, 16); 171 printf("[%s]:\n%s\n", s, str); 172 free(str); 173 } 174 175 void ep_print_(char* s, ep_st* p) { 176 printf("[%s]:\n", s); 177 g1_print(p); 178 } 179 180 void ep2_print_(char* s, ep2_st* p) { 181 printf("[%s]:\n", s); 182 g2_print(p); 183 } 184 185 // generates a random number less than the order r 186 void bn_randZr_star(bn_t x) { 187 // reduce the modular reduction bias 188 const int seed_len = BITS_TO_BYTES(Fr_BITS + SEC_BITS); 189 byte seed[seed_len]; 190 rand_bytes(seed, seed_len); 191 bn_map_to_Zr_star(x, seed, seed_len); 192 rand_bytes(seed, seed_len); // overwrite seed 193 } 194 195 // generates a random number less than the order r 196 void bn_randZr(bn_t x) { 197 // reduce the modular reduction bias 198 bn_new_size(x, BITS_TO_DIGITS(Fr_BITS + SEC_BITS)); 199 bn_rand(x, RLC_POS, Fr_BITS + SEC_BITS); 200 bn_mod(x, x, &core_get()->ep_r); 201 } 202 203 // Reads a scalar from an array and maps it to Zr. 204 // The resulting scalar `a` satisfies 0 <= a < r. 205 // `len` must be less than BITS_TO_BYTES(RLC_BN_BITS). 206 // It returns VALID if scalar is zero and INVALID otherwise 207 int bn_map_to_Zr(bn_t a, const uint8_t* bin, int len) { 208 bn_t tmp; 209 bn_new(tmp); 210 bn_new_size(tmp, BYTES_TO_DIGITS(len)); 211 bn_read_bin(tmp, bin, len); 212 bn_mod(a, tmp, &core_get()->ep_r); 213 bn_rand(tmp, RLC_POS, len << 3); // overwrite tmp 214 bn_free(tmp); 215 if (bn_cmp_dig(a, 0) == RLC_EQ) { 216 return VALID; 217 } 218 return INVALID; 219 } 220 221 // Reads a scalar from an array and maps it to Zr*. 222 // The resulting scalar `a` satisfies 0 < a < r. 223 // `len` must be less than BITS_TO_BYTES(RLC_BN_BITS) 224 void bn_map_to_Zr_star(bn_t a, const uint8_t* bin, int len) { 225 bn_t tmp; 226 bn_new(tmp); 227 bn_new_size(tmp, BYTES_TO_DIGITS(len)); 228 bn_read_bin(tmp, bin, len); 229 bn_t r_1; 230 bn_new(r_1); 231 bn_sub_dig(r_1, &core_get()->ep_r, 1); 232 bn_mod_basic(a,tmp,r_1); 233 bn_add_dig(a,a,1); 234 bn_rand(tmp, RLC_POS, len << 3); // overwrite tmp 235 bn_free(tmp); 236 bn_free(r_1); 237 } 238 239 // returns the sign of y. 240 // 1 if y > (p - 1)/2 and 0 otherwise. 241 static int fp_get_sign(const fp_t y) { 242 bn_t bn_y; 243 bn_new(bn_y); 244 fp_prime_back(bn_y, y); 245 return bn_cmp(bn_y, &bls_prec->p_1div2) == RLC_GT; 246 } 247 248 // ep_write_bin_compact exports a point a in E(Fp) to a buffer bin in a compressed or uncompressed form. 249 // len is the allocated size of the buffer bin. 250 // The serialization is following: 251 // https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-) 252 // The code is a modified version of Relic ep_write_bin 253 void ep_write_bin_compact(byte *bin, const ep_t a, const int len) { 254 const int G1_size = (G1_BYTES/(G1_SERIALIZATION+1)); 255 256 if (len!=G1_size) { 257 RLC_THROW(ERR_NO_BUFFER); 258 return; 259 } 260 261 if (ep_is_infty(a)) { 262 // set the infinity bit 263 bin[0] = (G1_SERIALIZATION << 7) | 0x40; 264 memset(bin+1, 0, G1_size-1); 265 return; 266 } 267 268 RLC_TRY { 269 ep_t t; 270 ep_null(t); 271 ep_new(t); 272 ep_norm(t, a); 273 fp_write_bin(bin, Fp_BYTES, t->x); 274 275 if (G1_SERIALIZATION == COMPRESSED) { 276 bin[0] |= (fp_get_sign(t->y) << 5); 277 } else { 278 fp_write_bin(bin + Fp_BYTES, Fp_BYTES, t->y); 279 } 280 ep_free(t); 281 } RLC_CATCH_ANY { 282 RLC_THROW(ERR_CAUGHT); 283 } 284 285 bin[0] |= (G1_SERIALIZATION << 7); 286 } 287 288 // fp_read_bin_safe is a modified version of Relic's (void fp_read_bin). 289 // It reads a field element from a buffer and makes sure the big number read can be 290 // written as a field element (is reduced modulo p). 291 // Unlike Relic's versions, the function does not reduce the read integer modulo p and does 292 // not throw an exception for an integer larger than p. The function returns RLC_OK if the input 293 // corresponds to a field element, and returns RLC_ERR otherwise. 294 static int fp_read_bin_safe(fp_t a, const uint8_t *bin, int len) { 295 if (len != Fp_BYTES) { 296 return RLC_ERR; 297 } 298 299 int ret = RLC_ERR; 300 bn_t t; 301 bn_new(t); 302 bn_read_bin(t, bin, Fp_BYTES); 303 304 // make sure read bn is reduced modulo p 305 // first check is sanity check, since current implementation of `bn_read_bin` insures 306 // output bn is positive 307 if (bn_sign(t) == RLC_NEG || bn_cmp(t, &core_get()->prime) != RLC_LT) { 308 goto out; 309 } 310 311 if (bn_is_zero(t)) { 312 fp_zero(a); 313 } else { 314 if (t->used == 1) { 315 fp_prime_conv_dig(a, t->dp[0]); 316 } else { 317 fp_prime_conv(a, t); 318 } 319 } 320 ret = RLC_OK; 321 out: 322 bn_free(t); 323 return ret; 324 } 325 326 // ep_read_bin_compact imports a point from a buffer in a compressed or uncompressed form. 327 // len is the size of the input buffer. 328 // 329 // The resulting point is guaranteed to be on the curve E1. 330 // The serialization follows: 331 // https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-) 332 // The code is a modified version of Relic ep_read_bin 333 // 334 // It returns RLC_OK if the inputs are valid (input buffer lengths are valid and coordinates correspond 335 // to a point on curve) and the execution completes, and RLC_ERR otherwise. 336 int ep_read_bin_compact(ep_t a, const byte *bin, const int len) { 337 // check the length 338 const int G1_size = (G1_BYTES/(G1_SERIALIZATION+1)); 339 if (len!=G1_size) { 340 return RLC_ERR; 341 } 342 343 // check the compression bit 344 int compressed = bin[0] >> 7; 345 if ((compressed == 1) != (G1_SERIALIZATION == COMPRESSED)) { 346 return RLC_ERR; 347 } 348 349 // check if the point is infinity 350 int is_infinity = bin[0] & 0x40; 351 if (is_infinity) { 352 // check if the remaining bits are cleared 353 if (bin[0] & 0x3F) { 354 return RLC_ERR; 355 } 356 for (int i=1; i<G1_size-1; i++) { 357 if (bin[i]) { 358 return RLC_ERR; 359 } 360 } 361 ep_set_infty(a); 362 return RLC_OK; 363 } 364 365 // read the sign bit and check for consistency 366 int y_sign = (bin[0] >> 5) & 1; 367 if (y_sign && (!compressed)) { 368 return RLC_ERR; 369 } 370 371 a->coord = BASIC; 372 fp_set_dig(a->z, 1); 373 // use a temporary buffer to mask the header bits and read a.x 374 byte temp[Fp_BYTES]; 375 memcpy(temp, bin, Fp_BYTES); 376 temp[0] &= 0x1F; 377 if (fp_read_bin_safe(a->x, temp, sizeof(temp)) != RLC_OK) { 378 return RLC_ERR; 379 } 380 381 if (G1_SERIALIZATION == UNCOMPRESSED) { 382 if (fp_read_bin_safe(a->y, bin + Fp_BYTES, Fp_BYTES) != RLC_OK) { 383 return RLC_ERR; 384 } 385 // check read point is on curve 386 if (!ep_on_curve(a)) { 387 return RLC_ERR; 388 } 389 return RLC_OK; 390 } 391 fp_zero(a->y); 392 fp_set_bit(a->y, 0, y_sign); 393 if (ep_upk(a, a) == 1) { 394 // resulting point is guaranteed to be on curve 395 return RLC_OK; 396 } 397 return RLC_ERR; 398 } 399 400 401 // returns the sign of y. 402 // sign(y_0) if y_1 = 0, else sign(y_1) 403 static int fp2_get_sign(fp2_t y) { 404 if (fp_is_zero(y[1])) { // no need to convert back as the montgomery form of 0 is 0 405 return fp_get_sign(y[0]); 406 } 407 return fp_get_sign(y[1]); 408 } 409 410 // ep2_write_bin_compact exports a point in E(Fp^2) to a buffer in a compressed or uncompressed form. 411 // len is the allocated size of the buffer bin. 412 // The serialization is following: 413 // https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-) 414 // The code is a modified version of Relic ep2_write_bin 415 void ep2_write_bin_compact(byte *bin, const ep2_t a, const int len) { 416 ep2_t t; 417 ep2_null(t); 418 const int G2_size = (G2_BYTES/(G2_SERIALIZATION+1)); 419 420 if (len!=G2_size) { 421 RLC_THROW(ERR_NO_BUFFER); 422 return; 423 } 424 425 if (ep2_is_infty((ep2_st *)a)) { 426 // set the infinity bit 427 bin[0] = (G2_SERIALIZATION << 7) | 0x40; 428 memset(bin+1, 0, G2_size-1); 429 return; 430 } 431 432 RLC_TRY { 433 ep2_new(t); 434 ep2_norm(t, (ep2_st *)a); 435 fp2_write_bin(bin, Fp2_BYTES, t->x, 0); 436 437 if (G2_SERIALIZATION == COMPRESSED) { 438 bin[0] |= (fp2_get_sign(t->y) << 5); 439 } else { 440 fp2_write_bin(bin + Fp2_BYTES, Fp2_BYTES, t->y, 0); 441 } 442 } RLC_CATCH_ANY { 443 RLC_THROW(ERR_CAUGHT); 444 } 445 446 bin[0] |= (G2_SERIALIZATION << 7); 447 ep_free(t); 448 } 449 450 // fp2_read_bin_safe is a modified version of Relic's (void fp2_read_bin). 451 // It reads an Fp^2 element from a buffer and makes sure the big numbers read can be 452 // written as field elements (are reduced modulo p). 453 // Unlike Relic's versions, the function does not reduce the read integers modulo p and does 454 // not throw an exception for integers larger than p. The function returns RLC_OK if the input 455 // corresponds to a field element in Fp^2, and returns RLC_ERR otherwise. 456 static int fp2_read_bin_safe(fp2_t a, const uint8_t *bin, int len) { 457 if (len != Fp2_BYTES) { 458 return RLC_ERR; 459 } 460 if (fp_read_bin_safe(a[0], bin, Fp_BYTES) != RLC_OK) { 461 return RLC_ERR; 462 } 463 if (fp_read_bin_safe(a[1], bin + Fp_BYTES, Fp_BYTES) != RLC_OK) { 464 return RLC_ERR; 465 } 466 return RLC_OK; 467 } 468 469 // ep2_read_bin_compact imports a point from a buffer in a compressed or uncompressed form. 470 // The resulting point is guaranteed to be on curve E2. 471 // 472 // It returns RLC_OK if the inputs are valid (input buffer lengths are valid and read coordinates 473 // correspond to a point on curve) and the execution completes and RLC_ERR otherwise. 474 // The code is a modified version of Relic ep2_read_bin 475 int ep2_read_bin_compact(ep2_t a, const byte *bin, const int len) { 476 // check the length 477 const int G2size = (G2_BYTES/(G2_SERIALIZATION+1)); 478 if (len!=G2size) { 479 return RLC_ERR; 480 } 481 482 // check the compression bit 483 int compressed = bin[0] >> 7; 484 if ((compressed == 1) != (G2_SERIALIZATION == COMPRESSED)) { 485 return RLC_ERR; 486 } 487 488 // check if the point in infinity 489 int is_infinity = bin[0] & 0x40; 490 if (is_infinity) { 491 // the remaining bits need to be cleared 492 if (bin[0] & 0x3F) { 493 return RLC_ERR; 494 } 495 for (int i=1; i<G2size-1; i++) { 496 if (bin[i]) { 497 return RLC_ERR; 498 } 499 } 500 ep2_set_infty(a); 501 return RLC_OK; 502 } 503 504 // read the sign bit and check for consistency 505 int y_sign = (bin[0] >> 5) & 1; 506 if (y_sign && (!compressed)) { 507 return RLC_ERR; 508 } 509 510 a->coord = BASIC; 511 fp2_set_dig(a->z, 1); // a.z 512 // use a temporary buffer to mask the header bits and read a.x 513 byte temp[Fp2_BYTES]; 514 memcpy(temp, bin, Fp2_BYTES); 515 temp[0] &= 0x1F; // clear the header bits 516 if (fp2_read_bin_safe(a->x, temp, sizeof(temp)) != RLC_OK) { 517 return RLC_ERR; 518 } 519 520 if (G2_SERIALIZATION == UNCOMPRESSED) { 521 if (fp2_read_bin_safe(a->y, bin + Fp2_BYTES, Fp2_BYTES) != RLC_OK){ 522 return RLC_ERR; 523 } 524 // check read point is on curve 525 if (!ep2_on_curve(a)) { 526 return RLC_ERR; 527 } 528 return RLC_OK; 529 } 530 531 fp2_zero(a->y); 532 fp_set_bit(a->y[0], 0, y_sign); 533 fp_zero(a->y[1]); 534 if (ep2_upk(a, a) == 1) { 535 // resulting point is guaranteed to be on curve 536 return RLC_OK; 537 } 538 return RLC_ERR; 539 } 540 541 // reads a scalar in a and checks it is a valid Zr element (a < r) 542 // returns RLC_OK if the scalar is valid and RLC_ERR otherwise. 543 int bn_read_Zr_bin(bn_t a, const uint8_t *bin, int len) { 544 if (len!=Fr_BYTES) { 545 return RLC_ERR; 546 } 547 bn_read_bin(a, bin, Fr_BYTES); 548 bn_t r; 549 bn_new(r); 550 g2_get_ord(r); 551 if (bn_cmp(a, r) == RLC_LT) { 552 return RLC_OK; 553 } 554 return RLC_ERR; 555 } 556 557 // computes the sum of the array elements x and writes the sum in jointx 558 // the sum is computed in Zr 559 void bn_sum_vector(bn_t jointx, const bn_st* x, const int len) { 560 bn_t r; 561 bn_new(r); 562 g2_get_ord(r); 563 bn_set_dig(jointx, 0); 564 bn_new_size(jointx, BITS_TO_DIGITS(Fr_BITS+1)); 565 for (int i=0; i<len; i++) { 566 bn_add(jointx, jointx, &x[i]); 567 if (bn_cmp(jointx, r) == RLC_GT) 568 bn_sub(jointx, jointx, r); 569 } 570 bn_free(r); 571 } 572 573 // computes the sum of the G2 array elements y and writes the sum in jointy 574 void ep2_sum_vector(ep2_t jointy, ep2_st* y, const int len){ 575 ep2_set_infty(jointy); 576 for (int i=0; i<len; i++){ 577 ep2_add_projc(jointy, jointy, &y[i]); 578 } 579 ep2_norm(jointy, jointy); // not necessary but left here to optimize the 580 // multiple pairing computations with the same 581 // public key 582 } 583 584 // Verifies the validity of 2 SPoCK proofs and 2 public keys. 585 // Membership check in G1 of both proofs is verified in this function. 586 // Membership check in G2 of both keys is not verified in this function. 587 // the membership check in G2 is separated to allow optimizing multiple verifications 588 // using the same public keys. 589 int bls_spock_verify(const ep2_t pk1, const byte* sig1, const ep2_t pk2, const byte* sig2) { 590 ep_t elemsG1[2]; 591 ep2_t elemsG2[2]; 592 593 // elemsG1[0] = s1 594 ep_new(elemsG1[0]); 595 int read_ret = ep_read_bin_compact(elemsG1[0], sig1, SIGNATURE_LEN); 596 if (read_ret != RLC_OK) 597 return read_ret; 598 599 // check s1 is in G1 600 if (check_membership_G1(elemsG1[0]) != VALID) // only enabled if MEMBERSHIP_CHECK==1 601 return INVALID; 602 603 // elemsG1[1] = s2 604 ep_new(elemsG1[1]); 605 read_ret = ep_read_bin_compact(elemsG1[1], sig2, SIGNATURE_LEN); 606 if (read_ret != RLC_OK) 607 return read_ret; 608 609 // check s2 in G1 610 if (check_membership_G1(elemsG1[1]) != VALID) // only enabled if MEMBERSHIP_CHECK==1 611 return INVALID; 612 613 // elemsG2[1] = pk1 614 ep2_new(elemsG2[1]); 615 ep2_copy(elemsG2[1], (ep2_st*)pk1); 616 617 // elemsG2[0] = pk2 618 ep2_new(elemsG2[0]); 619 ep2_copy(elemsG2[0], (ep2_st*)pk2); 620 621 #if DOUBLE_PAIRING 622 // elemsG2[0] = -pk2 623 ep2_neg(elemsG2[0], elemsG2[0]); 624 625 fp12_t pair; 626 fp12_new(&pair); 627 // double pairing with Optimal Ate 628 pp_map_sim_oatep_k12(pair, (ep_t*)(elemsG1) , (ep2_t*)(elemsG2), 2); 629 630 // compare the result to 1 631 int res = fp12_cmp_dig(pair, 1); 632 633 #elif SINGLE_PAIRING 634 fp12_t pair1, pair2; 635 fp12_new(&pair1); fp12_new(&pair2); 636 pp_map_oatep_k12(pair1, elemsG1[0], elemsG2[0]); 637 pp_map_oatep_k12(pair2, elemsG1[1], elemsG2[1]); 638 639 int res = fp12_cmp(pair1, pair2); 640 #endif 641 fp12_free(&one); 642 ep_free(elemsG1[0]); 643 ep_free(elemsG1[1]); 644 ep2_free(elemsG2[0]); 645 ep2_free(elemsG2[1]); 646 647 if (core_get()->code == RLC_OK) { 648 if (res == RLC_EQ) return VALID; 649 return INVALID; 650 } 651 return UNDEFINED; 652 } 653 654 // Subtracts the sum of a G2 array elements y from an element x and writes the 655 // result in res 656 void ep2_subtract_vector(ep2_t res, ep2_t x, ep2_st* y, const int len){ 657 ep2_sum_vector(res, y, len); 658 ep2_neg(res, res); 659 ep2_add_projc(res, x, res); 660 } 661 662 // computes the sum of the G1 array elements y and writes the sum in jointy 663 void ep_sum_vector(ep_t jointx, ep_st* x, const int len) { 664 ep_set_infty(jointx); 665 for (int i=0; i<len; i++){ 666 ep_add_jacob(jointx, jointx, &x[i]); 667 } 668 } 669 670 // Computes the sum of the signatures (G1 elements) flattened in a single sigs array 671 // and writes the sum (G1 element) as bytes in dest. 672 // The function assumes sigs is correctly allocated with regards to len. 673 int ep_sum_vector_byte(byte* dest, const byte* sigs_bytes, const int len) { 674 int error = UNDEFINED; 675 676 // temp variables 677 ep_t acc; 678 ep_new(acc); 679 ep_set_infty(acc); 680 ep_st* sigs = (ep_st*) malloc(len * sizeof(ep_st)); 681 if (!sigs) goto mem_error; 682 for (int i=0; i < len; i++) ep_new(sigs[i]); 683 684 // import the points from the array 685 for (int i=0; i < len; i++) { 686 // deserialize each point from the input array 687 error = ep_read_bin_compact(&sigs[i], &sigs_bytes[SIGNATURE_LEN*i], SIGNATURE_LEN); 688 if (error != RLC_OK) { 689 goto out; 690 } 691 } 692 // sum the points 693 ep_sum_vector(acc, sigs, len); 694 // export the result 695 ep_write_bin_compact(dest, acc, SIGNATURE_LEN); 696 697 error = VALID; 698 out: 699 // free the temp memory 700 ep_free(acc); 701 for (int i=0; i < len; i++) ep_free(sigs[i]); 702 free(sigs); 703 mem_error: 704 return error; 705 } 706 707 // uses a simple scalar multiplication by G1's order 708 // to check whether a point on the curve E1 is in G1. 709 int simple_subgroup_check_G1(const ep_t p){ 710 ep_t inf; 711 ep_new(inf); 712 // check p^order == infinity 713 // use basic double & add as lwnaf reduces the expo modulo r 714 ep_mul_basic(inf, p, &core_get()->ep_r); 715 if (!ep_is_infty(inf)){ 716 ep_free(inf); 717 return INVALID; 718 } 719 ep_free(inf); 720 return VALID; 721 } 722 723 // uses a simple scalar multiplication by G1's order 724 // to check whether a point on the curve E2 is in G2. 725 int simple_subgroup_check_G2(const ep2_t p){ 726 ep2_t inf; 727 ep2_new(inf); 728 // check p^order == infinity 729 // use basic double & add as lwnaf reduces the expo modulo r 730 ep2_mul_basic(inf, (ep2_st*)p, &core_get()->ep_r); 731 if (!ep2_is_infty(inf)){ 732 ep2_free(inf); 733 return INVALID; 734 } 735 ep2_free(inf); 736 return VALID; 737 } 738 739 #if (MEMBERSHIP_CHECK_G1 == BOWE) 740 // beta such that beta^3 == 1 mod p 741 // beta is in the Montgomery form 742 const uint64_t beta_data[Fp_DIGITS] = { 743 0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 744 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741, 745 }; 746 747 748 // (z^2-1)/3 with z being the parameter of bls12-381 749 const uint64_t z2_1_by3_data[2] = { 750 0x0000000055555555, 0x396c8c005555e156 751 }; 752 753 // uses Bowe's check from section 3.2 from https://eprint.iacr.org/2019/814.pdf 754 // to check whether a point on the curve E1 is in G1. 755 int bowe_subgroup_check_G1(const ep_t p){ 756 if (ep_is_infty(p) == 1) 757 return VALID; 758 fp_t b; 759 dv_copy(b, beta_data, Fp_DIGITS); 760 ep_t sigma, sigma2, p_inv; 761 ep_new(sigma); 762 ep_new(sigma2); 763 ep_new(p_inv); 764 765 // si(p) 766 ep_copy(sigma, p); 767 fp_mul(sigma[0].x, sigma[0].x, b); 768 // -si^2(p) 769 ep_copy(sigma2, sigma); 770 fp_mul(sigma2[0].x, sigma2[0].x, b); 771 fp_neg(sigma2[0].y, sigma2[0].y); 772 ep_dbl(sigma, sigma); 773 // -p 774 ep_copy(p_inv, p); 775 fp_neg(p_inv[0].y, p_inv[0].y); 776 // (z^2-1)/3 (2*si(p) - p - si^2(p)) - si^2(p) 777 ep_add(sigma, sigma, p_inv); 778 ep_add(sigma, sigma, sigma2); 779 // TODO: multiplication using a chain? 780 ep_mul_lwnaf(sigma, sigma, &bls_prec->z2_1_by3); 781 ep_add(sigma, sigma, sigma2); 782 783 ep_free(sigma2); 784 ep_free(p_inv); 785 // check result against infinity 786 if (!ep_is_infty(sigma)){ 787 ep_free(sigma); 788 return INVALID; 789 } 790 ep_free(sigma); 791 return VALID; 792 } 793 #endif 794 795 // generates a random point in G1 and stores it in p 796 void ep_rand_G1(ep_t p) { 797 // multiplies G1 generator by a random scalar 798 ep_rand(p); 799 } 800 801 // generates a random point in E1\G1 and stores it in p 802 void ep_rand_G1complement(ep_t p) { 803 // generate a random point in E1 804 p->coord = BASIC; 805 fp_set_dig(p->z, 1); 806 do { 807 fp_rand(p->x); // set x to a random field element 808 byte r; 809 rand_bytes(&r, 1); 810 fp_zero(p->y); 811 fp_set_bit(p->y, 0, r&1); // set y randomly to 0 or 1 812 } 813 while (ep_upk(p, p) == 0); // make sure p is in E1 814 815 // map the point to E1\G1 by clearing G1 order 816 ep_mul_basic(p, p, &core_get()->ep_r); 817 818 assert(ep_on_curve(p)); // sanity check to make sure p is in E1 819 } 820 821 // generates a random point in G2 and stores it in p 822 void ep2_rand_G2(ep2_t p) { 823 // multiplies G2 generator by a random scalar 824 ep2_rand(p); 825 } 826 827 // generates a random point in E2\G2 and stores it in p 828 void ep2_rand_G2complement(ep2_t p) { 829 // generate a random point in E2 830 p->coord = BASIC; 831 fp_set_dig(p->z[0], 1); 832 fp_zero(p->z[1]); 833 do { 834 fp2_rand(p->x); // set x to a random field element 835 byte r; 836 rand_bytes(&r, 1); 837 fp2_zero(p->y); 838 fp_set_bit(p->y[0], 0, r&1); // set y randomly to 0 or 1 839 } 840 while (ep2_upk(p, p) == 0); // make sure p is in E1 841 842 // map the point to E1\G1 by clearing G1 order 843 ep2_mul_basic(p, p, &core_get()->ep_r); 844 845 assert(ep2_on_curve(p)); // sanity check to make sure p is in E1 846 } 847 848 // This is a testing function. 849 // It wraps a call to a Relic macro since cgo can't call macros. 850 void xmd_sha256(uint8_t *hash, int len_hash, uint8_t *msg, int len_msg, uint8_t *dst, int len_dst){ 851 md_xmd_sh256(hash, len_hash, msg, len_msg, dst, len_dst); 852 }