-rw-r--r-- 1978 high-ctidh-20210523/elligator.c
#include "crypto_declassify.h"
#include "elligator.h"
void elligator(proj *plus,proj *minus,const proj *A)
{
for (;;) {
fp u; fp_random(&u);
long long reject = fp_iszero(&u);
crypto_declassify(&reject,sizeof reject);
if (reject) continue; /* bad RNG outputs 0 */
fp u2; fp_sq2(&u2,&u);
fp D; fp_sub3(&D,&u2,&fp_1);
reject = fp_iszero(&D);
crypto_declassify(&reject,sizeof reject);
if (reject) continue; /* bad RNG outputs +-1 */
fp M; fp_mul3(&M,&A->x,&u2); /* M = u^2 A->x */
fp T; fp_mul3(&T,&A->x,&M); /* T = u^2 A->x^2 */
long long control = fp_iszero(&A->x);
fp P = A->x;
fp_cmov(&P,&fp_1,control); /* P = 1 if A->x = 0 else A->x */
fp_cmov(&M,&fp_1,control); /* M = 1 if A->x = 0 else u^2 A->x */
fp_cmov(&T,&fp_1,control); /* T = 1 if A->x = 0 */
fp_mul2(&D,&A->z); /* D = (u^2-1) A->z */
fp D2; fp_sq2(&D2,&D); /* D2 = (u^2-1)^2 A->z^2 */
fp_add2(&T,&D2); /* T = 1 + (u^2-1)^2 A->z^2 if A->x = 0, else u^2 A->x^2 + (u^2-1)^2 A->z^2 */
fp_mul2(&T,&D);
fp_mul2(&T,&P);
/* T = (u^2-1)A->z(1+(u^2-1)^2 A->z^2) if A->x = 0 */
/* else (u^2-1) A->z A->x(u^2 A->x^2 + (u^2-1)^2 A->z^2) */
/* plus point will be P/D = 1/(u^2-1)A->z if A->x = 0 else A/(u^2-1) */
/* and minus point will be -M/D = -1/(u^2-1)A->z if A->x = 0 else -u^2 A/(u^2-1) */
/* unless they're flipped, which is determined by T */
/* T = Az^4 (1-u^2)^4 ((P/D)^3+A(P/D)^2+(P/D)) */
/* so T squareness says whether P/D is on curve */
/* also says whether -M/D is not on curve: */
/* in all cases -M/D = -P/D-A */
/* so (-M/D)^3+A(-M/D)^2+(-M/D) = (-P/D-A)^3+A(-P/D-A)^2+(-P/D-A) */
/* = ((P/D)^3+A(P/D)^2+(P/D)) (-1-AD/P) */
/* and by construction -1-AD/P is a non-square */
/* since it's -1 if A=0, else -u^2 */
plus->x = P;
fp_neg2(&minus->x,&M);
fp_cswap(&plus->x,&minus->x,1-fp_sqrt(&T));
plus->z = D;
minus->z = D;
return;
}
}