Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
ctidh_wombat_eval.c File Reference
#include <string.h>
#include <assert.h>
#include "ctidh.h"
#include "../common/primes.h"
#include "../common/int64mask.h"
#include "../common/elligator.h"
#include "../common/random.h"
Include dependency graph for ctidh_wombat_eval.c:

Go to the source code of this file.

Functions

void fulltorsion_points (fp u, fp const a)
void action (public_key *out, public_key const *in, private_key const *priv)
bool csidh (public_key *out, public_key const *in, private_key const *priv)

Variables

const public_key base = {.A = {0}, .seed = ELLIGATOR_SEED}

Function Documentation

◆ action()

void action ( public_key * out,
public_key const * in,
private_key const * priv )

Definition at line 177 of file ctidh_wombat_eval.c.

178{
179
180 init_counters();
181
182 proj A;
183 fp_copy(A.x, in->A);
184 fp_copy(A.z, fp_1);
185
186 proj A24;
187 xA24(&A24, &A);
188
189 proj Points[4];
190 fp seed;
191 fp_set(seed, in->seed);
192 fp_enc(seed, seed);
193 elligator_seeded(&Points[0], &Points[1], &A24, (const fp *)seed);
194
195 clearpublicprimes(&Points[0], &A24);
196 clearpublicprimes(&Points[1], &A24);
197
198 // clear ells not used in the keyspace
199 for (int16_t j = batch_stop[primes_batches - 1] + 1; j < primes_num; j++)
200 {
201 xMUL_dac(&Points[0], &A24, 0, &Points[0], primes_dac[j], primes_daclen[j], primes_daclen[j]);
202 xMUL_dac(&Points[1], &A24, 0, &Points[1], primes_dac[j], primes_daclen[j], primes_daclen[j]);
203 }
204
205 // collect primes not used in the key ...
206 int16_t unused[batch_stop[primes_batches - 1] + 1];
207 // int16_t unused[255] = {0};
208
209 int16_t u = 0;
210 int16_t e = 0;
211 int16_t w = 0;
212 for (e = 0; e <= batch_stop[primes_batches - 1]; e++)
213 {
214#ifdef ENABLE_CT_TESTING
215 VALGRIND_MAKE_MEM_DEFINED(&u, sizeof(int16_t));
216 VALGRIND_MAKE_MEM_DEFINED(&e, sizeof(int16_t));
217 VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(int16_t));
218#endif
219
220 unused[u] = e;
221
222 int64_t mov = -int64mask_equal((int64_t)e, (int64_t)priv->ells[w]);
223
224 fp t1, t2;
225 t1[0] = u;
226 t2[0] = u + 1;
227 fp_cmov(&t1, (const fp *)&t2, 1 - mov);
228 u = t1[0];
229
230 t1[0] = w;
231 t2[0] = w + 1;
232 fp_cmov(&t1, (const fp *)&t2, mov);
233 w = t1[0];
234 }
235
236 // ... and remove them from our points
237 int16_t tmp_b = 0;
238 for (u = 0; u <= batch_stop[primes_batches - 1] - WOMBATKEYS; u++)
239 {
240 int16_t t = unused[u];
241 if (t > batch_stop[tmp_b])
242 tmp_b++;
243
244 long long dac = lookup(t, primes_dac);
245 long long daclen = lookup(t, primes_daclen);
246
247 xMUL_dac(&Points[0], &A24, 0, &Points[0], dac, daclen, batch_maxdac[tmp_b]);
248 xMUL_dac(&Points[1], &A24, 0, &Points[1], dac, daclen, batch_maxdac[tmp_b]);
249 }
250
251 // ACTION!
252 // copy "outer" points
253 proj_copy(&Points[2], &Points[0]);
254 proj_copy(&Points[3], &Points[1]);
255
256 int16_t current_key = WOMBATKEYS - 1;
257 for (int16_t current_batch = primes_batches - 1; current_batch >= 0; current_batch--)
258 {
259 uint8_t inner_counter = 0;
260
261 // outer points are now the inner points
262 proj_copy(&Points[0], &Points[2]);
263 proj_copy(&Points[1], &Points[3]);
264
265 // remove degrees not in the batch
266 tmp_b = 0;
267 for (int16_t j = 0; j < batch_keybounds_start[current_batch]; j++)
268 {
269 if (j > batch_keybounds_stop[tmp_b])
270 tmp_b++;
271
272 long long dac = lookup(priv->ells[j], primes_dac);
273 long long daclen = lookup(priv->ells[j], primes_daclen);
274
275 xMUL_dac(&Points[0], &A24, 0, &Points[0], dac, daclen, batch_maxdac[tmp_b]);
276 xMUL_dac(&Points[1], &A24, 0, &Points[1], dac, daclen, batch_maxdac[tmp_b]);
277 }
278
279
280 for (; current_key >= batch_keybounds_start[current_batch]; current_key--)
281 {
282 uint16_t current_ell_index = priv->ells[current_key];
283 uint64_t current_ell = lookup(current_ell_index, primes);
284 // 0 -> dummy, 1 -> + direction, 2 -> - direction
285 int64_t direction = priv->directions[current_key];
286
287 uint64_t lowerend_ell = primes[batch_start[current_batch] + batch_numkeys[current_batch] - inner_counter - 1];
288 uint64_t upperend_ell = primes[batch_stop[current_batch] - inner_counter];
289 // printf("%3d: %2d - %4ld-isogeny to %ld for cost of (%4ld,%4ld)\n",
290 // current_key, current_batch, current_ell, direction, lowerend_ell, upperend_ell);
291
292 // multiply out other factors
293 proj K;
294 proj_cmov(&K, &Points[0], -int64mask_equal(direction, (int64_t)2));
295 proj_cmov(&K, &Points[1], 1 + int64mask_equal(direction, (int64_t)2));
296
297 // we skip the "last/already processed" and remove only the "other" degrees
298 for (int16_t j = batch_keybounds_start[current_batch]; j < batch_keybounds_stop[current_batch] - inner_counter; j++)
299 {
300 xMUL_dac(&K, &A24, 0, &K, lookup(priv->ells[j], primes_dac), lookup(priv->ells[j], primes_daclen), batch_maxdac[current_batch]);
301 }
302
303 // make a copy to trow away in the dummy case
304 proj A_;
305 proj Points_[4];
306 proj_copy(&Points_[0], &Points[0]);
307 proj_copy(&Points_[1], &Points[1]);
308 proj_copy(&Points_[2], &Points[2]);
309 proj_copy(&Points_[3], &Points[3]);
310 proj_copy(&A_, &A);
311 // we can now compute the isogeny
312 if (current_key == 0)
313 {
314 // this is the last isogeny we need to compute! so we don't need to push points
315 xISOG_matryoshka(&A_, Points_, 0, &K, current_ell, lowerend_ell, upperend_ell);
316 }
317 else if (current_key == batch_keybounds_start[current_batch])
318 {
319 // on the last isogeny of the batch, we only need to push the 2 "outer" points
320 xISOG_matryoshka(&A_, &Points_[2], 2, &K, current_ell, lowerend_ell, upperend_ell);
321 }
322 else if (current_batch == 0)
323 {
324 // on the last batch, we only need the inner points
325 xISOG_matryoshka(&A_, Points_, 2, &K, current_ell, lowerend_ell, upperend_ell);
326 }
327 else if (current_key == batch_keybounds_start[current_batch] + 1)
328 {
329 // on the second to last isogeny of a batch, we only need to push 3 points
330 // the one needed for the last isogeny of the batch + the two outer points
331 proj_cswap(&Points_[0], &Points_[1], -int64mask_equal(priv->directions[current_key - 1], (int64_t)2));
332 xISOG_matryoshka(&A_, &Points_[1], 3, &K, current_ell, lowerend_ell, upperend_ell);
333 proj_cswap(&Points_[0], &Points_[1], -int64mask_equal(priv->directions[current_key - 1], (int64_t)2));
334 }
335 else
336 {
337 xISOG_matryoshka(&A_, Points_, 4, &K, current_ell, lowerend_ell, upperend_ell);
338 }
339
340 // skip isogeny in case of dummy isog
341 proj_cmov(&A, &A_, -int64mask_nonzero(direction));
342 proj_cmov(&Points[0], &Points_[0], -int64mask_nonzero(direction));
343 proj_cmov(&Points[1], &Points_[1], -int64mask_nonzero(direction));
344 proj_cmov(&Points[2], &Points_[2], -int64mask_nonzero(direction));
345 proj_cmov(&Points[3], &Points_[3], -int64mask_nonzero(direction));
346
347 xA24(&A24, &A);
348
349
350 long long dac = lookup(current_ell_index, primes_dac);
351 long long daclen = lookup(current_ell_index, primes_daclen);
352
353 // needed to remove the order incase a dummy isogeny was used
354 if (current_key > batch_keybounds_start[current_batch])
355 {
356 // not needed for the inner points in the last round
357 if (current_key == batch_keybounds_start[current_batch] + 1)
358 {
359 proj_cswap(&Points[0], &Points[1], -int64mask_equal(priv->directions[current_key - 1], (int64_t)2));
360 xMUL_dac(&Points[1], &A24, 0, &Points[1], dac, daclen, batch_maxdac[current_batch]);
361 proj_cswap(&Points[0], &Points[1], -int64mask_equal(priv->directions[current_key - 1], (int64_t)2));
362 }
363 else
364 {
365 xMUL_dac(&Points[0], &A24, 0, &Points[0], dac, daclen, batch_maxdac[current_batch]);
366 xMUL_dac(&Points[1], &A24, 0, &Points[1], dac, daclen, batch_maxdac[current_batch]);
367 }
368 }
369
370 if (current_batch != 0)
371 {
372 xMUL_dac(&Points[2], &A24, 0, &Points[2], dac, daclen, batch_maxdac[current_batch]);
373 xMUL_dac(&Points[3], &A24, 0, &Points[3], dac, daclen, batch_maxdac[current_batch]);
374 }
375
376 inner_counter++;
377 }
378 }
379
380 fp_inv(A.z);
381 fp_mul2(&A.x, (const fp *)&A.z);
382 fp_copy(out->A, A.x);
383}
#define elligator_seeded
Definition elligator.h:8
uint64_t fp[NUMBER_OF_WORDS]
Definition fp-gmp.h:22
#define fp_1
Definition fp-gmp.h:48
#define fp_inv
Definition fp-gmp.h:88
#define fp_cmov
Definition fp-gmp.h:323
#define fp_enc
Definition fp-gmp.h:55
#define fp_copy
Definition fp-gmp.h:79
#define xA24
Definition mont.h:17
#define xMUL_dac
Definition mont.h:21
#define xISOG_matryoshka
Definition mont.h:24
A
Definition tests.py:29
for j
#define batch_keybounds_start
Definition primes.h:57
#define primes
Definition primes.h:51
#define batch_maxdac
Definition primes.h:60
#define batch_keybounds_stop
Definition primes.h:58
#define primes_dac
Definition primes.h:52
#define batch_start
Definition primes.h:55
#define primes_daclen
Definition primes.h:53
#define batch_numkeys
Definition primes.h:59
#define batch_stop
Definition primes.h:56
Definition proj.h:18

References public_key::A, batch_keybounds_start, batch_keybounds_stop, batch_maxdac, batch_numkeys, batch_start, batch_stop, private_key::directions, elligator_seeded, private_key::ells, fp_1, fp_cmov, fp_copy, fp_enc, fp_inv, j, primes, primes_dac, primes_daclen, public_key::seed, xA24, xISOG_matryoshka, and xMUL_dac.

◆ csidh()

bool csidh ( public_key * out,
public_key const * in,
private_key const * priv )

Definition at line 386 of file ctidh_wombat_eval.c.

387{
388 if (!validate(in))
389 {
390 fp_random(out->A);
391 return false;
392 }
393 action(out, in, priv);
394 return true;
395}
#define validate
Definition ctidh.h:53
#define action
Definition ctidh.h:54
#define fp_random
Definition fp-gmp.h:85

References public_key::A, action, fp_random, and validate.

◆ fulltorsion_points()

void fulltorsion_points ( fp u,
fp const a )

Definition at line 94 of file ctidh_wombat_eval.c.

95{
96 proj Tp, Tm, Pp[primes_num], Aux_Tp[3], Pm[primes_num], Aux_Tm[3], A;
97 int j;
98
99 // Convert curve to projective Montgomery form (A' + 2C : 4C)
100 fp_copy(A.x, a);
101 fp_set1(A.z);
102 fp_add(A.z, A.z, A.z); // 2C
103 fp_add(A.x, A.x, A.z); // A' + 2C
104 fp_add(A.z, A.z, A.z); // 4C
105
106 fp_set0(u); // u <- 0
107 uint8_t boolp = 0, boolm = 0;
108
109 do
110 {
111
112#ifdef ENABLE_CT_TESTING
113 VALGRIND_MAKE_MEM_DEFINED(Aux_Tp, sizeof(proj) * 3);
114 VALGRIND_MAKE_MEM_DEFINED(Aux_Tm, sizeof(proj) * 3);
115 VALGRIND_MAKE_MEM_DEFINED(&A, sizeof(proj));
116 VALGRIND_MAKE_MEM_DEFINED(&boolp, sizeof(uint8_t));
117 VALGRIND_MAKE_MEM_DEFINED(&boolm, sizeof(uint8_t));
118 VALGRIND_MAKE_MEM_DEFINED(&Tp, sizeof(proj));
119 VALGRIND_MAKE_MEM_DEFINED(Pp, sizeof(proj) * primes_num);
120 VALGRIND_MAKE_MEM_DEFINED(Pm, sizeof(proj) * primes_num);
121#endif
122
123 fp_add(u, u, fp_1); // u <- u + 1 ... Recall, 1 must be in Montgomery domain
124 elligator_seeded(&Tp, &Tm, &A, (const fp *)u);
125
126 clearpublicprimes(&Tp, &A);
127 clearpublicprimes(&Tm, &A);
128
129#ifdef ENABLE_CT_TESTING
130 memset(Aux_Tp, 0, sizeof(proj) * 3);
131#endif
132 multiples(Aux_Tp, Tp, A);
133 if (fp_iszero(Aux_Tp[0].z) | fp_iszero(Aux_Tp[1].z) | fp_iszero(Aux_Tp[2].z))
134 continue;
135
136#ifdef ENABLE_CT_TESTING
137 memset(Aux_Tm, 0, sizeof(proj) * 3);
138#endif
139 multiples(Aux_Tm, Tm, A);
140 if (fp_iszero(Aux_Tm[0].z) | fp_iszero(Aux_Tm[1].z) | fp_iszero(Aux_Tm[2].z))
141 continue;
142
143 // Checking if Tp is an order (p+1)/(2^e)
144 proj_copy(&Pp[0], &Tp);
145 cofactor_multiples(Pp, A, 0, primes_num);
146 boolp = 1;
147 boolp &= (1 - fp_iszero(Pp[0].z)) | (1 - fp_iszero(Aux_Tp[0].z));
148 boolp &= (1 - fp_iszero(Pp[1].z)) | (1 - fp_iszero(Aux_Tp[1].z));
149 boolp &= (1 - fp_iszero(Pp[2].z)) | (1 - fp_iszero(Aux_Tp[2].z));
150 for (j = 3; j < (int)primes_num; j++)
151 boolp &= (1 - fp_iszero(Pp[j].z));
152
153 if (1 - boolp)
154 continue;
155
156 // ---> This can be removed for wd1 style
157 // Checking if Tm is an order (p+1)/(2^e)
158 proj_copy(&Pm[0], &Tm);
159 cofactor_multiples(Pm, A, 0, primes_num);
160
161 boolm = 1;
162 boolm &= (1 - fp_iszero(Pm[0].z)) | (1 - fp_iszero(Aux_Tm[0].z));
163 boolm &= (1 - fp_iszero(Pm[1].z)) | (1 - fp_iszero(Aux_Tm[1].z));
164 boolm &= (1 - fp_iszero(Pm[2].z)) | (1 - fp_iszero(Aux_Tm[2].z));
165 for (j = 3; j < (int)primes_num; j++)
166 boolm &= (1 - fp_iszero(Pm[j].z));
167
168 if (1 - boolm)
169 continue;
170 // <---
171 } while ((1 - boolp) | (1 - boolm));
172
173 fp_dec(u, (uint64_t *const)u);
174}
#define cofactor_multiples
Definition ctidh.h:55
#define fp_add
Definition fp-gmp.h:64
#define fp_dec
Definition fp-gmp.h:58
f a
Definition to_model.m:12

References a, cofactor_multiples, elligator_seeded, fp_1, fp_add, fp_copy, fp_dec, and j.

Variable Documentation

◆ base

const public_key base = {.A = {0}, .seed = ELLIGATOR_SEED}

Definition at line 24 of file ctidh_wombat_eval.c.

24{.A = {0}, .seed = ELLIGATOR_SEED}; /* A = 0 */