MastersThesis/TIIGER_TLS/PQ_TIIGER_TLS/sal/miracl-ubuntu22-11-04-24/includes/ecp.cpp
2024-04-15 11:53:30 +02:00

1799 lines
46 KiB
C++

/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* CORE Elliptic Curve Functions */
/* SU=m, SU is Stack Usage (Weierstrass Curves) */
//#define HAS_MAIN
#include "ecp_ZZZ.h"
using namespace XXX;
using namespace YYY;
/* test for P=O point-at-infinity */
int ZZZ::ECP_isinf(ECP *P)
{
#if CURVETYPE_ZZZ==EDWARDS
return (FP_iszilch(&(P->x)) && FP_equals(&(P->y), &(P->z)));
#endif
#if CURVETYPE_ZZZ==WEIERSTRASS
return (FP_iszilch(&(P->x)) && FP_iszilch(&(P->z)));
#endif
#if CURVETYPE_ZZZ==MONTGOMERY
return FP_iszilch(&(P->z));
#endif
}
/* Conditional swap of P and Q dependant on d */
static void ECP_cswap(ZZZ::ECP *P, ZZZ::ECP *Q, int d)
{
FP_cswap(&(P->x), &(Q->x), d);
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_cswap(&(P->y), &(Q->y), d);
#endif
FP_cswap(&(P->z), &(Q->z), d);
}
#if CURVETYPE_ZZZ!=MONTGOMERY
/* Conditional move Q to P dependant on d */
static void ECP_cmove(ZZZ::ECP *P, ZZZ::ECP *Q, int d)
{
FP_cmove(&(P->x), &(Q->x), d);
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_cmove(&(P->y), &(Q->y), d);
#endif
FP_cmove(&(P->z), &(Q->z), d);
}
/* return 1 if b==c, no branching */
static int teq(sign32 b, sign32 c)
{
sign32 x = b ^ c;
x -= 1; // if x=0, x now -1
return (int)((x >> 31) & 1);
}
#endif // CURVETYPE_ZZZ!=MONTGOMERY
#if CURVETYPE_ZZZ!=MONTGOMERY
/* Constant time select from pre-computed table */
static void ECP_select(ZZZ::ECP *P, ZZZ::ECP W[], sign32 b)
{
ZZZ::ECP MP;
sign32 m = b >> 31;
sign32 babs = (b ^ m) - m;
babs = (babs - 1) / 2;
ECP_cmove(P, &W[0], teq(babs, 0)); // conditional move
ECP_cmove(P, &W[1], teq(babs, 1));
ECP_cmove(P, &W[2], teq(babs, 2));
ECP_cmove(P, &W[3], teq(babs, 3));
ECP_cmove(P, &W[4], teq(babs, 4));
ECP_cmove(P, &W[5], teq(babs, 5));
ECP_cmove(P, &W[6], teq(babs, 6));
ECP_cmove(P, &W[7], teq(babs, 7));
ECP_copy(&MP, P);
ECP_neg(&MP); // minus P
ECP_cmove(P, &MP, (int)(m & 1));
}
#endif
/* Test P == Q */
/* SU=168 */
int ZZZ::ECP_equals(ECP *P, ECP *Q)
{
FP a, b;
FP_mul(&a, &(P->x), &(Q->z));
FP_mul(&b, &(Q->x), &(P->z));
if (!FP_equals(&a, &b)) return 0;
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_mul(&a, &(P->y), &(Q->z));
FP_mul(&b, &(Q->y), &(P->z));
if (!FP_equals(&a, &b)) return 0;
#endif
return 1;
}
/* Set P=Q */
/* SU=16 */
void ZZZ::ECP_copy(ECP *P, ECP *Q)
{
FP_copy(&(P->x), &(Q->x));
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_copy(&(P->y), &(Q->y));
#endif
FP_copy(&(P->z), &(Q->z));
}
/* Set P=-Q */
#if CURVETYPE_ZZZ!=MONTGOMERY
/* SU=8 */
void ZZZ::ECP_neg(ECP *P)
{
#if CURVETYPE_ZZZ==WEIERSTRASS
FP_neg(&(P->y), &(P->y));
FP_norm(&(P->y));
#else
FP_neg(&(P->x), &(P->x));
FP_norm(&(P->x));
#endif
}
#endif
/* Set P=O */
void ZZZ::ECP_inf(ECP *P)
{
FP_zero(&(P->x));
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_one(&(P->y));
#endif
#if CURVETYPE_ZZZ!=EDWARDS
FP_zero(&(P->z));
#else
FP_one(&(P->z));
#endif
}
/* Calculate right Hand Side of curve equation y^2=RHS */
/* SU=56 */
void ZZZ::ECP_rhs(FP *v, FP *x)
{
#if CURVETYPE_ZZZ==WEIERSTRASS
/* x^3+Ax+B */
FP t;
FP_sqr(&t, x);
FP_mul(&t, &t, x);
#if CURVE_A_ZZZ == -3
FP_neg(v, x);
FP_norm(v);
FP_imul(v, v, -CURVE_A_ZZZ);
FP_norm(v);
FP_add(v, &t, v);
#else
FP_copy(v, &t);
#endif
FP_rcopy(&t, CURVE_B);
FP_add(v, &t, v);
FP_reduce(v);
#endif
#if CURVETYPE_ZZZ==EDWARDS
/* (Ax^2-1)/(Bx^2-1) */
FP t, one;
FP_sqr(v, x);
FP_one(&one);
FP_rcopy(&t, CURVE_B);
FP_mul(&t, v, &t);
FP_sub(&t, &t, &one);
FP_norm(&t);
#if CURVE_A_ZZZ == 1
FP_sub(v, v, &one);
#endif
#if CURVE_A_ZZZ == -1
FP_add(v, v, &one);
FP_norm(v);
FP_neg(v, v);
#endif
FP_norm(v);
FP_inv(&t, &t, NULL);
FP_mul(v, v, &t);
FP_reduce(v);
#endif
#if CURVETYPE_ZZZ==MONTGOMERY
/* x^3+Ax^2+x */
FP x2, x3;
FP_sqr(&x2, x);
FP_mul(&x3, &x2, x);
FP_copy(v, x);
FP_imul(&x2, &x2, CURVE_A_ZZZ);
FP_add(v, v, &x2);
FP_add(v, v, &x3);
FP_reduce(v);
#endif
}
/* Set P=(x,y) */
#if CURVETYPE_ZZZ==MONTGOMERY
/* Set P=(x,{y}) */
int ZZZ::ECP_set(ECP *P, BIG x)
{
FP rhs;
FP_nres(&rhs, x);
ECP_rhs(&rhs, &rhs);
if (!FP_qr(&rhs,NULL))
{
ECP_inf(P);
return 0;
}
FP_nres(&(P->x), x);
FP_one(&(P->z));
return 1;
}
/* Extract x coordinate as BIG */
int ZZZ::ECP_get(BIG x, ECP *P)
{
ECP W;
ECP_copy(&W, P);
ECP_affine(&W);
if (ECP_isinf(&W)) return -1;
FP_redc(x, &(W.x));
return 0;
}
#else
/* Extract (x,y) and return sign of y. If x and y are the same return only x */
/* SU=16 */
int ZZZ::ECP_get(BIG x, BIG y, ECP *P)
{
ECP W;
ECP_copy(&W, P);
ECP_affine(&W);
if (ECP_isinf(&W)) return -1;
FP_redc(y, &(W.y));
FP_redc(x, &(W.x));
return FP_sign(&(W.y));
}
/* Set P=(x,{y}) */
/* SU=96 */
int ZZZ::ECP_set(ECP *P, BIG x, BIG y)
{
FP rhs, y2;
FP_nres(&y2, y);
FP_sqr(&y2, &y2);
FP_reduce(&y2);
FP_nres(&rhs, x);
ECP_rhs(&rhs, &rhs);
if (!FP_equals(&y2, &rhs))
{
ECP_inf(P);
return 0;
}
FP_nres(&(P->x), x);
FP_nres(&(P->y), y);
FP_one(&(P->z));
return 1;
}
/* Set P=(x,y), where y is calculated from x with sign s */
/* SU=136 */
int ZZZ::ECP_setx(ECP *P, BIG x, int s)
{
FP rhs,hint;
FP_nres(&rhs, x);
ECP_rhs(&rhs, &rhs);
if (!FP_qr(&rhs,&hint))
{
ECP_inf(P);
return 0;
}
FP_nres(&(P->x), x);
FP_sqrt(&(P->y), &rhs, &hint);
if (FP_sign(&(P->y))!=s)
FP_neg(&(P->y), &(P->y));
FP_reduce(&(P->y));
FP_one(&(P->z));
return 1;
}
#endif
/* Convert P to Affine, from (x,y,z) to (x,y) */
/* SU=160 */
void ZZZ::ECP_affine(ECP *P)
{
FP one, iz;
if (ECP_isinf(P)) return;
FP_one(&one);
if (FP_equals(&(P->z), &one)) return;
FP_inv(&iz, &(P->z), NULL);
FP_mul(&(P->x), &(P->x), &iz);
#if CURVETYPE_ZZZ==EDWARDS || CURVETYPE_ZZZ==WEIERSTRASS
FP_mul(&(P->y), &(P->y), &iz);
FP_reduce(&(P->y));
#endif
FP_reduce(&(P->x));
FP_copy(&(P->z), &one);
}
/* SU=120 */
void ZZZ::ECP_outputxyz(ECP *P)
{
BIG x, z;
if (ECP_isinf(P))
{
printf("Infinity\n");
return;
}
FP_reduce(&(P->x));
FP_redc(x, &(P->x));
FP_reduce(&(P->z));
FP_redc(z, &(P->z));
#if CURVETYPE_ZZZ!=MONTGOMERY
BIG y;
FP_reduce(&(P->y));
FP_redc(y, &(P->y));
printf("(");
BIG_output(x);
printf(",");
BIG_output(y);
printf(",");
BIG_output(z);
printf(")\n");
#else
printf("(");
BIG_output(x);
printf(",");
BIG_output(z);
printf(")\n");
#endif
}
/* SU=16 */
/* Output point P */
void ZZZ::ECP_output(ECP *P)
{
BIG x, y;
if (ECP_isinf(P))
{
printf("Infinity\n");
return;
}
ECP_affine(P);
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_reduce(&(P->x));
FP_reduce(&(P->y));
FP_redc(x, &(P->x));
FP_redc(y, &(P->y));
printf("(");
BIG_output(x);
printf(",");
BIG_output(y);
printf(")\n");
#else
FP_reduce(&(P->x));
FP_redc(x, &(P->x));
printf("(");
BIG_output(x);
printf(")\n");
#endif
}
/* SU=16 */
/* Output point P */
void ZZZ::ECP_rawoutput(ECP *P)
{
BIG x, y, z;
#if CURVETYPE_ZZZ!=MONTGOMERY
FP_redc(x, &(P->x));
FP_redc(y, &(P->y));
FP_redc(z, &(P->z));
printf("(");
BIG_output(x);
printf(",");
BIG_output(y);
printf(",");
BIG_output(z);
printf(")\n");
#else
FP_redc(x, &(P->x));
FP_redc(z, &(P->z));
printf("(");
BIG_output(x);
printf(",");
BIG_output(z);
printf(")\n");
#endif
}
/* SU=88 */
/* Convert P to octet string, compressing if desired */
void ZZZ::ECP_toOctet(octet *W, ECP *P, bool compress)
{
#if CURVETYPE_ZZZ==MONTGOMERY
BIG x;
ECP_get(x, P);
W->len = MODBYTES_XXX; // + 1;
BIG_toBytes(&(W->val[0]), x);
#else
BIG x, y;
bool alt=false;
ECP_affine(P);
ECP_get(x, y, P);
#if (MBITS-1)%8 <= 4
#ifdef ALLOW_ALT_COMPRESS_ZZZ
alt=true;
#endif
#endif
if (alt)
{
BIG_toBytes(&(W->val[0]), x);
if (compress)
{
W->len = MODBYTES_XXX;
W->val[0]|=0x80;
if (FP_islarger(&(P->y))==1) W->val[0]|=0x20;
} else {
W->len = 2 * MODBYTES_XXX;
BIG_toBytes(&(W->val[MODBYTES_XXX]), y);
}
} else {
BIG_toBytes(&(W->val[1]), x);
if (compress)
{
W->val[0] = 0x02;
if (FP_sign(&(P->y)) == 1) W->val[0] = 0x03;
W->len = MODBYTES_XXX + 1;
} else {
W->val[0] = 0x04;
W->len = 2 * MODBYTES_XXX + 1;
BIG_toBytes(&(W->val[MODBYTES_XXX + 1]), y);
}
}
#endif
}
/* SU=88 */
/* Restore P from octet string */
int ZZZ::ECP_fromOctet(ECP *P, octet *W)
{
#if CURVETYPE_ZZZ==MONTGOMERY
BIG x;
BIG_fromBytes(x, &(W->val[0]));
if (ECP_set(P, x)) return 1;
return 0;
#else
BIG x, y;
bool alt=false;
int sgn,cmp,typ = W->val[0];
#if (MBITS-1)%8 <= 4
#ifdef ALLOW_ALT_COMPRESS_ZZZ
alt=true;
#endif
#endif
if (alt)
{
W->val[0]&=0x1f;
BIG_fromBytes(x, &(W->val[0]));
W->val[0]=typ;
if ((typ&0x80)==0)
{
BIG_fromBytes(y, &(W->val[MODBYTES_XXX]));
if (ECP_set(P, x, y)) return 1;
return 0;
} else {
if (!ECP_setx(P,x,0)) return 0;
sgn=(typ&0x20)>>5;
cmp=FP_islarger(&(P->y));
if ((sgn==1 && cmp!=1) || (sgn==0 && cmp==1)) ECP_neg(P);
return 1;
}
} else {
BIG_fromBytes(x, &(W->val[1]));
if (typ == 0x04)
{
BIG_fromBytes(y, &(W->val[MODBYTES_XXX + 1]));
if (ECP_set(P, x, y)) return 1;
}
if (typ == 0x02 || typ == 0x03)
{
if (ECP_setx(P, x, typ & 1)) return 1;
}
}
return 0;
#endif
}
/* Set P=2P */
/* SU=272 */
void ZZZ::ECP_dbl(ECP *P)
{
#if CURVETYPE_ZZZ==WEIERSTRASS
FP t0, t1, t2, t3, x3, y3, z3, b;
#if CURVE_A_ZZZ == 0
FP_sqr(&t0, &(P->y)); //t0.sqr();
FP_mul(&t1, &(P->y), &(P->z)); //t1.mul(z);
FP_sqr(&t2, &(P->z)); //t2.sqr();
FP_add(&(P->z), &t0, &t0); //z.add(t0);
FP_norm(&(P->z)); //z.norm();
FP_add(&(P->z), &(P->z), &(P->z)); //z.add(z);
FP_add(&(P->z), &(P->z), &(P->z)); //z.add(z);
FP_norm(&(P->z)); //z.norm();
FP_imul(&t2, &t2, 3 * CURVE_B_I); //t2.imul(3*ROM.CURVE_B_I);
FP_mul(&x3, &t2, &(P->z)); //x3.mul(z);
FP_add(&y3, &t0, &t2); //y3.add(t2);
FP_norm(&y3); //y3.norm();
FP_mul(&(P->z), &(P->z), &t1); //z.mul(t1);
FP_add(&t1, &t2, &t2); //t1.add(t2);
FP_add(&t2, &t2, &t1); //t2.add(t1);
FP_sub(&t0, &t0, &t2); //t0.sub(t2);
FP_norm(&t0); //t0.norm();
FP_mul(&y3, &y3, &t0); //y3.mul(t0);
FP_add(&y3, &y3, &x3); //y3.add(x3);
FP_mul(&t1, &(P->x), &(P->y)); //t1.mul(y);
FP_norm(&t0); //x.norm();
FP_mul(&(P->x), &t0, &t1); //x.mul(t1);
FP_add(&(P->x), &(P->x), &(P->x)); //x.add(x);
FP_norm(&(P->x)); //x.norm();
FP_copy(&(P->y), &y3); //y.copy(y3);
FP_norm(&(P->y)); //y.norm();
#else
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_rcopy(&b, CURVE_B); //b.copy(new FP(new BIG(ROM.CURVE_B)));
FP_sqr(&t0, &(P->x)); //t0.sqr(); //1 x^2
FP_sqr(&t1, &(P->y)); //t1.sqr(); //2 y^2
FP_sqr(&t2, &(P->z)); //t2.sqr(); //3
FP_mul(&t3, &(P->x), &(P->y)); //t3.mul(y); //4
FP_add(&t3, &t3, &t3); //t3.add(t3);
FP_norm(&t3); //t3.norm();//5
FP_mul(&z3, &(P->z), &(P->x)); //z3.mul(x); //6
FP_add(&z3, &z3, &z3); //z3.add(z3);
FP_norm(&z3); //z3.norm();//7
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_mul(&y3, &t2, &b); //y3.mul(b); //8
else
FP_imul(&y3, &t2, CURVE_B_I); //y3.imul(ROM.CURVE_B_I);
FP_sub(&y3, &y3, &z3); //y3.sub(z3); //y3.norm(); //9 ***
FP_add(&x3, &y3, &y3); //x3.add(y3);
FP_norm(&x3); //x3.norm();//10
FP_add(&y3, &y3, &x3); //y3.add(x3); //y3.norm();//11
FP_sub(&x3, &t1, &y3); //x3.sub(y3);
FP_norm(&x3); //x3.norm();//12
FP_add(&y3, &y3, &t1); //y3.add(t1);
FP_norm(&y3); //y3.norm();//13
FP_mul(&y3, &y3, &x3); //y3.mul(x3); //14
FP_mul(&x3, &x3, &t3); //x3.mul(t3); //15
FP_add(&t3, &t2, &t2); //t3.add(t2); //16
FP_add(&t2, &t2, &t3); //t2.add(t3); //17
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_mul(&z3, &z3, &b); //z3.mul(b); //18
else
FP_imul(&z3, &z3, CURVE_B_I); //z3.imul(ROM.CURVE_B_I);
FP_sub(&z3, &z3, &t2); //z3.sub(t2); //z3.norm();//19
FP_sub(&z3, &z3, &t0); //z3.sub(t0);
FP_norm(&z3); //z3.norm();//20 ***
FP_add(&t3, &z3, &z3); //t3.add(z3); //t3.norm();//21
FP_add(&z3, &z3, &t3); //z3.add(t3);
FP_norm(&z3); //z3.norm(); //22
FP_add(&t3, &t0, &t0); //t3.add(t0); //t3.norm(); //23
FP_add(&t0, &t0, &t3); //t0.add(t3); //t0.norm();//24
FP_sub(&t0, &t0, &t2); //t0.sub(t2);
FP_norm(&t0); //t0.norm();//25
FP_mul(&t0, &t0, &z3); //t0.mul(z3);//26
FP_add(&y3, &y3, &t0); //y3.add(t0); //y3.norm();//27
FP_mul(&t0, &(P->y), &(P->z)); //t0.mul(z);//28
FP_add(&t0, &t0, &t0); //t0.add(t0);
FP_norm(&t0); //t0.norm(); //29
FP_mul(&z3, &z3, &t0); //z3.mul(t0);//30
FP_sub(&(P->x), &x3, &z3); //x3.sub(z3); //x3.norm();//31
FP_add(&t0, &t0, &t0); //t0.add(t0);
FP_norm(&t0); //t0.norm();//32
FP_add(&t1, &t1, &t1); //t1.add(t1);
FP_norm(&t1); //t1.norm();//33
FP_mul(&(P->z), &t0, &t1); //z3.mul(t1);//34
FP_norm(&(P->x)); //x.norm();
FP_copy(&(P->y), &y3); //y.copy(y3);
FP_norm(&(P->y)); //y.norm();
FP_norm(&(P->z)); //z.norm();
#endif
#endif
#if CURVETYPE_ZZZ==EDWARDS
/* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
FP C, D, H, J;
FP_sqr(&C, &(P->x)); //C.sqr();
FP_mul(&(P->x), &(P->x), &(P->y)); //x.mul(y);
FP_add(&(P->x), &(P->x), &(P->x)); //x.add(x);
FP_norm(&(P->x)); //x.norm();
FP_sqr(&D, &(P->y)); //D.sqr();
#if CURVE_A_ZZZ == -1
FP_neg(&C, &C); // C.neg();
#endif
FP_add(&(P->y), &C, &D); //y.add(D);
FP_norm(&(P->y)); //y.norm();
FP_sqr(&H, &(P->z)); //H.sqr();
FP_add(&H, &H, &H); //H.add(H);
FP_sub(&J, &(P->y), &H); //J.sub(H);
FP_norm(&J); //J.norm();
FP_mul(&(P->x), &(P->x), &J); //x.mul(J);
FP_sub(&C, &C, &D); //C.sub(D);
FP_norm(&C); //C.norm();
FP_mul(&(P->z), &(P->y), &J); //z.mul(J);
FP_mul(&(P->y), &(P->y), &C); //y.mul(C);
#endif
#if CURVETYPE_ZZZ==MONTGOMERY
FP A, B, AA, BB, C;
FP_add(&A, &(P->x), &(P->z)); //A.add(z);
FP_norm(&A); //A.norm();
FP_sqr(&AA, &A); //AA.sqr();
FP_sub(&B, &(P->x), &(P->z)); //B.sub(z);
FP_norm(&B); //B.norm();
FP_sqr(&BB, &B); //BB.sqr();
FP_sub(&C, &AA, &BB); //C.sub(BB);
FP_norm(&C); //C.norm();
FP_mul(&(P->x), &AA, &BB); //x.mul(BB);
FP_imul(&A, &C, (CURVE_A_ZZZ + 2) / 4); //A.imul((ROM.CURVE_A+2)/4);
FP_add(&BB, &BB, &A); //BB.add(A);
FP_norm(&BB); //BB.norm();
FP_mul(&(P->z), &BB, &C); //z.mul(C);
#endif
}
#if CURVETYPE_ZZZ==MONTGOMERY
/* Set P+=Q. W is difference between P and Q and is affine */
void ZZZ::ECP_add(ECP *P, ECP *Q, ECP *W)
{
FP A, B, C, D, DA, CB;
FP_add(&A, &(P->x), &(P->z)); //A.add(z);
FP_sub(&B, &(P->x), &(P->z)); //B.sub(z);
FP_add(&C, &(Q->x), &(Q->z)); //C.add(Q.z);
FP_sub(&D, &(Q->x), &(Q->z)); //D.sub(Q.z);
FP_norm(&A); //A.norm();
FP_norm(&D); //D.norm();
FP_mul(&DA, &D, &A); //DA.mul(A);
FP_norm(&C); //C.norm();
FP_norm(&B); //B.norm();
FP_mul(&CB, &C, &B); //CB.mul(B);
FP_add(&A, &DA, &CB); //A.add(CB);
FP_norm(&A); //A.norm();
FP_sqr(&(P->x), &A); //A.sqr();
FP_sub(&B, &DA, &CB); //B.sub(CB);
FP_norm(&B); //B.norm();
FP_sqr(&B, &B); //B.sqr();
FP_mul(&(P->z), &(W->x), &B); //z.mul(B);
}
#else
/* Set P+=Q */
/* SU=248 */
void ZZZ::ECP_add(ECP *P, ECP *Q)
{
#if CURVETYPE_ZZZ==WEIERSTRASS
int b3;
FP t0, t1, t2, t3, t4, x3, y3, z3, b;
#if CURVE_A_ZZZ == 0
b3 = 3 * CURVE_B_I; //int b=3*ROM.CURVE_B_I;
FP_mul(&t0, &(P->x), &(Q->x)); //t0.mul(Q.x);
FP_mul(&t1, &(P->y), &(Q->y)); //t1.mul(Q.y);
FP_mul(&t2, &(P->z), &(Q->z)); //t2.mul(Q.z);
FP_add(&t3, &(P->x), &(P->y)); //t3.add(y);
FP_norm(&t3); //t3.norm();
FP_add(&t4, &(Q->x), &(Q->y)); //t4.add(Q.y);
FP_norm(&t4); //t4.norm();
FP_mul(&t3, &t3, &t4); //t3.mul(t4);
FP_add(&t4, &t0, &t1); //t4.add(t1);
FP_sub(&t3, &t3, &t4); //t3.sub(t4);
FP_norm(&t3); //t3.norm();
FP_add(&t4, &(P->y), &(P->z)); //t4.add(z);
FP_norm(&t4); //t4.norm();
FP_add(&x3, &(Q->y), &(Q->z)); //x3.add(Q.z);
FP_norm(&x3); //x3.norm();
FP_mul(&t4, &t4, &x3); //t4.mul(x3);
FP_add(&x3, &t1, &t2); //x3.add(t2);
FP_sub(&t4, &t4, &x3); //t4.sub(x3);
FP_norm(&t4); //t4.norm();
FP_add(&x3, &(P->x), &(P->z)); //x3.add(z);
FP_norm(&x3); //x3.norm();
FP_add(&y3, &(Q->x), &(Q->z)); //y3.add(Q.z);
FP_norm(&y3); //y3.norm();
FP_mul(&x3, &x3, &y3); //x3.mul(y3);
FP_add(&y3, &t0, &t2); //y3.add(t2);
FP_sub(&y3, &x3, &y3); //y3.rsub(x3);
FP_norm(&y3); //y3.norm();
FP_add(&x3, &t0, &t0); //x3.add(t0);
FP_add(&t0, &t0, &x3); //t0.add(x3);
FP_norm(&t0); //t0.norm();
FP_imul(&t2, &t2, b3); //t2.imul(b);
FP_add(&z3, &t1, &t2); //z3.add(t2);
FP_norm(&z3); //z3.norm();
FP_sub(&t1, &t1, &t2); //t1.sub(t2);
FP_norm(&t1); //t1.norm();
FP_imul(&y3, &y3, b3); //y3.imul(b);
FP_mul(&x3, &y3, &t4); //x3.mul(t4);
FP_mul(&t2, &t3, &t1); //t2.mul(t1);
FP_sub(&(P->x), &t2, &x3); //x3.rsub(t2);
FP_mul(&y3, &y3, &t0); //y3.mul(t0);
FP_mul(&t1, &t1, &z3); //t1.mul(z3);
FP_add(&(P->y), &y3, &t1); //y3.add(t1);
FP_mul(&t0, &t0, &t3); //t0.mul(t3);
FP_mul(&z3, &z3, &t4); //z3.mul(t4);
FP_add(&(P->z), &z3, &t0); //z3.add(t0);
FP_norm(&(P->x)); //x.norm();
FP_norm(&(P->y)); //y.norm();
FP_norm(&(P->z)); //z.norm();
#else
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_rcopy(&b, CURVE_B); //b.copy(new FP(new BIG(ROM.CURVE_B)));
FP_mul(&t0, &(P->x), &(Q->x)); //t0.mul(Q.x); //1
FP_mul(&t1, &(P->y), &(Q->y)); //t1.mul(Q.y); //2
FP_mul(&t2, &(P->z), &(Q->z)); //t2.mul(Q.z); //3
FP_add(&t3, &(P->x), &(P->y)); //t3.add(y);
FP_norm(&t3); //t3.norm(); //4
FP_add(&t4, &(Q->x), &(Q->y)); //t4.add(Q.y);
FP_norm(&t4); //t4.norm();//5
FP_mul(&t3, &t3, &t4); //t3.mul(t4);//6
FP_add(&t4, &t0, &t1); //t4.add(t1); //t4.norm(); //7
FP_sub(&t3, &t3, &t4); //t3.sub(t4);
FP_norm(&t3); //t3.norm(); //8
FP_add(&t4, &(P->y), &(P->z)); //t4.add(z);
FP_norm(&t4); //t4.norm();//9
FP_add(&x3, &(Q->y), &(Q->z)); //x3.add(Q.z);
FP_norm(&x3); //x3.norm();//10
FP_mul(&t4, &t4, &x3); //t4.mul(x3); //11
FP_add(&x3, &t1, &t2); //x3.add(t2); //x3.norm();//12
FP_sub(&t4, &t4, &x3); //t4.sub(x3);
FP_norm(&t4); //t4.norm();//13
FP_add(&x3, &(P->x), &(P->z)); //x3.add(z);
FP_norm(&x3); //x3.norm(); //14
FP_add(&y3, &(Q->x), &(Q->z)); //y3.add(Q.z);
FP_norm(&y3); //y3.norm();//15
FP_mul(&x3, &x3, &y3); //x3.mul(y3); //16
FP_add(&y3, &t0, &t2); //y3.add(t2); //y3.norm();//17
FP_sub(&y3, &x3, &y3); //y3.rsub(x3);
FP_norm(&y3); //y3.norm(); //18
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_mul(&z3, &t2, &b); //z3.mul(b); //18
else
FP_imul(&z3, &t2, CURVE_B_I); //z3.imul(ROM.CURVE_B_I);
FP_sub(&x3, &y3, &z3); //x3.sub(z3);
FP_norm(&x3); //x3.norm(); //20
FP_add(&z3, &x3, &x3); //z3.add(x3); //z3.norm(); //21
FP_add(&x3, &x3, &z3); //x3.add(z3); //x3.norm(); //22
FP_sub(&z3, &t1, &x3); //z3.sub(x3);
FP_norm(&z3); //z3.norm(); //23
FP_add(&x3, &x3, &t1); //x3.add(t1);
FP_norm(&x3); //x3.norm(); //24
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
FP_mul(&y3, &y3, &b); //y3.mul(b); //18
else
FP_imul(&y3, &y3, CURVE_B_I); //y3.imul(ROM.CURVE_B_I);
FP_add(&t1, &t2, &t2); //t1.add(t2); //t1.norm();//26
FP_add(&t2, &t2, &t1); //t2.add(t1); //t2.norm();//27
FP_sub(&y3, &y3, &t2); //y3.sub(t2); //y3.norm(); //28
FP_sub(&y3, &y3, &t0); //y3.sub(t0);
FP_norm(&y3); //y3.norm(); //29
FP_add(&t1, &y3, &y3); //t1.add(y3); //t1.norm();//30
FP_add(&y3, &y3, &t1); //y3.add(t1);
FP_norm(&y3); //y3.norm(); //31
FP_add(&t1, &t0, &t0); //t1.add(t0); //t1.norm(); //32
FP_add(&t0, &t0, &t1); //t0.add(t1); //t0.norm();//33
FP_sub(&t0, &t0, &t2); //t0.sub(t2);
FP_norm(&t0); //t0.norm();//34
FP_mul(&t1, &t4, &y3); //t1.mul(y3);//35
FP_mul(&t2, &t0, &y3); //t2.mul(y3);//36
FP_mul(&y3, &x3, &z3); //y3.mul(z3);//37
FP_add(&(P->y), &y3, &t2); //y3.add(t2); //y3.norm();//38
FP_mul(&x3, &x3, &t3); //x3.mul(t3);//39
FP_sub(&(P->x), &x3, &t1); //x3.sub(t1);//40
FP_mul(&z3, &z3, &t4); //z3.mul(t4);//41
FP_mul(&t1, &t3, &t0); //t1.mul(t0);//42
FP_add(&(P->z), &z3, &t1); //z3.add(t1);
FP_norm(&(P->x)); //x.norm();
FP_norm(&(P->y)); //y.norm();
FP_norm(&(P->z)); //z.norm();
#endif
#else
FP A, B, C, D, E, F, G, b;
FP_mul(&A, &(P->z), &(Q->z)); //A.mul(Q.z);
FP_sqr(&B, &A); //B.sqr();
FP_mul(&C, &(P->x), &(Q->x)); //C.mul(Q.x);
FP_mul(&D, &(P->y), &(Q->y)); //D.mul(Q.y);
FP_mul(&E, &C, &D); //E.mul(D);
if (CURVE_B_I == 0) //if (ROM.CURVE_B_I==0)
{
FP_rcopy(&b, CURVE_B); //FP b=new FP(new BIG(ROM.CURVE_B));
FP_mul(&E, &E, &b); //E.mul(b);
}
else
FP_imul(&E, &E, CURVE_B_I); //E.imul(ROM.CURVE_B_I);
FP_sub(&F, &B, &E); //F.sub(E);
FP_add(&G, &B, &E); //G.add(E);
#if CURVE_A_ZZZ == 1
FP_sub(&E, &D, &C); //E.sub(C);
#endif
FP_add(&C, &C, &D); //C.add(D);
FP_add(&B, &(P->x), &(P->y)); //B.add(y);
FP_add(&D, &(Q->x), &(Q->y)); //D.add(Q.y);
FP_norm(&B); //B.norm();
FP_norm(&D); //D.norm();
FP_mul(&B, &B, &D); //B.mul(D);
FP_sub(&B, &B, &C); //B.sub(C);
FP_norm(&B); //B.norm();
FP_norm(&F); //F.norm();
FP_mul(&B, &B, &F); //B.mul(F);
FP_mul(&(P->x), &A, &B); //x.mul(B);
FP_norm(&G); //G.norm();
#if CURVE_A_ZZZ == 1
FP_norm(&E); //E.norm();
FP_mul(&C, &E, &G); //C.mul(G);
#endif
#if CURVE_A_ZZZ == -1
FP_norm(&C); //C.norm();
FP_mul(&C, &C, &G); //C.mul(G);
#endif
FP_mul(&(P->y), &A, &C); //y.mul(C);
FP_mul(&(P->z), &F, &G); //z.mul(G);
#endif
}
/* Set P-=Q */
/* SU=16 */
void ZZZ::ECP_sub(ECP *P, ECP *Q)
{
ECP NQ;
ECP_copy(&NQ, Q);
ECP_neg(&NQ);
ECP_add(P, &NQ);
}
#endif
#if CURVETYPE_ZZZ!=MONTGOMERY
/* constant time multiply by small integer of length bts - use ladder */
void ZZZ::ECP_pinmul(ECP *P, int e, int bts)
{
int i, b;
ECP R0, R1;
ECP_affine(P);
ECP_inf(&R0);
ECP_copy(&R1, P);
for (i = bts - 1; i >= 0; i--)
{
b = (e >> i) & 1;
ECP_copy(P, &R1);
ECP_add(P, &R0);
ECP_cswap(&R0, &R1, b);
ECP_copy(&R1, P);
ECP_dbl(&R0);
ECP_cswap(&R0, &R1, b);
}
ECP_copy(P, &R0);
}
#endif
// Point multiplication, multiplies a point P by a scalar e
// This code has no inherent awareness of the order of the curve, or the order of the point.
// The order of the curve will be h.r, where h is a cofactor, and r is a large prime
// Typically P will be of order r (but not always), and typically e will be less than r (but not always)
// A problem can arise if a secret e is a few bits less than r, as the leading zeros in e will leak via a timing attack
// The secret e may however be greater than r (see RFC7748 which combines elimination of a small cofactor h with the point multiplication, using an e>r)
// Our solution is to use as a multiplier an e, whose length in bits is that of the logical OR of e and r, hence allowing e>r while forcing inclusion of leading zeros if e<r.
// The point multiplication methods used will process leading zeros correctly.
// So this function leaks information about the length of e...
void ZZZ::ECP_mul(ECP *P,BIG e)
{
ECP_clmul(P,e,e);
}
// .. but this one does not (typically set maxe=r)
// Set P=e*P
void ZZZ::ECP_clmul(ECP *P, BIG e, BIG maxe)
{
BIG cm;
BIG_or(cm,e,maxe);
int max=BIG_nbits(cm);
#if CURVETYPE_ZZZ==MONTGOMERY
/* Montgomery ladder */
int nb, i, b;
ECP R0, R1, D;
if (ECP_isinf(P)) return;
if (BIG_iszilch(e))
{
ECP_inf(P);
return;
}
ECP_copy(&R0, P);
ECP_copy(&R1, P);
ECP_dbl(&R1);
ECP_copy(&D, P);
ECP_affine(&D);
nb = max;
for (i = nb - 2; i >= 0; i--)
{
b = BIG_bit(e, i);
ECP_copy(P, &R1);
ECP_add(P, &R0, &D);
ECP_cswap(&R0, &R1, b);
ECP_copy(&R1, P);
ECP_dbl(&R0);
ECP_cswap(&R0, &R1, b);
}
ECP_copy(P, &R0);
#else
/* fixed size windows */
int i, nb, s, ns;
BIG mt, t;
ECP Q, W[8], C;
sign8 w[1 + (NLEN_XXX * BASEBITS_XXX + 3) / 4];
if (ECP_isinf(P)) return;
if (BIG_iszilch(e))
{
ECP_inf(P);
return;
}
/* precompute table */
ECP_copy(&Q, P);
ECP_dbl(&Q);
ECP_copy(&W[0], P);
for (i = 1; i < 8; i++)
{
ECP_copy(&W[i], &W[i - 1]);
ECP_add(&W[i], &Q);
}
/* make exponent odd - add 2P if even, P if odd */
BIG_copy(t, e);
s = BIG_parity(t);
BIG_inc(t, 1);
BIG_norm(t);
ns = BIG_parity(t);
BIG_copy(mt, t);
BIG_inc(mt, 1);
BIG_norm(mt);
BIG_cmove(t, mt, s);
ECP_cmove(&Q, P, ns);
ECP_copy(&C, &Q);
nb = 1 + (max + 3) / 4;
/* convert exponent to signed 4-bit window */
for (i = 0; i < nb; i++)
{
w[i] = BIG_lastbits(t, 5) - 16;
BIG_dec(t, w[i]);
BIG_norm(t);
BIG_fshr(t, 4);
}
w[nb] = BIG_lastbits(t, 5);
ECP_select(P, W, w[nb]);
for (i = nb - 1; i >= 0; i--)
{
ECP_select(&Q, W, w[i]);
ECP_dbl(P);
ECP_dbl(P);
ECP_dbl(P);
ECP_dbl(P);
ECP_add(P, &Q);
}
ECP_sub(P, &C); /* apply correction */
#endif
}
#if CURVETYPE_ZZZ!=MONTGOMERY
// Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i
// m point doublings
void ZZZ::ECP_muln(ECP *P,int n,ECP X[],BIG e[])
{
int i,j,k,nb;
BIG t,mt;
ECP S,R,B[16];
ECP_inf(P);
BIG_copy(mt,e[0]); BIG_norm(mt);
for (i=1;i<n;i++)
{ // find biggest
BIG_copy(t,e[i]); BIG_norm(t);
k=BIG_comp(t,mt);
BIG_cmove(mt,t,(k+1)/2);
}
nb=(BIG_nbits(mt)+3)/4;
for (int i=nb-1;i>=0;i--)
{ // Pippenger's algorithm
for (j=0;j<16;j++)
ECP_inf(&B[j]);
for (j=0;j<n;j++)
{
BIG_copy(mt,e[j]); BIG_norm(mt);
BIG_shr(mt,4*i);
k=BIG_lastbits(mt,4);
ECP_add(&B[k],&X[j]); // side channel risky
}
ECP_inf(&R); ECP_inf(&S);
for (j=15;j>=1;j--)
{
ECP_add(&R,&B[j]);
ECP_add(&S,&R);
}
for (j=0;j<4;j++)
ECP_dbl(P);
ECP_add(P,&S);
}
}
void ZZZ::ECP_mul2(ECP *P, ECP *Q, BIG e, BIG f)
{
ECP_clmul2(P,Q,e,f,e);
}
/* Set P=eP+fQ double multiplication */
/* constant time - as useful for GLV method in pairings */
/* SU=456 */
void ZZZ::ECP_clmul2(ECP *P, ECP *Q, BIG e, BIG f, BIG maxe)
{
BIG cm;
BIG te, tf, mt;
ECP S, T, W[8], C;
sign8 w[1 + (NLEN_XXX * BASEBITS_XXX + 1) / 2];
int i, a, b, s, ns, nb;
BIG_copy(cm,maxe); BIG_or(cm,cm,e); BIG_or(cm,cm,f);
int max=BIG_nbits(cm);
BIG_copy(te, e);
BIG_copy(tf, f);
/* precompute table */
ECP_copy(&W[1], P);
ECP_sub(&W[1], Q); /* P+Q */
ECP_copy(&W[2], P);
ECP_add(&W[2], Q); /* P-Q */
ECP_copy(&S, Q);
ECP_dbl(&S); /* S=2Q */
ECP_copy(&W[0], &W[1]);
ECP_sub(&W[0], &S);
ECP_copy(&W[3], &W[2]);
ECP_add(&W[3], &S);
ECP_copy(&T, P);
ECP_dbl(&T); /* T=2P */
ECP_copy(&W[5], &W[1]);
ECP_add(&W[5], &T);
ECP_copy(&W[6], &W[2]);
ECP_add(&W[6], &T);
ECP_copy(&W[4], &W[5]);
ECP_sub(&W[4], &S);
ECP_copy(&W[7], &W[6]);
ECP_add(&W[7], &S);
/* if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction */
s = BIG_parity(te);
BIG_inc(te, 1);
BIG_norm(te);
ns = BIG_parity(te);
BIG_copy(mt, te);
BIG_inc(mt, 1);
BIG_norm(mt);
BIG_cmove(te, mt, s);
ECP_cmove(&T, P, ns);
ECP_copy(&C, &T);
s = BIG_parity(tf);
BIG_inc(tf, 1);
BIG_norm(tf);
ns = BIG_parity(tf);
BIG_copy(mt, tf);
BIG_inc(mt, 1);
BIG_norm(mt);
BIG_cmove(tf, mt, s);
ECP_cmove(&S, Q, ns);
ECP_add(&C, &S);
//BIG_add(mt, te, tf);
//BIG_norm(mt);
nb = 1 + (max + 1) / 2;
/* convert exponent to signed 2-bit window */
for (i = 0; i < nb; i++)
{
a = BIG_lastbits(te, 3) - 4;
BIG_dec(te, a);
BIG_norm(te);
BIG_fshr(te, 2);
b = BIG_lastbits(tf, 3) - 4;
BIG_dec(tf, b);
BIG_norm(tf);
BIG_fshr(tf, 2);
w[i] = 4 * a + b;
}
w[nb] = (4 * BIG_lastbits(te, 3) + BIG_lastbits(tf, 3));
//ECP_copy(P, &W[(w[nb] - 1) / 2]);
ECP_select(P, W, w[nb]);
for (i = nb - 1; i >= 0; i--)
{
ECP_select(&T, W, w[i]);
ECP_dbl(P);
ECP_dbl(P);
ECP_add(P, &T);
}
ECP_sub(P, &C); /* apply correction */
}
#endif
void ZZZ::ECP_cfp(ECP *P)
{ /* multiply point by curves cofactor */
BIG c;
int cf = CURVE_Cof_I;
if (cf == 1) return;
if (cf == 4)
{
ECP_dbl(P);
ECP_dbl(P);
return;
}
if (cf == 8)
{
ECP_dbl(P);
ECP_dbl(P);
ECP_dbl(P);
return;
}
BIG_rcopy(c, CURVE_Cof);
ECP_mul(P, c);
return;
}
/* Constant time Map to Point */
void ZZZ::ECP_map2point(ECP *P,FP *h)
{
#if CURVETYPE_ZZZ==MONTGOMERY
// Elligator 2
int qres;
BIG a;
FP X1,X2,w,N,t,one,A,D,hint;
//BIG_zero(a); BIG_inc(a,CURVE_A); BIG_norm(a); FP_nres(&A,a);
FP_from_int(&A,CURVE_A_ZZZ);
FP_copy(&t,h);
FP_sqr(&t,&t); // t^2
if (PM1D2_YYY == 2)
FP_add(&t,&t,&t); // 2t^2
if (PM1D2_YYY == 1)
FP_neg(&t,&t); // -t^2
if (PM1D2_YYY > 2)
FP_imul(&t,&t,QNRI_YYY); // precomputed QNR
FP_norm(&t); // z.t^2
FP_one(&one);
FP_add(&D,&t,&one); FP_norm(&D); // Denominator D=1+z.t^2
FP_copy(&X1,&A);
FP_neg(&X1,&X1); FP_norm(&X1); // X1 = -A/D
FP_copy(&X2,&X1);
FP_mul(&X2,&X2,&t); // X2 = -At/D
FP_sqr(&w,&X1); FP_mul(&N,&w,&X1); // w=X1^2, N=X1^3
FP_mul(&w,&w,&A); FP_mul(&w,&w,&D); FP_add(&N,&N,&w); // N = X1^3+ADX1^2
FP_sqr(&t,&D);
FP_mul(&t,&t,&X1);
FP_add(&N,&N,&t); // N=X1^3+ADX1^2+D^2X1 // Numerator of gx = N/D^3
FP_norm(&N);
FP_mul(&t,&N,&D); // N.D
qres=FP_qr(&t,&hint); // *** exp
FP_inv(&w,&t,&hint);
FP_mul(&D,&w,&N); // 1/D
FP_mul(&X1,&X1,&D); // get X1
FP_mul(&X2,&X2,&D); // get X2
FP_cmove(&X1,&X2,1-qres);
FP_redc(a,&X1);
ECP_set(P,a);
return;
#endif
#if CURVETYPE_ZZZ==EDWARDS
// Elligator 2 - map to Montgomery, place point, map back
int qres,ne,rfc,qnr;
BIG x,y;
FP X1,X2,t,w,one,A,w1,w2,B,Y,K,D,hint;
FP_one(&one);
#if MODTYPE_YYY != GENERALISED_MERSENNE
// its NOT ed448!
// Figure out the Montgomery curve parameters
FP_rcopy(&B,CURVE_B);
#if CURVE_A_ZZZ == 1
FP_add(&A,&B,&one); // A=B+1 // A = a+d
FP_sub(&B,&B,&one); // B=B-1 // B = -a+d
#else
FP_sub(&A,&B,&one); // A=B-1
FP_add(&B,&B,&one); // B=B+1
#endif
FP_norm(&A); FP_norm(&B);
FP_div2(&A,&A); // (A+B)/2 // (a+d)/2 = J/K
FP_div2(&B,&B); // (B-A)/2 // (-a+d)/2
FP_div2(&B,&B); // (B-A)/4 // (-a+d)/4 = -1/K
FP_neg(&K,&B); FP_norm(&K);
//FP_inv(&K,&K,NULL); // K
FP_invsqrt(&K,&w1,&K); // *** return K, w1=sqrt(1/K) - - could be precalculated!
rfc=RIADZ_YYY;
if (rfc)
{ // RFC7748 method applies
FP_mul(&A,&A,&K); // = J
FP_mul(&K,&K,&w1);
// FP_sqrt(&K,&K,NULL);
} else { // generic method
FP_sqr(&B,&B);
}
#else
FP_from_int(&A,156326);
rfc=1;
#endif
// Map to this Montgomery curve X^2=X^3+AX^2+BX
FP_copy(&t,h);
FP_sqr(&t,&t); // t^2
if (PM1D2_YYY == 2)
{
FP_add(&t,&t,&t); // 2t^2
qnr=2;
}
if (PM1D2_YYY == 1)
{
FP_neg(&t,&t); // -t^2
qnr=-1;
}
if (PM1D2_YYY > 2)
{
FP_imul(&t,&t,QNRI_YYY); // precomputed QNR
qnr=QNRI_YYY;
}
FP_norm(&t);
FP_add(&D,&t,&one); FP_norm(&D); // Denominator=(1+z.u^2)
FP_copy(&X1,&A);
FP_neg(&X1,&X1); FP_norm(&X1); // X1=-(J/K).inv(1+z.u^2)
FP_mul(&X2,&X1,&t); // X2=X1*z.u^2
// Figure out RHS of Montgomery curve in rational form gx1/d^3
FP_sqr(&w,&X1); FP_mul(&w1,&w,&X1); // w=X1^2, w1=X1^3
FP_mul(&w,&w,&A); FP_mul(&w,&w,&D); FP_add(&w1,&w1,&w); // w1 = X1^3+ADX1^2
FP_sqr(&w2,&D);
if (!rfc)
{
FP_mul(&w,&X1,&B);
FP_mul(&w2,&w2,&w); //
FP_add(&w1,&w1,&w2); // w1=X1^3+ADX1^2+BD^2X1
} else {
FP_mul(&w2,&w2,&X1);
FP_add(&w1,&w1,&w2); // w1=X1^3+ADX1^2+D^2X1 // was &X1
}
FP_norm(&w1);
FP_mul(&B,&w1,&D); // gx1=num/den^3 - is_qr num*den (same as num/den, same as num/den^3)
qres=FP_qr(&B,&hint); // ***
FP_inv(&w,&B,&hint);
FP_mul(&D,&w,&w1); // 1/D
FP_mul(&X1,&X1,&D); // get X1
FP_mul(&X2,&X2,&D); // get X2
FP_sqr(&D,&D);
FP_imul(&w1,&B,qnr); // now for gx2 = Z.u^2.gx1
FP_rcopy(&w,CURVE_HTPC); // qnr^C3
FP_mul(&w,&w,&hint); // modify hint for gx2
FP_mul(&w2,&D,h);
FP_cmove(&X1,&X2,1-qres); // pick correct one
FP_cmove(&B,&w1,1-qres);
FP_cmove(&hint,&w,1-qres);
FP_cmove(&D,&w2,1-qres);
FP_sqrt(&Y,&B,&hint); // sqrt(num*den)
FP_mul(&Y,&Y,&D); // sqrt(num/den^3)
// correct sign of Y
FP_neg(&w,&Y); FP_norm(&w);
FP_cmove(&Y,&w,qres^FP_sign(&Y));
if (!rfc)
{
FP_mul(&X1,&X1,&K);
FP_mul(&Y,&Y,&K);
}
#if MODTYPE_YYY == GENERALISED_MERSENNE
// Ed448 isogeny
FP_sqr(&t,&X1); // t=u^2
FP_add(&w,&t,&one); // w=u^2+1
FP_norm(&w);
FP_sub(&t,&t,&one); // t=u^2-1
FP_norm(&t);
FP_mul(&w1,&t,&Y); // w1=v(u^2-1)
FP_add(&w1,&w1,&w1);
FP_add(&X2,&w1,&w1);
FP_norm(&X2); // w1=4v(u^2-1)
FP_sqr(&t,&t); // t=(u^2-1)^2
FP_sqr(&Y,&Y); // v^2
FP_add(&Y,&Y,&Y);
FP_add(&Y,&Y,&Y);
FP_norm(&Y); // 4v^2
FP_add(&B,&t,&Y); // w2=(u^2-1)^2+4v^2
FP_norm(&B); // X1=w1/w2 - X2=w1, B=w2
FP_sub(&w2,&Y,&t); // w2=4v^2-(u^2-1)^2
FP_norm(&w2);
FP_mul(&w2,&w2,&X1); // w2=u(4v^2-(u^2-1)^2)
FP_mul(&t,&t,&X1); // t=u(u^2-1)^2
FP_div2(&Y,&Y); // 2v^2
FP_mul(&w1,&Y,&w); // w1=2v^2(u^2+1)
FP_sub(&w1,&t,&w1); // w1=u(u^2-1)^2 - 2v^2(u^2+1)
FP_norm(&w1); // Y=w2/w1
FP_mul(&t,&X2,&w1); // output in projective to avoid inversion
FP_copy(&(P->x),&t);
FP_mul(&t,&w2,&B);
FP_copy(&(P->y),&t);
FP_mul(&t,&w1,&B);
FP_copy(&(P->z),&t);
return;
#else
FP_add(&w1,&X1,&one); FP_norm(&w1); // (s+1)
FP_sub(&w2,&X1,&one); FP_norm(&w2); // (s-1)
FP_mul(&t,&w1,&Y);
FP_mul(&X1,&X1,&w1);
if (rfc)
FP_mul(&X1,&X1,&K);
FP_mul(&Y,&Y,&w2); // output in projective to avoid inversion
FP_copy(&(P->x),&X1);
FP_copy(&(P->y),&Y);
FP_copy(&(P->z),&t);
return;
#endif
#endif
#if CURVETYPE_ZZZ==WEIERSTRASS
// SSWU or SVDW method
int sgn,ne;
BIG a,x,y;
FP X1,X2,X3,t,w,one,A,B,Y,D;
FP D2,hint,GX1;
#if HTC_ISO_ZZZ != 0
// Map to point on isogenous curve
int i,k,isox,isoy,iso=HTC_ISO_ZZZ;
FP xnum,xden,ynum,yden;
BIG z;
FP_rcopy(&A,CURVE_Ad);
FP_rcopy(&B,CURVE_Bd);
#else
FP_from_int(&A,CURVE_A_ZZZ);
FP_rcopy(&B,CURVE_B);
#endif
FP_one(&one);
FP_copy(&t,h);
sgn=FP_sign(&t);
#if CURVE_A_ZZZ != 0 || HTC_ISO_ZZZ != 0
FP_sqr(&t,&t);
FP_imul(&t,&t,RIADZ_YYY); // Z from hash-to-point draft standard
FP_add(&w,&t,&one); // w=Zt^2+1
FP_norm(&w);
FP_mul(&w,&w,&t); // w=Z^2*t^4+Zt^2
FP_mul(&D,&A,&w); // A=Aw
FP_add(&w,&w,&one); FP_norm(&w);
FP_mul(&w,&w,&B);
FP_neg(&w,&w); // -B(w+1)
FP_norm(&w);
FP_copy(&X2,&w); // Numerators
FP_mul(&X3,&t,&X2);
// x^3+Ad^2x+Bd^3
FP_sqr(&GX1,&X2);
FP_sqr(&D2,&D); FP_mul(&w,&A,&D2); FP_add(&GX1,&GX1,&w); FP_norm(&GX1); FP_mul(&GX1,&GX1,&X2); FP_mul(&D2,&D2,&D); FP_mul(&w,&B,&D2); FP_add(&GX1,&GX1,&w); FP_norm(&GX1);
FP_mul(&w,&GX1,&D);
int qr=FP_qr(&w,&hint); // qr(ad) - only exp happens here
FP_inv(&D,&w,&hint); // d=1/(ad)
FP_mul(&D,&D,&GX1); // 1/d
FP_mul(&X2,&X2,&D); // X2/=D
FP_mul(&X3,&X3,&D); // X3/=D
FP_mul(&t,&t,h); // t=Z.u^3
FP_sqr(&D2,&D);
FP_mul(&D,&D2,&t);
FP_imul(&t,&w,RIADZ_YYY);
FP_rcopy(&X1,CURVE_HTPC);
FP_mul(&X1,&X1,&hint); // modify hint
FP_cmove(&X2,&X3,1-qr);
FP_cmove(&D2,&D,1-qr);
FP_cmove(&w,&t,1-qr);
FP_cmove(&hint,&X1,1-qr);
FP_sqrt(&Y,&w,&hint); // first candidate if X2 is correct
FP_mul(&Y,&Y,&D2);
ne=FP_sign(&Y)^sgn;
FP_neg(&w,&Y); FP_norm(&w);
FP_cmove(&Y,&w,ne);
#if HTC_ISO_ZZZ != 0
// (X2,Y) is on isogenous curve
k=0;
isox=iso;
isoy=3*(iso-1)/2;
// xnum
FP_rcopy(&xnum,PC[k++]);
for (i=0;i<isox;i++)
{
FP_mul(&xnum,&xnum,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&xnum,&xnum,&w); FP_norm(&xnum);
}
// xden
FP_copy(&xden,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&xden,&xden,&w); FP_norm(&xden);
for (i=0;i<isox-2;i++)
{
FP_mul(&xden,&xden,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&xden,&xden,&w); FP_norm(&xden);
}
// ynum
FP_rcopy(&ynum,PC[k++]);
for (i=0;i<isoy;i++)
{
FP_mul(&ynum,&ynum,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&ynum,&ynum,&w); FP_norm(&ynum);
}
// yden
FP_copy(&yden,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&yden,&yden,&w); FP_norm(&yden);
for (i=0;i<isoy-1;i++)
{
FP_mul(&yden,&yden,&X2);
FP_rcopy(&w,PC[k++]);
FP_add(&yden,&yden,&w); FP_norm(&yden);
}
FP_mul(&ynum,&ynum,&Y);
// return in projective coordinates
FP_mul(&t,&xnum,&yden);
FP_copy(&(P->x),&t);
FP_mul(&t,&ynum,&xden);
FP_copy(&(P->y),&t);
FP_mul(&t,&xden,&yden);
FP_copy(&(P->z),&t);
return;
#else
FP_redc(x,&X2);
FP_redc(y,&Y);
ECP_set(P,x,y);
return;
#endif
#else
// SVDW - Shallue and van de Woestijne
FP_from_int(&Y,RIADZ_YYY);
ECP_rhs(&A,&Y); // A=g(Z)
FP_rcopy(&B,SQRTm3);
FP_imul(&B,&B,RIADZ_YYY); // B=Z*sqrt(-3)
FP_sqr(&t,&t);
FP_mul(&Y,&A,&t); // Y=tv1=u^2*g(Z)
FP_add(&t,&one,&Y); FP_norm(&t); // t=tv2=1+tv1
FP_sub(&Y,&one,&Y); FP_norm(&Y); // Y=tv1=1-tv1
FP_mul(&D,&t,&Y);
FP_mul(&D,&D,&B);
FP_copy(&w,&A);
FP_tpo(&D,&w); // D=tv3=inv0(tv1*tv2*Z*sqrt(-3)) and w=sqrt(g(Z)) // ***
FP_mul(&w,&w,&B); // w=tv4=Z.sqrt(-3).sqrt(g(Z))
if (FP_sign(&w)==1)
{ // depends only on sign of constant RIADZ
FP_neg(&w,&w);
FP_norm(&w);
}
FP_mul(&w,&w,&B); // Z.sqrt(-3)
FP_mul(&w,&w,h); // u
FP_mul(&w,&w,&Y); // tv1
FP_mul(&w,&w,&D); // tv3 // tv5=u*tv1*tv3*tv4*Z*sqrt(-3)
FP_from_int(&X1,RIADZ_YYY);
FP_copy(&X3,&X1);
FP_neg(&X1,&X1); FP_norm(&X1); FP_div2(&X1,&X1); // -Z/2
FP_copy(&X2,&X1);
FP_sub(&X1,&X1,&w); FP_norm(&X1);
FP_add(&X2,&X2,&w); FP_norm(&X2);
FP_add(&A,&A,&A);
FP_add(&A,&A,&A);
FP_norm(&A); // 4*g(Z)
FP_sqr(&t,&t);
FP_mul(&t,&t,&D);
FP_sqr(&t,&t); // (tv2^2*tv3)^2
FP_mul(&A,&A,&t); // 4*g(Z)*(tv2^2*tv3)^2
FP_add(&X3,&X3,&A); FP_norm(&X3);
ECP_rhs(&w,&X2);
FP_cmove(&X3,&X2,FP_qr(&w,NULL)); // ***
ECP_rhs(&w,&X1);
FP_cmove(&X3,&X1,FP_qr(&w,NULL)); // ***
ECP_rhs(&w,&X3);
FP_sqrt(&Y,&w,NULL); // ***
ne=FP_sign(&Y)^sgn;
FP_neg(&w,&Y); FP_norm(&w);
FP_cmove(&Y,&w,ne);
FP_redc(x,&X3);
FP_redc(y,&Y);
ECP_set(P,x,y);
return;
#endif
#endif
}
/* Hunt and Peck a BIG to a curve point */
/*
void ZZZ::ECP_hap2point(ECP *P,BIG h)
{
BIG x;
BIG_copy(x,h);
for (;;)
{
#if CURVETYPE_ZZZ!=MONTGOMERY
ECP_setx(P,x,0);
#else
ECP_set(P,x);
#endif
BIG_inc(x,1); BIG_norm(x);
if (!ECP_isinf(P)) break;
}
}
*/
/* Map octet to point */
/*
void ZZZ::ECP_mapit(ECP *P, octet *W)
{
BIG q, x;
DBIG dx;
BIG_rcopy(q, Modulus);
BIG_dfromBytesLen(dx,W->val,W->len);
BIG_dmod(x,dx,q);
ECP_hap2point(P,x);
ECP_cfp(P);
}
*/
int ZZZ::ECP_generator(ECP *G)
{
BIG x, y;
BIG_rcopy(x, CURVE_Gx);
#if CURVETYPE_ZZZ!=MONTGOMERY
BIG_rcopy(y, CURVE_Gy);
return ECP_set(G, x, y);
#else
return ECP_set(G, x);
#endif
}
#ifdef HAS_MAIN
using namespace ZZZ;
int main()
{
int i;
ECP G, P;
csprng RNG;
BIG r, s, x, y, b, m, w, q;
BIG_rcopy(x, CURVE_Gx);
#if CURVETYPE_ZZZ!=MONTGOMERY
BIG_rcopy(y, CURVE_Gy);
#endif
BIG_rcopy(m, Modulus);
printf("x= ");
BIG_output(x);
printf("\n");
#if CURVETYPE_ZZZ!=MONTGOMERY
printf("y= ");
BIG_output(y);
printf("\n");
#endif
RNG_seed(&RNG, 3, "abc");
#if CURVETYPE_ZZZ!=MONTGOMERY
ECP_set(&G, x, y);
#else
ECP_set(&G, x);
#endif
if (ECP_isinf(&G)) printf("Failed to set - point not on curve\n");
else printf("set success\n");
ECP_output(&G);
BIG_rcopy(r, CURVE_Order); //BIG_dec(r,7);
printf("r= ");
BIG_output(r);
printf("\n");
ECP_copy(&P, &G);
ECP_mul(&P, r);
ECP_output(&P);
BIG_randomnum(w, &RNG);
BIG_mod(w, r);
ECP_copy(&P, &G);
ECP_mul(&P, w);
ECP_output(&P);
return 0;
}
#endif