/***************************************************************************
*
Copyright 2013 CertiVox UK Ltd. *
*
This file is part of CertiVox MIRACL Crypto SDK. *
*
The CertiVox MIRACL Crypto SDK provides developers with an *
extensive and efficient set of cryptographic functions. *
For further information about its features and functionalities please *
refer to http://www.certivox.com *
*
* The CertiVox MIRACL Crypto SDK is free software: you can *
redistribute it and/or modify it under the terms of the *
GNU Affero General Public License as published by the *
Free Software Foundation, either version 3 of the License, *
or (at your option) any later version. *
*
* The CertiVox MIRACL Crypto SDK is distributed in the hope *
that it will be useful, but WITHOUT ANY WARRANTY; without even the *
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
See the GNU Affero General Public License for more details. *
*
* You should have received a copy of the GNU Affero General Public *
License along with CertiVox MIRACL Crypto SDK. *
If not, see . *
*
You can be released from the requirements of the license by purchasing *
a commercial license. Buying such a license is mandatory as soon as you *
develop commercial activities involving the CertiVox MIRACL Crypto SDK *
without disclosing the source code of your own applications, or shipping *
the CertiVox MIRACL Crypto SDK with a closed source product. *
*
***************************************************************************/
/*
* MIRACL E(F_p^2) support functions
* mrecn2.c
*/
#include
#include "miracl.h"
#ifdef MR_STATIC
#include
#endif
#ifndef MR_EDWARDS
BOOL ecn2_iszero(ecn2 *a)
{
if (a->marker==MR_EPOINT_INFINITY) return TRUE;
return FALSE;
}
void ecn2_copy(ecn2 *a,ecn2 *b)
{
zzn2_copy(&(a->x),&(b->x));
zzn2_copy(&(a->y),&(b->y));
#ifndef MR_AFFINE_ONLY
if (a->marker==MR_EPOINT_GENERAL) zzn2_copy(&(a->z),&(b->z));
#endif
b->marker=a->marker;
}
void ecn2_zero(ecn2 *a)
{
zzn2_zero(&(a->x)); zzn2_zero(&(a->y));
#ifndef MR_AFFINE_ONLY
if (a->marker==MR_EPOINT_GENERAL) zzn2_zero(&(a->z));
#endif
a->marker=MR_EPOINT_INFINITY;
}
BOOL ecn2_compare(_MIPD_ ecn2 *a,ecn2 *b)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(193)
ecn2_norm(_MIPP_ a);
ecn2_norm(_MIPP_ b);
MR_OUT
if (zzn2_compare(&(a->x),&(b->x)) && zzn2_compare(&(a->y),&(b->y)) && a->marker==b->marker) return TRUE;
return FALSE;
}
void ecn2_norm(_MIPD_ ecn2 *a)
{
zzn2 t;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
#ifndef MR_AFFINE_ONLY
if (mr_mip->ERNUM) return;
if (a->marker!=MR_EPOINT_GENERAL) return;
MR_IN(194)
zzn2_inv(_MIPP_ &(a->z));
t.a=mr_mip->w3;
t.b=mr_mip->w4;
zzn2_copy(&(a->z),&t);
zzn2_sqr(_MIPP_ &(a->z),&(a->z));
zzn2_mul(_MIPP_ &(a->x),&(a->z),&(a->x));
zzn2_mul(_MIPP_ &(a->z),&t,&(a->z));
zzn2_mul(_MIPP_ &(a->y),&(a->z),&(a->y));
zzn2_from_zzn(mr_mip->one,&(a->z));
a->marker=MR_EPOINT_NORMALIZED;
MR_OUT
#endif
}
void ecn2_get(_MIPD_ ecn2 *e,zzn2 *x,zzn2 *y,zzn2 *z)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2_copy(&(e->x),x);
zzn2_copy(&(e->y),y);
#ifndef MR_AFFINE_ONLY
if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z);
else zzn2_from_zzn(mr_mip->one,z);
#endif
}
void ecn2_getxy(ecn2 *e,zzn2 *x,zzn2 *y)
{
zzn2_copy(&(e->x),x);
zzn2_copy(&(e->y),y);
}
void ecn2_getx(ecn2 *e,zzn2 *x)
{
zzn2_copy(&(e->x),x);
}
void ecn2_psi(_MIPD_ zzn2 *psi,ecn2 *P)
{ /* apply GLS morphism to P */
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
MR_IN(212)
ecn2_norm(_MIPP_ P);
zzn2_conj(_MIPP_ &(P->x),&(P->x));
zzn2_conj(_MIPP_ &(P->y),&(P->y));
zzn2_mul(_MIPP_ &(P->x),&psi[0],&(P->x));
zzn2_mul(_MIPP_ &(P->y),&psi[1],&(P->y));
MR_OUT
}
#ifndef MR_AFFINE_ONLY
void ecn2_getz(_MIPD_ ecn2 *e,zzn2 *z)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z);
else zzn2_from_zzn(mr_mip->one,z);
}
#endif
void ecn2_rhs(_MIPD_ zzn2 *x,zzn2 *rhs)
{ /* calculate RHS of elliptic curve equation */
int twist;
zzn2 A,B;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
twist=mr_mip->TWIST;
MR_IN(202)
A.a=mr_mip->w10;
A.b=mr_mip->w11;
B.a=mr_mip->w12;
B.b=mr_mip->w13;
if (mr_abs(mr_mip->Asize)Asize,&A);
else zzn2_from_zzn(mr_mip->A,&A);
if (mr_abs(mr_mip->Bsize)Bsize,&B);
else zzn2_from_zzn(mr_mip->B,&B);
if (twist)
{ /* assume its the quartic or sextic twist, if such is possible */
if (twist==MR_QUARTIC_M)
{
zzn2_mul(_MIPP_ &A,x,&B);
zzn2_txx(_MIPP_ &B);
}
if (twist==MR_QUARTIC_D)
{
zzn2_mul(_MIPP_ &A,x,&B);
zzn2_txd(_MIPP_ &B);
}
if (twist==MR_SEXTIC_M)
{
zzn2_txx(_MIPP_ &B);
}
if (twist==MR_SEXTIC_D)
{
zzn2_txd(_MIPP_ &B);
}
if (twist==MR_QUADRATIC)
{
zzn2_txx(_MIPP_ &B);
zzn2_txx(_MIPP_ &B);
zzn2_txx(_MIPP_ &B);
zzn2_mul(_MIPP_ &A,x,&A);
zzn2_txx(_MIPP_ &A);
zzn2_txx(_MIPP_ &A);
zzn2_add(_MIPP_ &B,&A,&B);
}
/*
if (mr_mip->Asize==0 || mr_mip->Bsize==0)
{
if (mr_mip->Asize==0)
{ // CM Discriminant D=3 - its the sextic twist (Hope I got the right one!). This works for BN curves
zzn2_txd(_MIPP_ &B);
}
if (mr_mip->Bsize==0)
{ // CM Discriminant D=1 - its the quartic twist.
zzn2_mul(_MIPP_ &A,x,&B);
zzn2_txx(_MIPP_ &B);
}
}
else
{ // its the quadratic twist
zzn2_txx(_MIPP_ &B);
zzn2_txx(_MIPP_ &B);
zzn2_txx(_MIPP_ &B);
zzn2_mul(_MIPP_ &A,x,&A);
zzn2_txx(_MIPP_ &A);
zzn2_txx(_MIPP_ &A);
zzn2_add(_MIPP_ &B,&A,&B);
}
*/
}
else
{
zzn2_mul(_MIPP_ &A,x,&A);
zzn2_add(_MIPP_ &B,&A,&B);
}
zzn2_sqr(_MIPP_ x,&A);
zzn2_mul(_MIPP_ &A,x,&A);
zzn2_add(_MIPP_ &B,&A,rhs);
MR_OUT
}
BOOL ecn2_set(_MIPD_ zzn2 *x,zzn2 *y,ecn2 *e)
{
zzn2 lhs,rhs;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(195)
lhs.a=mr_mip->w10;
lhs.b=mr_mip->w11;
rhs.a=mr_mip->w12;
rhs.b=mr_mip->w13;
ecn2_rhs(_MIPP_ x,&rhs);
zzn2_sqr(_MIPP_ y,&lhs);
if (!zzn2_compare(&lhs,&rhs))
{
MR_OUT
return FALSE;
}
zzn2_copy(x,&(e->x));
zzn2_copy(y,&(e->y));
e->marker=MR_EPOINT_NORMALIZED;
MR_OUT
return TRUE;
}
#ifndef MR_NOSUPPORT_COMPRESSION
BOOL ecn2_setx(_MIPD_ zzn2 *x,ecn2 *e)
{
zzn2 rhs;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(201)
rhs.a=mr_mip->w12;
rhs.b=mr_mip->w13;
ecn2_rhs(_MIPP_ x,&rhs);
if (!zzn2_iszero(&rhs))
{
if (!zzn2_qr(_MIPP_ &rhs))
{
MR_OUT
return FALSE;
}
zzn2_sqrt(_MIPP_ &rhs,&rhs);
}
zzn2_copy(x,&(e->x));
zzn2_copy(&rhs,&(e->y));
e->marker=MR_EPOINT_NORMALIZED;
MR_OUT
return TRUE;
}
#endif
#ifndef MR_AFFINE_ONLY
void ecn2_setxyz(_MIPD_ zzn2 *x,zzn2 *y,zzn2 *z,ecn2 *e)
{
zzn2_copy(x,&(e->x));
zzn2_copy(y,&(e->y));
zzn2_copy(z,&(e->z));
if (zzn2_isunity(_MIPP_ z)) e->marker=MR_EPOINT_NORMALIZED;
else e->marker=MR_EPOINT_GENERAL;
}
#endif
/* Normalise an array of points of length mcoord==MR_AFFINE) return TRUE;
if (mr_mip->ERNUM) return FALSE;
if (m>MR_MAX_M_T_S) return FALSE;
MR_IN(215)
one.a=mr_mip->w12;
one.b=mr_mip->w13;
t.a=mr_mip->w14;
t.b=mr_mip->w15;
zzn2_from_int(_MIPP_ 1,&one);
for (i=0;imarker!=MR_EPOINT_INFINITY)
zzn2_negate(_MIPP_ &(w->y),&(w->y));
}
BOOL ecn2_add2(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam,zzn2 *ex1)
{
BOOL Doubling;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
Doubling=ecn2_add3(_MIPP_ Q,P,lam,ex1,NULL);
return Doubling;
}
BOOL ecn2_add1(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam)
{
BOOL Doubling;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
Doubling=ecn2_add3(_MIPP_ Q,P,lam,NULL,NULL);
return Doubling;
}
BOOL ecn2_add(_MIPD_ ecn2 *Q,ecn2 *P)
{
BOOL Doubling;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2 lam;
lam.a = mr_mip->w14;
lam.b = mr_mip->w15;
Doubling=ecn2_add3(_MIPP_ Q,P,&lam,NULL,NULL);
return Doubling;
}
BOOL ecn2_sub(_MIPD_ ecn2 *Q,ecn2 *P)
{
BOOL Doubling;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2 lam;
lam.a = mr_mip->w14;
lam.b = mr_mip->w15;
ecn2_negate(_MIPP_ Q,Q);
Doubling=ecn2_add3(_MIPP_ Q,P,&lam,NULL,NULL);
ecn2_negate(_MIPP_ Q,Q);
return Doubling;
}
BOOL ecn2_add_sub(_MIPD_ ecn2 *P,ecn2 *Q,ecn2 *PP,ecn2 *PM)
{ /* PP=P+Q, PM=P-Q. Assumes P and Q are both normalized, and P!=Q */
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2 t1,t2,lam;
if (mr_mip->ERNUM) return FALSE;
if (P->marker==MR_EPOINT_GENERAL || Q->marker==MR_EPOINT_GENERAL)
{ /* Sorry, some restrictions.. */
mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS);
MR_OUT
return FALSE;
}
if (zzn2_compare(&(P->x),&(Q->x)))
{ /* P=Q or P=-Q - shouldn't happen */
ecn2_copy(P,PP);
ecn2_add(_MIPP_ Q,PP);
ecn2_copy(P,PM);
ecn2_sub(_MIPP_ Q,PM);
MR_OUT
return TRUE;
}
t1.a = mr_mip->w8;
t1.b = mr_mip->w9;
t2.a = mr_mip->w10;
t2.b = mr_mip->w11;
lam.a = mr_mip->w12;
lam.b = mr_mip->w13;
zzn2_copy(&(P->x),&t2);
zzn2_sub(_MIPP_ &t2,&(Q->x),&t2);
zzn2_inv(_MIPP_ &t2); /* only one inverse required */
zzn2_add(_MIPP_ &(P->x),&(Q->x),&(PP->x));
zzn2_copy(&(PP->x),&(PM->x));
zzn2_copy(&(P->y),&t1);
zzn2_sub(_MIPP_ &t1,&(Q->y),&t1);
zzn2_copy(&t1,&lam);
zzn2_mul(_MIPP_ &lam,&t2,&lam);
zzn2_copy(&lam,&t1);
zzn2_sqr(_MIPP_ &t1,&t1);
zzn2_sub(_MIPP_ &t1,&(PP->x),&(PP->x));
zzn2_copy(&(Q->x),&(PP->y));
zzn2_sub(_MIPP_ &(PP->y),&(PP->x),&(PP->y));
zzn2_mul(_MIPP_ &(PP->y),&lam,&(PP->y));
zzn2_sub(_MIPP_ &(PP->y),&(Q->y),&(PP->y));
zzn2_copy(&(P->y),&t1);
zzn2_add(_MIPP_ &t1,&(Q->y),&t1);
zzn2_copy(&t1,&lam);
zzn2_mul(_MIPP_ &lam,&t2,&lam);
zzn2_copy(&lam,&t1);
zzn2_sqr(_MIPP_ &t1,&t1);
zzn2_sub(_MIPP_ &t1,&(PM->x),&(PM->x));
zzn2_copy(&(Q->x),&(PM->y));
zzn2_sub(_MIPP_ &(PM->y),&(PM->x),&(PM->y));
zzn2_mul(_MIPP_ &(PM->y),&lam,&(PM->y));
zzn2_add(_MIPP_ &(PM->y),&(Q->y),&(PM->y));
PP->marker=MR_EPOINT_NORMALIZED;
PM->marker=MR_EPOINT_NORMALIZED;
return TRUE;
}
BOOL ecn2_add3(_MIPD_ ecn2 *Q,ecn2 *P,zzn2 *lam,zzn2 *ex1,zzn2 *ex2)
{ /* P+=Q */
BOOL Doubling=FALSE;
int twist;
int iA;
zzn2 t1,t2,t3;
zzn2 Yzzz;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
t1.a = mr_mip->w8;
t1.b = mr_mip->w9;
t2.a = mr_mip->w10;
t2.b = mr_mip->w11;
t3.a = mr_mip->w12;
t3.b = mr_mip->w13;
Yzzz.a = mr_mip->w3;
Yzzz.b = mr_mip->w4;
twist=mr_mip->TWIST;
if (mr_mip->ERNUM) return FALSE;
if (P->marker==MR_EPOINT_INFINITY)
{
ecn2_copy(Q,P);
return Doubling;
}
if (Q->marker==MR_EPOINT_INFINITY) return Doubling;
MR_IN(205)
if (Q!=P && Q->marker==MR_EPOINT_GENERAL)
{ /* Sorry, this code is optimized for mixed addition only */
mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS);
MR_OUT
return Doubling;
}
#ifndef MR_AFFINE_ONLY
if (mr_mip->coord==MR_AFFINE)
{
#endif
if (!zzn2_compare(&(P->x),&(Q->x)))
{
zzn2_copy(&(P->y),&t1);
zzn2_sub(_MIPP_ &t1,&(Q->y),&t1);
zzn2_copy(&(P->x),&t2);
zzn2_sub(_MIPP_ &t2,&(Q->x),&t2);
zzn2_copy(&t1,lam);
zzn2_inv(_MIPP_ &t2);
zzn2_mul(_MIPP_ lam,&t2,lam);
zzn2_add(_MIPP_ &(P->x),&(Q->x),&(P->x));
zzn2_copy(lam,&t1);
zzn2_sqr(_MIPP_ &t1,&t1);
zzn2_sub(_MIPP_ &t1,&(P->x),&(P->x));
zzn2_copy(&(Q->x),&(P->y));
zzn2_sub(_MIPP_ &(P->y),&(P->x),&(P->y));
zzn2_mul(_MIPP_ &(P->y),lam,&(P->y));
zzn2_sub(_MIPP_ &(P->y),&(Q->y),&(P->y));
}
else
{
if (!zzn2_compare(&(P->y),&(Q->y)) || zzn2_iszero(&(P->y)))
{
ecn2_zero(P);
zzn2_from_int(_MIPP_ 1,lam);
MR_OUT
return Doubling;
}
zzn2_copy(&(P->x),&t1);
zzn2_copy(&(P->x),&t2);
zzn2_copy(&(P->x),lam);
zzn2_sqr(_MIPP_ lam,lam);
zzn2_add(_MIPP_ lam,lam,&t3);
zzn2_add(_MIPP_ lam,&t3,lam);
if (mr_abs(mr_mip->Asize)Asize,&t3);
else zzn2_from_zzn(mr_mip->A,&t3);
if (twist)
{
if (twist==MR_QUARTIC_M)
{
zzn2_txx(_MIPP_ &t3);
}
if (twist==MR_QUARTIC_D)
{
zzn2_txd(_MIPP_ &t3);
}
if (twist==MR_QUADRATIC)
{
zzn2_txx(_MIPP_ &t3);
zzn2_txx(_MIPP_ &t3);
}
/*
if (mr_mip->Bsize==0)
{ // assume its the quartic twist
zzn2_txx(_MIPP_ &t3);
}
else
{
zzn2_txx(_MIPP_ &t3);
zzn2_txx(_MIPP_ &t3);
}
*/
}
zzn2_add(_MIPP_ lam,&t3,lam);
zzn2_add(_MIPP_ &(P->y),&(P->y),&t3);
zzn2_inv(_MIPP_ &t3);
zzn2_mul(_MIPP_ lam,&t3,lam);
zzn2_add(_MIPP_ &t2,&(P->x),&t2);
zzn2_copy(lam,&(P->x));
zzn2_sqr(_MIPP_ &(P->x),&(P->x));
zzn2_sub(_MIPP_ &(P->x),&t2,&(P->x));
zzn2_sub(_MIPP_ &t1,&(P->x),&t1);
zzn2_mul(_MIPP_ &t1,lam,&t1);
zzn2_sub(_MIPP_ &t1,&(P->y),&(P->y));
}
P->marker=MR_EPOINT_NORMALIZED;
MR_OUT
return Doubling;
#ifndef MR_AFFINE_ONLY
}
if (Q==P) Doubling=TRUE;
zzn2_copy(&(Q->x),&t3);
zzn2_copy(&(Q->y),&Yzzz);
if (!Doubling)
{
if (P->marker!=MR_EPOINT_NORMALIZED)
{
zzn2_sqr(_MIPP_ &(P->z),&t1); /* 1S */
zzn2_mul(_MIPP_ &t3,&t1,&t3); /* 1M */
zzn2_mul(_MIPP_ &t1,&(P->z),&t1); /* 1M */
zzn2_mul(_MIPP_ &Yzzz,&t1,&Yzzz); /* 1M */
}
if (zzn2_compare(&t3,&(P->x)))
{
if (!zzn2_compare(&Yzzz,&(P->y)) || zzn2_iszero(&(P->y)))
{
ecn2_zero(P);
zzn2_from_int(_MIPP_ 1,lam);
MR_OUT
return Doubling;
}
else Doubling=TRUE;
}
}
if (!Doubling)
{ /* Addition */
zzn2_sub(_MIPP_ &t3,&(P->x),&t3);
zzn2_sub(_MIPP_ &Yzzz,&(P->y),lam);
if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&t3,&(P->z));
else zzn2_mul(_MIPP_ &(P->z),&t3,&(P->z)); /* 1M */
zzn2_sqr(_MIPP_ &t3,&t1); /* 1S */
zzn2_mul(_MIPP_ &t1,&t3,&Yzzz); /* 1M */
zzn2_mul(_MIPP_ &t1,&(P->x),&t1); /* 1M */
zzn2_copy(&t1,&t3);
zzn2_add(_MIPP_ &t3,&t3,&t3);
zzn2_sqr(_MIPP_ lam,&(P->x)); /* 1S */
zzn2_sub(_MIPP_ &(P->x),&t3,&(P->x));
zzn2_sub(_MIPP_ &(P->x),&Yzzz,&(P->x));
zzn2_sub(_MIPP_ &t1,&(P->x),&t1);
zzn2_mul(_MIPP_ &t1,lam,&t1); /* 1M */
zzn2_mul(_MIPP_ &Yzzz,&(P->y),&Yzzz); /* 1M */
zzn2_sub(_MIPP_ &t1,&Yzzz,&(P->y));
/*
zzn2_sub(_MIPP_ &(P->x),&t3,&t1);
zzn2_sub(_MIPP_ &(P->y),&Yzzz,lam);
if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&t1,&(P->z));
else zzn2_mul(_MIPP_ &(P->z),&t1,&(P->z));
zzn2_sqr(_MIPP_ &t1,&t2);
zzn2_add(_MIPP_ &(P->x),&t3,&t3);
zzn2_mul(_MIPP_ &t3,&t2,&t3);
zzn2_sqr(_MIPP_ lam,&(P->x));
zzn2_sub(_MIPP_ &(P->x),&t3,&(P->x));
zzn2_mul(_MIPP_ &t2,&t1,&t2);
zzn2_add(_MIPP_ &(P->x),&(P->x),&t1);
zzn2_sub(_MIPP_ &t3,&t1,&t3);
zzn2_mul(_MIPP_ &t3,lam,&t3);
zzn2_add(_MIPP_ &(P->y),&Yzzz,&t1);
zzn2_mul(_MIPP_ &t2,&t1,&t2);
zzn2_sub(_MIPP_ &t3,&t2,&(P->y));
zzn2_div2(_MIPP_ &(P->y));
*/
}
else
{ /* doubling */
zzn2_sqr(_MIPP_ &(P->y),&t3); /* 1S */
iA=mr_mip->Asize;
if (iA!=0)
{
if (P->marker==MR_EPOINT_NORMALIZED) zzn2_from_int(_MIPP_ 1,&t1);
else zzn2_sqr(_MIPP_ &(P->z),&t1); /* 1S */
if (ex2!=NULL) zzn2_copy(&t1,ex2);
if (iA==-3 && twist<=MR_QUADRATIC)
{
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t1); /* quadratic twist */
zzn2_sub(_MIPP_ &(P->x),&t1,lam);
zzn2_add(_MIPP_ &t1,&(P->x),&t1);
zzn2_mul(_MIPP_ lam,&t1,lam); /* 1M */
zzn2_add(_MIPP_ lam,lam,&t2);
zzn2_add(_MIPP_ lam,&t2,lam);
}
else
{
zzn2_sqr(_MIPP_ &(P->x),lam); /* 1S */
zzn2_add(_MIPP_ lam,lam,&t2);
zzn2_add(_MIPP_ lam,&t2,lam);
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t1); /* quadratic twist */
zzn2_sqr(_MIPP_ &t1,&t1); /* 1S */
if (twist==MR_QUARTIC_M) zzn2_txx(_MIPP_ &t1); /* quartic twist */
if (twist==MR_QUARTIC_D) zzn2_txd(_MIPP_ &t1); /* quartic twist */
if (iA!=1)
{ /* optimized for iA=1 case */
if (iAA,&t1);
}
zzn2_add(_MIPP_ lam,&t1,lam);
}
}
else
{
zzn2_sqr(_MIPP_ &(P->x),lam); /* 1S */
zzn2_add(_MIPP_ lam,lam,&t2);
zzn2_add(_MIPP_ lam,&t2,lam);
}
zzn2_mul(_MIPP_ &(P->x),&t3,&t1); /* 1M */
zzn2_add(_MIPP_ &t1,&t1,&t1);
zzn2_add(_MIPP_ &t1,&t1,&t1);
zzn2_sqr(_MIPP_ lam,&(P->x)); /* 1S */
zzn2_add(_MIPP_ &t1,&t1,&t2);
zzn2_sub(_MIPP_ &(P->x),&t2,&(P->x));
if (P->marker==MR_EPOINT_NORMALIZED) zzn2_copy(&(P->y),&(P->z));
else zzn2_mul(_MIPP_ &(P->z),&(P->y),&(P->z)); /* 1M */
zzn2_add(_MIPP_ &(P->z),&(P->z),&(P->z));
zzn2_add(_MIPP_ &t3,&t3,&t3);
if (ex1!=NULL) zzn2_copy(&t3,ex1);
zzn2_sqr(_MIPP_ &t3,&t3); /* 1S */
zzn2_add(_MIPP_ &t3,&t3,&t3);
zzn2_sub(_MIPP_ &t1,&(P->x),&t1);
zzn2_mul(_MIPP_ lam,&t1,&(P->y)); /* 1M */
zzn2_sub(_MIPP_ &(P->y),&t3,&(P->y));
}
P->marker=MR_EPOINT_GENERAL;
MR_OUT
return Doubling;
#endif
}
/* Dahmen, Okeya and Schepers "Affine Precomputation with Sole Inversion in Elliptic Curve Cryptography" */
/* Precomputes table into T. Assumes first P has been copied to P[0], then calculates 3P, 5P, 7P etc. into T */
#define MR_PRE_2 (14+4*MR_ECC_STORE_N2)
static void ecn2_pre(_MIPD_ int sz,BOOL norm,ecn2 *PT)
{
int twist;
int i,j;
zzn2 A,B,C,D,E,T,W;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
#ifndef MR_STATIC
zzn2 *d=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2));
zzn2 *e=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2));
char *mem = (char *)memalloc(_MIPP_ 14+4*sz);
#else
zzn2 d[MR_ECC_STORE_N2],e[MR_ECC_STORE_N2];
char mem[MR_BIG_RESERVE(MR_PRE_2)];
memset(mem, 0, MR_BIG_RESERVE(MR_PRE_2));
#endif
twist=mr_mip->TWIST;
j=0;
A.a= mirvar_mem(_MIPP_ mem, j++);
A.b= mirvar_mem(_MIPP_ mem, j++);
B.a= mirvar_mem(_MIPP_ mem, j++);
B.b= mirvar_mem(_MIPP_ mem, j++);
C.a= mirvar_mem(_MIPP_ mem, j++);
C.b= mirvar_mem(_MIPP_ mem, j++);
D.a= mirvar_mem(_MIPP_ mem, j++);
D.b= mirvar_mem(_MIPP_ mem, j++);
E.a= mirvar_mem(_MIPP_ mem, j++);
E.b= mirvar_mem(_MIPP_ mem, j++);
T.a= mirvar_mem(_MIPP_ mem, j++);
T.b= mirvar_mem(_MIPP_ mem, j++);
W.a= mirvar_mem(_MIPP_ mem, j++);
W.b= mirvar_mem(_MIPP_ mem, j++);
for (i=0;iAsize)Asize,&A);
else zzn2_from_zzn(mr_mip->A,&A);
if (twist)
{
if (twist==MR_QUARTIC_M)
{
zzn2_txx(_MIPP_ &A);
}
if (twist==MR_QUARTIC_D)
{
zzn2_txd(_MIPP_ &A);
}
if (twist==MR_QUADRATIC)
{
zzn2_txx(_MIPP_ &A);
zzn2_txx(_MIPP_ &A);
}
/*
if (mr_mip->Bsize==0)
{ // assume its the quartic twist
zzn2_txx(_MIPP_ &A);
}
else
{
zzn2_txx(_MIPP_ &A);
zzn2_txx(_MIPP_ &A);
}
*/
}
zzn2_add(_MIPP_ &A,&T,&A); /* 3. A=3x^2+a */
zzn2_copy(&A,&W);
zzn2_add(_MIPP_ &C,&C,&B);
zzn2_add(_MIPP_ &B,&C,&B);
zzn2_mul(_MIPP_ &B,&(PT[0].x),&B); /* 4. B=3C.x */
zzn2_sqr(_MIPP_ &A,&d[1]);
zzn2_sub(_MIPP_ &d[1],&B,&d[1]); /* 5. d_1=A^2-B */
zzn2_sqr(_MIPP_ &d[1],&E); /* 6. E=d_1^2 */
zzn2_mul(_MIPP_ &B,&E,&B); /* 7. B=E.B */
zzn2_sqr(_MIPP_ &C,&C); /* 8. C=C^2 */
zzn2_mul(_MIPP_ &E,&d[1],&D); /* 9. D=E.d_1 */
zzn2_mul(_MIPP_ &A,&d[1],&A);
zzn2_add(_MIPP_ &A,&C,&A);
zzn2_negate(_MIPP_ &A,&A); /* 10. A=-d_1*A-C */
zzn2_add(_MIPP_ &D,&D,&T);
zzn2_sqr(_MIPP_ &A,&d[2]);
zzn2_sub(_MIPP_ &d[2],&T,&d[2]);
zzn2_sub(_MIPP_ &d[2],&B,&d[2]); /* 11. d_2=A^2-2D-B */
if (sz>3)
{
zzn2_sqr(_MIPP_ &d[2],&E); /* 12. E=d_2^2 */
zzn2_add(_MIPP_ &T,&D,&T);
zzn2_add(_MIPP_ &T,&B,&T);
zzn2_mul(_MIPP_ &T,&E,&B); /* 13. B=E(B+3D) */
zzn2_add(_MIPP_ &A,&A,&T);
zzn2_add(_MIPP_ &C,&T,&C);
zzn2_mul(_MIPP_ &C,&D,&C); /* 14. C=D(2A+C) */
zzn2_mul(_MIPP_ &d[2],&E,&D); /* 15. D=E.d_2 */
zzn2_mul(_MIPP_ &A,&d[2],&A);
zzn2_add(_MIPP_ &A,&C,&A);
zzn2_negate(_MIPP_ &A,&A); /* 16. A=-d_2*A-C */
zzn2_sqr(_MIPP_ &A,&d[3]);
zzn2_sub(_MIPP_ &d[3],&D,&d[3]);
zzn2_sub(_MIPP_ &d[3],&B,&d[3]); /* 17. d_3=A^2-D-B */
for (i=4;i0;i--)
{
zzn2_copy(&d[i],&B);
zzn2_mul(_MIPP_ &e[i-1],&A,&d[i]);
zzn2_mul(_MIPP_ &A,&B,&A);
}
zzn2_copy(&A,&d[0]);
for (i=1;i=1;)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
n=mr_naf_window(_MIPP_ k,h,i,&nbs,&nzs,MR_ECC_STORE_N2);
for (j=0;j0) {nadds++; ecn2_add(_MIPP_ &T[n/2],P);}
if (n<0) {nadds++; ecn2_sub(_MIPP_ &T[(-n)/2],P);}
i-=nbs;
if (nzs)
{
for (j=0;j0) bb=logb2(_MIPP_ e)-1;
else bb=logb2(_MIPP_ f)-1;
ecn2_add_sub(_MIPP_ &P1,&P2,&PS,&PD);
ecn2_zero(R);
nadds=0;
while (bb>=0)
{ /* add/subtract method */
if (mr_mip->user!=NULL) (*mr_mip->user)();
ecn2_add(_MIPP_ R,R);
e1=h1=e2=h2=0;
if (mr_testbit(_MIPP_ d,bb)) e2=1;
if (mr_testbit(_MIPP_ e,bb)) h2=1;
if (mr_testbit(_MIPP_ c,bb)) e1=1;
if (mr_testbit(_MIPP_ f,bb)) h1=1;
if (e1!=h1)
{
if (e2==h2)
{
if (h1==1) {ecn2_add(_MIPP_ &P1,R); nadds++;}
else {ecn2_sub(_MIPP_ &P1,R); nadds++;}
}
else
{
if (h1==1)
{
if (h2==1) {ecn2_add(_MIPP_ &PS,R); nadds++;}
else {ecn2_add(_MIPP_ &PD,R); nadds++;}
}
else
{
if (h2==1) {ecn2_sub(_MIPP_ &PD,R); nadds++;}
else {ecn2_sub(_MIPP_ &PS,R); nadds++;}
}
}
}
else if (e2!=h2)
{
if (h2==1) {ecn2_add(_MIPP_ &P2,R); nadds++;}
else {ecn2_sub(_MIPP_ &P2,R); nadds++;}
}
bb-=1;
}
ecn2_norm(_MIPP_ R);
MR_OUT
#ifndef MR_STATIC
memkill(_MIPP_ mem, MR_MUL2_JSF_RESERVE);
#else
memset(mem, 0, MR_BIG_RESERVE(MR_MUL2_JSF_RESERVE));
#endif
return nadds;
}
/* General purpose multi-exponentiation engine, using inter-leaving algorithm. Calculate aP+bQ+cR+dS...
Inputs are divided into two groups of sizes wa<4 and wb<4. For the first group if the points are fixed the
first precomputed Table Ta[] may be taken from ROM. For the second group if the points are variable Tb[j] will
have to computed online. Each group has its own precomputed store size, sza (=8?) and szb (=20?) respectively.
The values a,b,c.. are provided in ma[] and mb[], and 3.a,3.b,3.c (as required by the NAF) are provided in
ma3[] and mb3[]. If only one group is required, set wb=0 and pass NULL pointers.
*/
int ecn2_muln_engine(_MIPD_ int wa,int sza,int wb,int szb,big *ma,big *ma3,big *mb,big *mb3,ecn2 *Ta,ecn2 *Tb,ecn2 *R)
{ /* general purpose interleaving algorithm engine for multi-exp */
int i,j,tba[4],pba[4],na[4],sa[4],tbb[4],pbb[4],nb[4],sb[4],nbits,nbs,nzs;
int nadds;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
ecn2_zero(R);
nbits=0;
for (i=0;inbits) nbits=j; }
for (i=0;inbits) nbits=j; }
nadds=0;
for (i=nbits-1;i>=1;i--)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
if (R->marker!=MR_EPOINT_INFINITY) ecn2_add(_MIPP_ R,R);
for (j=0;j0) {ecn2_add(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;}
if (na[j]<0) {ecn2_sub(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;}
}
else
{
if (na[j]>0) {ecn2_sub(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;}
if (na[j]<0) {ecn2_add(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;}
}
}
}
for (j=0;j0) {ecn2_add(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;}
if (nb[j]<0) {ecn2_sub(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;}
}
else
{
if (nb[j]>0) {ecn2_sub(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;}
if (nb[j]<0) {ecn2_add(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;}
}
}
}
}
ecn2_norm(_MIPP_ R);
return nadds;
}
/* Routines to support Galbraith, Lin, Scott (GLS) method for ECC */
/* requires an endomorphism psi */
/* *********************** */
/* Precompute T - first half from i.P, second half from i.psi(P) */
void ecn2_precomp_gls(_MIPD_ int sz,BOOL norm,ecn2 *P,zzn2 *psi,ecn2 *T)
{
int i,j;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
j=0;
MR_IN(219)
ecn2_norm(_MIPP_ P);
ecn2_copy(P,&T[0]);
ecn2_pre(_MIPP_ sz,norm,T); /* precompute table */
for (i=sz;inb || mr_mip->ERNUM) return FALSE;
t=MR_ROUNDUP(nb,window);
if (t<2) return FALSE;
MR_IN(221)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return FALSE;
}
#endif
B->window=window;
B->max=nb;
table=(ecn2 *)mr_alloc(_MIPP_ (1<a=mirvar(_MIPP_ 0);
B->b=mirvar(_MIPP_ 0);
B->n=mirvar(_MIPP_ 0);
copy(a,B->a);
copy(b,B->b);
copy(n,B->n);
ecurve_init(_MIPP_ a,b,n,MR_AFFINE);
mr_mip->TWIST=MR_QUADRATIC;
w.x.a=mirvar(_MIPP_ 0);
w.x.b=mirvar(_MIPP_ 0);
w.y.a=mirvar(_MIPP_ 0);
w.y.b=mirvar(_MIPP_ 0);
w.marker=MR_EPOINT_INFINITY;
ecn2_set(_MIPP_ x,y,&w);
table[0].x.a=mirvar(_MIPP_ 0);
table[0].x.b=mirvar(_MIPP_ 0);
table[0].y.a=mirvar(_MIPP_ 0);
table[0].y.b=mirvar(_MIPP_ 0);
table[0].marker=MR_EPOINT_INFINITY;
table[1].x.a=mirvar(_MIPP_ 0);
table[1].x.b=mirvar(_MIPP_ 0);
table[1].y.a=mirvar(_MIPP_ 0);
table[1].y.b=mirvar(_MIPP_ 0);
table[1].marker=MR_EPOINT_INFINITY;
ecn2_copy(&w,&table[1]);
for (j=0;jlen;
bptr=0;
B->table=(mr_small *)mr_alloc(_MIPP_ 4*len*(1<table[bptr++]=table[i].x.a->w[j];
for (j=0;jtable[bptr++]=table[i].x.b->w[j];
for (j=0;jtable[bptr++]=table[i].y.a->w[j];
for (j=0;jtable[bptr++]=table[i].y.b->w[j];
mr_free(table[i].x.a);
mr_free(table[i].x.b);
mr_free(table[i].y.a);
mr_free(table[i].y.b);
}
mr_free(table);
MR_OUT
return TRUE;
}
void ecn2_brick_end(ebrick *B)
{
mirkill(B->n);
mirkill(B->b);
mirkill(B->a);
mr_free(B->table);
}
#else
/* use precomputated table in ROM */
void ecn2_brick_init(ebrick *B,const mr_small* rom,big a,big b,big n,int window,int nb)
{
B->table=rom;
B->a=a; /* just pass a pointer */
B->b=b;
B->n=n;
B->window=window; /* 2^4=16 stored values */
B->max=nb;
}
#endif
/*
void ecn2_mul_brick(_MIPD_ ebrick *B,big e,zzn2 *x,zzn2 *y)
{
int i,j,t,len,maxsize,promptr;
ecn2 w,z;
#ifdef MR_STATIC
char mem[MR_BIG_RESERVE(10)];
#else
char *mem;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (size(e)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
t=MR_ROUNDUP(B->max,B->window);
MR_IN(116)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return;
}
#endif
if (logb2(_MIPP_ e) > B->max)
{
mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG);
MR_OUT
return;
}
ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST);
mr_mip->TWIST=MR_QUADRATIC;
#ifdef MR_STATIC
memset(mem,0,MR_BIG_RESERVE(10));
#else
mem=memalloc(_MIPP_ 10);
#endif
w.x.a=mirvar_mem(_MIPP_ mem, 0);
w.x.b=mirvar_mem(_MIPP_ mem, 1);
w.y.a=mirvar_mem(_MIPP_ mem, 2);
w.y.b=mirvar_mem(_MIPP_ mem, 3);
w.z.a=mirvar_mem(_MIPP_ mem, 4);
w.z.b=mirvar_mem(_MIPP_ mem, 5);
w.marker=MR_EPOINT_INFINITY;
z.x.a=mirvar_mem(_MIPP_ mem, 6);
z.x.b=mirvar_mem(_MIPP_ mem, 7);
z.y.a=mirvar_mem(_MIPP_ mem, 8);
z.y.b=mirvar_mem(_MIPP_ mem, 9);
z.marker=MR_EPOINT_INFINITY;
len=B->n->len;
maxsize=4*(1<window)*len;
for (i=t-1;i>=0;i--)
{
j=recode(_MIPP_ e,t,B->window,i);
ecn2_add(_MIPP_ &w,&w);
if (j>0)
{
promptr=4*j*len;
init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr);
z.marker=MR_EPOINT_NORMALIZED;
ecn2_add(_MIPP_ &z,&w);
}
}
ecn2_norm(_MIPP_ &w);
ecn2_getxy(&w,x,y);
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
#else
memset(mem,0,MR_BIG_RESERVE(10));
#endif
MR_OUT
}
*/
void ecn2_mul_brick_gls(_MIPD_ ebrick *B,big *e,zzn2 *psi,zzn2 *x,zzn2 *y)
{
int i,j,k,t,len,maxsize,promptr,se[2];
ecn2 w,z;
#ifdef MR_STATIC
char mem[MR_BIG_RESERVE(10)];
#else
char *mem;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
for (k=0;k<2;k++) se[k]=exsign(e[k]);
t=MR_ROUNDUP(B->max,B->window);
MR_IN(222)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return;
}
#endif
if (logb2(_MIPP_ e[0])>B->max || logb2(_MIPP_ e[1])>B->max)
{
mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG);
MR_OUT
return;
}
ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST);
mr_mip->TWIST=MR_QUADRATIC;
#ifdef MR_STATIC
memset(mem,0,MR_BIG_RESERVE(10));
#else
mem=(char *)memalloc(_MIPP_ 10);
#endif
z.x.a=mirvar_mem(_MIPP_ mem, 0);
z.x.b=mirvar_mem(_MIPP_ mem, 1);
z.y.a=mirvar_mem(_MIPP_ mem, 2);
z.y.b=mirvar_mem(_MIPP_ mem, 3);
z.marker=MR_EPOINT_INFINITY;
w.x.a=mirvar_mem(_MIPP_ mem, 4);
w.x.b=mirvar_mem(_MIPP_ mem, 5);
w.y.a=mirvar_mem(_MIPP_ mem, 6);
w.y.b=mirvar_mem(_MIPP_ mem, 7);
#ifndef MR_AFFINE_ONLY
w.z.a=mirvar_mem(_MIPP_ mem, 8);
w.z.b=mirvar_mem(_MIPP_ mem, 9);
#endif
w.marker=MR_EPOINT_INFINITY;
len=B->n->len;
maxsize=4*(1<window)*len;
for (i=t-1;i>=0;i--)
{
ecn2_add(_MIPP_ &w,&w);
for (k=0;k<2;k++)
{
j=recode(_MIPP_ e[k],t,B->window,i);
if (j>0)
{
promptr=4*j*len;
init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr);
z.marker=MR_EPOINT_NORMALIZED;
if (k==1) ecn2_psi(_MIPP_ psi,&z);
if (se[k]==PLUS) ecn2_add(_MIPP_ &z,&w);
else ecn2_sub(_MIPP_ &z,&w);
}
}
}
ecn2_norm(_MIPP_ &w);
ecn2_getxy(&w,x,y);
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
#else
memset(mem,0,MR_BIG_RESERVE(10));
#endif
MR_OUT
}
#else
/* Now for curves in Inverted Twisted Edwards Form */
BOOL ecn2_iszero(ecn2 *a)
{
if (a->marker==MR_EPOINT_INFINITY) return TRUE;
return FALSE;
}
void ecn2_copy(ecn2 *a,ecn2 *b)
{
zzn2_copy(&(a->x),&(b->x));
zzn2_copy(&(a->y),&(b->y));
if (a->marker==MR_EPOINT_GENERAL) zzn2_copy(&(a->z),&(b->z));
b->marker=a->marker;
}
void ecn2_zero(ecn2 *a)
{
zzn2_zero(&(a->x));
zzn2_zero(&(a->y));
if (a->marker==MR_EPOINT_GENERAL) zzn2_zero(&(a->z));
a->marker=MR_EPOINT_INFINITY;
}
BOOL ecn2_compare(_MIPD_ ecn2 *a,ecn2 *b)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(193)
ecn2_norm(_MIPP_ a);
ecn2_norm(_MIPP_ b);
MR_OUT
if (zzn2_compare(&(a->x),&(b->x)) && zzn2_compare(&(a->y),&(b->y)) && a->marker==b->marker) return TRUE;
return FALSE;
}
void ecn2_norm(_MIPD_ ecn2 *a)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
if (a->marker!=MR_EPOINT_GENERAL) return;
MR_IN(194)
zzn2_inv(_MIPP_ &(a->z));
zzn2_mul(_MIPP_ &(a->x),&(a->z),&(a->x));
zzn2_mul(_MIPP_ &(a->y),&(a->z),&(a->y));
zzn2_from_zzn(mr_mip->one,&(a->z));
a->marker=MR_EPOINT_NORMALIZED;
MR_OUT
}
void ecn2_get(_MIPD_ ecn2 *e,zzn2 *x,zzn2 *y,zzn2 *z)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2_copy(&(e->x),x);
zzn2_copy(&(e->y),y);
if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z);
else zzn2_from_zzn(mr_mip->one,z);
}
void ecn2_getxy(ecn2 *e,zzn2 *x,zzn2 *y)
{
zzn2_copy(&(e->x),x);
zzn2_copy(&(e->y),y);
}
void ecn2_getx(ecn2 *e,zzn2 *x)
{
zzn2_copy(&(e->x),x);
}
void ecn2_getz(_MIPD_ ecn2 *e,zzn2 *z)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (e->marker==MR_EPOINT_GENERAL) zzn2_copy(&(e->z),z);
else zzn2_from_zzn(mr_mip->one,z);
}
void ecn2_psi(_MIPD_ zzn2 *psi,ecn2 *P)
{ /* apply GLS morphism to P */
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
MR_IN(212)
zzn2_conj(_MIPP_ &(P->x),&(P->x));
zzn2_conj(_MIPP_ &(P->y),&(P->y));
if (P->marker==MR_EPOINT_GENERAL)
zzn2_conj(_MIPP_ &(P->z),&(P->z));
zzn2_mul(_MIPP_ &(P->x),&psi[0],&(P->x));
MR_OUT
}
/*
static void out_zzn2(zzn2 *x)
{
redc(x->a,x->a);
redc(x->b,x->b);
cotnum(x->a,stdout);
cotnum(x->b,stdout);
nres(x->a,x->a);
nres(x->b,x->b);
}
*/
/* find RHS=(x^2-B)/(x^2-A) */
void ecn2_rhs(_MIPD_ zzn2 *x,zzn2 *rhs)
{ /* calculate RHS of elliptic curve equation */
int twist;
zzn2 A,B;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
twist=mr_mip->TWIST;
MR_IN(202)
A.a=mr_mip->w8;
A.b=mr_mip->w9;
B.a=mr_mip->w10;
B.b=mr_mip->w11;
zzn2_from_zzn(mr_mip->A,&A);
zzn2_from_zzn(mr_mip->B,&B);
if (twist==MR_QUADRATIC)
{ /* quadratic twist */
zzn2_txx(_MIPP_ &A);
zzn2_txx(_MIPP_ &B);
}
zzn2_sqr(_MIPP_ x,rhs);
zzn2_sub(_MIPP_ rhs,&B,&B);
zzn2_sub(_MIPP_ rhs,&A,&A);
zzn2_inv(_MIPP_ &A);
zzn2_mul(_MIPP_ &A,&B,rhs);
MR_OUT
}
BOOL ecn2_set(_MIPD_ zzn2 *x,zzn2 *y,ecn2 *e)
{
zzn2 lhs,rhs;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(195)
lhs.a=mr_mip->w12;
lhs.b=mr_mip->w13;
rhs.a=mr_mip->w14;
rhs.b=mr_mip->w15;
ecn2_rhs(_MIPP_ x,&rhs);
zzn2_sqr(_MIPP_ y,&lhs);
if (!zzn2_compare(&lhs,&rhs))
{
MR_OUT
return FALSE;
}
zzn2_copy(x,&(e->x));
zzn2_copy(y,&(e->y));
e->marker=MR_EPOINT_NORMALIZED;
MR_OUT
return TRUE;
}
#ifndef MR_NOSUPPORT_COMPRESSION
BOOL ecn2_setx(_MIPD_ zzn2 *x,ecn2 *e)
{
zzn2 rhs;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(201)
rhs.a=mr_mip->w12;
rhs.b=mr_mip->w13;
ecn2_rhs(_MIPP_ x,&rhs);
if (!zzn2_iszero(&rhs))
{
if (!zzn2_qr(_MIPP_ &rhs))
{
MR_OUT
return FALSE;
}
zzn2_sqrt(_MIPP_ &rhs,&rhs);
}
zzn2_copy(x,&(e->x));
zzn2_copy(&rhs,&(e->y));
e->marker=MR_EPOINT_NORMALIZED;
MR_OUT
return TRUE;
}
#endif
void ecn2_setxyz(zzn2 *x,zzn2 *y,zzn2 *z,ecn2 *e)
{
zzn2_copy(x,&(e->x));
zzn2_copy(y,&(e->y));
zzn2_copy(z,&(e->z));
e->marker=MR_EPOINT_GENERAL;
}
/* Normalise an array of points of length mERNUM) return FALSE;
if (m>MR_MAX_M_T_S) return FALSE;
MR_IN(215)
one.a=mr_mip->w12;
one.b=mr_mip->w13;
zzn2_from_zzn(mr_mip->one,&one);
for (i=0;ione,&(p[i].z));
}
MR_OUT
return TRUE;
}
BOOL ecn2_add(_MIPD_ ecn2 *Q,ecn2 *P)
{ /* P+=Q */
BOOL Doubling=FALSE;
int twist;
zzn2 t2,t3,t4;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
t2.a = mr_mip->w8;
t2.b = mr_mip->w9;
t3.a = mr_mip->w10;
t3.b = mr_mip->w11;
t4.a = mr_mip->w12;
t4.b = mr_mip->w13;
twist=mr_mip->TWIST;
if (mr_mip->ERNUM) return FALSE;
if (P->marker==MR_EPOINT_INFINITY)
{
ecn2_copy(Q,P);
return Doubling;
}
if (Q->marker==MR_EPOINT_INFINITY) return Doubling;
if (Q==P)
{
Doubling=TRUE;
if (P->marker==MR_EPOINT_INFINITY)
{ /* 2 times infinity == infinity ! */
return Doubling;
}
}
MR_IN(205)
if (!Doubling)
{ /* Addition */
zzn2_add(_MIPP_ &(Q->x),&(Q->y),&t2);
zzn2_add(_MIPP_ &(P->x),&(P->y),&t4);
zzn2_mul(_MIPP_ &t4,&t2,&t4); /* I = t4 = (x1+y1)(x2+y2) */
if (Q->marker!=MR_EPOINT_NORMALIZED)
{
if (P->marker==MR_EPOINT_NORMALIZED)
zzn2_copy(&(Q->z),&(P->z));
else
zzn2_mul(_MIPP_ &(Q->z),&(P->z),&(P->z)); /* Z = z1*z2 */
}
else
{
if (P->marker==MR_EPOINT_NORMALIZED)
zzn2_from_zzn(mr_mip->one,&(P->z));
}
zzn2_sqr(_MIPP_ &(P->z),&t2); /* P->z = z1.z2 */
if (mr_abs(mr_mip->Bsize)==MR_TOOBIG)
zzn2_smul(_MIPP_ &t2,mr_mip->B,&t2);
else
zzn2_imul(_MIPP_ &t2,mr_mip->Bsize,&t2);
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &t2); /* B = t2 = d*A^2 */
zzn2_mul(_MIPP_ &(P->x),&(Q->x),&(P->x)); /* X = x1*x2 */
zzn2_mul(_MIPP_ &(P->y),&(Q->y),&(P->y)); /* Y = y1*y2 */
zzn2_sub(_MIPP_ &t4,&(P->x),&t4);
zzn2_sub(_MIPP_ &t4,&(P->y),&t4); /* I = (x1+y1)(x2+y2)-X-Y */
zzn2_mul(_MIPP_ &(P->x),&(P->y),&t3); /* E = t3 = X*Y */
if (mr_abs(mr_mip->Asize)==MR_TOOBIG)
zzn2_smul(_MIPP_ &(P->y),mr_mip->A,&(P->y));
else
zzn2_imul(_MIPP_ &(P->y),mr_mip->Asize,&(P->y));
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->y)); /* Y=aY */
zzn2_sub(_MIPP_ &(P->x),&(P->y),&(P->x)); /* X=X-aY */
zzn2_mul(_MIPP_ &(P->z),&(P->x),&(P->z));
zzn2_mul(_MIPP_ &(P->z),&t4,&(P->z));
zzn2_sub(_MIPP_ &t3,&t2,&(P->y));
zzn2_mul(_MIPP_ &(P->y),&t4,&(P->y));
zzn2_add(_MIPP_ &t3,&t2,&t4);
zzn2_mul(_MIPP_ &(P->x),&t4,&(P->x));
}
else
{ /* doubling */
zzn2_add(_MIPP_ &(P->x),&(P->y),&t2);
zzn2_sqr(_MIPP_ &t2,&t2);
zzn2_sqr(_MIPP_ &(P->x),&(P->x));
zzn2_sqr(_MIPP_ &(P->y),&(P->y));
zzn2_sub(_MIPP_ &t2,&(P->x),&t2);
zzn2_sub(_MIPP_ &t2,&(P->y),&t2); /* E=(X+Y)^2-X^2-Y^2 */
if (P->marker!=MR_EPOINT_NORMALIZED)
zzn2_sqr(_MIPP_ &(P->z),&(P->z));
else
zzn2_from_zzn(mr_mip->one,&(P->z));
zzn2_add(_MIPP_ &(P->z),&(P->z),&(P->z));
if (mr_abs(mr_mip->Bsize)==MR_TOOBIG)
zzn2_smul(_MIPP_ &(P->z),mr_mip->B,&(P->z));
else
zzn2_imul(_MIPP_ &(P->z),mr_mip->Bsize,&(P->z));
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->z));
if (mr_abs(mr_mip->Asize)==MR_TOOBIG)
zzn2_smul(_MIPP_ &(P->y),mr_mip->A,&(P->y));
else
zzn2_imul(_MIPP_ &(P->y),mr_mip->Asize,&(P->y));
if (twist==MR_QUADRATIC) zzn2_txx(_MIPP_ &(P->y));
zzn2_add(_MIPP_ &(P->x),&(P->y),&t3);
zzn2_sub(_MIPP_ &(P->x),&(P->y),&t4);
zzn2_mul(_MIPP_ &t3,&t4,&(P->x));
zzn2_sub(_MIPP_ &t3,&(P->z),&t3);
zzn2_mul(_MIPP_ &t2,&t3,&(P->y));
zzn2_mul(_MIPP_ &t2,&t4,&(P->z));
}
if (zzn2_iszero(&(P->z)))
{
zzn2_from_zzn(mr_mip->one,&(P->x));
zzn2_zero(&(P->y));
P->marker=MR_EPOINT_INFINITY;
}
else P->marker=MR_EPOINT_GENERAL;
MR_OUT
return Doubling;
}
void ecn2_negate(_MIPD_ ecn2 *u,ecn2 *w)
{
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
ecn2_copy(u,w);
if (w->marker!=MR_EPOINT_INFINITY)
zzn2_negate(_MIPP_ &(w->x),&(w->x));
}
BOOL ecn2_sub(_MIPD_ ecn2 *Q,ecn2 *P)
{
BOOL Doubling;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2 lam;
lam.a = mr_mip->w14;
lam.b = mr_mip->w15;
ecn2_negate(_MIPP_ Q,Q);
Doubling=ecn2_add(_MIPP_ Q,P);
ecn2_negate(_MIPP_ Q,Q);
return Doubling;
}
/*
BOOL ecn2_add_sub(_MIPD_ ecn2 *P,ecn2 *Q,ecn2 *PP,ecn2 *PM)
{ PP=P+Q, PM=P-Q. Assumes P and Q are both normalized, and P!=Q
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
zzn2 t1,t2,lam;
if (mr_mip->ERNUM) return FALSE;
PP->marker=MR_EPOINT_NORMALIZED;
PM->marker=MR_EPOINT_NORMALIZED;
return TRUE;
}
*/
/* Precomputation of 3P, 5P, 7P etc. into PT. Assume PT[0] contains P */
#define MR_PRE_2 (6+2*MR_ECC_STORE_N2)
static void ecn2_pre(_MIPD_ int sz,BOOL norm,ecn2 *PT)
{
int i,j;
ecn2 P2;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
#ifndef MR_STATIC
zzn2 *work=(zzn2 *)mr_alloc(_MIPP_ sz,sizeof(zzn2));
char *mem = memalloc(_MIPP_ 6+2*sz);
#else
zzn2 work[MR_ECC_STORE_N2];
char mem[MR_BIG_RESERVE(MR_PRE_2)];
memset(mem, 0, MR_BIG_RESERVE(MR_PRE_2));
#endif
j=0;
P2.x.a=mirvar_mem(_MIPP_ mem, j++);
P2.x.b=mirvar_mem(_MIPP_ mem, j++);
P2.y.a=mirvar_mem(_MIPP_ mem, j++);
P2.y.b=mirvar_mem(_MIPP_ mem, j++);
P2.z.a=mirvar_mem(_MIPP_ mem, j++);
P2.z.b=mirvar_mem(_MIPP_ mem, j++);
for (i=0;i=1;)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
n=mr_naf_window(_MIPP_ k,h,i,&nbs,&nzs,MR_ECC_STORE_N2);
for (j=0;j0) {nadds++; ecn2_add(_MIPP_ &T[n/2],P);}
if (n<0) {nadds++; ecn2_sub(_MIPP_ &T[(-n)/2],P);}
i-=nbs;
if (nzs)
{
for (j=0;j0) bb=logb2(_MIPP_ e)-1;
else bb=logb2(_MIPP_ f)-1;
/*ecn2_add_sub(_MIPP_ &P1,&P2,&PS,&PD);*/
ecn2_copy(&P1,&PS);
ecn2_copy(&P1,&PD);
ecn2_add(_MIPP_ &P2,&PS);
ecn2_sub(_MIPP_ &P2,&PD);
ecn2_zero(R);
nadds=0;
while (bb>=0)
{ /* add/subtract method */
if (mr_mip->user!=NULL) (*mr_mip->user)();
ecn2_add(_MIPP_ R,R);
e1=h1=e2=h2=0;
if (mr_testbit(_MIPP_ d,bb)) e2=1;
if (mr_testbit(_MIPP_ e,bb)) h2=1;
if (mr_testbit(_MIPP_ c,bb)) e1=1;
if (mr_testbit(_MIPP_ f,bb)) h1=1;
if (e1!=h1)
{
if (e2==h2)
{
if (h1==1) {ecn2_add(_MIPP_ &P1,R); nadds++;}
else {ecn2_sub(_MIPP_ &P1,R); nadds++;}
}
else
{
if (h1==1)
{
if (h2==1) {ecn2_add(_MIPP_ &PS,R); nadds++;}
else {ecn2_add(_MIPP_ &PD,R); nadds++;}
}
else
{
if (h2==1) {ecn2_sub(_MIPP_ &PD,R); nadds++;}
else {ecn2_sub(_MIPP_ &PS,R); nadds++;}
}
}
}
else if (e2!=h2)
{
if (h2==1) {ecn2_add(_MIPP_ &P2,R); nadds++;}
else {ecn2_sub(_MIPP_ &P2,R); nadds++;}
}
bb-=1;
}
ecn2_norm(_MIPP_ R);
MR_OUT
#ifndef MR_STATIC
memkill(_MIPP_ mem, MR_MUL2_JSF_RESERVE);
#else
memset(mem, 0, MR_BIG_RESERVE(MR_MUL2_JSF_RESERVE));
#endif
return nadds;
}
/* General purpose multi-exponentiation engine, using inter-leaving algorithm. Calculate aP+bQ+cR+dS...
Inputs are divided into two groups of sizes wa<4 and wb<4. For the first group if the points are fixed the
first precomputed Table Ta[] may be taken from ROM. For the second group if the points are variable Tb[j] will
have to computed online. Each group has its own precomputed store size, sza (=8?) and szb (=20?) respectively.
The values a,b,c.. are provided in ma[] and mb[], and 3.a,3.b,3.c (as required by the NAF) are provided in
ma3[] and mb3[]. If only one group is required, set wb=0 and pass NULL pointers.
*/
int ecn2_muln_engine(_MIPD_ int wa,int sza,int wb,int szb,big *ma,big *ma3,big *mb,big *mb3,ecn2 *Ta,ecn2 *Tb,ecn2 *R)
{ /* general purpose interleaving algorithm engine for multi-exp */
int i,j,tba[4],pba[4],na[4],sa[4],tbb[4],pbb[4],nb[4],sb[4],nbits,nbs,nzs;
int nadds;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
ecn2_zero(R);
nbits=0;
for (i=0;inbits) nbits=j; }
for (i=0;inbits) nbits=j; }
nadds=0;
for (i=nbits-1;i>=1;i--)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
if (R->marker!=MR_EPOINT_INFINITY) ecn2_add(_MIPP_ R,R);
for (j=0;j0) {ecn2_add(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;}
if (na[j]<0) {ecn2_sub(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;}
}
else
{
if (na[j]>0) {ecn2_sub(_MIPP_ &Ta[j*sza+na[j]/2],R); nadds++;}
if (na[j]<0) {ecn2_add(_MIPP_ &Ta[j*sza+(-na[j])/2],R); nadds++;}
}
}
}
for (j=0;j0) {ecn2_add(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;}
if (nb[j]<0) {ecn2_sub(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;}
}
else
{
if (nb[j]>0) {ecn2_sub(_MIPP_ &Tb[j*szb+nb[j]/2],R); nadds++;}
if (nb[j]<0) {ecn2_add(_MIPP_ &Tb[j*szb+(-nb[j])/2],R); nadds++;}
}
}
}
}
ecn2_norm(_MIPP_ R);
return nadds;
}
/* Routines to support Galbraith, Lin, Scott (GLS) method for ECC */
/* requires an endomorphism psi */
/* *********************** */
/* Precompute T - first half from i.P, second half from i.psi(P) */
/* norm=TRUE if the table is to be normalised - which it should be */
/* if it is to be calculated off-line */
void ecn2_precomp_gls(_MIPD_ int sz,BOOL norm,ecn2 *P,zzn2 *psi,ecn2 *T)
{
int i,j;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
j=0;
MR_IN(219)
ecn2_norm(_MIPP_ P);
ecn2_copy(P,&T[0]);
ecn2_pre(_MIPP_ sz,norm,T); /* precompute table */
for (i=sz;inb || mr_mip->ERNUM) return FALSE;
t=MR_ROUNDUP(nb,window);
if (t<2) return FALSE;
MR_IN(221)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return FALSE;
}
#endif
B->window=window;
B->max=nb;
table=mr_alloc(_MIPP_ (1<a=mirvar(_MIPP_ 0);
B->b=mirvar(_MIPP_ 0);
B->n=mirvar(_MIPP_ 0);
copy(a,B->a);
copy(b,B->b);
copy(n,B->n);
ecurve_init(_MIPP_ a,b,n,MR_BEST);
mr_mip->TWIST=MR_QUADRATIC;
w.x.a=mirvar(_MIPP_ 0);
w.x.b=mirvar(_MIPP_ 0);
w.y.a=mirvar(_MIPP_ 0);
w.y.b=mirvar(_MIPP_ 0);
w.z.a=mirvar(_MIPP_ 0);
w.z.b=mirvar(_MIPP_ 0);
w.marker=MR_EPOINT_INFINITY;
ecn2_set(_MIPP_ x,y,&w);
table[0].x.a=mirvar(_MIPP_ 0);
table[0].x.b=mirvar(_MIPP_ 0);
table[0].y.a=mirvar(_MIPP_ 0);
table[0].y.b=mirvar(_MIPP_ 0);
table[0].z.a=mirvar(_MIPP_ 0);
table[0].z.b=mirvar(_MIPP_ 0);
table[0].marker=MR_EPOINT_INFINITY;
table[1].x.a=mirvar(_MIPP_ 0);
table[1].x.b=mirvar(_MIPP_ 0);
table[1].y.a=mirvar(_MIPP_ 0);
table[1].y.b=mirvar(_MIPP_ 0);
table[1].z.a=mirvar(_MIPP_ 0);
table[1].z.b=mirvar(_MIPP_ 0);
table[1].marker=MR_EPOINT_INFINITY;
ecn2_copy(&w,&table[1]);
for (j=0;jlen;
bptr=0;
B->table=mr_alloc(_MIPP_ 4*len*(1<table[bptr++]=table[i].x.a->w[j];
for (j=0;jtable[bptr++]=table[i].x.b->w[j];
for (j=0;jtable[bptr++]=table[i].y.a->w[j];
for (j=0;jtable[bptr++]=table[i].y.b->w[j];
mr_free(table[i].x.a);
mr_free(table[i].x.b);
mr_free(table[i].y.a);
mr_free(table[i].y.b);
mr_free(table[i].z.a);
mr_free(table[i].z.b);
}
mr_free(table);
MR_OUT
return TRUE;
}
void ecn2_brick_end(ebrick *B)
{
mirkill(B->n);
mirkill(B->b);
mirkill(B->a);
mr_free(B->table);
}
#else
/* use precomputated table in ROM */
void ecn2_brick_init(ebrick *B,const mr_small* rom,big a,big b,big n,int window,int nb)
{
B->table=rom;
B->a=a; /* just pass a pointer */
B->b=b;
B->n=n;
B->window=window; /* 2^4=16 stored values */
B->max=nb;
}
#endif
/*
void ecn2_mul_brick(_MIPD_ ebrick *B,big e,zzn2 *x,zzn2 *y)
{
int i,j,t,len,maxsize,promptr;
ecn2 w,z;
#ifdef MR_STATIC
char mem[MR_BIG_RESERVE(10)];
#else
char *mem;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (size(e)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
t=MR_ROUNDUP(B->max,B->window);
MR_IN(116)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return;
}
#endif
if (logb2(_MIPP_ e) > B->max)
{
mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG);
MR_OUT
return;
}
ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST);
mr_mip->TWIST=MR_QUADRATIC;
#ifdef MR_STATIC
memset(mem,0,MR_BIG_RESERVE(10));
#else
mem=memalloc(_MIPP_ 10);
#endif
w.x.a=mirvar_mem(_MIPP_ mem, 0);
w.x.b=mirvar_mem(_MIPP_ mem, 1);
w.y.a=mirvar_mem(_MIPP_ mem, 2);
w.y.b=mirvar_mem(_MIPP_ mem, 3);
w.z.a=mirvar_mem(_MIPP_ mem, 4);
w.z.b=mirvar_mem(_MIPP_ mem, 5);
w.marker=MR_EPOINT_INFINITY;
z.x.a=mirvar_mem(_MIPP_ mem, 6);
z.x.b=mirvar_mem(_MIPP_ mem, 7);
z.y.a=mirvar_mem(_MIPP_ mem, 8);
z.y.b=mirvar_mem(_MIPP_ mem, 9);
z.marker=MR_EPOINT_INFINITY;
len=B->n->len;
maxsize=4*(1<window)*len;
for (i=t-1;i>=0;i--)
{
j=recode(_MIPP_ e,t,B->window,i);
ecn2_add(_MIPP_ &w,&w);
if (j>0)
{
promptr=4*j*len;
init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr);
z.marker=MR_EPOINT_NORMALIZED;
ecn2_add(_MIPP_ &z,&w);
}
}
ecn2_norm(_MIPP_ &w);
ecn2_getxy(&w,x,y);
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
#else
memset(mem,0,MR_BIG_RESERVE(10));
#endif
MR_OUT
}
*/
void ecn2_mul_brick_gls(_MIPD_ ebrick *B,big *e,zzn2 *psi,zzn2 *x,zzn2 *y)
{
int i,j,k,t,len,maxsize,promptr,se[2];
ecn2 w,z;
#ifdef MR_STATIC
char mem[MR_BIG_RESERVE(10)];
#else
char *mem;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
for (k=0;k<2;k++) se[k]=exsign(e[k]);
t=MR_ROUNDUP(B->max,B->window);
MR_IN(222)
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base != mr_mip->base2)
{
mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
MR_OUT
return;
}
#endif
if (logb2(_MIPP_ e[0])>B->max || logb2(_MIPP_ e[1])>B->max)
{
mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG);
MR_OUT
return;
}
ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST);
mr_mip->TWIST=MR_QUADRATIC;
#ifdef MR_STATIC
memset(mem,0,MR_BIG_RESERVE(10));
#else
mem=memalloc(_MIPP_ 10);
#endif
z.x.a=mirvar_mem(_MIPP_ mem, 0);
z.x.b=mirvar_mem(_MIPP_ mem, 1);
z.y.a=mirvar_mem(_MIPP_ mem, 2);
z.y.b=mirvar_mem(_MIPP_ mem, 3);
z.marker=MR_EPOINT_INFINITY;
w.x.a=mirvar_mem(_MIPP_ mem, 4);
w.x.b=mirvar_mem(_MIPP_ mem, 5);
w.y.a=mirvar_mem(_MIPP_ mem, 6);
w.y.b=mirvar_mem(_MIPP_ mem, 7);
w.z.a=mirvar_mem(_MIPP_ mem, 8);
w.z.b=mirvar_mem(_MIPP_ mem, 9);
w.marker=MR_EPOINT_INFINITY;
len=B->n->len;
maxsize=4*(1<window)*len;
for (i=t-1;i>=0;i--)
{
ecn2_add(_MIPP_ &w,&w);
for (k=0;k<2;k++)
{
j=recode(_MIPP_ e[k],t,B->window,i);
if (j>0)
{
promptr=4*j*len;
init_big_from_rom(z.x.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.x.b,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.a,len,B->table,maxsize,&promptr);
init_big_from_rom(z.y.b,len,B->table,maxsize,&promptr);
z.marker=MR_EPOINT_NORMALIZED;
if (k==1) ecn2_psi(_MIPP_ psi,&z);
if (se[k]==PLUS) ecn2_add(_MIPP_ &z,&w);
else ecn2_sub(_MIPP_ &z,&w);
}
}
}
ecn2_norm(_MIPP_ &w);
ecn2_getxy(&w,x,y);
#ifndef MR_STATIC
memkill(_MIPP_ mem,10);
#else
memset(mem,0,MR_BIG_RESERVE(10));
#endif
MR_OUT
}
#endif
#ifndef MR_NO_ECC_MULTIADD
void ecn2_mult4(_MIPD_ big *e,ecn2 *P,ecn2 *R)
{ /* R=e[0]*P[0]+e[1]*P[1]+ .... e[n-1]*P[n-1] */
int i,j,k,l,nb,ea,c;
ecn2 G[16];
zzn2 work[16];
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
#ifndef MR_STATIC
char *mem=(char *)memalloc(_MIPP_ 120);
#else
char mem[MR_BIG_RESERVE(120)];
memset(mem, 0, MR_BIG_RESERVE(120));
#endif
if (mr_mip->ERNUM) return;
MR_IN(243)
l=0;
for (k=1;k<16;k++)
{
G[k].x.a=mirvar_mem(_MIPP_ mem, l++);
G[k].x.b=mirvar_mem(_MIPP_ mem, l++);
G[k].y.a=mirvar_mem(_MIPP_ mem, l++);
G[k].y.b=mirvar_mem(_MIPP_ mem, l++);
G[k].z.a=mirvar_mem(_MIPP_ mem, l++);
G[k].z.b=mirvar_mem(_MIPP_ mem, l++);
G[k].marker=MR_EPOINT_INFINITY;
i=k; j=1; c=0; while (i>=(2*j)) {j*=2; c++;}
if (i>j) ecn2_copy(&G[i-j],&G[k]);
ecn2_add(_MIPP_ &P[c],&G[k]);
}
for (i=0;i<15;i++)
{
work[i].a=mirvar_mem(_MIPP_ mem, l++);
work[i].b=mirvar_mem(_MIPP_ mem, l++);
}
ecn2_multi_norm(_MIPP_ 15,work,&G[1]);
nb=0;
for (j=0;j<4;j++) if ((k=logb2(_MIPP_ e[j])) > nb) nb=k;
ecn2_zero(R);
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base==mr_mip->base2)
{
#endif
for (i=nb-1;i>=0;i--)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
ea=0;
k=1;
for (j=0;j<4;j++)
{
if (mr_testbit(_MIPP_ e[j],i)) ea+=k;
k<<=1;
}
ecn2_add(_MIPP_ R,R);
if (ea!=0) ecn2_add(_MIPP_ &G[ea],R);
}
#ifndef MR_ALWAYS_BINARY
}
else mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
#endif
#ifndef MR_STATIC
memkill(_MIPP_ mem,120);
#else
memset(mem, 0, MR_BIG_RESERVE(120));
#endif
MR_OUT
}
#ifndef MR_STATIC
void ecn2_multn(_MIPD_ int n,big *e,ecn2 *P,ecn2 *R)
{ /* R=e[0]*P[0]+e[1]*P[1]+ .... e[n-1]*P[n-1] */
int i,j,k,l,nb,ea,c;
int m=1<ERNUM) return;
MR_IN(223)
G= (ecn2 *)mr_alloc(_MIPP_ m,sizeof(ecn2));
work=(zzn2 *)mr_alloc(_MIPP_ m,sizeof(zzn2));
l=0;
for (k=1;k=(2*j)) {j*=2; c++;}
if (i>j) ecn2_copy(&G[i-j],&G[k]);
ecn2_add(_MIPP_ &P[c],&G[k]);
}
for (i=0;i nb) nb=k;
ecn2_zero(R);
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base==mr_mip->base2)
{
#endif
for (i=nb-1;i>=0;i--)
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
ea=0;
k=1;
for (j=0;j