Coverage Report

Created: 2025-12-31 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/blst/src/map_to_g1.c
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
#include "point.h"
8
#include "fields.h"
9
10
/*
11
 * y^2 = x^3 + A'*x + B', isogenous one
12
 */
13
static const vec384 Aprime_E1 = {
14
    /* (0x00144698a3b8e9433d693a02c96d4982b0ea985383ee66a8
15
          d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d << 384) % P */
16
    TO_LIMB_T(0x2f65aa0e9af5aa51), TO_LIMB_T(0x86464c2d1e8416c3),
17
    TO_LIMB_T(0xb85ce591b7bd31e2), TO_LIMB_T(0x27e11c91b5f24e7c),
18
    TO_LIMB_T(0x28376eda6bfc1835), TO_LIMB_T(0x155455c3e5071d85)
19
};
20
static const vec384 Bprime_E1 = {
21
    /* (0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070
22
          a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0 << 384) % P */
23
    TO_LIMB_T(0xfb996971fe22a1e0), TO_LIMB_T(0x9aa93eb35b742d6f),
24
    TO_LIMB_T(0x8c476013de99c5c4), TO_LIMB_T(0x873e27c3a221e571),
25
    TO_LIMB_T(0xca72b5e45a52d888), TO_LIMB_T(0x06824061418a386b)
26
};
27
28
static void map_fp_times_Zz(vec384 map[], const vec384 isogeny_map[],
29
                            const vec384 Zz_powers[], size_t n)
30
108
{
31
1.48k
    while (n--)
32
1.37k
        mul_fp(map[n], isogeny_map[n], Zz_powers[n]);
33
108
}
34
35
static void map_fp(vec384 acc, const vec384 x, const vec384 map[], size_t n)
36
108
{
37
1.37k
    while (n--) {
38
1.26k
        mul_fp(acc, acc, x);
39
1.26k
        add_fp(acc, acc, map[n]);
40
1.26k
    }
41
108
}
42
43
static void isogeny_map_to_E1(POINTonE1 *out, const POINTonE1 *p)
44
27
{
45
    /*
46
     * x = x_num / x_den, where
47
     * x_num = k_(1,11) * x'^11 + k_(1,10) * x'^10 + k_(1,9) * x'^9 +
48
     *         ... + k_(1,0)
49
     * ...
50
     */
51
27
    static const vec384 isogeny_map_x_num[] = { /*  (k_(1,*)<<384) % P  */
52
27
      { TO_LIMB_T(0x4d18b6f3af00131c), TO_LIMB_T(0x19fa219793fee28c),
53
27
        TO_LIMB_T(0x3f2885f1467f19ae), TO_LIMB_T(0x23dcea34f2ffb304),
54
27
        TO_LIMB_T(0xd15b58d2ffc00054), TO_LIMB_T(0x0913be200a20bef4)  },
55
27
      { TO_LIMB_T(0x898985385cdbbd8b), TO_LIMB_T(0x3c79e43cc7d966aa),
56
27
        TO_LIMB_T(0x1597e193f4cd233a), TO_LIMB_T(0x8637ef1e4d6623ad),
57
27
        TO_LIMB_T(0x11b22deed20d827b), TO_LIMB_T(0x07097bc5998784ad)  },
58
27
      { TO_LIMB_T(0xa542583a480b664b), TO_LIMB_T(0xfc7169c026e568c6),
59
27
        TO_LIMB_T(0x5ba2ef314ed8b5a6), TO_LIMB_T(0x5b5491c05102f0e7),
60
27
        TO_LIMB_T(0xdf6e99707d2a0079), TO_LIMB_T(0x0784151ed7605524)  },
61
27
      { TO_LIMB_T(0x494e212870f72741), TO_LIMB_T(0xab9be52fbda43021),
62
27
        TO_LIMB_T(0x26f5577994e34c3d), TO_LIMB_T(0x049dfee82aefbd60),
63
27
        TO_LIMB_T(0x65dadd7828505289), TO_LIMB_T(0x0e93d431ea011aeb)  },
64
27
      { TO_LIMB_T(0x90ee774bd6a74d45), TO_LIMB_T(0x7ada1c8a41bfb185),
65
27
        TO_LIMB_T(0x0f1a8953b325f464), TO_LIMB_T(0x104c24211be4805c),
66
27
        TO_LIMB_T(0x169139d319ea7a8f), TO_LIMB_T(0x09f20ead8e532bf6)  },
67
27
      { TO_LIMB_T(0x6ddd93e2f43626b7), TO_LIMB_T(0xa5482c9aa1ccd7bd),
68
27
        TO_LIMB_T(0x143245631883f4bd), TO_LIMB_T(0x2e0a94ccf77ec0db),
69
27
        TO_LIMB_T(0xb0282d480e56489f), TO_LIMB_T(0x18f4bfcbb4368929)  },
70
27
      { TO_LIMB_T(0x23c5f0c953402dfd), TO_LIMB_T(0x7a43ff6958ce4fe9),
71
27
        TO_LIMB_T(0x2c390d3d2da5df63), TO_LIMB_T(0xd0df5c98e1f9d70f),
72
27
        TO_LIMB_T(0xffd89869a572b297), TO_LIMB_T(0x1277ffc72f25e8fe)  },
73
27
      { TO_LIMB_T(0x79f4f0490f06a8a6), TO_LIMB_T(0x85f894a88030fd81),
74
27
        TO_LIMB_T(0x12da3054b18b6410), TO_LIMB_T(0xe2a57f6505880d65),
75
27
        TO_LIMB_T(0xbba074f260e400f1), TO_LIMB_T(0x08b76279f621d028)  },
76
27
      { TO_LIMB_T(0xe67245ba78d5b00b), TO_LIMB_T(0x8456ba9a1f186475),
77
27
        TO_LIMB_T(0x7888bff6e6b33bb4), TO_LIMB_T(0xe21585b9a30f86cb),
78
27
        TO_LIMB_T(0x05a69cdcef55feee), TO_LIMB_T(0x09e699dd9adfa5ac)  },
79
27
      { TO_LIMB_T(0x0de5c357bff57107), TO_LIMB_T(0x0a0db4ae6b1a10b2),
80
27
        TO_LIMB_T(0xe256bb67b3b3cd8d), TO_LIMB_T(0x8ad456574e9db24f),
81
27
        TO_LIMB_T(0x0443915f50fd4179), TO_LIMB_T(0x098c4bf7de8b6375)  },
82
27
      { TO_LIMB_T(0xe6b0617e7dd929c7), TO_LIMB_T(0xfe6e37d442537375),
83
27
        TO_LIMB_T(0x1dafdeda137a489e), TO_LIMB_T(0xe4efd1ad3f767ceb),
84
27
        TO_LIMB_T(0x4a51d8667f0fe1cf), TO_LIMB_T(0x054fdf4bbf1d821c)  },
85
27
      { TO_LIMB_T(0x72db2a50658d767b), TO_LIMB_T(0x8abf91faa257b3d5),
86
27
        TO_LIMB_T(0xe969d6833764ab47), TO_LIMB_T(0x464170142a1009eb),
87
27
        TO_LIMB_T(0xb14f01aadb30be2f), TO_LIMB_T(0x18ae6a856f40715d)  }
88
27
    };
89
    /* ...
90
     * x_den = x'^10 + k_(2,9) * x'^9 + k_(2,8) * x'^8 + ... + k_(2,0)
91
     */
92
27
    static const vec384 isogeny_map_x_den[] = { /*  (k_(2,*)<<384) % P  */
93
27
      { TO_LIMB_T(0xb962a077fdb0f945), TO_LIMB_T(0xa6a9740fefda13a0),
94
27
        TO_LIMB_T(0xc14d568c3ed6c544), TO_LIMB_T(0xb43fc37b908b133e),
95
27
        TO_LIMB_T(0x9c0b3ac929599016), TO_LIMB_T(0x0165aa6c93ad115f)  },
96
27
      { TO_LIMB_T(0x23279a3ba506c1d9), TO_LIMB_T(0x92cfca0a9465176a),
97
27
        TO_LIMB_T(0x3b294ab13755f0ff), TO_LIMB_T(0x116dda1c5070ae93),
98
27
        TO_LIMB_T(0xed4530924cec2045), TO_LIMB_T(0x083383d6ed81f1ce)  },
99
27
      { TO_LIMB_T(0x9885c2a6449fecfc), TO_LIMB_T(0x4a2b54ccd37733f0),
100
27
        TO_LIMB_T(0x17da9ffd8738c142), TO_LIMB_T(0xa0fba72732b3fafd),
101
27
        TO_LIMB_T(0xff364f36e54b6812), TO_LIMB_T(0x0f29c13c660523e2)  },
102
27
      { TO_LIMB_T(0xe349cc118278f041), TO_LIMB_T(0xd487228f2f3204fb),
103
27
        TO_LIMB_T(0xc9d325849ade5150), TO_LIMB_T(0x43a92bd69c15c2df),
104
27
        TO_LIMB_T(0x1c2c7844bc417be4), TO_LIMB_T(0x12025184f407440c)  },
105
27
      { TO_LIMB_T(0x587f65ae6acb057b), TO_LIMB_T(0x1444ef325140201f),
106
27
        TO_LIMB_T(0xfbf995e71270da49), TO_LIMB_T(0xccda066072436a42),
107
27
        TO_LIMB_T(0x7408904f0f186bb2), TO_LIMB_T(0x13b93c63edf6c015)  },
108
27
      { TO_LIMB_T(0xfb918622cd141920), TO_LIMB_T(0x4a4c64423ecaddb4),
109
27
        TO_LIMB_T(0x0beb232927f7fb26), TO_LIMB_T(0x30f94df6f83a3dc2),
110
27
        TO_LIMB_T(0xaeedd424d780f388), TO_LIMB_T(0x06cc402dd594bbeb)  },
111
27
      { TO_LIMB_T(0xd41f761151b23f8f), TO_LIMB_T(0x32a92465435719b3),
112
27
        TO_LIMB_T(0x64f436e888c62cb9), TO_LIMB_T(0xdf70a9a1f757c6e4),
113
27
        TO_LIMB_T(0x6933a38d5b594c81), TO_LIMB_T(0x0c6f7f7237b46606)  },
114
27
      { TO_LIMB_T(0x693c08747876c8f7), TO_LIMB_T(0x22c9850bf9cf80f0),
115
27
        TO_LIMB_T(0x8e9071dab950c124), TO_LIMB_T(0x89bc62d61c7baf23),
116
27
        TO_LIMB_T(0xbc6be2d8dad57c23), TO_LIMB_T(0x17916987aa14a122)  },
117
27
      { TO_LIMB_T(0x1be3ff439c1316fd), TO_LIMB_T(0x9965243a7571dfa7),
118
27
        TO_LIMB_T(0xc7f7f62962f5cd81), TO_LIMB_T(0x32c6aa9af394361c),
119
27
        TO_LIMB_T(0xbbc2ee18e1c227f4), TO_LIMB_T(0x0c102cbac531bb34)  },
120
27
      { TO_LIMB_T(0x997614c97bacbf07), TO_LIMB_T(0x61f86372b99192c0),
121
27
        TO_LIMB_T(0x5b8c95fc14353fc3), TO_LIMB_T(0xca2b066c2a87492f),
122
27
        TO_LIMB_T(0x16178f5bbf698711), TO_LIMB_T(0x12a6dcd7f0f4e0e8)  }
123
27
    };
124
    /*
125
     * y = y' * y_num / y_den, where
126
     * y_num = k_(3,15) * x'^15 + k_(3,14) * x'^14 + k_(3,13) * x'^13 +
127
     *         ... + k_(3,0)
128
     * ...
129
     */
130
27
    static const vec384 isogeny_map_y_num[] = { /*  (k_(3,*)<<384) % P  */
131
27
      { TO_LIMB_T(0x2b567ff3e2837267), TO_LIMB_T(0x1d4d9e57b958a767),
132
27
        TO_LIMB_T(0xce028fea04bd7373), TO_LIMB_T(0xcc31a30a0b6cd3df),
133
27
        TO_LIMB_T(0x7d7b18a682692693), TO_LIMB_T(0x0d300744d42a0310)  },
134
27
      { TO_LIMB_T(0x99c2555fa542493f), TO_LIMB_T(0xfe7f53cc4874f878),
135
27
        TO_LIMB_T(0x5df0608b8f97608a), TO_LIMB_T(0x14e03832052b49c8),
136
27
        TO_LIMB_T(0x706326a6957dd5a4), TO_LIMB_T(0x0a8dadd9c2414555)  },
137
27
      { TO_LIMB_T(0x13d942922a5cf63a), TO_LIMB_T(0x357e33e36e261e7d),
138
27
        TO_LIMB_T(0xcf05a27c8456088d), TO_LIMB_T(0x0000bd1de7ba50f0),
139
27
        TO_LIMB_T(0x83d0c7532f8c1fde), TO_LIMB_T(0x13f70bf38bbf2905)  },
140
27
      { TO_LIMB_T(0x5c57fd95bfafbdbb), TO_LIMB_T(0x28a359a65e541707),
141
27
        TO_LIMB_T(0x3983ceb4f6360b6d), TO_LIMB_T(0xafe19ff6f97e6d53),
142
27
        TO_LIMB_T(0xb3468f4550192bf7), TO_LIMB_T(0x0bb6cde49d8ba257)  },
143
27
      { TO_LIMB_T(0x590b62c7ff8a513f), TO_LIMB_T(0x314b4ce372cacefd),
144
27
        TO_LIMB_T(0x6bef32ce94b8a800), TO_LIMB_T(0x6ddf84a095713d5f),
145
27
        TO_LIMB_T(0x64eace4cb0982191), TO_LIMB_T(0x0386213c651b888d)  },
146
27
      { TO_LIMB_T(0xa5310a31111bbcdd), TO_LIMB_T(0xa14ac0f5da148982),
147
27
        TO_LIMB_T(0xf9ad9cc95423d2e9), TO_LIMB_T(0xaa6ec095283ee4a7),
148
27
        TO_LIMB_T(0xcf5b1f022e1c9107), TO_LIMB_T(0x01fddf5aed881793)  },
149
27
      { TO_LIMB_T(0x65a572b0d7a7d950), TO_LIMB_T(0xe25c2d8183473a19),
150
27
        TO_LIMB_T(0xc2fcebe7cb877dbd), TO_LIMB_T(0x05b2d36c769a89b0),
151
27
        TO_LIMB_T(0xba12961be86e9efb), TO_LIMB_T(0x07eb1b29c1dfde1f)  },
152
27
      { TO_LIMB_T(0x93e09572f7c4cd24), TO_LIMB_T(0x364e929076795091),
153
27
        TO_LIMB_T(0x8569467e68af51b5), TO_LIMB_T(0xa47da89439f5340f),
154
27
        TO_LIMB_T(0xf4fa918082e44d64), TO_LIMB_T(0x0ad52ba3e6695a79)  },
155
27
      { TO_LIMB_T(0x911429844e0d5f54), TO_LIMB_T(0xd03f51a3516bb233),
156
27
        TO_LIMB_T(0x3d587e5640536e66), TO_LIMB_T(0xfa86d2a3a9a73482),
157
27
        TO_LIMB_T(0xa90ed5adf1ed5537), TO_LIMB_T(0x149c9c326a5e7393)  },
158
27
      { TO_LIMB_T(0x462bbeb03c12921a), TO_LIMB_T(0xdc9af5fa0a274a17),
159
27
        TO_LIMB_T(0x9a558ebde836ebed), TO_LIMB_T(0x649ef8f11a4fae46),
160
27
        TO_LIMB_T(0x8100e1652b3cdc62), TO_LIMB_T(0x1862bd62c291dacb)  },
161
27
      { TO_LIMB_T(0x05c9b8ca89f12c26), TO_LIMB_T(0x0194160fa9b9ac4f),
162
27
        TO_LIMB_T(0x6a643d5a6879fa2c), TO_LIMB_T(0x14665bdd8846e19d),
163
27
        TO_LIMB_T(0xbb1d0d53af3ff6bf), TO_LIMB_T(0x12c7e1c3b28962e5)  },
164
27
      { TO_LIMB_T(0xb55ebf900b8a3e17), TO_LIMB_T(0xfedc77ec1a9201c4),
165
27
        TO_LIMB_T(0x1f07db10ea1a4df4), TO_LIMB_T(0x0dfbd15dc41a594d),
166
27
        TO_LIMB_T(0x389547f2334a5391), TO_LIMB_T(0x02419f98165871a4)  },
167
27
      { TO_LIMB_T(0xb416af000745fc20), TO_LIMB_T(0x8e563e9d1ea6d0f5),
168
27
        TO_LIMB_T(0x7c763e17763a0652), TO_LIMB_T(0x01458ef0159ebbef),
169
27
        TO_LIMB_T(0x8346fe421f96bb13), TO_LIMB_T(0x0d2d7b829ce324d2)  },
170
27
      { TO_LIMB_T(0x93096bb538d64615), TO_LIMB_T(0x6f2a2619951d823a),
171
27
        TO_LIMB_T(0x8f66b3ea59514fa4), TO_LIMB_T(0xf563e63704f7092f),
172
27
        TO_LIMB_T(0x724b136c4cf2d9fa), TO_LIMB_T(0x046959cfcfd0bf49)  },
173
27
      { TO_LIMB_T(0xea748d4b6e405346), TO_LIMB_T(0x91e9079c2c02d58f),
174
27
        TO_LIMB_T(0x41064965946d9b59), TO_LIMB_T(0xa06731f1d2bbe1ee),
175
27
        TO_LIMB_T(0x07f897e267a33f1b), TO_LIMB_T(0x1017290919210e5f)  },
176
27
      { TO_LIMB_T(0x872aa6c17d985097), TO_LIMB_T(0xeecc53161264562a),
177
27
        TO_LIMB_T(0x07afe37afff55002), TO_LIMB_T(0x54759078e5be6838),
178
27
        TO_LIMB_T(0xc4b92d15db8acca8), TO_LIMB_T(0x106d87d1b51d13b9)  }
179
27
    };
180
    /* ...
181
     * y_den = x'^15 + k_(4,14) * x'^14 + k_(4,13) * x'^13 + ... + k_(4,0)
182
     */
183
27
    static const vec384 isogeny_map_y_den[] = { /*  (k_(4,*)<<384) % P  */
184
27
      { TO_LIMB_T(0xeb6c359d47e52b1c), TO_LIMB_T(0x18ef5f8a10634d60),
185
27
        TO_LIMB_T(0xddfa71a0889d5b7e), TO_LIMB_T(0x723e71dcc5fc1323),
186
27
        TO_LIMB_T(0x52f45700b70d5c69), TO_LIMB_T(0x0a8b981ee47691f1)  },
187
27
      { TO_LIMB_T(0x616a3c4f5535b9fb), TO_LIMB_T(0x6f5f037395dbd911),
188
27
        TO_LIMB_T(0xf25f4cc5e35c65da), TO_LIMB_T(0x3e50dffea3c62658),
189
27
        TO_LIMB_T(0x6a33dca523560776), TO_LIMB_T(0x0fadeff77b6bfe3e)  },
190
27
      { TO_LIMB_T(0x2be9b66df470059c), TO_LIMB_T(0x24a2c159a3d36742),
191
27
        TO_LIMB_T(0x115dbe7ad10c2a37), TO_LIMB_T(0xb6634a652ee5884d),
192
27
        TO_LIMB_T(0x04fe8bb2b8d81af4), TO_LIMB_T(0x01c2a7a256fe9c41)  },
193
27
      { TO_LIMB_T(0xf27bf8ef3b75a386), TO_LIMB_T(0x898b367476c9073f),
194
27
        TO_LIMB_T(0x24482e6b8c2f4e5f), TO_LIMB_T(0xc8e0bbd6fe110806),
195
27
        TO_LIMB_T(0x59b0c17f7631448a), TO_LIMB_T(0x11037cd58b3dbfbd)  },
196
27
      { TO_LIMB_T(0x31c7912ea267eec6), TO_LIMB_T(0x1dbf6f1c5fcdb700),
197
27
        TO_LIMB_T(0xd30d4fe3ba86fdb1), TO_LIMB_T(0x3cae528fbee9a2a4),
198
27
        TO_LIMB_T(0xb1cce69b6aa9ad9a), TO_LIMB_T(0x044393bb632d94fb)  },
199
27
      { TO_LIMB_T(0xc66ef6efeeb5c7e8), TO_LIMB_T(0x9824c289dd72bb55),
200
27
        TO_LIMB_T(0x71b1a4d2f119981d), TO_LIMB_T(0x104fc1aafb0919cc),
201
27
        TO_LIMB_T(0x0e49df01d942a628), TO_LIMB_T(0x096c3a09773272d4)  },
202
27
      { TO_LIMB_T(0x9abc11eb5fadeff4), TO_LIMB_T(0x32dca50a885728f0),
203
27
        TO_LIMB_T(0xfb1fa3721569734c), TO_LIMB_T(0xc4b76271ea6506b3),
204
27
        TO_LIMB_T(0xd466a75599ce728e), TO_LIMB_T(0x0c81d4645f4cb6ed)  },
205
27
      { TO_LIMB_T(0x4199f10e5b8be45b), TO_LIMB_T(0xda64e495b1e87930),
206
27
        TO_LIMB_T(0xcb353efe9b33e4ff), TO_LIMB_T(0x9e9efb24aa6424c6),
207
27
        TO_LIMB_T(0xf08d33680a237465), TO_LIMB_T(0x0d3378023e4c7406)  },
208
27
      { TO_LIMB_T(0x7eb4ae92ec74d3a5), TO_LIMB_T(0xc341b4aa9fac3497),
209
27
        TO_LIMB_T(0x5be603899e907687), TO_LIMB_T(0x03bfd9cca75cbdeb),
210
27
        TO_LIMB_T(0x564c2935a96bfa93), TO_LIMB_T(0x0ef3c33371e2fdb5)  },
211
27
      { TO_LIMB_T(0x7ee91fd449f6ac2e), TO_LIMB_T(0xe5d5bd5cb9357a30),
212
27
        TO_LIMB_T(0x773a8ca5196b1380), TO_LIMB_T(0xd0fda172174ed023),
213
27
        TO_LIMB_T(0x6cb95e0fa776aead), TO_LIMB_T(0x0d22d5a40cec7cff)  },
214
27
      { TO_LIMB_T(0xf727e09285fd8519), TO_LIMB_T(0xdc9d55a83017897b),
215
27
        TO_LIMB_T(0x7549d8bd057894ae), TO_LIMB_T(0x178419613d90d8f8),
216
27
        TO_LIMB_T(0xfce95ebdeb5b490a), TO_LIMB_T(0x0467ffaef23fc49e)  },
217
27
      { TO_LIMB_T(0xc1769e6a7c385f1b), TO_LIMB_T(0x79bc930deac01c03),
218
27
        TO_LIMB_T(0x5461c75a23ede3b5), TO_LIMB_T(0x6e20829e5c230c45),
219
27
        TO_LIMB_T(0x828e0f1e772a53cd), TO_LIMB_T(0x116aefa749127bff)  },
220
27
      { TO_LIMB_T(0x101c10bf2744c10a), TO_LIMB_T(0xbbf18d053a6a3154),
221
27
        TO_LIMB_T(0xa0ecf39ef026f602), TO_LIMB_T(0xfc009d4996dc5153),
222
27
        TO_LIMB_T(0xb9000209d5bd08d3), TO_LIMB_T(0x189e5fe4470cd73c)  },
223
27
      { TO_LIMB_T(0x7ebd546ca1575ed2), TO_LIMB_T(0xe47d5a981d081b55),
224
27
        TO_LIMB_T(0x57b2b625b6d4ca21), TO_LIMB_T(0xb0a1ba04228520cc),
225
27
        TO_LIMB_T(0x98738983c2107ff3), TO_LIMB_T(0x13dddbc4799d81d6)  },
226
27
      { TO_LIMB_T(0x09319f2e39834935), TO_LIMB_T(0x039e952cbdb05c21),
227
27
        TO_LIMB_T(0x55ba77a9a2f76493), TO_LIMB_T(0xfd04e3dfc6086467),
228
27
        TO_LIMB_T(0xfb95832e7d78742e), TO_LIMB_T(0x0ef9c24eccaf5e0e)  }
229
27
    };
230
27
    vec384 Zz_powers[15], map[15], xn, xd, yn, yd;
231
232
    /* lay down Z^2 powers in descending order                          */
233
27
    sqr_fp(Zz_powers[14], p->Z);                        /* ZZ^1         */
234
#ifdef __OPTIMIZE_SIZE__
235
    for (size_t i = 14; i > 0; i--)
236
        mul_fp(Zz_powers[i-1], Zz_powers[i], Zz_powers[14]);
237
#else
238
27
    sqr_fp(Zz_powers[13], Zz_powers[14]);               /* ZZ^2  1+1    */
239
27
    mul_fp(Zz_powers[12], Zz_powers[14], Zz_powers[13]);/* ZZ^3  2+1    */
240
27
    sqr_fp(Zz_powers[11], Zz_powers[13]);               /* ZZ^4  2+2    */
241
27
    mul_fp(Zz_powers[10], Zz_powers[13], Zz_powers[12]);/* ZZ^5  2+3    */
242
27
    sqr_fp(Zz_powers[9],  Zz_powers[12]);               /* ZZ^6  3+3    */
243
27
    mul_fp(Zz_powers[8],  Zz_powers[12], Zz_powers[11]);/* ZZ^7  3+4    */
244
27
    sqr_fp(Zz_powers[7],  Zz_powers[11]);               /* ZZ^8  4+4    */
245
27
    mul_fp(Zz_powers[6],  Zz_powers[11], Zz_powers[10]);/* ZZ^9  4+5    */
246
27
    sqr_fp(Zz_powers[5],  Zz_powers[10]);               /* ZZ^10 5+5    */
247
27
    mul_fp(Zz_powers[4],  Zz_powers[10], Zz_powers[9]); /* ZZ^11 5+6    */
248
27
    sqr_fp(Zz_powers[3],  Zz_powers[9]);                /* ZZ^12 6+6    */
249
27
    mul_fp(Zz_powers[2],  Zz_powers[9],  Zz_powers[8]); /* ZZ^13 6+7    */
250
27
    sqr_fp(Zz_powers[1],  Zz_powers[8]);                /* ZZ^14 7+7    */
251
27
    mul_fp(Zz_powers[0],  Zz_powers[8],  Zz_powers[7]); /* ZZ^15 7+8    */
252
27
#endif
253
254
27
    map_fp_times_Zz(map, isogeny_map_x_num, Zz_powers + 4, 11);
255
27
    mul_fp(xn, p->X, isogeny_map_x_num[11]);
256
27
    add_fp(xn, xn, map[10]);
257
27
    map_fp(xn, p->X, map, 10);
258
259
27
    map_fp_times_Zz(map, isogeny_map_x_den, Zz_powers + 5, 10);
260
27
    add_fp(xd, p->X, map[9]);
261
27
    map_fp(xd, p->X, map, 9);
262
27
    mul_fp(xd, xd, Zz_powers[14]);      /* xd *= Z^2                    */
263
264
27
    map_fp_times_Zz(map, isogeny_map_y_num, Zz_powers, 15);
265
27
    mul_fp(yn, p->X, isogeny_map_y_num[15]);
266
27
    add_fp(yn, yn, map[14]);
267
27
    map_fp(yn, p->X, map, 14);
268
27
    mul_fp(yn, yn, p->Y);               /* yn *= Y                      */
269
270
27
    map_fp_times_Zz(map, isogeny_map_y_den, Zz_powers, 15);
271
27
    add_fp(yd, p->X, map[14]);
272
27
    map_fp(yd, p->X, map, 14);
273
27
    mul_fp(Zz_powers[14], Zz_powers[14], p->Z);
274
27
    mul_fp(yd, yd, Zz_powers[14]);      /* yd *= Z^3                    */
275
276
    /* convert (xn, xd, yn, yd) to Jacobian coordinates                 */
277
27
    mul_fp(out->Z, xd, yd);             /* Z = xd * yd                  */
278
27
    mul_fp(out->X, xn, yd);
279
27
    mul_fp(out->X, out->X, out->Z);     /* X = xn * xd * yd^2           */
280
27
    sqr_fp(out->Y, out->Z);
281
27
    mul_fp(out->Y, out->Y, xd);
282
27
    mul_fp(out->Y, out->Y, yn);         /* Y = yn * xd^3 * yd^2         */
283
27
}
284
285
static void map_to_isogenous_E1(POINTonE1 *p, const vec384 u)
286
54
{
287
54
    static const vec384 minus_A = { /* P - A */
288
54
        TO_LIMB_T(0x8a9955f1650a005a), TO_LIMB_T(0x9865b3d192cfe93c),
289
54
        TO_LIMB_T(0xaed3ed0f3ef3c441), TO_LIMB_T(0x3c962ef33d92c442),
290
54
        TO_LIMB_T(0x22e438dbd74f94a2), TO_LIMB_T(0x04acbc265478c915)
291
54
    };
292
54
    static const vec384 Z = {       /* (11<<384) % P */
293
54
        TO_LIMB_T(0x886c00000023ffdc), TO_LIMB_T(0x0f70008d3090001d),
294
54
        TO_LIMB_T(0x77672417ed5828c3), TO_LIMB_T(0x9dac23e943dc1740),
295
54
        TO_LIMB_T(0x50553f1b9c131521), TO_LIMB_T(0x078c712fbe0ab6e8)
296
54
    };
297
54
    static const vec384 sqrt_minus_ZZZ = {
298
54
        TO_LIMB_T(0x43b571cad3215f1f), TO_LIMB_T(0xccb460ef1c702dc2),
299
54
        TO_LIMB_T(0x742d884f4f97100b), TO_LIMB_T(0xdb2c3e3238a3382b),
300
54
        TO_LIMB_T(0xe40f3fa13fce8f88), TO_LIMB_T(0x0073a2af9892a2ff)
301
54
    };
302
54
    static const vec384 ZxA = {
303
54
        TO_LIMB_T(0x7f674ea0a8915178), TO_LIMB_T(0xb0f945fc13b8fa65),
304
54
        TO_LIMB_T(0x4b46759a38e87d76), TO_LIMB_T(0x2e7a929641bbb6a1),
305
54
        TO_LIMB_T(0x1668ddfa462bf6b6), TO_LIMB_T(0x00960e2ed1cf294c)
306
54
    };
307
54
    vec384 uu, tv2, x2n, gx1, gxd, y2;
308
#if 0
309
    vec384 xn, x1n, xd, y, y1, Zuu, tv4;
310
#else
311
540
# define xn     p->X
312
756
# define y      p->Y
313
486
# define xd     p->Z
314
378
# define x1n    xn
315
486
# define y1     y
316
216
# define Zuu    x2n
317
216
# define tv4    y1
318
54
#endif
319
108
#define sgn0_fp(a) (sgn0_pty_mont_384((a), BLS12_381_P, p0) & 1)
320
54
    bool_t e1, e2;
321
322
    /*
323
     * as per map_to_curve() from poc/sswu_opt.sage at
324
     * https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve
325
     */
326
    /* x numerator variants                                             */
327
54
    sqr_fp(uu, u);                      /* uu = u^2                     */
328
54
    mul_fp(Zuu, Z, uu);                 /* Zuu = Z * uu                 */
329
54
    sqr_fp(tv2, Zuu);                   /* tv2 = Zuu^2                  */
330
54
    add_fp(tv2, tv2, Zuu);              /* tv2 = tv2 + Zuu              */
331
54
    add_fp(x1n, tv2, BLS12_381_Rx.p);   /* x1n = tv2 + 1                */
332
54
    mul_fp(x1n, x1n, Bprime_E1);        /* x1n = x1n * B                */
333
54
    mul_fp(x2n, Zuu, x1n);              /* x2n = Zuu * x1n              */
334
335
    /* x denumenator                                                    */
336
54
    mul_fp(xd, minus_A, tv2);           /* xd = -A * tv2                */
337
54
    e1 = vec_is_zero(xd, sizeof(xd));   /* e1 = xd == 0                 */
338
54
    vec_select(xd, ZxA, xd, sizeof(xd), e1);    /*              # If xd == 0, set xd = Z*A */
339
340
    /* y numerators variants                                            */
341
54
    sqr_fp(tv2, xd);                    /* tv2 = xd^2                   */
342
54
    mul_fp(gxd, xd, tv2);               /* gxd = xd^3                   */
343
54
    mul_fp(tv2, Aprime_E1, tv2);        /* tv2 = A * tv2                */
344
54
    sqr_fp(gx1, x1n);                   /* gx1 = x1n^2                  */
345
54
    add_fp(gx1, gx1, tv2);              /* gx1 = gx1 + tv2      # x1n^2 + A*xd^2 */
346
54
    mul_fp(gx1, gx1, x1n);              /* gx1 = gx1 * x1n      # x1n^3 + A*x1n*xd^2 */
347
54
    mul_fp(tv2, Bprime_E1, gxd);        /* tv2 = B * gxd                */
348
54
    add_fp(gx1, gx1, tv2);              /* gx1 = gx1 + tv2      # x1^3 + A*x1*xd^2 + B*xd^3 */
349
54
    sqr_fp(tv4, gxd);                   /* tv4 = gxd^2                  */
350
54
    mul_fp(tv2, gx1, gxd);              /* tv2 = gx1 * gxd              */
351
54
    mul_fp(tv4, tv4, tv2);              /* tv4 = tv4 * tv2      # gx1*gxd^3 */
352
54
    e2 = recip_sqrt_fp(y1, tv4);        /* y1 = tv4^c1          # (gx1*gxd^3)^((p-3)/4) */
353
54
    mul_fp(y1, y1, tv2);                /* y1 = y1 * tv2        # gx1*gxd*y1 */
354
54
    mul_fp(y2, y1, sqrt_minus_ZZZ);     /* y2 = y1 * c2         # y2 = y1*sqrt(-Z^3) */
355
54
    mul_fp(y2, y2, uu);                 /* y2 = y2 * uu                 */
356
54
    mul_fp(y2, y2, u);                  /* y2 = y2 * u                  */
357
358
    /* choose numerators                                                */
359
54
    vec_select(xn, x1n, x2n, sizeof(xn), e2);   /* xn = e2 ? x1n : x2n  */
360
54
    vec_select(y, y1, y2, sizeof(y), e2);       /* y  = e2 ? y1 : y2    */
361
362
54
    e1 = sgn0_fp(u);
363
54
    e2 = sgn0_fp(y);
364
54
    cneg_fp(y, y, e1^e2);               /* fix sign of y                */
365
                                        /* return (xn, xd, y, 1)        */
366
367
    /* convert (xn, xd, y, 1) to Jacobian projective coordinates        */
368
54
    mul_fp(p->X, xn, xd);               /* X = xn * xd                  */
369
54
    mul_fp(p->Y, y, gxd);               /* Y = y * xd^3                 */
370
#ifndef xd
371
    vec_copy(p->Z, xd, sizeof(xd));     /* Z = xd                       */
372
#else
373
54
# undef xn
374
54
# undef y
375
54
# undef xd
376
54
# undef x1n
377
54
# undef y1
378
54
# undef Zuu
379
54
# undef tv4
380
54
#endif
381
54
#undef sgn0_fp
382
54
}
383
384
static void POINTonE1_add_n_dbl(POINTonE1 *out, const POINTonE1 *p, size_t n)
385
1.61k
{
386
1.61k
    POINTonE1_dadd(out, out, p, NULL);
387
21.6k
    while(n--)
388
20.0k
        POINTonE1_double(out, out);
389
1.61k
}
390
391
static void POINTonE1_times_minus_z(POINTonE1 *out, const POINTonE1 *in)
392
323
{
393
323
    POINTonE1_double(out, in);          /*      1: 0x2                  */
394
323
    POINTonE1_add_n_dbl(out, in, 2);    /*   2..4: 0x3..0xc             */
395
323
    POINTonE1_add_n_dbl(out, in, 3);    /*   5..8: 0xd..0x68            */
396
323
    POINTonE1_add_n_dbl(out, in, 9);    /*  9..18: 0x69..0xd200         */
397
323
    POINTonE1_add_n_dbl(out, in, 32);   /* 19..51: ..0xd20100000000     */
398
323
    POINTonE1_add_n_dbl(out, in, 16);   /* 52..68: ..0xd201000000010000 */
399
323
}
400
401
/*
402
 * |u|, |v| are expected to be in Montgomery representation
403
 */
404
static void map_to_g1(POINTonE1 *out, const vec384 u, const vec384 v)
405
27
{
406
27
    POINTonE1 p;
407
408
27
    map_to_isogenous_E1(&p, u);
409
410
27
    if (v != NULL) {
411
27
        map_to_isogenous_E1(out, v);    /* borrow |out|                 */
412
27
        POINTonE1_dadd(&p, &p, out, Aprime_E1);
413
27
    }
414
415
27
    isogeny_map_to_E1(&p, &p);          /* sprinkle isogenous powder    */
416
417
    /* clear the cofactor by multiplying |p| by 1-z, 0xd201000000010001 */
418
27
    POINTonE1_times_minus_z(out, &p);
419
27
    POINTonE1_dadd(out, out, &p, NULL);
420
27
}
421
422
void blst_map_to_g1(POINTonE1 *out, const vec384 u, const vec384 v)
423
0
{   map_to_g1(out, u, v);   }
424
425
static void Encode_to_G1(POINTonE1 *p, const unsigned char *msg, size_t msg_len,
426
                                       const unsigned char *DST, size_t DST_len,
427
                                       const unsigned char *aug, size_t aug_len)
428
0
{
429
0
    vec384 u[1];
430
431
0
    hash_to_field(u, 1, aug, aug_len, msg, msg_len, DST, DST_len);
432
0
    map_to_g1(p, u[0], NULL);
433
0
}
434
435
void blst_encode_to_g1(POINTonE1 *p, const unsigned char *msg, size_t msg_len,
436
                                     const unsigned char *DST, size_t DST_len,
437
                                     const unsigned char *aug, size_t aug_len)
438
0
{   Encode_to_G1(p, msg, msg_len, DST, DST_len, aug, aug_len);   }
439
440
static void Hash_to_G1(POINTonE1 *p, const unsigned char *msg, size_t msg_len,
441
                                     const unsigned char *DST, size_t DST_len,
442
                                     const unsigned char *aug, size_t aug_len)
443
27
{
444
27
    vec384 u[2];
445
446
27
    hash_to_field(u, 2, aug, aug_len, msg, msg_len, DST, DST_len);
447
27
    map_to_g1(p, u[0], u[1]);
448
27
}
449
450
void blst_hash_to_g1(POINTonE1 *p, const unsigned char *msg, size_t msg_len,
451
                                   const unsigned char *DST, size_t DST_len,
452
                                   const unsigned char *aug, size_t aug_len)
453
27
{   Hash_to_G1(p, msg, msg_len, DST, DST_len, aug, aug_len);   }
454
455
static void sigma(POINTonE1 *out, const POINTonE1 *in);
456
457
#if 0
458
#ifdef __OPTIMIZE_SIZE__
459
static void POINTonE1_times_zz_minus_1_div_by_3(POINTonE1 *out,
460
                                                const POINTonE1 *in)
461
{
462
    static const byte zz_minus_1_div_by_3[] = {
463
        TO_BYTES(0x0000000055555555ULL), TO_BYTES(0x396c8c005555e156)
464
    };
465
    size_t n = 126-1;
466
    const POINTonE1 *dblin = in;
467
468
    while(n--) {
469
        POINTonE1_double(out, dblin);   dblin = out;
470
        if (is_bit_set(zz_minus_1_div_by_3, n))
471
            POINTonE1_dadd(out, out, in, NULL);
472
    }
473
}
474
#else
475
static void POINTonE1_dbl_n_add(POINTonE1 *out, size_t n, const POINTonE1 *p)
476
{
477
    while(n--)
478
        POINTonE1_double(out, out);
479
    POINTonE1_dadd(out, out, p, NULL);
480
}
481
482
static void POINTonE1_times_zz_minus_1_div_by_3(POINTonE1 *out,
483
                                                const POINTonE1 *in)
484
{
485
    POINTonE1 t3, t5, t7, t11, t85;
486
487
    POINTonE1_double(&t7, in);              /* 2P */
488
    POINTonE1_dadd(&t3, &t7, in, NULL);     /* 3P */
489
    POINTonE1_dadd(&t5, &t3, &t7, NULL);    /* 5P */
490
    POINTonE1_dadd(&t7, &t5, &t7, NULL);    /* 7P */
491
    POINTonE1_double(&t85, &t5);            /* 10P */
492
    POINTonE1_dadd(&t11, &t85, in, NULL);   /* 11P */
493
    POINTonE1_dbl_n_add(&t85, 3, &t5);      /* 0x55P */
494
                                            /* (-0xd201000000010000^2 - 1) / 3 */
495
    POINTonE1_double(out, &t7);             /* 0xe */
496
    POINTonE1_dbl_n_add(out, 5,  &t11);     /* 0x1cb */
497
    POINTonE1_dbl_n_add(out, 3,  &t3);      /* 0xe5b */
498
    POINTonE1_dbl_n_add(out, 3,  in);       /* 0x72d9 */
499
    POINTonE1_dbl_n_add(out, 5,  &t3);      /* 0xe5b23 */
500
    POINTonE1_dbl_n_add(out, 18, &t85);     /* 0x396c8c0055 */
501
    POINTonE1_dbl_n_add(out, 8,  &t85);     /* 0x396c8c005555 */
502
    POINTonE1_dbl_n_add(out, 3,  &t7);      /* 0x1cb646002aaaf */
503
    POINTonE1_dbl_n_add(out, 7,  &t5);      /* 0xe5b23001555785 */
504
    POINTonE1_dbl_n_add(out, 5,  &t11);     /* 0x1cb646002aaaf0ab */
505
    POINTonE1_dbl_n_add(out, 41, &t85);     /* 0x396c8c005555e1560000000055 */
506
    POINTonE1_dbl_n_add(out, 8,  &t85);     /* 0x396c8c005555e156000000005555 */
507
    POINTonE1_dbl_n_add(out, 8,  &t85);     /* 0x396c8c005555e15600000000555555 */
508
    POINTonE1_dbl_n_add(out, 8,  &t85);     /* 0x396c8c005555e1560000000055555555 */
509
}
510
#endif
511
512
static bool_t POINTonE1_in_G1(const POINTonE1 *P)
513
{
514
    POINTonE1 t0, t1, t2;
515
516
    /* Bowe, S., "Faster subgroup checks for BLS12-381"                   */
517
    sigma(&t0, P);                        /* σ(P)                         */
518
    sigma(&t1, &t0);                      /* σ²(P)                        */
519
520
    POINTonE1_double(&t0, &t0);           /* 2σ(P)                        */
521
    POINTonE1_dadd(&t2, &t1, P, NULL);    /* P +  σ²(P)                   */
522
    POINTonE1_cneg(&t2, 1);               /* - P - σ²(P)                  */
523
    POINTonE1_dadd(&t2, &t2, &t0, NULL);  /* 2σ(P) - P - σ²(P)            */
524
    POINTonE1_times_zz_minus_1_div_by_3(  &t0, &t2);
525
    POINTonE1_cneg(&t1, 1);
526
    POINTonE1_dadd(&t0, &t0, &t1, NULL);  /* [(z²-1)/3](2σ(P) - P - σ²(P)) */
527
                                          /* - σ²(P) */
528
    return vec_is_zero(t0.Z, sizeof(t0.Z));
529
}
530
#else
531
static bool_t POINTonE1_in_G1(const POINTonE1 *P)
532
148
{
533
148
    POINTonE1 t0, t1;
534
535
    /* Scott, M., https://eprint.iacr.org/2021/1130 */
536
148
    POINTonE1_times_minus_z(&t0, P);
537
148
    POINTonE1_times_minus_z(&t1, &t0);
538
148
    POINTonE1_cneg(&t1, 1);             /* [-z²]P   */
539
540
148
    sigma(&t0, P);                      /* σ(P)     */
541
148
    sigma(&t0, &t0);                    /* σ²(P)    */
542
543
148
    return POINTonE1_is_equal(&t0, &t1);
544
148
}
545
#endif
546
547
int blst_p1_in_g1(const POINTonE1 *p)
548
111
{   return (int)POINTonE1_in_G1(p);   }
549
550
int blst_p1_affine_in_g1(const POINTonE1_affine *p)
551
37
{
552
37
    POINTonE1 P;
553
554
37
    vec_copy(P.X, p->X, 2*sizeof(P.X));
555
37
    vec_select(P.Z, p->X, BLS12_381_Rx.p, sizeof(P.Z),
556
37
                     vec_is_zero(p, sizeof(*p)));
557
558
37
    return (int)POINTonE1_in_G1(&P);
559
37
}