/src/blst_normal/src/map_to_g2.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 | | #include "point.h" |
8 | | #include "fields.h" |
9 | | |
10 | | /* |
11 | | * y^2 = x^3 + A'*x + B', isogenous one |
12 | | */ |
13 | | static const vec384x Aprime_E2 = { /* 240*i */ |
14 | | { 0 }, |
15 | | { TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285), |
16 | | TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601), |
17 | | TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) } |
18 | | }; |
19 | | static const vec384x Bprime_E2 = { /* 1012 + 1012*i */ |
20 | | { TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4), |
21 | | TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba), |
22 | | TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) }, |
23 | | { TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4), |
24 | | TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba), |
25 | | TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) } |
26 | | }; |
27 | | |
28 | | static void map_fp2_times_Zz(vec384x map[], const vec384x isogeny_map[], |
29 | | const vec384x Zz_powers[], size_t n) |
30 | 9.24k | { |
31 | 34.6k | while (n--) |
32 | 25.4k | mul_fp2(map[n], isogeny_map[n], Zz_powers[n]); |
33 | 9.24k | } |
34 | | |
35 | | static void map_fp2(vec384x acc, const vec384x x, const vec384x map[], size_t n) |
36 | 9.24k | { |
37 | 25.4k | while (n--) { |
38 | 16.1k | mul_fp2(acc, acc, x); |
39 | 16.1k | add_fp2(acc, acc, map[n]); |
40 | 16.1k | } |
41 | 9.24k | } |
42 | | |
43 | | static void isogeny_map_to_E2(POINTonE2 *out, const POINTonE2 *p) |
44 | 2.31k | { |
45 | | /* |
46 | | * x = x_num / x_den, where |
47 | | * x_num = k_(1,3) * x'^3 + k_(1,2) * x'^2 + k_(1,1) * x' + k_(1,0) |
48 | | * ... |
49 | | */ |
50 | 2.31k | static const vec384x isogeny_map_x_num[] = { /* (k_(1,*)<<384) % P */ |
51 | 2.31k | {{ TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e), |
52 | 2.31k | TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062), |
53 | 2.31k | TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) }, |
54 | 2.31k | { TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e), |
55 | 2.31k | TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062), |
56 | 2.31k | TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) }}, |
57 | 2.31k | {{ 0 }, |
58 | 2.31k | { TO_LIMB_T(0x5fe55555554c71d0), TO_LIMB_T(0x873fffdd236aaaa3), |
59 | 2.31k | TO_LIMB_T(0x6a6b4619b26ef918), TO_LIMB_T(0x21c2888408874945), |
60 | 2.31k | TO_LIMB_T(0x2836cda7028cabc5), TO_LIMB_T(0x0ac73310a7fd5abd) }}, |
61 | 2.31k | {{ TO_LIMB_T(0x0a0c5555555971c3), TO_LIMB_T(0xdb0c00101f9eaaae), |
62 | 2.31k | TO_LIMB_T(0xb1fb2f941d797997), TO_LIMB_T(0xd3960742ef416e1c), |
63 | 2.31k | TO_LIMB_T(0xb70040e2c20556f4), TO_LIMB_T(0x149d7861e581393b) }, |
64 | 2.31k | { TO_LIMB_T(0xaff2aaaaaaa638e8), TO_LIMB_T(0x439fffee91b55551), |
65 | 2.31k | TO_LIMB_T(0xb535a30cd9377c8c), TO_LIMB_T(0x90e144420443a4a2), |
66 | 2.31k | TO_LIMB_T(0x941b66d3814655e2), TO_LIMB_T(0x0563998853fead5e) }}, |
67 | 2.31k | {{ TO_LIMB_T(0x40aac71c71c725ed), TO_LIMB_T(0x190955557a84e38e), |
68 | 2.31k | TO_LIMB_T(0xd817050a8f41abc3), TO_LIMB_T(0xd86485d4c87f6fb1), |
69 | 2.31k | TO_LIMB_T(0x696eb479f885d059), TO_LIMB_T(0x198e1a74328002d2) }, |
70 | 2.31k | { 0 }} |
71 | 2.31k | }; |
72 | | /* ... |
73 | | * x_den = x'^2 + k_(2,1) * x' + k_(2,0) |
74 | | */ |
75 | 2.31k | static const vec384x isogeny_map_x_den[] = { /* (k_(2,*)<<384) % P */ |
76 | 2.31k | {{ 0 }, |
77 | 2.31k | { TO_LIMB_T(0x1f3affffff13ab97), TO_LIMB_T(0xf25bfc611da3ff3e), |
78 | 2.31k | TO_LIMB_T(0xca3757cb3819b208), TO_LIMB_T(0x3e6427366f8cec18), |
79 | 2.31k | TO_LIMB_T(0x03977bc86095b089), TO_LIMB_T(0x04f69db13f39a952) }}, |
80 | 2.31k | {{ TO_LIMB_T(0x447600000027552e), TO_LIMB_T(0xdcb8009a43480020), |
81 | 2.31k | TO_LIMB_T(0x6f7ee9ce4a6e8b59), TO_LIMB_T(0xb10330b7c0a95bc6), |
82 | 2.31k | TO_LIMB_T(0x6140b1fcfb1e54b7), TO_LIMB_T(0x0381be097f0bb4e1) }, |
83 | 2.31k | { TO_LIMB_T(0x7588ffffffd8557d), TO_LIMB_T(0x41f3ff646e0bffdf), |
84 | 2.31k | TO_LIMB_T(0xf7b1e8d2ac426aca), TO_LIMB_T(0xb3741acd32dbb6f8), |
85 | 2.31k | TO_LIMB_T(0xe9daf5b9482d581f), TO_LIMB_T(0x167f53e0ba7431b8) }} |
86 | 2.31k | }; |
87 | | /* |
88 | | * y = y' * y_num / y_den, where |
89 | | * y_num = k_(3,3) * x'^3 + k_(3,2) * x'^2 + k_(3,1) * x' + k_(3,0) |
90 | | * ... |
91 | | */ |
92 | 2.31k | static const vec384x isogeny_map_y_num[] = { /* (k_(3,*)<<384) % P */ |
93 | 2.31k | {{ TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2), |
94 | 2.31k | TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1), |
95 | 2.31k | TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) }, |
96 | 2.31k | { TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2), |
97 | 2.31k | TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1), |
98 | 2.31k | TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) }}, |
99 | 2.31k | {{ 0 }, |
100 | 2.31k | { TO_LIMB_T(0xbf0a71c71c91b406), TO_LIMB_T(0x4d6d55d28b7638fd), |
101 | 2.31k | TO_LIMB_T(0x9d82f98e5f205aee), TO_LIMB_T(0xa27aa27b1d1a18d5), |
102 | 2.31k | TO_LIMB_T(0x02c3b2b2d2938e86), TO_LIMB_T(0x0c7d13420b09807f) }}, |
103 | 2.31k | {{ TO_LIMB_T(0xd7f9555555531c74), TO_LIMB_T(0x21cffff748daaaa8), |
104 | 2.31k | TO_LIMB_T(0x5a9ad1866c9bbe46), TO_LIMB_T(0x4870a2210221d251), |
105 | 2.31k | TO_LIMB_T(0x4a0db369c0a32af1), TO_LIMB_T(0x02b1ccc429ff56af) }, |
106 | 2.31k | { TO_LIMB_T(0xe205aaaaaaac8e37), TO_LIMB_T(0xfcdc000768795556), |
107 | 2.31k | TO_LIMB_T(0x0c96011a8a1537dd), TO_LIMB_T(0x1c06a963f163406e), |
108 | 2.31k | TO_LIMB_T(0x010df44c82a881e6), TO_LIMB_T(0x174f45260f808feb) }}, |
109 | 2.31k | {{ TO_LIMB_T(0xa470bda12f67f35c), TO_LIMB_T(0xc0fe38e23327b425), |
110 | 2.31k | TO_LIMB_T(0xc9d3d0f2c6f0678d), TO_LIMB_T(0x1c55c9935b5a982e), |
111 | 2.31k | TO_LIMB_T(0x27f6c0e2f0746764), TO_LIMB_T(0x117c5e6e28aa9054) }, |
112 | 2.31k | { 0 }} |
113 | 2.31k | }; |
114 | | /* ... |
115 | | * y_den = x'^3 + k_(4,2) * x'^2 + k_(4,1) * x' + k_(4,0) |
116 | | */ |
117 | 2.31k | static const vec384x isogeny_map_y_den[] = { /* (k_(4,*)<<384) % P */ |
118 | 2.31k | {{ TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75), |
119 | 2.31k | TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5), |
120 | 2.31k | TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) }, |
121 | 2.31k | { TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75), |
122 | 2.31k | TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5), |
123 | 2.31k | TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) }}, |
124 | 2.31k | {{ 0 }, |
125 | 2.31k | { TO_LIMB_T(0x5db0fffffd3b02c5), TO_LIMB_T(0xd713f52358ebfdba), |
126 | 2.31k | TO_LIMB_T(0x5ea60761a84d161a), TO_LIMB_T(0xbb2c75a34ea6c44a), |
127 | 2.31k | TO_LIMB_T(0x0ac6735921c1119b), TO_LIMB_T(0x0ee3d913bdacfbf6) }}, |
128 | 2.31k | {{ TO_LIMB_T(0x66b10000003affc5), TO_LIMB_T(0xcb1400e764ec0030), |
129 | 2.31k | TO_LIMB_T(0xa73e5eb56fa5d106), TO_LIMB_T(0x8984c913a0fe09a9), |
130 | 2.31k | TO_LIMB_T(0x11e10afb78ad7f13), TO_LIMB_T(0x05429d0e3e918f52) }, |
131 | 2.31k | { TO_LIMB_T(0x534dffffffc4aae6), TO_LIMB_T(0x5397ff174c67ffcf), |
132 | 2.31k | TO_LIMB_T(0xbff273eb870b251d), TO_LIMB_T(0xdaf2827152870915), |
133 | 2.31k | TO_LIMB_T(0x393a9cbaca9e2dc3), TO_LIMB_T(0x14be74dbfaee5748) }} |
134 | 2.31k | }; |
135 | 2.31k | vec384x Zz_powers[3], map[3], xn, xd, yn, yd; |
136 | | |
137 | | /* lay down Z^2 powers in descending order */ |
138 | 2.31k | sqr_fp2(Zz_powers[2], p->Z); /* ZZ^1 */ |
139 | 2.31k | sqr_fp2(Zz_powers[1], Zz_powers[2]); /* ZZ^2 1+1 */ |
140 | 2.31k | mul_fp2(Zz_powers[0], Zz_powers[2], Zz_powers[1]); /* ZZ^3 2+1 */ |
141 | | |
142 | 2.31k | map_fp2_times_Zz(map, isogeny_map_x_num, Zz_powers, 3); |
143 | 2.31k | mul_fp2(xn, p->X, isogeny_map_x_num[3]); |
144 | 2.31k | add_fp2(xn, xn, map[2]); |
145 | 2.31k | map_fp2(xn, p->X, map, 2); |
146 | | |
147 | 2.31k | map_fp2_times_Zz(map, isogeny_map_x_den, Zz_powers + 1, 2); |
148 | 2.31k | add_fp2(xd, p->X, map[1]); |
149 | 2.31k | map_fp2(xd, p->X, map, 1); |
150 | 2.31k | mul_fp2(xd, xd, Zz_powers[2]); /* xd *= Z^2 */ |
151 | | |
152 | 2.31k | map_fp2_times_Zz(map, isogeny_map_y_num, Zz_powers, 3); |
153 | 2.31k | mul_fp2(yn, p->X, isogeny_map_y_num[3]); |
154 | 2.31k | add_fp2(yn, yn, map[2]); |
155 | 2.31k | map_fp2(yn, p->X, map, 2); |
156 | 2.31k | mul_fp2(yn, yn, p->Y); /* yn *= Y */ |
157 | | |
158 | 2.31k | map_fp2_times_Zz(map, isogeny_map_y_den, Zz_powers, 3); |
159 | 2.31k | add_fp2(yd, p->X, map[2]); |
160 | 2.31k | map_fp2(yd, p->X, map, 2); |
161 | 2.31k | mul_fp2(Zz_powers[2], Zz_powers[2], p->Z); |
162 | 2.31k | mul_fp2(yd, yd, Zz_powers[2]); /* yd *= Z^3 */ |
163 | | |
164 | | /* convert (xn, xd, yn, yd) to Jacobian coordinates */ |
165 | 2.31k | mul_fp2(out->Z, xd, yd); /* Z = xd * yd */ |
166 | 2.31k | mul_fp2(out->X, xn, yd); |
167 | 2.31k | mul_fp2(out->X, out->X, out->Z); /* X = xn * xd * yd^2 */ |
168 | 2.31k | sqr_fp2(out->Y, out->Z); |
169 | 2.31k | mul_fp2(out->Y, out->Y, xd); |
170 | 2.31k | mul_fp2(out->Y, out->Y, yn); /* Y = yn * xd^3 * yd^2 */ |
171 | 2.31k | } |
172 | | |
173 | | static void map_to_isogenous_E2(POINTonE2 *p, const vec384x u) |
174 | 4.62k | { |
175 | 4.62k | static const vec384x minus_A = { |
176 | 4.62k | { 0 }, |
177 | 4.62k | { TO_LIMB_T(0xd4c4fffffcec5869), TO_LIMB_T(0x1da3f3eed25bfd79), |
178 | 4.62k | TO_LIMB_T(0x7fa833c5136fff67), TO_LIMB_T(0x59261433cd540cbd), |
179 | 4.62k | TO_LIMB_T(0x48450f5f2b84682c), TO_LIMB_T(0x07e05d00bf959233) } |
180 | 4.62k | }; |
181 | 4.62k | static const vec384x Z = { /* -2 - i */ |
182 | 4.62k | { TO_LIMB_T(0x87ebfffffff9555c), TO_LIMB_T(0x656fffe5da8ffffa), |
183 | 4.62k | TO_LIMB_T(0x0fd0749345d33ad2), TO_LIMB_T(0xd951e663066576f4), |
184 | 4.62k | TO_LIMB_T(0xde291a3d41e980d3), TO_LIMB_T(0x0815664c7dfe040d) }, |
185 | 4.62k | { TO_LIMB_T(0x43f5fffffffcaaae), TO_LIMB_T(0x32b7fff2ed47fffd), |
186 | 4.62k | TO_LIMB_T(0x07e83a49a2e99d69), TO_LIMB_T(0xeca8f3318332bb7a), |
187 | 4.62k | TO_LIMB_T(0xef148d1ea0f4c069), TO_LIMB_T(0x040ab3263eff0206) } |
188 | 4.62k | }; |
189 | 4.62k | static const vec384x recip_ZZZ = { /* 1/(Z^3) */ |
190 | 4.62k | { TO_LIMB_T(0x65018f5c28f598eb), TO_LIMB_T(0xe6020417f022d916), |
191 | 4.62k | TO_LIMB_T(0xd6327313288369c7), TO_LIMB_T(0x622ded8eb447156f), |
192 | 4.62k | TO_LIMB_T(0xe52a2aee72c2a01f), TO_LIMB_T(0x089812fb8481ffe4) }, |
193 | 4.62k | { TO_LIMB_T(0x2574eb851eb8619f), TO_LIMB_T(0xdba2e97912925604), |
194 | 4.62k | TO_LIMB_T(0x67e495a909e7a18e), TO_LIMB_T(0xdf2da23b8145b8f7), |
195 | 4.62k | TO_LIMB_T(0xcf5d3728310ebf6d), TO_LIMB_T(0x11be446236f4c116) } |
196 | 4.62k | }; |
197 | 4.62k | static const vec384x magic_ZZZ = { /* 1/Z^3 = a + b*i */ |
198 | | /* a^2 + b^2 */ |
199 | 4.62k | { TO_LIMB_T(0xaa7eb851eb8508e0), TO_LIMB_T(0x1c54fdf360989374), |
200 | 4.62k | TO_LIMB_T(0xc87f2fc6e716c62e), TO_LIMB_T(0x0124aefb1f9efea7), |
201 | 4.62k | TO_LIMB_T(0xb2f8be63e844865c), TO_LIMB_T(0x08b47f775a7ef35a) }, |
202 | | /* (a^2 + b^2)^((P-3)/4) */ |
203 | 4.62k | { TO_LIMB_T(0xe4132bbd838cf70a), TO_LIMB_T(0x01d769ac83772c19), |
204 | 4.62k | TO_LIMB_T(0xa83dd6e974c22e45), TO_LIMB_T(0xbc8ec3e777b08dff), |
205 | 4.62k | TO_LIMB_T(0xc035c2042ecf5da3), TO_LIMB_T(0x073929e97f0850bf) } |
206 | 4.62k | }; |
207 | 4.62k | static const vec384x ZxA = { /* 240 - 480*i */ |
208 | 4.62k | { TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285), |
209 | 4.62k | TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601), |
210 | 4.62k | TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) }, |
211 | 4.62k | { TO_LIMB_T(0xa989fffff9d8b0d2), TO_LIMB_T(0x3b47e7dda4b7faf3), |
212 | 4.62k | TO_LIMB_T(0xff50678a26dffece), TO_LIMB_T(0xb24c28679aa8197a), |
213 | 4.62k | TO_LIMB_T(0x908a1ebe5708d058), TO_LIMB_T(0x0fc0ba017f2b2466) } |
214 | 4.62k | }; |
215 | 4.62k | vec384x uu, tv2, tv4, x2n, gx1, gxd, y2; |
216 | | #if 0 |
217 | | vec384x xn, x1n, xd, y, y1, Zuu; |
218 | | #else |
219 | 46.2k | # define xn p->X |
220 | 46.2k | # define y p->Y |
221 | 41.5k | # define xd p->Z |
222 | 32.3k | # define x1n xn |
223 | 23.1k | # define y1 y |
224 | 18.4k | # define Zuu x2n |
225 | 4.62k | #endif |
226 | 9.24k | #define sgn0_fp2(a) (sgn0_pty_mont_384x((a), BLS12_381_P, p0) & 1) |
227 | 4.62k | bool_t e1, e2; |
228 | | |
229 | | /* |
230 | | * as per map_to_curve() from poc/sswu_opt.sage at |
231 | | * https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve |
232 | | * with 9mod16 twists... |
233 | | */ |
234 | | /* x numerator variants */ |
235 | 4.62k | sqr_fp2(uu, u); /* uu = u^2 */ |
236 | 4.62k | mul_fp2(Zuu, Z, uu); /* Zuu = Z * uu */ |
237 | 4.62k | sqr_fp2(tv2, Zuu); /* tv2 = Zuu^2 */ |
238 | 4.62k | add_fp2(tv2, tv2, Zuu); /* tv2 = tv2 + Zuu */ |
239 | 4.62k | add_fp2(x1n, tv2, BLS12_381_Rx.p2); /* x1n = tv2 + 1 */ |
240 | 4.62k | mul_fp2(x1n, x1n, Bprime_E2); /* x1n = x1n * B */ |
241 | 4.62k | mul_fp2(x2n, Zuu, x1n); /* x2n = Zuu * x1n */ |
242 | | |
243 | | /* x denumenator */ |
244 | 4.62k | mul_fp2(xd, minus_A, tv2); /* xd = -A * tv2 */ |
245 | 4.62k | e1 = vec_is_zero(xd, sizeof(xd)); /* e1 = xd == 0 */ |
246 | 4.62k | vec_select(xd, ZxA, xd, sizeof(xd), e1); /* # If xd == 0, set xd = Z*A */ |
247 | | |
248 | | /* y numerators variants */ |
249 | 4.62k | sqr_fp2(tv2, xd); /* tv2 = xd^2 */ |
250 | 4.62k | mul_fp2(gxd, xd, tv2); /* gxd = xd^3 */ |
251 | 4.62k | mul_fp2(tv2, Aprime_E2, tv2); /* tv2 = A * tv2 */ |
252 | 4.62k | sqr_fp2(gx1, x1n); /* gx1 = x1n^2 */ |
253 | 4.62k | add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1n^2 + A*xd^2 */ |
254 | 4.62k | mul_fp2(gx1, gx1, x1n); /* gx1 = gx1 * x1n # x1n^3 + A*x1n*xd^2 */ |
255 | 4.62k | mul_fp2(tv2, Bprime_E2, gxd); /* tv2 = B * gxd */ |
256 | 4.62k | add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1^3 + A*x1*xd^2 + B*xd^3 */ |
257 | 4.62k | sqr_fp2(tv4, gxd); /* tv4 = gxd^2 */ |
258 | 4.62k | mul_fp2(tv2, gx1, gxd); /* tv2 = gx1 * gxd */ |
259 | 4.62k | mul_fp2(tv4, tv4, tv2); /* tv4 = tv4 * tv2 # gx1*gxd^3 */ |
260 | 4.62k | e2 = recip_sqrt_fp2(y1, tv4, /* y1 = tv4^c1 # (gx1*gxd^3)^((p^2-9)/16) */ |
261 | 4.62k | recip_ZZZ, magic_ZZZ); |
262 | 4.62k | mul_fp2(y1, y1, tv2); /* y1 = y1 * tv2 # gx1*gxd*y1 */ |
263 | 4.62k | mul_fp2(y2, y1, uu); /* y2 = y1 * uu */ |
264 | 4.62k | mul_fp2(y2, y2, u); /* y2 = y2 * u */ |
265 | | |
266 | | /* choose numerators */ |
267 | 4.62k | vec_select(xn, x1n, x2n, sizeof(xn), e2); /* xn = e2 ? x1n : x2n */ |
268 | 4.62k | vec_select(y, y1, y2, sizeof(y), e2); /* y = e2 ? y1 : y2 */ |
269 | | |
270 | 4.62k | e1 = sgn0_fp2(u); |
271 | 4.62k | e2 = sgn0_fp2(y); |
272 | 4.62k | cneg_fp2(y, y, e1^e2); /* fix sign of y */ |
273 | | /* return (xn, xd, y, 1) */ |
274 | | |
275 | | /* convert (xn, xd, y, 1) to Jacobian projective coordinates */ |
276 | 4.62k | mul_fp2(p->X, xn, xd); /* X = xn * xd */ |
277 | 4.62k | mul_fp2(p->Y, y, gxd); /* Y = y * xd^3 */ |
278 | | #ifndef xd |
279 | | vec_copy(p->Z, xd, sizeof(xd)); /* Z = xd */ |
280 | | #else |
281 | 4.62k | # undef xn |
282 | 4.62k | # undef y |
283 | 4.62k | # undef xd |
284 | 4.62k | # undef x1n |
285 | 4.62k | # undef y1 |
286 | 4.62k | # undef Zuu |
287 | 4.62k | # undef tv4 |
288 | 4.62k | #endif |
289 | 4.62k | #undef sgn0_fp2 |
290 | 4.62k | } |
291 | | |
292 | | #if 0 |
293 | | static const byte h_eff[] = { |
294 | | TO_BYTES(0xe8020005aaa95551), TO_BYTES(0x59894c0adebbf6b4), |
295 | | TO_BYTES(0xe954cbc06689f6a3), TO_BYTES(0x2ec0ec69d7477c1a), |
296 | | TO_BYTES(0x6d82bf015d1212b0), TO_BYTES(0x329c2f178731db95), |
297 | | TO_BYTES(0x9986ff031508ffe1), TO_BYTES(0x88e2a8e9145ad768), |
298 | | TO_BYTES(0x584c6a0ea91b3528), TO_BYTES(0x0bc69f08f2ee75b3) |
299 | | }; |
300 | | |
301 | | static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p) |
302 | | { POINTonE2_mult_w5(out, p, h_eff, 636); } |
303 | | #else |
304 | | /* |
305 | | * As per suggestions in "7. Clearing the cofactor" at |
306 | | * https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06 |
307 | | */ |
308 | | static void POINTonE2_add_n_dbl(POINTonE2 *out, const POINTonE2 *p, size_t n) |
309 | 102k | { |
310 | 102k | POINTonE2_dadd(out, out, p, NULL); |
311 | 1.37M | while(n--) |
312 | 1.27M | POINTonE2_double(out, out); |
313 | 102k | } |
314 | | |
315 | | static void POINTonE2_times_minus_z(POINTonE2 *out, const POINTonE2 *in) |
316 | 20.4k | { |
317 | 20.4k | POINTonE2_double(out, in); /* 1: 0x2 */ |
318 | 20.4k | POINTonE2_add_n_dbl(out, in, 2); /* 2..4: 0x3..0xc */ |
319 | 20.4k | POINTonE2_add_n_dbl(out, in, 3); /* 5..8: 0xd..0x68 */ |
320 | 20.4k | POINTonE2_add_n_dbl(out, in, 9); /* 9..18: 0x69..0xd200 */ |
321 | 20.4k | POINTonE2_add_n_dbl(out, in, 32); /* 19..51: ..0xd20100000000 */ |
322 | 20.4k | POINTonE2_add_n_dbl(out, in, 16); /* 52..68: ..0xd201000000010000 */ |
323 | 20.4k | } |
324 | | |
325 | | static void psi(POINTonE2 *out, const POINTonE2 *in); |
326 | | |
327 | | static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p) |
328 | 2.31k | { |
329 | 2.31k | POINTonE2 t0, t1; |
330 | | |
331 | | /* A.Budroni, F.Pintore, "Efficient hash maps to G2 on BLS curves" */ |
332 | 2.31k | POINTonE2_double(out, p); /* out = 2P */ |
333 | 2.31k | psi(out, out); /* out = Ψ(2P) */ |
334 | 2.31k | psi(out, out); /* out = Ψ²(2P) */ |
335 | | |
336 | 2.31k | vec_copy(&t0, p, sizeof(t0)); |
337 | 2.31k | POINTonE2_cneg(&t0, 1); /* t0 = -P */ |
338 | 2.31k | psi(&t1, &t0); /* t1 = -Ψ(P) */ |
339 | 2.31k | POINTonE2_dadd(out, out, &t0, NULL);/* out = Ψ²(2P) - P */ |
340 | 2.31k | POINTonE2_dadd(out, out, &t1, NULL);/* out = Ψ²(2P) - P - Ψ(P) */ |
341 | | |
342 | 2.31k | POINTonE2_times_minus_z(&t0, p); /* t0 = [-z]P */ |
343 | 2.31k | POINTonE2_dadd(&t0, &t0, p, NULL); /* t0 = [-z + 1]P */ |
344 | 2.31k | POINTonE2_dadd(&t0, &t0, &t1, NULL);/* t0 = [-z + 1]P - Ψ(P) */ |
345 | 2.31k | POINTonE2_times_minus_z(&t1, &t0); /* t1 = [z² - z]P + [z]Ψ(P) */ |
346 | 2.31k | POINTonE2_dadd(out, out, &t1, NULL);/* out = [z² - z - 1]P */ |
347 | | /* + [z - 1]Ψ(P) */ |
348 | | /* + Ψ²(2P) */ |
349 | 2.31k | } |
350 | | #endif |
351 | | |
352 | | /* |
353 | | * |u|, |v| are expected to be in Montgomery representation |
354 | | */ |
355 | | static void map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v) |
356 | 2.31k | { |
357 | 2.31k | POINTonE2 p; |
358 | | |
359 | 2.31k | map_to_isogenous_E2(&p, u); |
360 | | |
361 | 2.31k | if (v != NULL) { |
362 | 2.31k | map_to_isogenous_E2(out, v); /* borrow |out| */ |
363 | 2.31k | POINTonE2_dadd(&p, &p, out, Aprime_E2); |
364 | 2.31k | } |
365 | | |
366 | 2.31k | isogeny_map_to_E2(&p, &p); /* sprinkle isogenous powder */ |
367 | 2.31k | clear_cofactor(out, &p); |
368 | 2.31k | } |
369 | | |
370 | | void blst_map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v) |
371 | 152 | { map_to_g2(out, u, v); } |
372 | | |
373 | | static void Encode_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len, |
374 | | const unsigned char *DST, size_t DST_len, |
375 | | const unsigned char *aug, size_t aug_len) |
376 | 0 | { |
377 | 0 | vec384x u[1]; |
378 | |
|
379 | 0 | hash_to_field(u[0], 2, aug, aug_len, msg, msg_len, DST, DST_len); |
380 | 0 | map_to_g2(p, u[0], NULL); |
381 | 0 | } |
382 | | |
383 | | void blst_encode_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len, |
384 | | const unsigned char *DST, size_t DST_len, |
385 | | const unsigned char *aug, size_t aug_len) |
386 | 0 | { Encode_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); } |
387 | | |
388 | | static void Hash_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len, |
389 | | const unsigned char *DST, size_t DST_len, |
390 | | const unsigned char *aug, size_t aug_len) |
391 | 2.15k | { |
392 | 2.15k | vec384x u[2]; |
393 | | |
394 | 2.15k | hash_to_field(u[0], 4, aug, aug_len, msg, msg_len, DST, DST_len); |
395 | 2.15k | map_to_g2(p, u[0], u[1]); |
396 | 2.15k | } |
397 | | |
398 | | void blst_hash_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len, |
399 | | const unsigned char *DST, size_t DST_len, |
400 | | const unsigned char *aug, size_t aug_len) |
401 | 1.19k | { Hash_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); } |
402 | | |
403 | | static bool_t POINTonE2_in_G2(const POINTonE2 *P) |
404 | 15.8k | { |
405 | | #if 0 |
406 | | POINTonE2 t0, t1, t2; |
407 | | |
408 | | /* Bowe, S., "Faster subgroup checks for BLS12-381" */ |
409 | | psi(&t0, P); /* Ψ(P) */ |
410 | | psi(&t0, &t0); /* Ψ²(P) */ |
411 | | psi(&t1, &t0); /* Ψ³(P) */ |
412 | | |
413 | | POINTonE2_times_minus_z(&t2, &t1); |
414 | | POINTonE2_dadd(&t0, &t0, &t2, NULL); |
415 | | POINTonE2_cneg(&t0, 1); |
416 | | POINTonE2_dadd(&t0, &t0, P, NULL); /* [z]Ψ³(P) - Ψ²(P) + P */ |
417 | | |
418 | | return vec_is_zero(t0.Z, sizeof(t0.Z)); |
419 | | #else |
420 | 15.8k | POINTonE2 t0, t1; |
421 | | |
422 | | /* Scott, M., https://eprint.iacr.org/2021/1130 */ |
423 | 15.8k | psi(&t0, P); /* Ψ(P) */ |
424 | | |
425 | 15.8k | POINTonE2_times_minus_z(&t1, P); |
426 | 15.8k | POINTonE2_cneg(&t1, 1); /* [z]P */ |
427 | | |
428 | 15.8k | return POINTonE2_is_equal(&t0, &t1); |
429 | 15.8k | #endif |
430 | 15.8k | } |
431 | | |
432 | | int blst_p2_in_g2(const POINTonE2 *p) |
433 | 2.08k | { return (int)POINTonE2_in_G2(p); } |
434 | | |
435 | | int blst_p2_affine_in_g2(const POINTonE2_affine *p) |
436 | 12.7k | { |
437 | 12.7k | POINTonE2 P; |
438 | | |
439 | 12.7k | vec_copy(P.X, p->X, 2*sizeof(P.X)); |
440 | 12.7k | vec_select(P.Z, p->X, BLS12_381_Rx.p, sizeof(P.Z), |
441 | 12.7k | vec_is_zero(p, sizeof(*p))); |
442 | | |
443 | 12.7k | return (int)POINTonE2_in_G2(&P); |
444 | 12.7k | } |