Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
ctidh.h File Reference
#include "../common/namespace.h"
#include "../common/fp/mulx/fp.h"
#include "../common/mont.h"
#include "../common/primes.h"
Include dependency graph for ctidh.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  private_key
struct  public_key

Macros

#define csidh_stattried   NS(csidh_stattried)
#define csidh_statsucceeded   NS(csidh_statsucceeded)
#define base   NS(base)
#define ctidh_private   NS(ctidh_private)
#define csidh   NS(csidh)
#define validate_cutofforder_v2   NS(validate_cutofforder_v2)
#define validate   NS(validate)
#define action   NS(action)
#define cofactor_multiples   NS(cofactor_multiples)
#define get_full_point   NS(get_full_point)
#define fulltorsion_points   NS(fulltorsion_points)
#define validate2   NS(validate2)

Typedefs

typedef struct private_key private_key
typedef struct public_key public_key

Functions

void ctidh_private (private_key *priv)
bool csidh (public_key *out, public_key const *in, private_key const *priv)
bool validate (public_key const *in)
void action (public_key *out, public_key const *in, private_key const *priv)
void cofactor_multiples (proj P[], proj const A, size_t lower, size_t upper)
uint64_t get_full_point (proj *P, proj *A)
void fulltorsion_points (fp u, fp const a)

Variables

long long csidh_stattried [primes_batches]
long long csidh_statsucceeded [primes_batches]
const public_key base

Macro Definition Documentation

◆ action

#define action   NS(action)

Definition at line 54 of file ctidh.h.

Referenced by csidh(), internal_derive(), internal_keygen(), and pkgen().

◆ base

#define base   NS(base)

Definition at line 44 of file ctidh.h.

Referenced by internal_keygen(), and pkgen().

◆ cofactor_multiples

#define cofactor_multiples   NS(cofactor_multiples)

Definition at line 55 of file ctidh.h.

Referenced by cofactor_multiples(), and fulltorsion_points().

◆ csidh

#define csidh   NS(csidh)

Definition at line 51 of file ctidh.h.

◆ csidh_statsucceeded

#define csidh_statsucceeded   NS(csidh_statsucceeded)

Definition at line 23 of file ctidh.h.

◆ csidh_stattried

#define csidh_stattried   NS(csidh_stattried)

Definition at line 21 of file ctidh.h.

◆ ctidh_private

#define ctidh_private   NS(ctidh_private)

Definition at line 47 of file ctidh.h.

Referenced by internal_keygen(), and skgen().

◆ fulltorsion_points

#define fulltorsion_points   NS(fulltorsion_points)

Definition at line 57 of file ctidh.h.

Referenced by internal_keygen().

◆ get_full_point

#define get_full_point   NS(get_full_point)

Definition at line 56 of file ctidh.h.

◆ validate

#define validate   NS(validate)

Definition at line 53 of file ctidh.h.

Referenced by csidh(), and internal_derive().

◆ validate2

#define validate2   NS(validate2)

Definition at line 58 of file ctidh.h.

◆ validate_cutofforder_v2

#define validate_cutofforder_v2   NS(validate_cutofforder_v2)

Definition at line 52 of file ctidh.h.

Typedef Documentation

◆ private_key

typedef struct private_key private_key

◆ public_key

typedef struct public_key public_key

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:

◆ cofactor_multiples()

void cofactor_multiples ( proj P[],
proj const A,
size_t lower,
size_t upper )

Definition at line 77 of file validate.c.

78{
79 assert(lower < upper);
80 if (upper - lower == 1)
81 return;
82
83 int i;
84 size_t mid = lower + (upper - lower + 1) / 2;
85
86 // proj_copy(P[mid], (const fp*)P[lower]);
87 fp_copy(P[mid].x, P[lower].x);
88 fp_copy(P[mid].z, P[lower].z);
89
90 for (i = lower; i < (int)mid; i++)
91 xMUL_dac(&P[mid], &A, 1, &P[mid], primes_dac[i], primes_daclen[i], primes_daclen[i]);
92 // xmul(P[mid], i, (const fp*)P[mid], A);
93
94 for (i = (int)mid; i < (int)upper; i++)
95 xMUL_dac(&P[lower], &A, 1, &P[lower], primes_dac[i], primes_daclen[i], primes_daclen[i]);
96 // xmul(P[lower], i, (const fp*)P[lower], A);
97
98 cofactor_multiples(P, A, lower, mid);
99 cofactor_multiples(P, A, mid, upper);
100}
#define cofactor_multiples
Definition ctidh.h:55
assert(var1 eq var2)

References assert(), cofactor_multiples, fp_copy, i, primes_dac, primes_daclen, 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.

◆ ctidh_private()

void ctidh_private ( private_key * priv)

◆ 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 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.

◆ get_full_point()

uint64_t get_full_point ( proj * P,
proj * A )

References a.

◆ validate()

bool validate ( public_key const * in)

Definition at line 22 of file validate.c.

22 {
23// #if !defined(_M1_) && !defined(_M2_) && !defined(_M3_) && !defined(_M4_) && !defined(_M5_)
24// printf("\nNOT using radical 3-isogenies.\n\n");
25// #else
26// printf("\nUsing 2^%ld radical 3-isogenies.\n\n", batch_start[0] - 1);
27// #endif
28 proj A, A24;
29 fp_copy(A.x, in->A);
30 fp_copy(A.z, fp_1);
31 xA24(&A24, &A);
32
33 proj Pp, Pm;
34
35#ifdef ENABLE_CT_TESTING
36 memset(&Pp, 0, sizeof(proj));
37 memset(&Pp.z, 0, sizeof(proj));
38 VALGRIND_MAKE_MEM_DEFINED(&Pp.z, sizeof(fp));
39 VALGRIND_MAKE_MEM_DEFINED(&Pp, sizeof(proj));
40 VALGRIND_MAKE_MEM_DEFINED(&A24, sizeof(proj));
41#endif
42
43 fp seed;
44 fp_set(seed, in->seed);
45 fp_enc(seed, seed);
46 elligator_seeded(&Pp, &Pm, &A24, (const fp *)seed);
47
48
49 for (int64_t j = 0; j < two_cofactor; j++)
50 {
51 xDBL(&Pp, &Pp, &A24, 0);
52 }
53 // clear ells replaced by radical 3-isogenies
54 for (int16_t j = 0; j < batch_start[0]; j++)
55 {
56 xMUL_dac(&Pp, &A24, 0, &Pp, primes_dac[j], primes_daclen[j], primes_daclen[j]);
57 }
58 // remove ells and check that we do not reach the point at infinity
59 for(int i = primes_num-1; i > batch_start[0]; i--)
60 {
61 xMUL_dac(&Pp, &A24, 0, &Pp, primes_dac[i], primes_daclen[i], primes_daclen[i]);
62 if(fp_iszero(Pp.z))
63 return false;
64 }
65
66 // after removing the last ell, now we should have the point at infinity
68 return fp_iszero(Pp.z);
69}
#define xDBL
Definition mont.h:18
fp z
Definition proj.h:20

References public_key::A, batch_start, elligator_seeded, fp_1, fp_copy, fp_enc, i, j, primes_dac, primes_daclen, public_key::seed, xA24, xDBL, xMUL_dac, and proj::z.

Variable Documentation

◆ base

const public_key base
extern

Definition at line 29 of file ctidh.c.

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

◆ csidh_statsucceeded

long long csidh_statsucceeded[primes_batches]
extern

◆ csidh_stattried

long long csidh_stattried[primes_batches]
extern