/*************************************************************************** * 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 F_p^4 support functions * mrzzn4.c */ #include #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 }