445 lines
19 KiB
C
445 lines
19 KiB
C
/*
|
|
* Copyright Supranational LLC
|
|
* Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include "point.h"
|
|
#include "fields.h"
|
|
|
|
/*
|
|
* y^2 = x^3 + A'*x + B', isogenous one
|
|
*/
|
|
static const vec384x Aprime_E2 = { /* 240*i */
|
|
{ 0 },
|
|
{ TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285),
|
|
TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601),
|
|
TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) }
|
|
};
|
|
static const vec384x Bprime_E2 = { /* 1012 + 1012*i */
|
|
{ TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4),
|
|
TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba),
|
|
TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) },
|
|
{ TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4),
|
|
TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba),
|
|
TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) }
|
|
};
|
|
|
|
static void map_fp2_times_Zz(vec384x map[], const vec384x isogeny_map[],
|
|
const vec384x Zz_powers[], size_t n)
|
|
{
|
|
while (n--)
|
|
mul_fp2(map[n], isogeny_map[n], Zz_powers[n]);
|
|
}
|
|
|
|
static void map_fp2(vec384x acc, const vec384x x, const vec384x map[], size_t n)
|
|
{
|
|
while (n--) {
|
|
mul_fp2(acc, acc, x);
|
|
add_fp2(acc, acc, map[n]);
|
|
}
|
|
}
|
|
|
|
static void isogeny_map_to_E2(POINTonE2 *out, const POINTonE2 *p)
|
|
{
|
|
/*
|
|
* x = x_num / x_den, where
|
|
* x_num = k_(1,3) * x'^3 + k_(1,2) * x'^2 + k_(1,1) * x' + k_(1,0)
|
|
* ...
|
|
*/
|
|
static const vec384x isogeny_map_x_num[] = { /* (k_(1,*)<<384) % P */
|
|
{{ TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e),
|
|
TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062),
|
|
TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) },
|
|
{ TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e),
|
|
TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062),
|
|
TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) }},
|
|
{{ 0 },
|
|
{ TO_LIMB_T(0x5fe55555554c71d0), TO_LIMB_T(0x873fffdd236aaaa3),
|
|
TO_LIMB_T(0x6a6b4619b26ef918), TO_LIMB_T(0x21c2888408874945),
|
|
TO_LIMB_T(0x2836cda7028cabc5), TO_LIMB_T(0x0ac73310a7fd5abd) }},
|
|
{{ TO_LIMB_T(0x0a0c5555555971c3), TO_LIMB_T(0xdb0c00101f9eaaae),
|
|
TO_LIMB_T(0xb1fb2f941d797997), TO_LIMB_T(0xd3960742ef416e1c),
|
|
TO_LIMB_T(0xb70040e2c20556f4), TO_LIMB_T(0x149d7861e581393b) },
|
|
{ TO_LIMB_T(0xaff2aaaaaaa638e8), TO_LIMB_T(0x439fffee91b55551),
|
|
TO_LIMB_T(0xb535a30cd9377c8c), TO_LIMB_T(0x90e144420443a4a2),
|
|
TO_LIMB_T(0x941b66d3814655e2), TO_LIMB_T(0x0563998853fead5e) }},
|
|
{{ TO_LIMB_T(0x40aac71c71c725ed), TO_LIMB_T(0x190955557a84e38e),
|
|
TO_LIMB_T(0xd817050a8f41abc3), TO_LIMB_T(0xd86485d4c87f6fb1),
|
|
TO_LIMB_T(0x696eb479f885d059), TO_LIMB_T(0x198e1a74328002d2) },
|
|
{ 0 }}
|
|
};
|
|
/* ...
|
|
* x_den = x'^2 + k_(2,1) * x' + k_(2,0)
|
|
*/
|
|
static const vec384x isogeny_map_x_den[] = { /* (k_(2,*)<<384) % P */
|
|
{{ 0 },
|
|
{ TO_LIMB_T(0x1f3affffff13ab97), TO_LIMB_T(0xf25bfc611da3ff3e),
|
|
TO_LIMB_T(0xca3757cb3819b208), TO_LIMB_T(0x3e6427366f8cec18),
|
|
TO_LIMB_T(0x03977bc86095b089), TO_LIMB_T(0x04f69db13f39a952) }},
|
|
{{ TO_LIMB_T(0x447600000027552e), TO_LIMB_T(0xdcb8009a43480020),
|
|
TO_LIMB_T(0x6f7ee9ce4a6e8b59), TO_LIMB_T(0xb10330b7c0a95bc6),
|
|
TO_LIMB_T(0x6140b1fcfb1e54b7), TO_LIMB_T(0x0381be097f0bb4e1) },
|
|
{ TO_LIMB_T(0x7588ffffffd8557d), TO_LIMB_T(0x41f3ff646e0bffdf),
|
|
TO_LIMB_T(0xf7b1e8d2ac426aca), TO_LIMB_T(0xb3741acd32dbb6f8),
|
|
TO_LIMB_T(0xe9daf5b9482d581f), TO_LIMB_T(0x167f53e0ba7431b8) }}
|
|
};
|
|
/*
|
|
* y = y' * y_num / y_den, where
|
|
* y_num = k_(3,3) * x'^3 + k_(3,2) * x'^2 + k_(3,1) * x' + k_(3,0)
|
|
* ...
|
|
*/
|
|
static const vec384x isogeny_map_y_num[] = { /* (k_(3,*)<<384) % P */
|
|
{{ TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2),
|
|
TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1),
|
|
TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) },
|
|
{ TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2),
|
|
TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1),
|
|
TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) }},
|
|
{{ 0 },
|
|
{ TO_LIMB_T(0xbf0a71c71c91b406), TO_LIMB_T(0x4d6d55d28b7638fd),
|
|
TO_LIMB_T(0x9d82f98e5f205aee), TO_LIMB_T(0xa27aa27b1d1a18d5),
|
|
TO_LIMB_T(0x02c3b2b2d2938e86), TO_LIMB_T(0x0c7d13420b09807f) }},
|
|
{{ TO_LIMB_T(0xd7f9555555531c74), TO_LIMB_T(0x21cffff748daaaa8),
|
|
TO_LIMB_T(0x5a9ad1866c9bbe46), TO_LIMB_T(0x4870a2210221d251),
|
|
TO_LIMB_T(0x4a0db369c0a32af1), TO_LIMB_T(0x02b1ccc429ff56af) },
|
|
{ TO_LIMB_T(0xe205aaaaaaac8e37), TO_LIMB_T(0xfcdc000768795556),
|
|
TO_LIMB_T(0x0c96011a8a1537dd), TO_LIMB_T(0x1c06a963f163406e),
|
|
TO_LIMB_T(0x010df44c82a881e6), TO_LIMB_T(0x174f45260f808feb) }},
|
|
{{ TO_LIMB_T(0xa470bda12f67f35c), TO_LIMB_T(0xc0fe38e23327b425),
|
|
TO_LIMB_T(0xc9d3d0f2c6f0678d), TO_LIMB_T(0x1c55c9935b5a982e),
|
|
TO_LIMB_T(0x27f6c0e2f0746764), TO_LIMB_T(0x117c5e6e28aa9054) },
|
|
{ 0 }}
|
|
};
|
|
/* ...
|
|
* y_den = x'^3 + k_(4,2) * x'^2 + k_(4,1) * x' + k_(4,0)
|
|
*/
|
|
static const vec384x isogeny_map_y_den[] = { /* (k_(4,*)<<384) % P */
|
|
{{ TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75),
|
|
TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5),
|
|
TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) },
|
|
{ TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75),
|
|
TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5),
|
|
TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) }},
|
|
{{ 0 },
|
|
{ TO_LIMB_T(0x5db0fffffd3b02c5), TO_LIMB_T(0xd713f52358ebfdba),
|
|
TO_LIMB_T(0x5ea60761a84d161a), TO_LIMB_T(0xbb2c75a34ea6c44a),
|
|
TO_LIMB_T(0x0ac6735921c1119b), TO_LIMB_T(0x0ee3d913bdacfbf6) }},
|
|
{{ TO_LIMB_T(0x66b10000003affc5), TO_LIMB_T(0xcb1400e764ec0030),
|
|
TO_LIMB_T(0xa73e5eb56fa5d106), TO_LIMB_T(0x8984c913a0fe09a9),
|
|
TO_LIMB_T(0x11e10afb78ad7f13), TO_LIMB_T(0x05429d0e3e918f52) },
|
|
{ TO_LIMB_T(0x534dffffffc4aae6), TO_LIMB_T(0x5397ff174c67ffcf),
|
|
TO_LIMB_T(0xbff273eb870b251d), TO_LIMB_T(0xdaf2827152870915),
|
|
TO_LIMB_T(0x393a9cbaca9e2dc3), TO_LIMB_T(0x14be74dbfaee5748) }}
|
|
};
|
|
vec384x Zz_powers[3], map[3], xn, xd, yn, yd;
|
|
|
|
/* lay down Z^2 powers in descending order */
|
|
sqr_fp2(Zz_powers[2], p->Z); /* ZZ^1 */
|
|
sqr_fp2(Zz_powers[1], Zz_powers[2]); /* ZZ^2 1+1 */
|
|
mul_fp2(Zz_powers[0], Zz_powers[2], Zz_powers[1]); /* ZZ^3 2+1 */
|
|
|
|
map_fp2_times_Zz(map, isogeny_map_x_num, Zz_powers, 3);
|
|
mul_fp2(xn, p->X, isogeny_map_x_num[3]);
|
|
add_fp2(xn, xn, map[2]);
|
|
map_fp2(xn, p->X, map, 2);
|
|
|
|
map_fp2_times_Zz(map, isogeny_map_x_den, Zz_powers + 1, 2);
|
|
add_fp2(xd, p->X, map[1]);
|
|
map_fp2(xd, p->X, map, 1);
|
|
mul_fp2(xd, xd, Zz_powers[2]); /* xd *= Z^2 */
|
|
|
|
map_fp2_times_Zz(map, isogeny_map_y_num, Zz_powers, 3);
|
|
mul_fp2(yn, p->X, isogeny_map_y_num[3]);
|
|
add_fp2(yn, yn, map[2]);
|
|
map_fp2(yn, p->X, map, 2);
|
|
mul_fp2(yn, yn, p->Y); /* yn *= Y */
|
|
|
|
map_fp2_times_Zz(map, isogeny_map_y_den, Zz_powers, 3);
|
|
add_fp2(yd, p->X, map[2]);
|
|
map_fp2(yd, p->X, map, 2);
|
|
mul_fp2(Zz_powers[2], Zz_powers[2], p->Z);
|
|
mul_fp2(yd, yd, Zz_powers[2]); /* yd *= Z^3 */
|
|
|
|
/* convert (xn, xd, yn, yd) to Jacobian coordinates */
|
|
mul_fp2(out->Z, xd, yd); /* Z = xd * yd */
|
|
mul_fp2(out->X, xn, yd);
|
|
mul_fp2(out->X, out->X, out->Z); /* X = xn * xd * yd^2 */
|
|
sqr_fp2(out->Y, out->Z);
|
|
mul_fp2(out->Y, out->Y, xd);
|
|
mul_fp2(out->Y, out->Y, yn); /* Y = yn * xd^3 * yd^2 */
|
|
}
|
|
|
|
static void map_to_isogenous_E2(POINTonE2 *p, const vec384x u)
|
|
{
|
|
static const vec384x minus_A = {
|
|
{ 0 },
|
|
{ TO_LIMB_T(0xd4c4fffffcec5869), TO_LIMB_T(0x1da3f3eed25bfd79),
|
|
TO_LIMB_T(0x7fa833c5136fff67), TO_LIMB_T(0x59261433cd540cbd),
|
|
TO_LIMB_T(0x48450f5f2b84682c), TO_LIMB_T(0x07e05d00bf959233) }
|
|
};
|
|
static const vec384x Z = { /* -2 - i */
|
|
{ TO_LIMB_T(0x87ebfffffff9555c), TO_LIMB_T(0x656fffe5da8ffffa),
|
|
TO_LIMB_T(0x0fd0749345d33ad2), TO_LIMB_T(0xd951e663066576f4),
|
|
TO_LIMB_T(0xde291a3d41e980d3), TO_LIMB_T(0x0815664c7dfe040d) },
|
|
{ TO_LIMB_T(0x43f5fffffffcaaae), TO_LIMB_T(0x32b7fff2ed47fffd),
|
|
TO_LIMB_T(0x07e83a49a2e99d69), TO_LIMB_T(0xeca8f3318332bb7a),
|
|
TO_LIMB_T(0xef148d1ea0f4c069), TO_LIMB_T(0x040ab3263eff0206) }
|
|
};
|
|
static const vec384x recip_ZZZ = { /* 1/(Z^3) */
|
|
{ TO_LIMB_T(0x65018f5c28f598eb), TO_LIMB_T(0xe6020417f022d916),
|
|
TO_LIMB_T(0xd6327313288369c7), TO_LIMB_T(0x622ded8eb447156f),
|
|
TO_LIMB_T(0xe52a2aee72c2a01f), TO_LIMB_T(0x089812fb8481ffe4) },
|
|
{ TO_LIMB_T(0x2574eb851eb8619f), TO_LIMB_T(0xdba2e97912925604),
|
|
TO_LIMB_T(0x67e495a909e7a18e), TO_LIMB_T(0xdf2da23b8145b8f7),
|
|
TO_LIMB_T(0xcf5d3728310ebf6d), TO_LIMB_T(0x11be446236f4c116) }
|
|
};
|
|
static const vec384x magic_ZZZ = { /* 1/Z^3 = a + b*i */
|
|
/* a^2 + b^2 */
|
|
{ TO_LIMB_T(0xaa7eb851eb8508e0), TO_LIMB_T(0x1c54fdf360989374),
|
|
TO_LIMB_T(0xc87f2fc6e716c62e), TO_LIMB_T(0x0124aefb1f9efea7),
|
|
TO_LIMB_T(0xb2f8be63e844865c), TO_LIMB_T(0x08b47f775a7ef35a) },
|
|
/* (a^2 + b^2)^((P-3)/4) */
|
|
{ TO_LIMB_T(0xe4132bbd838cf70a), TO_LIMB_T(0x01d769ac83772c19),
|
|
TO_LIMB_T(0xa83dd6e974c22e45), TO_LIMB_T(0xbc8ec3e777b08dff),
|
|
TO_LIMB_T(0xc035c2042ecf5da3), TO_LIMB_T(0x073929e97f0850bf) }
|
|
};
|
|
static const vec384x ZxA = { /* 240 - 480*i */
|
|
{ TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285),
|
|
TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601),
|
|
TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) },
|
|
{ TO_LIMB_T(0xa989fffff9d8b0d2), TO_LIMB_T(0x3b47e7dda4b7faf3),
|
|
TO_LIMB_T(0xff50678a26dffece), TO_LIMB_T(0xb24c28679aa8197a),
|
|
TO_LIMB_T(0x908a1ebe5708d058), TO_LIMB_T(0x0fc0ba017f2b2466) }
|
|
};
|
|
vec384x uu, tv2, tv4, x2n, gx1, gxd, y2;
|
|
#if 0
|
|
vec384x xn, x1n, xd, y, y1, Zuu;
|
|
#else
|
|
# define xn p->X
|
|
# define y p->Y
|
|
# define xd p->Z
|
|
# define x1n xn
|
|
# define y1 y
|
|
# define Zuu x2n
|
|
#endif
|
|
#define sgn0_fp2(a) (sgn0_pty_mont_384x((a), BLS12_381_P, p0) & 1)
|
|
bool_t e1, e2;
|
|
|
|
/*
|
|
* as per map_to_curve() from poc/sswu_opt.sage at
|
|
* https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve
|
|
* with 9mod16 twists...
|
|
*/
|
|
/* x numerator variants */
|
|
sqr_fp2(uu, u); /* uu = u^2 */
|
|
mul_fp2(Zuu, Z, uu); /* Zuu = Z * uu */
|
|
sqr_fp2(tv2, Zuu); /* tv2 = Zuu^2 */
|
|
add_fp2(tv2, tv2, Zuu); /* tv2 = tv2 + Zuu */
|
|
add_fp2(x1n, tv2, BLS12_381_Rx.p2); /* x1n = tv2 + 1 */
|
|
mul_fp2(x1n, x1n, Bprime_E2); /* x1n = x1n * B */
|
|
mul_fp2(x2n, Zuu, x1n); /* x2n = Zuu * x1n */
|
|
|
|
/* x denumenator */
|
|
mul_fp2(xd, minus_A, tv2); /* xd = -A * tv2 */
|
|
e1 = vec_is_zero(xd, sizeof(xd)); /* e1 = xd == 0 */
|
|
vec_select(xd, ZxA, xd, sizeof(xd), e1); /* # If xd == 0, set xd = Z*A */
|
|
|
|
/* y numerators variants */
|
|
sqr_fp2(tv2, xd); /* tv2 = xd^2 */
|
|
mul_fp2(gxd, xd, tv2); /* gxd = xd^3 */
|
|
mul_fp2(tv2, Aprime_E2, tv2); /* tv2 = A * tv2 */
|
|
sqr_fp2(gx1, x1n); /* gx1 = x1n^2 */
|
|
add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1n^2 + A*xd^2 */
|
|
mul_fp2(gx1, gx1, x1n); /* gx1 = gx1 * x1n # x1n^3 + A*x1n*xd^2 */
|
|
mul_fp2(tv2, Bprime_E2, gxd); /* tv2 = B * gxd */
|
|
add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1^3 + A*x1*xd^2 + B*xd^3 */
|
|
sqr_fp2(tv4, gxd); /* tv4 = gxd^2 */
|
|
mul_fp2(tv2, gx1, gxd); /* tv2 = gx1 * gxd */
|
|
mul_fp2(tv4, tv4, tv2); /* tv4 = tv4 * tv2 # gx1*gxd^3 */
|
|
e2 = recip_sqrt_fp2(y1, tv4, /* y1 = tv4^c1 # (gx1*gxd^3)^((p^2-9)/16) */
|
|
recip_ZZZ, magic_ZZZ);
|
|
mul_fp2(y1, y1, tv2); /* y1 = y1 * tv2 # gx1*gxd*y1 */
|
|
mul_fp2(y2, y1, uu); /* y2 = y1 * uu */
|
|
mul_fp2(y2, y2, u); /* y2 = y2 * u */
|
|
|
|
/* choose numerators */
|
|
vec_select(xn, x1n, x2n, sizeof(xn), e2); /* xn = e2 ? x1n : x2n */
|
|
vec_select(y, y1, y2, sizeof(y), e2); /* y = e2 ? y1 : y2 */
|
|
|
|
e1 = sgn0_fp2(u);
|
|
e2 = sgn0_fp2(y);
|
|
cneg_fp2(y, y, e1^e2); /* fix sign of y */
|
|
/* return (xn, xd, y, 1) */
|
|
|
|
/* convert (xn, xd, y, 1) to Jacobian projective coordinates */
|
|
mul_fp2(p->X, xn, xd); /* X = xn * xd */
|
|
mul_fp2(p->Y, y, gxd); /* Y = y * xd^3 */
|
|
#ifndef xd
|
|
vec_copy(p->Z, xd, sizeof(xd)); /* Z = xd */
|
|
#else
|
|
# undef xn
|
|
# undef y
|
|
# undef xd
|
|
# undef x1n
|
|
# undef y1
|
|
# undef Zuu
|
|
# undef tv4
|
|
#endif
|
|
#undef sgn0_fp2
|
|
}
|
|
|
|
#if 0
|
|
static const byte h_eff[] = {
|
|
TO_BYTES(0xe8020005aaa95551), TO_BYTES(0x59894c0adebbf6b4),
|
|
TO_BYTES(0xe954cbc06689f6a3), TO_BYTES(0x2ec0ec69d7477c1a),
|
|
TO_BYTES(0x6d82bf015d1212b0), TO_BYTES(0x329c2f178731db95),
|
|
TO_BYTES(0x9986ff031508ffe1), TO_BYTES(0x88e2a8e9145ad768),
|
|
TO_BYTES(0x584c6a0ea91b3528), TO_BYTES(0x0bc69f08f2ee75b3)
|
|
};
|
|
|
|
static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p)
|
|
{ POINTonE2_mult_w5(out, p, h_eff, 636); }
|
|
#else
|
|
/*
|
|
* As per suggestions in "7. Clearing the cofactor" at
|
|
* https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
|
|
*/
|
|
static void POINTonE2_add_n_dbl(POINTonE2 *out, const POINTonE2 *p, size_t n)
|
|
{
|
|
POINTonE2_dadd(out, out, p, NULL);
|
|
while(n--)
|
|
POINTonE2_double(out, out);
|
|
}
|
|
|
|
static void POINTonE2_times_minus_z(POINTonE2 *out, const POINTonE2 *in)
|
|
{
|
|
POINTonE2_double(out, in); /* 1: 0x2 */
|
|
POINTonE2_add_n_dbl(out, in, 2); /* 2..4: 0x3..0xc */
|
|
POINTonE2_add_n_dbl(out, in, 3); /* 5..8: 0xd..0x68 */
|
|
POINTonE2_add_n_dbl(out, in, 9); /* 9..18: 0x69..0xd200 */
|
|
POINTonE2_add_n_dbl(out, in, 32); /* 19..51: ..0xd20100000000 */
|
|
POINTonE2_add_n_dbl(out, in, 16); /* 52..68: ..0xd201000000010000 */
|
|
}
|
|
|
|
static void psi(POINTonE2 *out, const POINTonE2 *in);
|
|
|
|
static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p)
|
|
{
|
|
POINTonE2 t0, t1;
|
|
|
|
/* A.Budroni, F.Pintore, "Efficient hash maps to G2 on BLS curves" */
|
|
POINTonE2_double(out, p); /* out = 2P */
|
|
psi(out, out); /* out = Ψ(2P) */
|
|
psi(out, out); /* out = Ψ²(2P) */
|
|
|
|
vec_copy(&t0, p, sizeof(t0));
|
|
POINTonE2_cneg(&t0, 1); /* t0 = -P */
|
|
psi(&t1, &t0); /* t1 = -Ψ(P) */
|
|
POINTonE2_dadd(out, out, &t0, NULL);/* out = Ψ²(2P) - P */
|
|
POINTonE2_dadd(out, out, &t1, NULL);/* out = Ψ²(2P) - P - Ψ(P) */
|
|
|
|
POINTonE2_times_minus_z(&t0, p); /* t0 = [-z]P */
|
|
POINTonE2_dadd(&t0, &t0, p, NULL); /* t0 = [-z + 1]P */
|
|
POINTonE2_dadd(&t0, &t0, &t1, NULL);/* t0 = [-z + 1]P - Ψ(P) */
|
|
POINTonE2_times_minus_z(&t1, &t0); /* t1 = [z² - z]P + [z]Ψ(P) */
|
|
POINTonE2_dadd(out, out, &t1, NULL);/* out = [z² - z - 1]P */
|
|
/* + [z - 1]Ψ(P) */
|
|
/* + Ψ²(2P) */
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* |u|, |v| are expected to be in Montgomery representation
|
|
*/
|
|
static void map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v)
|
|
{
|
|
POINTonE2 p;
|
|
|
|
map_to_isogenous_E2(&p, u);
|
|
|
|
if (v != NULL) {
|
|
map_to_isogenous_E2(out, v); /* borrow |out| */
|
|
POINTonE2_dadd(&p, &p, out, Aprime_E2);
|
|
}
|
|
|
|
isogeny_map_to_E2(&p, &p); /* sprinkle isogenous powder */
|
|
clear_cofactor(out, &p);
|
|
}
|
|
|
|
void blst_map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v)
|
|
{ map_to_g2(out, u, v); }
|
|
|
|
static void Encode_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
|
|
const unsigned char *DST, size_t DST_len,
|
|
const unsigned char *aug, size_t aug_len)
|
|
{
|
|
vec384x u[1];
|
|
|
|
hash_to_field(u[0], 2, aug, aug_len, msg, msg_len, DST, DST_len);
|
|
map_to_g2(p, u[0], NULL);
|
|
}
|
|
|
|
void blst_encode_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
|
|
const unsigned char *DST, size_t DST_len,
|
|
const unsigned char *aug, size_t aug_len)
|
|
{ Encode_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); }
|
|
|
|
static void Hash_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
|
|
const unsigned char *DST, size_t DST_len,
|
|
const unsigned char *aug, size_t aug_len)
|
|
{
|
|
vec384x u[2];
|
|
|
|
hash_to_field(u[0], 4, aug, aug_len, msg, msg_len, DST, DST_len);
|
|
map_to_g2(p, u[0], u[1]);
|
|
}
|
|
|
|
void blst_hash_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
|
|
const unsigned char *DST, size_t DST_len,
|
|
const unsigned char *aug, size_t aug_len)
|
|
{ Hash_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); }
|
|
|
|
static bool_t POINTonE2_in_G2(const POINTonE2 *P)
|
|
{
|
|
#if 0
|
|
POINTonE2 t0, t1, t2;
|
|
|
|
/* Bowe, S., "Faster subgroup checks for BLS12-381" */
|
|
psi(&t0, P); /* Ψ(P) */
|
|
psi(&t0, &t0); /* Ψ²(P) */
|
|
psi(&t1, &t0); /* Ψ³(P) */
|
|
|
|
POINTonE2_times_minus_z(&t2, &t1);
|
|
POINTonE2_dadd(&t0, &t0, &t2, NULL);
|
|
POINTonE2_cneg(&t0, 1);
|
|
POINTonE2_dadd(&t0, &t0, P, NULL); /* [z]Ψ³(P) - Ψ²(P) + P */
|
|
|
|
return vec_is_zero(t0.Z, sizeof(t0.Z));
|
|
#else
|
|
POINTonE2 t0, t1;
|
|
|
|
/* Scott, M., https://eprint.iacr.org/2021/1130 */
|
|
psi(&t0, P); /* Ψ(P) */
|
|
|
|
POINTonE2_times_minus_z(&t1, P);
|
|
POINTonE2_cneg(&t1, 1); /* [z]P */
|
|
|
|
return POINTonE2_is_equal(&t0, &t1);
|
|
#endif
|
|
}
|
|
|
|
int blst_p2_in_g2(const POINTonE2 *p)
|
|
{ return (int)POINTonE2_in_G2(p); }
|
|
|
|
int blst_p2_affine_in_g2(const POINTonE2_affine *p)
|
|
{
|
|
POINTonE2 P;
|
|
|
|
vec_copy(P.X, p->X, 2*sizeof(P.X));
|
|
vec_select(P.Z, p->X, BLS12_381_Rx.p, sizeof(P.Z),
|
|
vec_is_zero(p, sizeof(*p)));
|
|
|
|
return (int)POINTonE2_in_G2(&P);
|
|
}
|