440 lines
11 KiB
C
440 lines
11 KiB
C
|
|
/***************************************************************************
|
|
*
|
|
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 <http://www.gnu.org/licenses/>. *
|
|
*
|
|
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 F_p^4 support functions
|
|
* mrzzn4.c
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include "miracl.h"
|
|
|
|
#define FUNC_BASE 226
|
|
|
|
BOOL zzn4_iszero(zzn4 *x)
|
|
{
|
|
if (zzn2_iszero(&(x->a)) && zzn2_iszero(&(x->b))) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL zzn4_isunity(_MIPD_ zzn4 *x)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM || !zzn2_iszero(&(x->b))) return FALSE;
|
|
|
|
if (zzn2_isunity(_MIPP_ &x->a)) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL zzn4_compare(zzn4 *x,zzn4 *y)
|
|
{
|
|
if (zzn2_compare(&(x->a),&(y->a)) && zzn2_compare(&(x->b),&(y->b))) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
void zzn4_from_int(_MIPD_ int i,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+0)
|
|
if (i==1)
|
|
{
|
|
copy(mr_mip->one,w->a.a);
|
|
w->unitary=TRUE;
|
|
}
|
|
else
|
|
{
|
|
convert(_MIPP_ i,mr_mip->w1);
|
|
nres(_MIPP_ mr_mip->w1,(w->a).a);
|
|
w->unitary=FALSE;
|
|
}
|
|
zero((w->a).b);
|
|
zero((w->b).a);
|
|
zero((w->b).b);
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_copy(zzn4 *x,zzn4 *w)
|
|
{
|
|
if (x==w) return;
|
|
zzn2_copy(&(x->a),&(w->a));
|
|
zzn2_copy(&(x->b),&(w->b));
|
|
w->unitary=x->unitary;
|
|
}
|
|
|
|
void zzn4_zero(zzn4 *w)
|
|
{
|
|
zzn2_zero(&(w->a));
|
|
zzn2_zero(&(w->b));
|
|
w->unitary=FALSE;
|
|
}
|
|
|
|
void zzn4_from_zzn2s(zzn2 *x,zzn2 *y,zzn4 *w)
|
|
{
|
|
zzn2_copy(x,&(w->a));
|
|
zzn2_copy(y,&(w->b));
|
|
w->unitary=FALSE;
|
|
}
|
|
|
|
void zzn4_from_zzn2(zzn2 *x,zzn4 *w)
|
|
{
|
|
zzn2_copy(x,&(w->a));
|
|
zzn2_zero(&(w->b));
|
|
w->unitary=FALSE;
|
|
}
|
|
|
|
void zzn4_from_zzn2h(zzn2 *x,zzn4 *w)
|
|
{
|
|
zzn2_copy(x,&(w->b));
|
|
zzn2_zero(&(w->a));
|
|
w->unitary=FALSE;
|
|
}
|
|
|
|
void zzn4_from_zzn(big x,zzn4 *w)
|
|
{
|
|
zzn2_from_zzn(x,&(w->a));
|
|
zzn2_zero(&(w->b));
|
|
w->unitary=FALSE;
|
|
}
|
|
|
|
void zzn4_from_big(_MIPD_ big x, zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+16)
|
|
zzn2_from_big(_MIPP_ x,&(w->a));
|
|
zzn2_zero(&(w->b));
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_negate(_MIPD_ zzn4 *x,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+1)
|
|
zzn4_copy(x,w);
|
|
zzn2_negate(_MIPP_ &(w->a),&(w->a));
|
|
zzn2_negate(_MIPP_ &(w->b),&(w->b));
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_conj(_MIPD_ zzn4 *x,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
MR_IN(FUNC_BASE+2)
|
|
if (mr_mip->ERNUM) return;
|
|
zzn4_copy(x,w);
|
|
zzn2_negate(_MIPP_ &(w->b),&(w->b));
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_add(_MIPD_ zzn4 *x,zzn4 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+3)
|
|
zzn2_add(_MIPP_ &(x->a),&(y->a),&(w->a));
|
|
zzn2_add(_MIPP_ &(x->b),&(y->b),&(w->b));
|
|
w->unitary=FALSE;
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_sadd(_MIPD_ zzn4 *x,zzn2 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+4)
|
|
zzn2_add(_MIPP_ &(x->a),y,&(w->a));
|
|
w->unitary=FALSE;
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_sub(_MIPD_ zzn4 *x,zzn4 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+5)
|
|
zzn2_sub(_MIPP_ &(x->a),&(y->a),&(w->a));
|
|
zzn2_sub(_MIPP_ &(x->b),&(y->b),&(w->b));
|
|
w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_ssub(_MIPD_ zzn4 *x,zzn2 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+6)
|
|
zzn2_sub(_MIPP_ &(x->a),y,&(w->a));
|
|
w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_smul(_MIPD_ zzn4 *x,zzn2 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+7)
|
|
if (!zzn2_iszero(&(x->a))) zzn2_mul(_MIPP_ &(x->a),y,&(w->a));
|
|
else zzn2_zero(&(w->a));
|
|
if (!zzn2_iszero(&(x->b))) zzn2_mul(_MIPP_ &(x->b),y,&(w->b));
|
|
else zzn2_zero(&(w->b));
|
|
w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_lmul(_MIPD_ zzn4 *x,big y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+15)
|
|
|
|
if (!zzn2_iszero(&(x->a))) zzn2_smul(_MIPP_ &(x->a),y,&(w->a));
|
|
else zzn2_zero(&(w->a));
|
|
if (!zzn2_iszero(&(x->b))) zzn2_smul(_MIPP_ &(x->b),y,&(w->b));
|
|
else zzn2_zero(&(w->b));
|
|
w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
|
|
void zzn4_imul(_MIPD_ zzn4 *x,int y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+14)
|
|
zzn2_imul(_MIPP_ &(x->a),y,&(w->a));
|
|
zzn2_imul(_MIPP_ &(x->b),y,&(w->b));
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_sqr(_MIPD_ zzn4 *x,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
zzn2 t1,t2;
|
|
if (mr_mip->ERNUM) return;
|
|
|
|
MR_IN(FUNC_BASE+8)
|
|
|
|
t1.a=mr_mip->w10;
|
|
t1.b=mr_mip->w11;
|
|
t2.a=mr_mip->w8;
|
|
t2.b=mr_mip->w9;
|
|
|
|
zzn4_copy(x,w);
|
|
if (x->unitary)
|
|
{ /* this is a lot faster.. - see Lenstra & Stam */
|
|
zzn2_mul(_MIPP_ &(w->b),&(w->b),&t1);
|
|
zzn2_add(_MIPP_ &(w->b),&(w->a),&(w->b));
|
|
zzn2_mul(_MIPP_ &(w->b),&(w->b),&(w->b));
|
|
zzn2_sub(_MIPP_ &(w->b),&t1,&(w->b));
|
|
zzn2_txx(_MIPP_ &t1);
|
|
zzn2_copy(&t1,&(w->a));
|
|
zzn2_sub(_MIPP_ &(w->b),&(w->a),&(w->b));
|
|
zzn2_add(_MIPP_ &(w->a),&(w->a),&(w->a));
|
|
zzn2_sadd(_MIPP_ &(w->a),mr_mip->one,&(w->a));
|
|
zzn2_ssub(_MIPP_ &(w->b),mr_mip->one,&(w->b));
|
|
}
|
|
else
|
|
{
|
|
zzn2_copy(&(w->b),&t2); // t2=b;
|
|
zzn2_add(_MIPP_ &(w->a),&t2,&t1); // t1=a+b
|
|
|
|
zzn2_txx(_MIPP_ &t2);
|
|
zzn2_add(_MIPP_ &t2,&(w->a),&t2); // t2=a+txx(b)
|
|
|
|
zzn2_mul(_MIPP_ &(w->b),&(w->a),&(w->b)); // b*=a
|
|
zzn2_mul(_MIPP_ &t1,&t2,&(w->a)); // a=t1*t2
|
|
|
|
zzn2_copy(&(w->b),&t2); //t2=b
|
|
zzn2_sub(_MIPP_ &(w->a),&t2,&(w->a)); //a-=b
|
|
zzn2_txx(_MIPP_ &t2); // t2=txx(b)
|
|
zzn2_sub(_MIPP_ &(w->a),&t2,&(w->a)); // a-=txx(b);
|
|
zzn2_add(_MIPP_ &(w->b),&(w->b),&(w->b)); // b+=b;
|
|
|
|
}
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_mul(_MIPD_ zzn4 *x,zzn4 *y,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
zzn2 t1,t2,t3;
|
|
if (mr_mip->ERNUM) return;
|
|
if (x==y) {zzn4_sqr(_MIPP_ x,w); return; }
|
|
MR_IN(FUNC_BASE+9)
|
|
|
|
t1.a=mr_mip->w12;
|
|
t1.b=mr_mip->w13;
|
|
t2.a=mr_mip->w8;
|
|
t2.b=mr_mip->w9;
|
|
t3.a=mr_mip->w10;
|
|
t3.b=mr_mip->w11;
|
|
zzn2_copy(&(x->a),&t1);
|
|
zzn2_copy(&(x->b),&t2);
|
|
zzn2_mul(_MIPP_ &t1,&(y->a),&t1); /* t1= x->a * y->a */
|
|
zzn2_mul(_MIPP_ &t2,&(y->b),&t2); /* t2 = x->b * y->b */
|
|
zzn2_copy(&(y->a),&t3);
|
|
zzn2_add(_MIPP_ &t3,&(y->b),&t3); /* y->a + y->b */
|
|
|
|
zzn2_add(_MIPP_ &(x->b),&(x->a),&(w->b)); /* x->a + x->b */
|
|
zzn2_mul(_MIPP_ &(w->b),&t3,&(w->b)); /* t3= (x->a + x->b)*(y->a + y->b) */
|
|
zzn2_sub(_MIPP_ &(w->b),&t1,&(w->b));
|
|
zzn2_sub(_MIPP_ &(w->b),&t2,&(w->b)); /* w->b = t3-(t1+t2) */
|
|
zzn2_copy(&t1,&(w->a));
|
|
zzn2_txx(_MIPP_ &t2);
|
|
zzn2_add(_MIPP_ &(w->a),&t2,&(w->a)); /* w->a = t1+tx(t2) */
|
|
if (x->unitary && y->unitary) w->unitary=TRUE;
|
|
else w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_inv(_MIPD_ zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
zzn2 t1,t2;
|
|
if (mr_mip->ERNUM) return;
|
|
if (w->unitary)
|
|
{
|
|
zzn4_conj(_MIPP_ w,w);
|
|
return;
|
|
}
|
|
MR_IN(FUNC_BASE+10)
|
|
|
|
t1.a=mr_mip->w8;
|
|
t1.b=mr_mip->w9;
|
|
t2.a=mr_mip->w10;
|
|
t2.b=mr_mip->w11;
|
|
zzn2_mul(_MIPP_ &(w->a),&(w->a),&t1);
|
|
zzn2_mul(_MIPP_ &(w->b),&(w->b),&t2);
|
|
zzn2_txx(_MIPP_ &t2);
|
|
zzn2_sub(_MIPP_ &t1,&t2,&t1);
|
|
zzn2_inv(_MIPP_ &t1);
|
|
zzn2_mul(_MIPP_ &(w->a),&t1,&(w->a));
|
|
zzn2_negate(_MIPP_ &t1,&t1);
|
|
zzn2_mul(_MIPP_ &(w->b),&t1,&(w->b));
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
/* divide zzn4 by 2 */
|
|
|
|
void zzn4_div2(_MIPD_ zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
if (mr_mip->ERNUM) return;
|
|
MR_IN(FUNC_BASE+11)
|
|
|
|
zzn2_div2(_MIPP_ &(w->a));
|
|
zzn2_div2(_MIPP_ &(w->b));
|
|
w->unitary=FALSE;
|
|
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_powq(_MIPD_ zzn2 *fr,zzn4 *w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
MR_IN(FUNC_BASE+12)
|
|
zzn2_conj(_MIPP_ &(w->a),&(w->a));
|
|
zzn2_conj(_MIPP_ &(w->b),&(w->b));
|
|
zzn2_mul(_MIPP_ &(w->b),fr,&(w->b));
|
|
MR_OUT
|
|
}
|
|
|
|
void zzn4_tx(_MIPD_ zzn4* w)
|
|
{
|
|
#ifdef MR_OS_THREADS
|
|
miracl *mr_mip=get_mip();
|
|
#endif
|
|
zzn2 t;
|
|
MR_IN(FUNC_BASE+13)
|
|
|
|
t.a=mr_mip->w8;
|
|
t.b=mr_mip->w9;
|
|
zzn2_copy(&(w->b),&t);
|
|
zzn2_txx(_MIPP_ &t);
|
|
zzn2_copy(&(w->a),&(w->b));
|
|
zzn2_copy(&t,&(w->a));
|
|
|
|
MR_OUT
|
|
}
|