You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
476 lines
11 KiB
476 lines
11 KiB
/*
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you 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.
|
|
*/
|
|
|
|
/* AMCL Fp^2 functions */
|
|
/* SU=m, m is Stack Usage (no lazy )*/
|
|
|
|
/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
|
|
|
|
#include "fp2_FP256BN.h"
|
|
|
|
/* test x==0 ? */
|
|
/* SU= 8 */
|
|
int FP2_FP256BN_iszilch(FP2_FP256BN *x)
|
|
{
|
|
FP2_FP256BN_reduce(x);
|
|
if (FP_FP256BN_iszilch(&(x->a)) && FP_FP256BN_iszilch(&(x->b))) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* Move b to a if d=1 */
|
|
void FP2_FP256BN_cmove(FP2_FP256BN *f,FP2_FP256BN *g,int d)
|
|
{
|
|
FP_FP256BN_cmove(&(f->a),&(g->a),d);
|
|
FP_FP256BN_cmove(&(f->b),&(g->b),d);
|
|
}
|
|
|
|
/* test x==1 ? */
|
|
/* SU= 48 */
|
|
int FP2_FP256BN_isunity(FP2_FP256BN *x)
|
|
{
|
|
FP_FP256BN one;
|
|
FP_FP256BN_one(&one);
|
|
FP2_FP256BN_reduce(x);
|
|
if (FP_FP256BN_equals(&(x->a),&one) && FP_FP256BN_iszilch(&(x->b))) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* SU= 8 */
|
|
/* Fully reduce a and b mod Modulus */
|
|
void FP2_FP256BN_reduce(FP2_FP256BN *w)
|
|
{
|
|
FP_FP256BN_reduce(&(w->a));
|
|
FP_FP256BN_reduce(&(w->b));
|
|
}
|
|
|
|
/* return 1 if x==y, else 0 */
|
|
/* SU= 16 */
|
|
int FP2_FP256BN_equals(FP2_FP256BN *x,FP2_FP256BN *y)
|
|
{
|
|
FP2_FP256BN_reduce(x);
|
|
FP2_FP256BN_reduce(y);
|
|
if (FP_FP256BN_equals(&(x->a),&(y->a)) && FP_FP256BN_equals(&(x->b),&(y->b)))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* Create FP2 from two FPs */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_from_FPs(FP2_FP256BN *w,FP_FP256BN *x,FP_FP256BN *y)
|
|
{
|
|
FP_FP256BN_copy(&(w->a),x);
|
|
FP_FP256BN_copy(&(w->b),y);
|
|
}
|
|
|
|
/* Create FP2 from two BIGS */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_from_BIGs(FP2_FP256BN *w,BIG_256_56 x,BIG_256_56 y)
|
|
{
|
|
FP_FP256BN_nres(&(w->a),x);
|
|
FP_FP256BN_nres(&(w->b),y);
|
|
}
|
|
|
|
/* Create FP2 from FP */
|
|
/* SU= 8 */
|
|
void FP2_FP256BN_from_FP(FP2_FP256BN *w,FP_FP256BN *x)
|
|
{
|
|
FP_FP256BN_copy(&(w->a),x);
|
|
FP_FP256BN_zero(&(w->b));
|
|
}
|
|
|
|
/* Create FP2 from BIG */
|
|
/* SU= 8 */
|
|
void FP2_FP256BN_from_BIG(FP2_FP256BN *w,BIG_256_56 x)
|
|
{
|
|
FP_FP256BN_nres(&(w->a),x);
|
|
FP_FP256BN_zero(&(w->b));
|
|
}
|
|
|
|
/* FP2 copy w=x */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_copy(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
if (w==x) return;
|
|
FP_FP256BN_copy(&(w->a),&(x->a));
|
|
FP_FP256BN_copy(&(w->b),&(x->b));
|
|
}
|
|
|
|
/* FP2 set w=0 */
|
|
/* SU= 8 */
|
|
void FP2_FP256BN_zero(FP2_FP256BN *w)
|
|
{
|
|
FP_FP256BN_zero(&(w->a));
|
|
FP_FP256BN_zero(&(w->b));
|
|
}
|
|
|
|
/* FP2 set w=1 */
|
|
/* SU= 48 */
|
|
void FP2_FP256BN_one(FP2_FP256BN *w)
|
|
{
|
|
FP_FP256BN one;
|
|
FP_FP256BN_one(&one);
|
|
FP2_FP256BN_from_FP(w,&one);
|
|
}
|
|
|
|
/* Set w=-x */
|
|
/* SU= 88 */
|
|
void FP2_FP256BN_neg(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
/* Just one neg! */
|
|
FP_FP256BN m,t;
|
|
// FP2_FP256BN_norm(x);
|
|
FP_FP256BN_add(&m,&(x->a),&(x->b));
|
|
FP_FP256BN_neg(&m,&m);
|
|
FP_FP256BN_add(&t,&m,&(x->b));
|
|
FP_FP256BN_add(&(w->b),&m,&(x->a));
|
|
FP_FP256BN_copy(&(w->a),&t);
|
|
|
|
}
|
|
|
|
/* Set w=conj(x) */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_conj(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
FP_FP256BN_copy(&(w->a),&(x->a));
|
|
// BIG_256_56_norm(x->b);
|
|
FP_FP256BN_neg(&(w->b),&(x->b));
|
|
FP_FP256BN_norm(&(w->b));
|
|
}
|
|
|
|
/* Set w=x+y */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_add(FP2_FP256BN *w,FP2_FP256BN *x,FP2_FP256BN *y)
|
|
{
|
|
FP_FP256BN_add(&(w->a),&(x->a),&(y->a));
|
|
FP_FP256BN_add(&(w->b),&(x->b),&(y->b));
|
|
}
|
|
|
|
/* Set w=x-y */
|
|
/* Input y MUST be normed */
|
|
void FP2_FP256BN_sub(FP2_FP256BN *w,FP2_FP256BN *x,FP2_FP256BN *y)
|
|
{
|
|
FP2_FP256BN m;
|
|
FP2_FP256BN_neg(&m,y);
|
|
FP2_FP256BN_add(w,x,&m);
|
|
}
|
|
|
|
/* Set w=s*x, where s is FP */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_pmul(FP2_FP256BN *w,FP2_FP256BN *x,FP_FP256BN *s)
|
|
{
|
|
FP_FP256BN_mul(&(w->a),&(x->a),s);
|
|
FP_FP256BN_mul(&(w->b),&(x->b),s);
|
|
}
|
|
|
|
/* SU= 16 */
|
|
/* Set w=s*x, where s is int */
|
|
void FP2_FP256BN_imul(FP2_FP256BN *w,FP2_FP256BN *x,int s)
|
|
{
|
|
FP_FP256BN_imul(&(w->a),&(x->a),s);
|
|
FP_FP256BN_imul(&(w->b),&(x->b),s);
|
|
}
|
|
|
|
/* Set w=x^2 */
|
|
/* SU= 128 */
|
|
void FP2_FP256BN_sqr(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
FP_FP256BN w1,w3,mb;
|
|
|
|
FP_FP256BN_add(&w1,&(x->a),&(x->b));
|
|
FP_FP256BN_neg(&mb,&(x->b));
|
|
|
|
FP_FP256BN_add(&w3,&(x->a),&(x->a));
|
|
FP_FP256BN_norm(&w3);
|
|
FP_FP256BN_mul(&(w->b),&w3,&(x->b));
|
|
|
|
FP_FP256BN_add(&(w->a),&(x->a),&mb);
|
|
|
|
FP_FP256BN_norm(&w1);
|
|
FP_FP256BN_norm(&(w->a));
|
|
|
|
FP_FP256BN_mul(&(w->a),&w1,&(w->a)); /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
|
|
}
|
|
|
|
|
|
/* Set w=x*y */
|
|
/* Inputs MUST be normed */
|
|
/* Now uses Lazy reduction */
|
|
void FP2_FP256BN_mul(FP2_FP256BN *w,FP2_FP256BN *x,FP2_FP256BN *y)
|
|
{
|
|
DBIG_256_56 A,B,E,F,pR;
|
|
BIG_256_56 C,D,p;
|
|
|
|
BIG_256_56_rcopy(p,Modulus_FP256BN);
|
|
BIG_256_56_dsucopy(pR,p);
|
|
|
|
// reduce excesses of a and b as required (so product < pR)
|
|
|
|
if ((sign64)(x->a.XES+x->b.XES)*(y->a.XES+y->b.XES)>(sign64)FEXCESS_FP256BN)
|
|
{
|
|
#ifdef DEBUG_REDUCE
|
|
printf("FP2 Product too large - reducing it\n");
|
|
#endif
|
|
if (x->a.XES>1) FP_FP256BN_reduce(&(x->a));
|
|
if (x->b.XES>1) FP_FP256BN_reduce(&(x->b));
|
|
}
|
|
|
|
BIG_256_56_mul(A,x->a.g,y->a.g);
|
|
BIG_256_56_mul(B,x->b.g,y->b.g);
|
|
|
|
BIG_256_56_add(C,x->a.g,x->b.g);
|
|
BIG_256_56_norm(C);
|
|
BIG_256_56_add(D,y->a.g,y->b.g);
|
|
BIG_256_56_norm(D);
|
|
|
|
BIG_256_56_mul(E,C,D);
|
|
BIG_256_56_dadd(F,A,B);
|
|
BIG_256_56_dsub(B,pR,B); //
|
|
|
|
BIG_256_56_dadd(A,A,B); // A<pR? Not necessarily, but <2pR
|
|
BIG_256_56_dsub(E,E,F); // E<pR ? Yes
|
|
|
|
BIG_256_56_dnorm(A);
|
|
FP_FP256BN_mod(w->a.g,A);
|
|
w->a.XES=3;// may drift above 2p...
|
|
BIG_256_56_dnorm(E);
|
|
FP_FP256BN_mod(w->b.g,E);
|
|
w->b.XES=2;
|
|
|
|
}
|
|
|
|
/* output FP2 in hex format [a,b] */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_output(FP2_FP256BN *w)
|
|
{
|
|
BIG_256_56 bx,by;
|
|
FP2_FP256BN_reduce(w);
|
|
FP_FP256BN_redc(bx,&(w->a));
|
|
FP_FP256BN_redc(by,&(w->b));
|
|
printf("[");
|
|
BIG_256_56_output(bx);
|
|
printf(",");
|
|
BIG_256_56_output(by);
|
|
printf("]");
|
|
FP_FP256BN_nres(&(w->a),bx);
|
|
FP_FP256BN_nres(&(w->b),by);
|
|
}
|
|
|
|
/* SU= 8 */
|
|
void FP2_FP256BN_rawoutput(FP2_FP256BN *w)
|
|
{
|
|
printf("[");
|
|
BIG_256_56_rawoutput(w->a.g);
|
|
printf(",");
|
|
BIG_256_56_rawoutput(w->b.g);
|
|
printf("]");
|
|
}
|
|
|
|
|
|
/* Set w=1/x */
|
|
/* SU= 128 */
|
|
void FP2_FP256BN_inv(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
BIG_256_56 m,b;
|
|
FP_FP256BN w1,w2;
|
|
BIG_256_56_rcopy(m,Modulus_FP256BN);
|
|
FP2_FP256BN_norm(x);
|
|
FP_FP256BN_sqr(&w1,&(x->a));
|
|
FP_FP256BN_sqr(&w2,&(x->b));
|
|
FP_FP256BN_add(&w1,&w1,&w2);
|
|
|
|
FP_FP256BN_redc(b,&w1);
|
|
BIG_256_56_invmodp(b,b,m);
|
|
FP_FP256BN_nres(&w1,b);
|
|
FP_FP256BN_mul(&(w->a),&(x->a),&w1);
|
|
FP_FP256BN_neg(&w1,&w1);
|
|
FP_FP256BN_norm(&w1);
|
|
FP_FP256BN_mul(&(w->b),&(x->b),&w1);
|
|
// FP2_FP256BN_norm(w);
|
|
}
|
|
|
|
|
|
/* Set w=x/2 */
|
|
/* SU= 16 */
|
|
void FP2_FP256BN_div2(FP2_FP256BN *w,FP2_FP256BN *x)
|
|
{
|
|
FP_FP256BN_div2(&(w->a),&(x->a));
|
|
FP_FP256BN_div2(&(w->b),&(x->b));
|
|
}
|
|
|
|
/* Set w*=(1+sqrt(-1)) */
|
|
/* where X^2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
|
|
|
|
/* Input MUST be normed */
|
|
void FP2_FP256BN_mul_ip(FP2_FP256BN *w)
|
|
{
|
|
FP_FP256BN z;
|
|
FP2_FP256BN t;
|
|
|
|
// FP2_FP256BN_norm(w);
|
|
FP2_FP256BN_copy(&t,w);
|
|
|
|
FP_FP256BN_copy(&z,&(w->a));
|
|
FP_FP256BN_neg(&(w->a),&(w->b));
|
|
FP_FP256BN_copy(&(w->b),&z);
|
|
|
|
FP2_FP256BN_add(w,&t,w);
|
|
// Output NOT normed, so use with care
|
|
}
|
|
|
|
|
|
void FP2_FP256BN_div_ip2(FP2_FP256BN *w)
|
|
{
|
|
FP2_FP256BN t;
|
|
FP_FP256BN_add(&(t.a),&(w->a),&(w->b));
|
|
FP_FP256BN_sub(&(t.b),&(w->b),&(w->a));
|
|
FP2_FP256BN_copy(w,&t);
|
|
}
|
|
|
|
/* Set w/=(1+sqrt(-1)) */
|
|
/* SU= 88 */
|
|
void FP2_FP256BN_div_ip(FP2_FP256BN *w)
|
|
{
|
|
FP2_FP256BN t;
|
|
FP2_FP256BN_norm(w);
|
|
FP_FP256BN_add(&t.a,&(w->a),&(w->b));
|
|
FP_FP256BN_sub(&t.b,&(w->b),&(w->a));
|
|
FP2_FP256BN_norm(&t);
|
|
FP2_FP256BN_div2(w,&t);
|
|
}
|
|
|
|
/* SU= 8 */
|
|
/* normalise a and b components of w */
|
|
void FP2_FP256BN_norm(FP2_FP256BN *w)
|
|
{
|
|
FP_FP256BN_norm(&(w->a));
|
|
FP_FP256BN_norm(&(w->b));
|
|
}
|
|
|
|
/* Set w=a^b mod m */
|
|
/* SU= 208 */
|
|
void FP2_FP256BN_pow(FP2_FP256BN *r,FP2_FP256BN* a,BIG_256_56 b)
|
|
{
|
|
FP2_FP256BN w;
|
|
FP_FP256BN one;
|
|
BIG_256_56 z,zilch;
|
|
int bt;
|
|
|
|
BIG_256_56_norm(b);
|
|
BIG_256_56_copy(z,b);
|
|
FP2_FP256BN_copy(&w,a);
|
|
FP_FP256BN_one(&one);
|
|
BIG_256_56_zero(zilch);
|
|
FP2_FP256BN_from_FP(r,&one);
|
|
while(1)
|
|
{
|
|
bt=BIG_256_56_parity(z);
|
|
BIG_256_56_shr(z,1);
|
|
if (bt) FP2_FP256BN_mul(r,r,&w);
|
|
if (BIG_256_56_comp(z,zilch)==0) break;
|
|
FP2_FP256BN_sqr(&w,&w);
|
|
}
|
|
FP2_FP256BN_reduce(r);
|
|
}
|
|
|
|
/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
|
|
/* returns true if u is QR */
|
|
|
|
int FP2_FP256BN_sqrt(FP2_FP256BN *w,FP2_FP256BN *u)
|
|
{
|
|
BIG_256_56 b,q;
|
|
FP_FP256BN w1,w2;
|
|
FP2_FP256BN_copy(w,u);
|
|
if (FP2_FP256BN_iszilch(w)) return 1;
|
|
|
|
BIG_256_56_rcopy(q,Modulus_FP256BN);
|
|
|
|
FP_FP256BN_sqr(&w1,&(w->b));
|
|
FP_FP256BN_sqr(&w2,&(w->a));
|
|
FP_FP256BN_add(&w1,&w1,&w2);
|
|
if (!FP_FP256BN_qr(&w1))
|
|
{
|
|
FP2_FP256BN_zero(w);
|
|
return 0;
|
|
}
|
|
FP_FP256BN_sqrt(&w1,&w1);
|
|
FP_FP256BN_add(&w2,&(w->a),&w1);
|
|
FP_FP256BN_norm(&w2);
|
|
FP_FP256BN_div2(&w2,&w2);
|
|
if (!FP_FP256BN_qr(&w2))
|
|
{
|
|
FP_FP256BN_sub(&w2,&(w->a),&w1);
|
|
FP_FP256BN_norm(&w2);
|
|
FP_FP256BN_div2(&w2,&w2);
|
|
if (!FP_FP256BN_qr(&w2))
|
|
{
|
|
FP2_FP256BN_zero(w);
|
|
return 0;
|
|
}
|
|
}
|
|
FP_FP256BN_sqrt(&w2,&w2);
|
|
FP_FP256BN_copy(&(w->a),&w2);
|
|
FP_FP256BN_add(&w2,&w2,&w2);
|
|
FP_FP256BN_redc(b,&w2);
|
|
BIG_256_56_invmodp(b,b,q);
|
|
FP_FP256BN_nres(&w2,b);
|
|
FP_FP256BN_mul(&(w->b),&(w->b),&w2);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
int main()
|
|
{
|
|
int i;
|
|
FP2_FP256BN w,z;
|
|
BIG_256_56 a,b,e;
|
|
BIG_256_56 pp1,pm1;
|
|
BIG_256_56_unity(a); BIG_256_56_unity(b);
|
|
FP2_FP256BN_from_BIGs(&w,a,b);
|
|
// for (i=0;i<100;i++)
|
|
// {
|
|
// BIG_256_56_randomnum(a); BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus_FP256BN); BIG_256_56_mod(b,Modulus_FP256BN);
|
|
// FP2_FP256BN_from_FPs(&w,a,b);
|
|
// FP2_FP256BN_output(&w);
|
|
// FP2_FP256BN_inv(&z,&w);
|
|
// FP2_FP256BN_output(&z);
|
|
// FP2_FP256BN_inv(&z,&z);
|
|
// FP2_FP256BN_output(&z);
|
|
// FP2_FP256BN_output(&w);
|
|
// if (FP2_FP256BN_comp(&w,&z)!=1) printf("error \n");
|
|
// else printf("OK \n");
|
|
// }
|
|
//exit(0);
|
|
printf("w= "); FP2_FP256BN_output(&w); printf("\n");
|
|
BIG_256_56_zero(e); BIG_256_56_inc(e,27);
|
|
FP2_FP256BN_pow(&w,&w,e);
|
|
FP2_FP256BN_output(&w);
|
|
exit(0);
|
|
BIG_256_56_rcopy(pp1,Modulus_FP256BN);
|
|
BIG_256_56_rcopy(pm1,Modulus_FP256BN);
|
|
BIG_256_56_inc(pp1,1);
|
|
BIG_256_56_dec(pm1,1);
|
|
BIG_256_56_norm(pp1);
|
|
BIG_256_56_norm(pm1);
|
|
FP2_FP256BN_pow(&w,&w,pp1);
|
|
FP2_FP256BN_pow(&w,&w,pm1);
|
|
FP2_FP256BN_output(&w);
|
|
}
|
|
|
|
*/
|
|
|