1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#include "crypto_uint32.h"
#include "ge.h"
#include "crypto_additions.h"
static unsigned char equal(signed char b,signed char c)
{
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
crypto_uint32 y = x; /* 0: yes; 1..255: no */
y -= 1; /* 4294967295: yes; 0..254: no */
y >>= 31; /* 1: yes; 0: no */
return y;
}
static unsigned char negative(signed char b)
{
unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return x;
}
static void cmov(ge_cached *t,const ge_cached *u,unsigned char b)
{
fe_cmov(t->YplusX,u->YplusX,b);
fe_cmov(t->YminusX,u->YminusX,b);
fe_cmov(t->Z,u->Z,b);
fe_cmov(t->T2d,u->T2d,b);
}
static void select(ge_cached *t,const ge_cached *pre, signed char b)
{
ge_cached minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
fe_1(t->YplusX);
fe_1(t->YminusX);
fe_1(t->Z);
fe_0(t->T2d);
cmov(t,pre+0,equal(babs,1));
cmov(t,pre+1,equal(babs,2));
cmov(t,pre+2,equal(babs,3));
cmov(t,pre+3,equal(babs,4));
cmov(t,pre+4,equal(babs,5));
cmov(t,pre+5,equal(babs,6));
cmov(t,pre+6,equal(babs,7));
cmov(t,pre+7,equal(babs,8));
fe_copy(minust.YplusX,t->YminusX);
fe_copy(minust.YminusX,t->YplusX);
fe_copy(minust.Z,t->Z);
fe_neg(minust.T2d,t->T2d);
cmov(t,&minust,bnegative);
}
/*
h = a * B
where a = a[0]+256*a[1]+...+256^31 a[31]
B is the Ed25519 base point (x,4/5) with x positive.
Preconditions:
a[31] <= 127
*/
void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A)
{
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_p3 t0, t1, t2;
ge_cached t, pre[8];
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 << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
// Precomputation:
ge_p3_to_cached(pre+0, A); // A
ge_p3_dbl(&r, A);
ge_p1p1_to_p3(&t0, &r);
ge_p3_to_cached(pre+1, &t0); // 2A
ge_add(&r, A, pre+1);
ge_p1p1_to_p3(&t1, &r);
ge_p3_to_cached(pre+2, &t1); // 3A
ge_p3_dbl(&r, &t0);
ge_p1p1_to_p3(&t0, &r);
ge_p3_to_cached(pre+3, &t0); // 4A
ge_add(&r, A, pre+3);
ge_p1p1_to_p3(&t2, &r);
ge_p3_to_cached(pre+4, &t2); // 5A
ge_p3_dbl(&r, &t1);
ge_p1p1_to_p3(&t1, &r);
ge_p3_to_cached(pre+5, &t1); // 6A
ge_add(&r, A, pre+5);
ge_p1p1_to_p3(&t1, &r);
ge_p3_to_cached(pre+6, &t1); // 7A
ge_p3_dbl(&r, &t0);
ge_p1p1_to_p3(&t0, &r);
ge_p3_to_cached(pre+7, &t0); // 8A
ge_p3_0(h);
for (i = 63;i > 0; i--) {
select(&t,pre,e[i]);
ge_add(&r, h, &t);
ge_p1p1_to_p2(&s,&r);
ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
}
select(&t,pre,e[0]);
ge_add(&r, h, &t);
ge_p1p1_to_p3(h,&r);
}
|