2 #include "crypto_uint32.h"
6 # pragma GCC diagnostic ignored "-Wlong-long"
10 static unsigned char equal(signed char b,signed char c)
14 unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
15 crypto_uint32 y = x; /* 0: yes; 1..255: no */
16 y -= 1; /* 4294967295: yes; 0..254: no */
17 y >>= 31; /* 1: yes; 0: no */
21 static unsigned char negative(signed char b)
23 unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
24 x >>= 63; /* 1: yes; 0: no */
28 static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b)
30 fe_cmov(t->yplusx,u->yplusx,b);
31 fe_cmov(t->yminusx,u->yminusx,b);
32 fe_cmov(t->xy2d,u->xy2d,b);
35 /* base[i][j] = (j+1)*256^i*B */
36 static ge_precomp base[32][8] = {
40 static void ge_select(ge_precomp *t,int pos,signed char b)
43 unsigned char bnegative = negative(b);
44 unsigned char babs = b - (((-bnegative) & b) << 1);
47 cmov(t,&base[pos][0],equal(babs,1));
48 cmov(t,&base[pos][1],equal(babs,2));
49 cmov(t,&base[pos][2],equal(babs,3));
50 cmov(t,&base[pos][3],equal(babs,4));
51 cmov(t,&base[pos][4],equal(babs,5));
52 cmov(t,&base[pos][5],equal(babs,6));
53 cmov(t,&base[pos][6],equal(babs,7));
54 cmov(t,&base[pos][7],equal(babs,8));
55 fe_copy(minust.yplusx,t->yminusx);
56 fe_copy(minust.yminusx,t->yplusx);
57 fe_neg(minust.xy2d,t->xy2d);
58 cmov(t,&minust,bnegative);
63 where a = a[0]+256*a[1]+...+256^31 a[31]
64 B is the Ed25519 base point (x,4/5) with x positive.
70 void ge_scalarmult_base(ge_p3 *h,const unsigned char *a)
79 for (i = 0;i < 32;++i) {
80 e[2 * i + 0] = (a[i] >> 0) & 15;
81 e[2 * i + 1] = (a[i] >> 4) & 15;
83 /* each e[i] is between 0 and 15 */
84 /* e[63] is between 0 and 7 */
87 for (i = 0;i < 63;++i) {
94 /* each e[i] is between -8 and 8 */
97 for (i = 1;i < 64;i += 2) {
98 ge_select(&t,i / 2,e[i]);
99 ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
102 ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r);
103 ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
104 ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
105 ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
107 for (i = 0;i < 64;i += 2) {
108 ge_select(&t,i / 2,e[i]);
109 ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);