#include "ckconfig.h"
#if ENGINE_127_BITS
#error Hey! New curveParam-dependent 127-bit elliptic() needed!
#warning Using NSA-approved 127-bit security engine...
#include "NSGiantIntegers.h"
#define D 65536
#define DM 65535
#define SHORTCOUNT (8 * 2)
#define BORROW_SIZE 0
static void
ENGINEmul(giant a, giant b) {
int a0,a1,a2,a3,a4,a5,a6,a7,
b0,b1,b2,b3,b4,b5,b6,b7;
int asign, bsign;
int i, j, car;
unsigned int prod;
unsigned short mult;
gmersennemod(127, a);
gmersennemod(127, b);
asign = a->sign;
bsign = b->sign;
for(j = abs(asign); j < SHORTCOUNT; j++) a->n[j] = 0;
for(j = abs(bsign); j < SHORTCOUNT; j++) b->n[j] = 0;
a0 = a->n[0];
a1 = a->n[1];
a2 = a->n[2];
a3 = a->n[3];
a4 = a->n[4];
a5 = a->n[5];
a6 = a->n[6];
a7 = a->n[7];
b0 = b->n[0];
b1 = b->n[1];
b2 = b->n[2];
b3 = b->n[3];
b4 = b->n[4];
b5 = b->n[5];
b6 = b->n[6];
b7 = b->n[7];
for(j = 0; j < SHORTCOUNT; j++) b->n[j] = 0;
i = 0;
mult = b0;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 1;
mult = b1;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 2;
mult = b2;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 3;
mult = b3;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 4;
mult = b4;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 5;
mult = b5;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 6;
mult = b6;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
i = 7;
mult = b7;
car = 0;
prod = a0 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a1 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a2 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a3 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a4 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a5 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a6 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
prod = a7 * mult + b->n[i] + car;
b->n[i++] = prod & DM;
car = prod/D;
b->n[i] = car;
b->sign = abs(b->sign) + abs(a->sign);
for(j = (b->sign)-1; j >= 0; j--) {
if(b->n[j] != 0) {
break;
}
}
b->sign = j+1;
gmersennemod(127,b);
}
static void
ell_even(giant x1, giant z1, giant x2, giant z2, giant a, int q)
{
giant t1, t2, t3;
t1 = borrowGiant(BORROW_SIZE);
t2 = borrowGiant(BORROW_SIZE);
t3 = borrowGiant(BORROW_SIZE);
gtog(x1, t1); gsquare(t1); gmersennemod(q, t1);
gtog(z1, t2); gsquare(t2); gmersennemod(q, t2);
gtog(x1, t3); ENGINEmul(z1, t3);
gtog(t1, x2); subg(t2, x2); gsquare(x2); gmersennemod(q, x2);
gtog(a, z2);
ENGINEmul(t3, z2);
addg(t1, z2); addg(t2, z2); ENGINEmul(t3, z2);
gshiftleft(2, z2);
gmersennemod(q, z2);
returnGiant(t1);
returnGiant(t2);
returnGiant(t3);
}
static void
ell_odd(giant x1, giant z1, giant x2, giant z2, giant xor, giant zor, int q)
{
giant t1, t2, t3;
t1 = borrowGiant(BORROW_SIZE);
t2 = borrowGiant(BORROW_SIZE);
t3 = borrowGiant(BORROW_SIZE);
gtog(x1, t1); subg(z1, t1);
gtog(x2, t2); addg(z2, t2);
ENGINEmul(t1, t2);
gtog(x1, t1); addg(z1, t1);
gtog(x2, t3); subg(z2, t3);
ENGINEmul(t3, t1);
gtog(t2, x2); addg(t1, x2);
gsquare(x2); gmersennemod(q, x2); gtog(t2, z2); subg(t1, z2);
gsquare(z2); gmersennemod(q, z2); ENGINEmul(zor, x2);
ENGINEmul(xor, z2);
returnGiant(t1);
returnGiant(t2);
returnGiant(t3);
}
void
elliptic(giant xx, giant zz, giant k, giant a, int q)
{
int len = bitlen(k), pos = len-2;
giant xs;
giant zs;
giant xorg;
giant zorg;
if(scompg(1,k)) return;
if(scompg(2,k)) {
ell_even(xx, zz, xx, zz, a, q);
return;
}
zs = borrowGiant(BORROW_SIZE);
xs = borrowGiant(BORROW_SIZE);
zorg = borrowGiant(BORROW_SIZE);
xorg = borrowGiant(BORROW_SIZE);
gtog(xx, xorg); gtog(zz, zorg);
ell_even(xx, zz, xs, zs, a, q);
do{
if(bitval(k, pos--)) {
ell_odd(xs, zs, xx, zz, xorg, zorg, q);
ell_even(xs, zs, xs, zs, a, q);
} else {
ell_odd(xx, zz, xs, zs, xorg, zorg, q);
ell_even(xx, zz, xx, zz, a, q);
}
} while(pos >=0);
returnGiant(xs);
returnGiant(zs);
returnGiant(xorg);
returnGiant(zorg);
}
#endif