123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- #include <string.h> // memcpy
- #include <stdint.h>
- typedef unsigned __int128 uint128_t;
- typedef uint64_t fe25519[5];
- typedef struct {
- fe25519 X;
- fe25519 Y;
- fe25519 Z;
- } ge25519_p2;
- typedef struct {
- fe25519 X;
- fe25519 Y;
- fe25519 Z;
- fe25519 T;
- } ge25519_p3;
- typedef struct {
- fe25519 X;
- fe25519 Y;
- fe25519 Z;
- fe25519 T;
- } ge25519_p1p1;
- typedef struct {
- fe25519 yplusx;
- fe25519 yminusx;
- fe25519 xy2d;
- } ge25519_precomp;
- /*
- h = 0
- */
- static inline void
- fe25519_0(fe25519 h)
- {
- memset(&h[0], 0, 5 * sizeof h[0]);
- }
- /*
- h = 1
- */
- static inline void
- fe25519_1(fe25519 h)
- {
- h[0] = 1;
- memset(&h[1], 0, 4 * sizeof h[0]);
- }
- /*
- h = f + g
- Can overlap h with f or g.
- */
- static inline void
- fe25519_add(fe25519 h, const fe25519 f, const fe25519 g)
- {
- uint64_t h0 = f[0] + g[0];
- uint64_t h1 = f[1] + g[1];
- uint64_t h2 = f[2] + g[2];
- uint64_t h3 = f[3] + g[3];
- uint64_t h4 = f[4] + g[4];
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- }
- /*
- h = f - g
- */
- static void
- fe25519_sub(fe25519 h, const fe25519 f, const fe25519 g)
- {
- const uint64_t mask = 0x7ffffffffffffULL;
- uint64_t h0, h1, h2, h3, h4;
- h0 = g[0];
- h1 = g[1];
- h2 = g[2];
- h3 = g[3];
- h4 = g[4];
- h1 += h0 >> 51;
- h0 &= mask;
- h2 += h1 >> 51;
- h1 &= mask;
- h3 += h2 >> 51;
- h2 &= mask;
- h4 += h3 >> 51;
- h3 &= mask;
- h0 += 19ULL * (h4 >> 51);
- h4 &= mask;
- h0 = (f[0] + 0xfffffffffffdaULL) - h0;
- h1 = (f[1] + 0xffffffffffffeULL) - h1;
- h2 = (f[2] + 0xffffffffffffeULL) - h2;
- h3 = (f[3] + 0xffffffffffffeULL) - h3;
- h4 = (f[4] + 0xffffffffffffeULL) - h4;
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- }
- /*
- h = -f
- */
- static inline void
- fe25519_neg(fe25519 h, const fe25519 f)
- {
- fe25519 zero;
- fe25519_0(zero);
- fe25519_sub(h, zero, f);
- }
- /*
- h = f * g
- Can overlap h with f or g.
- */
- extern "C" void x25519_fe51_mul(fe25519 h, const fe25519 f, const fe25519 g);
- #define fe25519_mul x25519_fe51_mul
- /*
- static void
- fe25519_mul(fe25519 h, const fe25519 f, const fe25519 g)
- {
- const uint64_t mask = 0x7ffffffffffffULL;
- uint128_t r0, r1, r2, r3, r4, carry;
- uint64_t f0, f1, f2, f3, f4;
- uint64_t f1_19, f2_19, f3_19, f4_19;
- uint64_t g0, g1, g2, g3, g4;
- uint64_t r00, r01, r02, r03, r04;
- f0 = f[0];
- f1 = f[1];
- f2 = f[2];
- f3 = f[3];
- f4 = f[4];
- g0 = g[0];
- g1 = g[1];
- g2 = g[2];
- g3 = g[3];
- g4 = g[4];
- f1_19 = 19ULL * f1;
- f2_19 = 19ULL * f2;
- f3_19 = 19ULL * f3;
- f4_19 = 19ULL * f4;
- r0 = ((uint128_t)f0) * ((uint128_t)g0);
- r0 += ((uint128_t)f1_19) * ((uint128_t)g4);
- r0 += ((uint128_t)f2_19) * ((uint128_t)g3);
- r0 += ((uint128_t)f3_19) * ((uint128_t)g2);
- r0 += ((uint128_t)f4_19) * ((uint128_t)g1);
- r1 = ((uint128_t)f0) * ((uint128_t)g1);
- r1 += ((uint128_t)f1) * ((uint128_t)g0);
- r1 += ((uint128_t)f2_19) * ((uint128_t)g4);
- r1 += ((uint128_t)f3_19) * ((uint128_t)g3);
- r1 += ((uint128_t)f4_19) * ((uint128_t)g2);
- r2 = ((uint128_t)f0) * ((uint128_t)g2);
- r2 += ((uint128_t)f1) * ((uint128_t)g1);
- r2 += ((uint128_t)f2) * ((uint128_t)g0);
- r2 += ((uint128_t)f3_19) * ((uint128_t)g4);
- r2 += ((uint128_t)f4_19) * ((uint128_t)g3);
- r3 = ((uint128_t)f0) * ((uint128_t)g3);
- r3 += ((uint128_t)f1) * ((uint128_t)g2);
- r3 += ((uint128_t)f2) * ((uint128_t)g1);
- r3 += ((uint128_t)f3) * ((uint128_t)g0);
- r3 += ((uint128_t)f4_19) * ((uint128_t)g4);
- r4 = ((uint128_t)f0) * ((uint128_t)g4);
- r4 += ((uint128_t)f1) * ((uint128_t)g3);
- r4 += ((uint128_t)f2) * ((uint128_t)g2);
- r4 += ((uint128_t)f3) * ((uint128_t)g1);
- r4 += ((uint128_t)f4) * ((uint128_t)g0);
- r00 = ((uint64_t)r0) & mask;
- carry = r0 >> 51;
- r1 += carry;
- r01 = ((uint64_t)r1) & mask;
- carry = r1 >> 51;
- r2 += carry;
- r02 = ((uint64_t)r2) & mask;
- carry = r2 >> 51;
- r3 += carry;
- r03 = ((uint64_t)r3) & mask;
- carry = r3 >> 51;
- r4 += carry;
- r04 = ((uint64_t)r4) & mask;
- carry = r4 >> 51;
- r00 += 19ULL * (uint64_t)carry;
- carry = r00 >> 51;
- r00 &= mask;
- r01 += (uint64_t)carry;
- carry = r01 >> 51;
- r01 &= mask;
- r02 += (uint64_t)carry;
- h[0] = r00;
- h[1] = r01;
- h[2] = r02;
- h[3] = r03;
- h[4] = r04;
- }
- */
- /*
- h = f * f
- Can overlap h with f.
- */
- extern "C" void x25519_fe51_sqr(fe25519 h, const fe25519 f);
- #define fe25519_sq x25519_fe51_sqr
- /*
- static void
- fe25519_sq(fe25519 h, const fe25519 f)
- {
- const uint64_t mask = 0x7ffffffffffffULL;
- uint128_t r0, r1, r2, r3, r4, carry;
- uint64_t f0, f1, f2, f3, f4;
- uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
- uint64_t r00, r01, r02, r03, r04;
- f0 = f[0];
- f1 = f[1];
- f2 = f[2];
- f3 = f[3];
- f4 = f[4];
- f0_2 = f0 << 1;
- f1_2 = f1 << 1;
- f1_38 = 38ULL * f1;
- f2_38 = 38ULL * f2;
- f3_38 = 38ULL * f3;
- f3_19 = 19ULL * f3;
- f4_19 = 19ULL * f4;
- r0 = ((uint128_t)f0) * ((uint128_t)f0);
- r0 += ((uint128_t)f1_38) * ((uint128_t)f4);
- r0 += ((uint128_t)f2_38) * ((uint128_t)f3);
- r1 = ((uint128_t)f0_2) * ((uint128_t)f1);
- r1 += ((uint128_t)f2_38) * ((uint128_t)f4);
- r1 += ((uint128_t)f3_19) * ((uint128_t)f3);
- r2 = ((uint128_t)f0_2) * ((uint128_t)f2);
- r2 += ((uint128_t)f1) * ((uint128_t)f1);
- r2 += ((uint128_t)f3_38) * ((uint128_t)f4);
- r3 = ((uint128_t)f0_2) * ((uint128_t)f3);
- r3 += ((uint128_t)f1_2) * ((uint128_t)f2);
- r3 += ((uint128_t)f4_19) * ((uint128_t)f4);
- r4 = ((uint128_t)f0_2) * ((uint128_t)f4);
- r4 += ((uint128_t)f1_2) * ((uint128_t)f3);
- r4 += ((uint128_t)f2) * ((uint128_t)f2);
- r00 = ((uint64_t)r0) & mask;
- carry = r0 >> 51;
- r1 += carry;
- r01 = ((uint64_t)r1) & mask;
- carry = r1 >> 51;
- r2 += carry;
- r02 = ((uint64_t)r2) & mask;
- carry = r2 >> 51;
- r3 += carry;
- r03 = ((uint64_t)r3) & mask;
- carry = r3 >> 51;
- r4 += carry;
- r04 = ((uint64_t)r4) & mask;
- carry = r4 >> 51;
- r00 += 19ULL * (uint64_t)carry;
- carry = r00 >> 51;
- r00 &= mask;
- r01 += (uint64_t)carry;
- carry = r01 >> 51;
- r01 &= mask;
- r02 += (uint64_t)carry;
- h[0] = r00;
- h[1] = r01;
- h[2] = r02;
- h[3] = r03;
- h[4] = r04;
- }
- */
- static void
- fe25519_invert(fe25519 out, const fe25519 z)
- {
- fe25519 t0;
- fe25519 t1;
- fe25519 t2;
- fe25519 t3;
- int i;
- fe25519_sq(t0, z);
- fe25519_sq(t1, t0);
- fe25519_sq(t1, t1);
- fe25519_mul(t1, z, t1);
- fe25519_mul(t0, t0, t1);
- fe25519_sq(t2, t0);
- fe25519_mul(t1, t1, t2);
- fe25519_sq(t2, t1);
- for (i = 1; i < 5; ++i) {
- fe25519_sq(t2, t2);
- }
- fe25519_mul(t1, t2, t1);
- fe25519_sq(t2, t1);
- for (i = 1; i < 10; ++i) {
- fe25519_sq(t2, t2);
- }
- fe25519_mul(t2, t2, t1);
- fe25519_sq(t3, t2);
- for (i = 1; i < 20; ++i) {
- fe25519_sq(t3, t3);
- }
- fe25519_mul(t2, t3, t2);
- for (i = 1; i < 11; ++i) {
- fe25519_sq(t2, t2);
- }
- fe25519_mul(t1, t2, t1);
- fe25519_sq(t2, t1);
- for (i = 1; i < 50; ++i) {
- fe25519_sq(t2, t2);
- }
- fe25519_mul(t2, t2, t1);
- fe25519_sq(t3, t2);
- for (i = 1; i < 100; ++i) {
- fe25519_sq(t3, t3);
- }
- fe25519_mul(t2, t3, t2);
- for (i = 1; i < 51; ++i) {
- fe25519_sq(t2, t2);
- }
- fe25519_mul(t1, t2, t1);
- for (i = 1; i < 6; ++i) {
- fe25519_sq(t1, t1);
- }
- fe25519_mul(out, t1, t0);
- }
- static void
- fe25519_reduce(fe25519 h, const fe25519 f)
- {
- const uint64_t mask = 0x7ffffffffffffULL;
- uint128_t t[5];
- t[0] = f[0];
- t[1] = f[1];
- t[2] = f[2];
- t[3] = f[3];
- t[4] = f[4];
- t[1] += t[0] >> 51;
- t[0] &= mask;
- t[2] += t[1] >> 51;
- t[1] &= mask;
- t[3] += t[2] >> 51;
- t[2] &= mask;
- t[4] += t[3] >> 51;
- t[3] &= mask;
- t[0] += 19 * (t[4] >> 51);
- t[4] &= mask;
- t[1] += t[0] >> 51;
- t[0] &= mask;
- t[2] += t[1] >> 51;
- t[1] &= mask;
- t[3] += t[2] >> 51;
- t[2] &= mask;
- t[4] += t[3] >> 51;
- t[3] &= mask;
- t[0] += 19 * (t[4] >> 51);
- t[4] &= mask;
- /* now t is between 0 and 2^255-1, properly carried. */
- /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
- t[0] += 19ULL;
- t[1] += t[0] >> 51;
- t[0] &= mask;
- t[2] += t[1] >> 51;
- t[1] &= mask;
- t[3] += t[2] >> 51;
- t[2] &= mask;
- t[4] += t[3] >> 51;
- t[3] &= mask;
- t[0] += 19ULL * (t[4] >> 51);
- t[4] &= mask;
- /* now between 19 and 2^255-1 in both cases, and offset by 19. */
- t[0] += 0x8000000000000 - 19ULL;
- t[1] += 0x8000000000000 - 1ULL;
- t[2] += 0x8000000000000 - 1ULL;
- t[3] += 0x8000000000000 - 1ULL;
- t[4] += 0x8000000000000 - 1ULL;
- /* now between 2^255 and 2^256-20, and offset by 2^255. */
- t[1] += t[0] >> 51;
- t[0] &= mask;
- t[2] += t[1] >> 51;
- t[1] &= mask;
- t[3] += t[2] >> 51;
- t[2] &= mask;
- t[4] += t[3] >> 51;
- t[3] &= mask;
- t[4] &= mask;
- h[0] = t[0];
- h[1] = t[1];
- h[2] = t[2];
- h[3] = t[3];
- h[4] = t[4];
- }
- /*
- h = 2 * f * f
- Can overlap h with f.
- */
- static void
- fe25519_sq2(fe25519 h, const fe25519 f)
- {
- const uint64_t mask = 0x7ffffffffffffULL;
- uint128_t r0, r1, r2, r3, r4, carry;
- uint64_t f0, f1, f2, f3, f4;
- uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
- uint64_t r00, r01, r02, r03, r04;
- f0 = f[0];
- f1 = f[1];
- f2 = f[2];
- f3 = f[3];
- f4 = f[4];
- f0_2 = f0 << 1;
- f1_2 = f1 << 1;
- f1_38 = 38ULL * f1;
- f2_38 = 38ULL * f2;
- f3_38 = 38ULL * f3;
- f3_19 = 19ULL * f3;
- f4_19 = 19ULL * f4;
- r0 = ((uint128_t)f0) * ((uint128_t)f0);
- r0 += ((uint128_t)f1_38) * ((uint128_t)f4);
- r0 += ((uint128_t)f2_38) * ((uint128_t)f3);
- r1 = ((uint128_t)f0_2) * ((uint128_t)f1);
- r1 += ((uint128_t)f2_38) * ((uint128_t)f4);
- r1 += ((uint128_t)f3_19) * ((uint128_t)f3);
- r2 = ((uint128_t)f0_2) * ((uint128_t)f2);
- r2 += ((uint128_t)f1) * ((uint128_t)f1);
- r2 += ((uint128_t)f3_38) * ((uint128_t)f4);
- r3 = ((uint128_t)f0_2) * ((uint128_t)f3);
- r3 += ((uint128_t)f1_2) * ((uint128_t)f2);
- r3 += ((uint128_t)f4_19) * ((uint128_t)f4);
- r4 = ((uint128_t)f0_2) * ((uint128_t)f4);
- r4 += ((uint128_t)f1_2) * ((uint128_t)f3);
- r4 += ((uint128_t)f2) * ((uint128_t)f2);
- r0 <<= 1;
- r1 <<= 1;
- r2 <<= 1;
- r3 <<= 1;
- r4 <<= 1;
- r00 = ((uint64_t)r0) & mask;
- carry = r0 >> 51;
- r1 += carry;
- r01 = ((uint64_t)r1) & mask;
- carry = r1 >> 51;
- r2 += carry;
- r02 = ((uint64_t)r2) & mask;
- carry = r2 >> 51;
- r3 += carry;
- r03 = ((uint64_t)r3) & mask;
- carry = r3 >> 51;
- r4 += carry;
- r04 = ((uint64_t)r4) & mask;
- carry = r4 >> 51;
- r00 += 19ULL * (uint64_t)carry;
- carry = r00 >> 51;
- r00 &= mask;
- r01 += (uint64_t)carry;
- carry = r01 >> 51;
- r01 &= mask;
- r02 += (uint64_t)carry;
- h[0] = r00;
- h[1] = r01;
- h[2] = r02;
- h[3] = r03;
- h[4] = r04;
- }
- /*
- h = f
- */
- static inline void
- fe25519_copy(fe25519 h, const fe25519 f)
- {
- uint64_t f0 = f[0];
- uint64_t f1 = f[1];
- uint64_t f2 = f[2];
- uint64_t f3 = f[3];
- uint64_t f4 = f[4];
- h[0] = f0;
- h[1] = f1;
- h[2] = f2;
- h[3] = f3;
- h[4] = f4;
- }
- static void
- fe25519_tobytes(unsigned char *s, const fe25519 h)
- {
- fe25519 t;
- uint64_t t0, t1, t2, t3;
- fe25519_reduce(t, h);
- t0 = t[0] | (t[1] << 51);
- t1 = (t[1] >> 13) | (t[2] << 38);
- t2 = (t[2] >> 26) | (t[3] << 25);
- t3 = (t[3] >> 39) | (t[4] << 12);
- memcpy(s + 0, &t0, sizeof t0);
- memcpy(s + 8, &t1, sizeof t1);
- memcpy(s + 16, &t2, sizeof t2);
- memcpy(s + 24, &t3, sizeof t3);
- }
- static void
- ge25519_p3_0(ge25519_p3 *h)
- {
- fe25519_0(h->X);
- fe25519_1(h->Y);
- fe25519_1(h->Z);
- fe25519_0(h->T);
- }
- /*
- Replace (t,u) with (u,u) if b == 1;
- replace (t,u) with (t,u) if b == 0.
- *
- Preconditions: b in {0,1}.
- */
- static void
- ge25519_cmov(ge25519_precomp *t, const ge25519_precomp *u, unsigned char b)
- {
- if (b)
- memcpy(t, u, sizeof *t);
- }
- static void
- ge25519_copy(ge25519_precomp *t, const ge25519_precomp *u)
- {
- memcpy(t, u, sizeof *t);
- }
- /*
- r = p
- */
- static void
- ge25519_p3_to_p2(ge25519_p2 *r, const ge25519_p3 *p)
- {
- fe25519_copy(r->X, p->X);
- fe25519_copy(r->Y, p->Y);
- fe25519_copy(r->Z, p->Z);
- }
- /*
- r = 2 * p
- */
- static void
- ge25519_p2_dbl(ge25519_p1p1 *r, const ge25519_p2 *p)
- {
- fe25519 t0;
- fe25519_sq(r->X, p->X);
- fe25519_sq(r->Z, p->Y);
- fe25519_sq2(r->T, p->Z);
- fe25519_add(r->Y, p->X, p->Y);
- fe25519_sq(t0, r->Y);
- fe25519_add(r->Y, r->Z, r->X);
- fe25519_sub(r->Z, r->Z, r->X);
- fe25519_sub(r->X, t0, r->Y);
- fe25519_sub(r->T, r->T, r->Z);
- }
- /*
- r = 2 * p
- */
- static void
- ge25519_p3_dbl(ge25519_p1p1 *r, const ge25519_p3 *p)
- {
- ge25519_p2 q;
- ge25519_p3_to_p2(&q, p);
- ge25519_p2_dbl(r, &q);
- }
- static void
- ge25519_precomp_0(ge25519_precomp *h)
- {
- fe25519_1(h->yplusx);
- fe25519_1(h->yminusx);
- fe25519_0(h->xy2d);
- }
- static void
- ge25519_cmov8_base(ge25519_precomp *t, const int pos, const signed char b)
- {
- static const ge25519_precomp base[32][8] = { /* base[i][j] = (j+1)*256^i*B */
- #include "fe_51_base.h"
- };
- ge25519_precomp_0(t);
- const unsigned char babs = b < 0 ? -b : b;
- if (babs == 0)
- return;
- ge25519_copy(t, &base[pos][babs - 1]);
- if (b < 0)
- {
- ge25519_precomp minust;
- fe25519_copy(minust.yplusx, t->yminusx);
- fe25519_copy(minust.yminusx, t->yplusx);
- fe25519_neg(minust.xy2d, t->xy2d);
- ge25519_copy(t, &minust);
- }
- }
- /*
- r = p + q
- */
- static void
- ge25519_madd(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_precomp *q)
- {
- fe25519 t0;
- fe25519_add(r->X, p->Y, p->X);
- fe25519_sub(r->Y, p->Y, p->X);
- fe25519_mul(r->Z, r->X, q->yplusx);
- fe25519_mul(r->Y, r->Y, q->yminusx);
- fe25519_mul(r->T, q->xy2d, p->T);
- fe25519_add(t0, p->Z, p->Z);
- fe25519_sub(r->X, r->Z, r->Y);
- fe25519_add(r->Y, r->Z, r->Y);
- fe25519_add(r->Z, t0, r->T);
- fe25519_sub(r->T, t0, r->T);
- }
- /*
- r = p
- */
- static void
- ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
- {
- fe25519_mul(r->X, p->X, p->T);
- fe25519_mul(r->Y, p->Y, p->Z);
- fe25519_mul(r->Z, p->Z, p->T);
- }
- /*
- r = p
- */
- static void
- ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
- {
- fe25519_mul(r->X, p->X, p->T);
- fe25519_mul(r->Y, p->Y, p->Z);
- fe25519_mul(r->Z, p->Z, p->T);
- fe25519_mul(r->T, p->X, p->Y);
- }
- /*
- h = a * B (with precomputation)
- where a = a[0]+256*a[1]+...+256^31 a[31]
- B is the Ed25519 base point (x,4/5) with x positive
- (as bytes: 0x5866666666666666666666666666666666666666666666666666666666666666)
- Preconditions:
- a[31] <= 127
- */
- static void
- ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a)
- {
- signed char e[64];
- signed char carry;
- ge25519_p1p1 r;
- ge25519_p2 s;
- ge25519_precomp t;
- int i;
- for (i = 0; i < 32; ++i) {
- e[2 * i + 0] = (a[i] >> 0) & 15;
- e[2 * i + 1] = (a[i] >> 4) & 15;
- }
- /* each e[i] is between 0 and 15 */
- /* e[63] is between 0 and 7 */
- carry = 0;
- for (i = 0; i < 63; ++i) {
- e[i] += carry;
- carry = e[i] + 8;
- carry >>= 4;
- e[i] -= carry * ((signed char)1 << 4);
- }
- e[63] += carry;
- /* each e[i] is between -8 and 8 */
- ge25519_p3_0(h);
- for (i = 1; i < 64; i += 2) {
- ge25519_cmov8_base(&t, i / 2, e[i]);
- ge25519_madd(&r, h, &t);
- ge25519_p1p1_to_p3(h, &r);
- }
- ge25519_p3_dbl(&r, h);
- ge25519_p1p1_to_p2(&s, &r);
- ge25519_p2_dbl(&r, &s);
- ge25519_p1p1_to_p2(&s, &r);
- ge25519_p2_dbl(&r, &s);
- ge25519_p1p1_to_p2(&s, &r);
- ge25519_p2_dbl(&r, &s);
- ge25519_p1p1_to_p3(h, &r);
- for (i = 0; i < 64; i += 2) {
- ge25519_cmov8_base(&t, i / 2, e[i]);
- ge25519_madd(&r, h, &t);
- ge25519_p1p1_to_p3(h, &r);
- }
- }
- static void
- edwards_to_montgomery(fe25519 montgomeryX, const fe25519 edwardsY, const fe25519 edwardsZ)
- {
- fe25519 tempX;
- fe25519 tempZ;
- fe25519_add(tempX, edwardsZ, edwardsY);
- fe25519_sub(tempZ, edwardsZ, edwardsY);
- fe25519_invert(tempZ, tempZ);
- fe25519_mul(montgomeryX, tempX, tempZ);
- }
- int
- crypto_scalarmult_curve25519_base_internal(
- unsigned char *q, const unsigned char *n)
- {
- unsigned char *t = q;
- ge25519_p3 A;
- fe25519 pk;
- unsigned int i;
- for (i = 0; i < 32; i++) {
- t[i] = n[i];
- }
- t[0] &= 248;
- t[31] &= 127;
- t[31] |= 64;
- ge25519_scalarmult_base(&A, t);
- edwards_to_montgomery(pk, A.Y, A.Z);
- fe25519_tobytes(q, pk);
- return 0;
- }
|