static void setneutral(ge25519 *r) { fe25519_setzero(&r->x); fe25519_setone(&r->y); fe25519_setone(&r->z); fe25519_setzero(&r->t); }
void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) { signed char b[64]; signed char i; //1 byte ge25519_aff t; //64 bytes ge25519_p1p1 tp1p1; //128 bytes sc25519_window4(b,s); choose_t((ge25519_aff *)r, b[63]); fe25519_setone(&r->z); fe25519_mul(&r->t, &r->x, &r->y); for(i=62;i>=0;i--) { dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *)r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *)r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *)r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p3(r, &tp1p1); choose_t(&t, b[i]); ge25519_mixadd2(r, &t); } }
/* return 0 on success, -1 otherwise */ int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) { unsigned char par; fe25519 t, chk, num, den, den2, den4, den6; fe25519_setone(&r->z); par = p[31] >> 7; fe25519_unpack(&r->y, p); fe25519_square(&num, &r->y); /* x = y^2 */ fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ /* Computation of sqrt(num/den) */ /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ fe25519_square(&den2, &den); fe25519_square(&den4, &den2); fe25519_mul(&den6, &den4, &den2); fe25519_mul(&t, &den6, &num); fe25519_mul(&t, &t, &den); fe25519_pow2523(&t, &t); /* 2. computation of r->x = t * num * den^3 */ fe25519_mul(&t, &t, &num); fe25519_mul(&t, &t, &den); fe25519_mul(&t, &t, &den); fe25519_mul(&r->x, &t, &den); /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) { fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); } /* 4. Now we have one of the two square roots, except if input was not a square */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) { return -1; } /* 5. Choose the desired square root according to parity: */ if(fe25519_getparity(&r->x) != (1-par)) { fe25519_neg(&r->x, &r->x); } fe25519_mul(&r->t, &r->x, &r->y); return 0; }
void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) { signed char b[85]; int i; ge25519_aff t; sc25519_window3(b,s); choose_t((ge25519_aff *)r, 0, b[0]); fe25519_setone(&r->z); fe25519_mul(&r->t, &r->x, &r->y); for(i=1;i<85;i++) { choose_t(&t, (unsigned long long) i, b[i]); ge25519_mixadd2(r, &t); } }
int edmont_conv(unsigned char r[crypto_scalarmult_curve25519_BYTES], const unsigned char p[ED25519_PUBLICKEYBYTES]) { fe25519 u, y, num, den, inv, one; fe25519_unpack(&y, p); // u = (1 + y) / (1 -y) fe25519_setone(&one); fe25519_add(&num, &one, &y); fe25519_sub(&den, &one, &y); fe25519_invert(&inv, &den); fe25519_mul(&u, &num, &inv); fe25519_pack(r, &u); return 0; }