Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
ctidh.c File Reference
#include <string.h>
#include <assert.h>
#include "ctidh.h"
#include "isogeny_walks.h"
#include "../common/primes.h"
#include "../common/int64mask.h"
#include "../common/elligator.h"
#include "../common/random.h"
#include "../common/fp/fp-counters.h"
Include dependency graph for ctidh.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 176 of file ctidh.c.

177{
178// #if !defined(_M1_) && !defined(_M2_) && !defined(_M3_) && !defined(_M4_) && !defined(_M5_)
179// printf("\nNOT using radical 3-isogenies (action).\n\n");
180// #else
181// printf("\nUsing 2^%ld radical 3-isogenies.\n\n", batch_start[0] - 1);
182// #endif
183
184 init_counters();
185
186 proj A;
187 fp_copy(A.x, in->A);
188 fp_copy(A.z, fp_1);
189
190 proj A24;
191 xA24(&A24, &A);
192
193 proj Points[2];
194 fp seed;
195 fp_set(seed, in->seed);
196 fp_enc(seed, seed);
197 elligator_seeded(&Points[0], &Points[1], &A24, (const fp *)seed);
198
199 clearpublicprimes(&Points[0], &A24);
200 clearpublicprimes(&Points[1], &A24);
201
202 // clear ells replaced by radical 3-isogenies
203 for (int16_t j = 0; j < batch_start[0]; j++)
204 {
205 xMUL_dac(&Points[0], &A24, 0, &Points[0], primes_dac[j], primes_daclen[j], primes_daclen[j]);
206 xMUL_dac(&Points[1], &A24, 0, &Points[1], primes_dac[j], primes_daclen[j], primes_daclen[j]);
207 }
208 // clear ells not used in the keyspace
209 for (int16_t j = batch_stop[primes_batches - 1] + 1; j < primes_num; j++)
210 {
211 xMUL_dac(&Points[0], &A24, 0, &Points[0], primes_dac[j], primes_daclen[j], primes_daclen[j]);
212 xMUL_dac(&Points[1], &A24, 0, &Points[1], primes_dac[j], primes_daclen[j], primes_daclen[j]);
213 }
214
215 // collect primes not used in the key ...
216 int16_t unused[batch_stop[primes_batches - 1] + 1];
217
218 int16_t u = 0;
219 int16_t e = 0;
220 int16_t w = 0;
221 for (e = 0; e <= batch_stop[primes_batches - 1]; e++)
222 {
223#ifdef ENABLE_CT_TESTING
224 VALGRIND_MAKE_MEM_DEFINED(&u, sizeof(int16_t));
225 VALGRIND_MAKE_MEM_DEFINED(&e, sizeof(int16_t));
226 VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(int16_t));
227#endif
228
229 unused[u] = e;
230
231 int64_t mov = -int64mask_equal((int64_t)e, (int64_t)priv->ells[w]);
232
233 fp t1, t2;
234 t1[0] = u;
235 t2[0] = u + 1;
236 fp_cmov(&t1, (const fp *)&t2, 1 - mov);
237 u = t1[0];
238
239 t1[0] = w;
240 t2[0] = w + 1;
241 fp_cmov(&t1, (const fp *)&t2, mov);
242 w = t1[0];
243 }
244
245 // ... and remove them from our points
246 int16_t tmp_b = 0;
247 for (u = 0; u <= batch_stop[primes_batches - 1] - WOMBATKEYS; u++)
248 {
249 int16_t t = unused[u];
250 if (t > batch_stop[tmp_b])
251 tmp_b++;
252
253 int64_t dac = lookup(t, primes_dac);
254 int64_t daclen = lookup(t, primes_daclen);
255
256 xMUL_dac(&Points[0], &A24, 0, &Points[0], dac, daclen, batch_maxdac[tmp_b]);
257 xMUL_dac(&Points[1], &A24, 0, &Points[1], dac, daclen, batch_maxdac[tmp_b]);
258 }
259
260
261 proj ramifications[2 * WOMBATKEYS] = {0};
262 int inner,
263 block = 0, // current size of ramifications
264 pos, // index of the current small odd prime to be processed
265 k = 0; // strategy element
266
267 int64_t moves = 0, // required for reaching an torsion-(l_pos) point
268 xmul_counter[WOMBATKEYS] = {0},
269 Plen = 0;
270 (void)pos;
271
272 int8_t swap = 0;
273
274 proj_copy(&ramifications[0], (const proj *)&Points[0]); // point on E[\pi + 1]
275 proj_copy(&ramifications[1], (const proj *)&Points[1]); // point on E[\pi - 1]
276
277 int16_t current_batch = 0; //primes_batches - 1;
278 int16_t current_batch_inner = batch_numkeys[current_batch];
279
280 proj Points_[2 * WOMBATKEYS] = {0};
281
282 // #pragma unroll WOMBATKEYS
283 //int64_t tmp_cost = fpmul+fpsqr;
284 for (int i = WOMBATKEYS - 1; i >= 0; i--)
285 {
286 if ((WOMBATKEYS - i - 1) > batch_keybounds_stop[current_batch])
287 {
288 current_batch++;
289 current_batch_inner = batch_numkeys[current_batch];
290 }
291
292
293 uint16_t flip_index = WOMBATKEYS - i -1;
294 uint16_t current_ell_index = priv->ells[flip_index];
295 uint64_t current_ell = lookup(current_ell_index, primes);
296 // 0 -> dummy, 1 -> + direction, 2 -> - direction
297 int64_t direction = priv->directions[flip_index];
298
299 uint64_t lowerend_ell = primes[batch_start[current_batch] + batch_numkeys[current_batch] - current_batch_inner];
300 uint64_t upperend_ell = primes[batch_stop[current_batch] - current_batch_inner + 1];
301
302
303 // conditional swap based on direction
304 swap = -int64mask_equal(direction, (int64_t)2);
305 proj_cswap(&ramifications[0+ 2 * block], &ramifications[1+ 2 * block], swap);
306
307 tmp_b = primes_batches-1;
308 while (moves < i)
309 {
310 block += 1;
311
312 proj_copy(&ramifications[0 + 2 * block], (const proj *)&ramifications[0 + 2 * (block - 1)]); // point on E[\pi + 1]
313 proj_copy(&ramifications[1 + 2 * block], (const proj *)&ramifications[1 + 2 * (block - 1)]); // point on E[\pi - 1]
314
315 // #pragma unroll
316 for (inner = moves; inner < (moves + strategy[k]); inner++)
317 {
318 pos = WOMBATKEYS - inner -1;
319 while (pos < batch_keybounds_start[tmp_b])
320 tmp_b--;
321
322 int64_t dac = lookup(priv->ells[pos], primes_dac);
323 int64_t daclen = lookup(priv->ells[pos], primes_daclen);
324
325 if(moves + strategy[k] < i)
326 {
327 xMUL_dac(&ramifications[0 + 2 * block], &A24, 0, &ramifications[0 + 2 * block], dac, daclen, batch_maxdac[tmp_b]);
328 xMUL_dac(&ramifications[1 + 2 * block], &A24, 0, &ramifications[1 + 2 * block], dac, daclen, batch_maxdac[tmp_b]);
329 }
330 else { // current block
331 xMUL_dac(&ramifications[0 + 2 * block], &A24, 0, &ramifications[0 + 2 * block], dac, daclen, batch_maxdac[tmp_b]);
332 }
333 }
334
335 xmul_counter[block] = strategy[k]; // the k-th element is used for next iteration on moves
336 moves += strategy[k]; // moves is incremented
337 k += 1;
338 }
339
340 // how many points should be evaluated?
341 Plen = 2 * block;
342
343
344 proj Anew;
345 proj_copy(&Anew, &A);
346 for (int j = 0; j < Plen; j++)
347 {
348 // backup for the dummy case
349 proj_copy(&Points_[j], &ramifications[j]);
350 }
351
352 xISOG_matryoshka(&Anew, Points_, Plen, &ramifications[0 + 2 * block], current_ell, lowerend_ell, upperend_ell);
353
354
355 // copy back
356 proj_cmov(&A, &Anew, -int64mask_nonzero(direction));
357 xA24(&A24, &A);
358
359
360 for (int j = 0; j < Plen; j++)
361 {
362 proj_cmov(&ramifications[j], &Points_[j], -int64mask_nonzero(direction));
363
364 // in case of dummy, we still need to "remove" degree
365
366 int64_t dac = lookup(current_ell_index, primes_dac);
367 int64_t daclen = lookup(current_ell_index, primes_daclen);
368
369 xMUL_dac(&ramifications[j], &A24, 0, &ramifications[j], dac, daclen, batch_maxdac[current_batch]);
370 }
371
372
373 // Configuring for the next iteration
374 moves -= xmul_counter[block];
375 xmul_counter[block] = 0;
376 block -= 1;
377 // swap back based on direction
378 proj_cswap(&ramifications[0+ 2 * block], &ramifications[1+ 2 * block], swap);
379
380 current_batch_inner--;
381 }
382
383#if defined(_M0_)
384 fp_inv(A.z);
385 fp_mul2(&A.x, (const fp *)&A.z);
386 fp_copy(out->A, A.x);
387#else
388 isogeny_walks_3_fp(out->A, A, priv->radical_length, priv->radical_direction);
389#endif
390
391}
void swap(ticks *a, ticks *b)
void isogeny_walks_3_fp(fp_t output_A, const fp_t input_A, int input_length)
#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 i
for j
#define batch_keybounds_start
Definition primes.h:57
#define primes
Definition primes.h:51
const int8_t strategy[WOMBATKEYS]
#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, i, isogeny_walks_3_fp(), j, primes, primes_dac, primes_daclen, private_key::radical_direction, private_key::radical_length, public_key::seed, strategy, swap(), xA24, xISOG_matryoshka, and xMUL_dac.

Here is the call graph for this function:

◆ csidh()

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

Definition at line 394 of file ctidh.c.

395{
396 if (!validate(in))
397 {
398 fp_random(out->A);
399 return false;
400 }
401 action(out, in, priv);
402 return true;
403}
#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 103 of file ctidh.c.

104{
105 proj Tp, Tm, Pp[batch_stop[primes_batches - 1] + 1], Pm[batch_stop[primes_batches - 1] + 1], A;
106 int j;
107
108 // Convert curve to projective Montgomery form (A' + 2C : 4C)
109 fp_copy(A.x, a);
110 fp_set1(A.z);
111 fp_add(A.z, A.z, A.z); // 2C
112 fp_add(A.x, A.x, A.z); // A' + 2C
113 fp_add(A.z, A.z, A.z); // 4C
114
115 fp_set0(u); // u <- 0
116 uint8_t boolp = 0, boolm = 0;
117
118 do
119 {
120
121#ifdef ENABLE_CT_TESTING
122 VALGRIND_MAKE_MEM_DEFINED(&A, sizeof(proj));
123 VALGRIND_MAKE_MEM_DEFINED(&boolp, sizeof(uint8_t));
124 VALGRIND_MAKE_MEM_DEFINED(&boolm, sizeof(uint8_t));
125 VALGRIND_MAKE_MEM_DEFINED(&Tp, sizeof(proj));
126 VALGRIND_MAKE_MEM_DEFINED(Pp, sizeof(proj) * (batch_stop[primes_batches - 1] + 1 - batch_start[0]));
127 VALGRIND_MAKE_MEM_DEFINED(Pm, sizeof(proj) * (batch_stop[primes_batches - 1] + 1 - batch_start[0]));
128#endif
129
130 fp_add(u, u, fp_1); // u <- u + 1 ... Recall, 1 must be in Montgomery domain
131 elligator_seeded(&Tp, &Tm, &A, (const fp *)u);
132
133 clearpublicprimes(&Tp, &A);
134 clearpublicprimes(&Tm, &A);
135 // clear ells replaced by radical 3-isogenies
136 for (j = 0; j < batch_start[0]; j++)
137 {
138 xMUL_dac(&Tp, &A, 0, &Tp, primes_dac[j], primes_daclen[j], primes_daclen[j]);
139 xMUL_dac(&Tm, &A, 0, &Tm, primes_dac[j], primes_daclen[j], primes_daclen[j]);
140 }
141 // clear ells not used in the keyspace
142 for (j = batch_stop[primes_batches - 1] + 1; j < primes_num; j++)
143 {
144 xMUL_dac(&Tp, &A, 0, &Tp, primes_dac[j], primes_daclen[j], primes_daclen[j]);
145 xMUL_dac(&Tm, &A, 0, &Tm, primes_dac[j], primes_daclen[j], primes_daclen[j]);
146 }
147
148 // Checking if Tp is an order (p+1)/(2^e)
149 proj_copy(&Pp[0], &Tp);
150 cofactor_multiples(Pp, A, 0, batch_stop[primes_batches - 1] + 1);
151 boolp = 1;
152 for (j = batch_start[0]; j < (int)(batch_stop[primes_batches - 1] + 1); j++)
153 boolp &= (1 - fp_iszero(Pp[j].z));
154
155 if (1 - boolp)
156 continue;
157
158 // ---> This can be removed for wd1 style
159 // Checking if Tm is an order (p+1)/(2^e)
160 proj_copy(&Pm[0], &Tm);
161 cofactor_multiples(Pm, A, 0, batch_stop[primes_batches - 1] + 1);
162
163 boolm = 1;
164 for (j = batch_start[0]; j < (int)(batch_stop[primes_batches - 1] + 1); j++)
165 boolm &= (1 - fp_iszero(Pm[j].z));
166
167 if (1 - boolm)
168 continue;
169 // <---
170 } while ((1 - boolp) | (1 - boolm));
171
172 fp_dec(u, (uint64_t *const)u);
173}
#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, batch_start, batch_stop, cofactor_multiples, elligator_seeded, fp_1, fp_add, fp_copy, fp_dec, j, primes_dac, primes_daclen, and xMUL_dac.

Variable Documentation

◆ base

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

Definition at line 29 of file ctidh.c.

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