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.
849 lines
22 KiB
849 lines
22 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^12 functions */
|
|
/* SU=m, m is Stack Usage (no lazy )*/
|
|
/* FP12 elements are of the form a+i.b+i^2.c */
|
|
|
|
#include "fp12_FP256BN.h"
|
|
|
|
/* test x==0 ? */
|
|
/* SU= 8 */
|
|
int FP12_FP256BN_iszilch(FP12_FP256BN *x)
|
|
{
|
|
if (FP4_FP256BN_iszilch(&(x->a)) && FP4_FP256BN_iszilch(&(x->b)) && FP4_FP256BN_iszilch(&(x->c))) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* test x==1 ? */
|
|
/* SU= 8 */
|
|
int FP12_FP256BN_isunity(FP12_FP256BN *x)
|
|
{
|
|
if (FP4_FP256BN_isunity(&(x->a)) && FP4_FP256BN_iszilch(&(x->b)) && FP4_FP256BN_iszilch(&(x->c))) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* FP12 copy w=x */
|
|
/* SU= 16 */
|
|
void FP12_FP256BN_copy(FP12_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
if (x==w) return;
|
|
FP4_FP256BN_copy(&(w->a),&(x->a));
|
|
FP4_FP256BN_copy(&(w->b),&(x->b));
|
|
FP4_FP256BN_copy(&(w->c),&(x->c));
|
|
}
|
|
|
|
/* FP12 w=1 */
|
|
/* SU= 8 */
|
|
void FP12_FP256BN_one(FP12_FP256BN *w)
|
|
{
|
|
FP4_FP256BN_one(&(w->a));
|
|
FP4_FP256BN_zero(&(w->b));
|
|
FP4_FP256BN_zero(&(w->c));
|
|
}
|
|
|
|
/* return 1 if x==y, else 0 */
|
|
/* SU= 16 */
|
|
int FP12_FP256BN_equals(FP12_FP256BN *x,FP12_FP256BN *y)
|
|
{
|
|
if (FP4_FP256BN_equals(&(x->a),&(y->a)) && FP4_FP256BN_equals(&(x->b),&(y->b)) && FP4_FP256BN_equals(&(x->b),&(y->b)))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* Set w=conj(x) */
|
|
/* SU= 8 */
|
|
void FP12_FP256BN_conj(FP12_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
FP12_FP256BN_copy(w,x);
|
|
FP4_FP256BN_conj(&(w->a),&(w->a));
|
|
FP4_FP256BN_nconj(&(w->b),&(w->b));
|
|
FP4_FP256BN_conj(&(w->c),&(w->c));
|
|
}
|
|
|
|
/* Create FP12 from FP4 */
|
|
/* SU= 8 */
|
|
void FP12_FP256BN_from_FP4(FP12_FP256BN *w,FP4_FP256BN *a)
|
|
{
|
|
FP4_FP256BN_copy(&(w->a),a);
|
|
FP4_FP256BN_zero(&(w->b));
|
|
FP4_FP256BN_zero(&(w->c));
|
|
}
|
|
|
|
/* Create FP12 from 3 FP4's */
|
|
/* SU= 16 */
|
|
void FP12_FP256BN_from_FP4s(FP12_FP256BN *w,FP4_FP256BN *a,FP4_FP256BN *b,FP4_FP256BN *c)
|
|
{
|
|
FP4_FP256BN_copy(&(w->a),a);
|
|
FP4_FP256BN_copy(&(w->b),b);
|
|
FP4_FP256BN_copy(&(w->c),c);
|
|
}
|
|
|
|
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
|
|
/* SU= 600 */
|
|
void FP12_FP256BN_usqr(FP12_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
FP4_FP256BN A,B,C,D;
|
|
|
|
FP4_FP256BN_copy(&A,&(x->a));
|
|
|
|
FP4_FP256BN_sqr(&(w->a),&(x->a));
|
|
FP4_FP256BN_add(&D,&(w->a),&(w->a));
|
|
FP4_FP256BN_add(&(w->a),&D,&(w->a));
|
|
|
|
FP4_FP256BN_norm(&(w->a));
|
|
FP4_FP256BN_nconj(&A,&A);
|
|
|
|
FP4_FP256BN_add(&A,&A,&A);
|
|
FP4_FP256BN_add(&(w->a),&(w->a),&A);
|
|
FP4_FP256BN_sqr(&B,&(x->c));
|
|
FP4_FP256BN_times_i(&B);
|
|
|
|
FP4_FP256BN_add(&D,&B,&B);
|
|
FP4_FP256BN_add(&B,&B,&D);
|
|
FP4_FP256BN_norm(&B);
|
|
|
|
FP4_FP256BN_sqr(&C,&(x->b));
|
|
|
|
FP4_FP256BN_add(&D,&C,&C);
|
|
FP4_FP256BN_add(&C,&C,&D);
|
|
|
|
FP4_FP256BN_norm(&C);
|
|
FP4_FP256BN_conj(&(w->b),&(x->b));
|
|
FP4_FP256BN_add(&(w->b),&(w->b),&(w->b));
|
|
FP4_FP256BN_nconj(&(w->c),&(x->c));
|
|
|
|
FP4_FP256BN_add(&(w->c),&(w->c),&(w->c));
|
|
FP4_FP256BN_add(&(w->b),&B,&(w->b));
|
|
FP4_FP256BN_add(&(w->c),&C,&(w->c));
|
|
|
|
FP12_FP256BN_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
|
|
}
|
|
|
|
/* FP12 squaring w=x^2 */
|
|
/* SU= 600 */
|
|
void FP12_FP256BN_sqr(FP12_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
/* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
|
|
|
|
FP4_FP256BN A,B,C,D;
|
|
|
|
FP4_FP256BN_sqr(&A,&(x->a));
|
|
FP4_FP256BN_mul(&B,&(x->b),&(x->c));
|
|
FP4_FP256BN_add(&B,&B,&B);
|
|
FP4_FP256BN_norm(&B);
|
|
FP4_FP256BN_sqr(&C,&(x->c));
|
|
|
|
FP4_FP256BN_mul(&D,&(x->a),&(x->b));
|
|
FP4_FP256BN_add(&D,&D,&D);
|
|
FP4_FP256BN_add(&(w->c),&(x->a),&(x->c));
|
|
FP4_FP256BN_add(&(w->c),&(x->b),&(w->c));
|
|
FP4_FP256BN_norm(&(w->c));
|
|
|
|
FP4_FP256BN_sqr(&(w->c),&(w->c));
|
|
|
|
FP4_FP256BN_copy(&(w->a),&A);
|
|
FP4_FP256BN_add(&A,&A,&B);
|
|
|
|
FP4_FP256BN_norm(&A);
|
|
|
|
FP4_FP256BN_add(&A,&A,&C);
|
|
FP4_FP256BN_add(&A,&A,&D);
|
|
|
|
FP4_FP256BN_norm(&A);
|
|
FP4_FP256BN_neg(&A,&A);
|
|
FP4_FP256BN_times_i(&B);
|
|
FP4_FP256BN_times_i(&C);
|
|
|
|
FP4_FP256BN_add(&(w->a),&(w->a),&B);
|
|
FP4_FP256BN_add(&(w->b),&C,&D);
|
|
FP4_FP256BN_add(&(w->c),&(w->c),&A);
|
|
|
|
FP12_FP256BN_norm(w);
|
|
}
|
|
|
|
/* FP12 full multiplication w=w*y */
|
|
|
|
|
|
/* SU= 896 */
|
|
/* FP12 full multiplication w=w*y */
|
|
void FP12_FP256BN_mul(FP12_FP256BN *w,FP12_FP256BN *y)
|
|
{
|
|
FP4_FP256BN z0,z1,z2,z3,t0,t1;
|
|
|
|
FP4_FP256BN_mul(&z0,&(w->a),&(y->a));
|
|
FP4_FP256BN_mul(&z2,&(w->b),&(y->b)); //
|
|
|
|
FP4_FP256BN_add(&t0,&(w->a),&(w->b));
|
|
FP4_FP256BN_add(&t1,&(y->a),&(y->b)); //
|
|
|
|
FP4_FP256BN_norm(&t0);
|
|
FP4_FP256BN_norm(&t1);
|
|
|
|
FP4_FP256BN_mul(&z1,&t0,&t1);
|
|
FP4_FP256BN_add(&t0,&(w->b),&(w->c));
|
|
FP4_FP256BN_add(&t1,&(y->b),&(y->c)); //
|
|
|
|
FP4_FP256BN_norm(&t0);
|
|
FP4_FP256BN_norm(&t1);
|
|
|
|
FP4_FP256BN_mul(&z3,&t0,&t1);
|
|
|
|
FP4_FP256BN_neg(&t0,&z0);
|
|
FP4_FP256BN_neg(&t1,&z2);
|
|
|
|
FP4_FP256BN_add(&z1,&z1,&t0); // z1=z1-z0
|
|
// FP4_FP256BN_norm(&z1);
|
|
FP4_FP256BN_add(&(w->b),&z1,&t1);
|
|
// z1=z1-z2
|
|
FP4_FP256BN_add(&z3,&z3,&t1); // z3=z3-z2
|
|
FP4_FP256BN_add(&z2,&z2,&t0); // z2=z2-z0
|
|
|
|
FP4_FP256BN_add(&t0,&(w->a),&(w->c));
|
|
FP4_FP256BN_add(&t1,&(y->a),&(y->c));
|
|
|
|
FP4_FP256BN_norm(&t0);
|
|
FP4_FP256BN_norm(&t1);
|
|
|
|
FP4_FP256BN_mul(&t0,&t1,&t0);
|
|
FP4_FP256BN_add(&z2,&z2,&t0);
|
|
|
|
FP4_FP256BN_mul(&t0,&(w->c),&(y->c));
|
|
FP4_FP256BN_neg(&t1,&t0);
|
|
|
|
FP4_FP256BN_add(&(w->c),&z2,&t1);
|
|
FP4_FP256BN_add(&z3,&z3,&t1);
|
|
FP4_FP256BN_times_i(&t0);
|
|
FP4_FP256BN_add(&(w->b),&(w->b),&t0);
|
|
FP4_FP256BN_norm(&z3);
|
|
FP4_FP256BN_times_i(&z3);
|
|
FP4_FP256BN_add(&(w->a),&z0,&z3);
|
|
|
|
FP12_FP256BN_norm(w);
|
|
}
|
|
|
|
/* FP12 multiplication w=w*y */
|
|
/* SU= 744 */
|
|
/* catering for special case that arises from special form of ATE pairing line function */
|
|
void FP12_FP256BN_smul(FP12_FP256BN *w,FP12_FP256BN *y,int type)
|
|
{
|
|
FP4_FP256BN z0,z1,z2,z3,t0,t1;
|
|
|
|
if (type==D_TYPE)
|
|
{
|
|
// y->c is 0
|
|
|
|
FP4_FP256BN_copy(&z3,&(w->b));
|
|
FP4_FP256BN_mul(&z0,&(w->a),&(y->a));
|
|
|
|
FP4_FP256BN_pmul(&z2,&(w->b),&(y->b).a);
|
|
FP4_FP256BN_add(&(w->b),&(w->a),&(w->b));
|
|
FP4_FP256BN_copy(&t1,&(y->a));
|
|
FP2_FP256BN_add(&t1.a,&t1.a,&(y->b).a);
|
|
|
|
FP4_FP256BN_norm(&t1);
|
|
FP4_FP256BN_norm(&(w->b));
|
|
|
|
FP4_FP256BN_mul(&(w->b),&(w->b),&t1);
|
|
FP4_FP256BN_add(&z3,&z3,&(w->c));
|
|
FP4_FP256BN_norm(&z3);
|
|
FP4_FP256BN_pmul(&z3,&z3,&(y->b).a);
|
|
FP4_FP256BN_neg(&t0,&z0);
|
|
FP4_FP256BN_neg(&t1,&z2);
|
|
|
|
FP4_FP256BN_add(&(w->b),&(w->b),&t0); // z1=z1-z0
|
|
// FP4_FP256BN_norm(&(w->b));
|
|
FP4_FP256BN_add(&(w->b),&(w->b),&t1); // z1=z1-z2
|
|
|
|
FP4_FP256BN_add(&z3,&z3,&t1); // z3=z3-z2
|
|
FP4_FP256BN_add(&z2,&z2,&t0); // z2=z2-z0
|
|
|
|
FP4_FP256BN_add(&t0,&(w->a),&(w->c));
|
|
|
|
FP4_FP256BN_norm(&t0);
|
|
FP4_FP256BN_norm(&z3);
|
|
|
|
FP4_FP256BN_mul(&t0,&(y->a),&t0);
|
|
FP4_FP256BN_add(&(w->c),&z2,&t0);
|
|
|
|
FP4_FP256BN_times_i(&z3);
|
|
FP4_FP256BN_add(&(w->a),&z0,&z3);
|
|
}
|
|
|
|
if (type==M_TYPE)
|
|
{
|
|
// y->b is zero
|
|
FP4_FP256BN_mul(&z0,&(w->a),&(y->a));
|
|
FP4_FP256BN_add(&t0,&(w->a),&(w->b));
|
|
FP4_FP256BN_norm(&t0);
|
|
|
|
FP4_FP256BN_mul(&z1,&t0,&(y->a));
|
|
FP4_FP256BN_add(&t0,&(w->b),&(w->c));
|
|
FP4_FP256BN_norm(&t0);
|
|
|
|
FP4_FP256BN_pmul(&z3,&t0,&(y->c).b);
|
|
FP4_FP256BN_times_i(&z3);
|
|
|
|
FP4_FP256BN_neg(&t0,&z0);
|
|
FP4_FP256BN_add(&z1,&z1,&t0); // z1=z1-z0
|
|
|
|
FP4_FP256BN_copy(&(w->b),&z1);
|
|
|
|
FP4_FP256BN_copy(&z2,&t0);
|
|
|
|
FP4_FP256BN_add(&t0,&(w->a),&(w->c));
|
|
FP4_FP256BN_add(&t1,&(y->a),&(y->c));
|
|
|
|
FP4_FP256BN_norm(&t0);
|
|
FP4_FP256BN_norm(&t1);
|
|
|
|
FP4_FP256BN_mul(&t0,&t1,&t0);
|
|
FP4_FP256BN_add(&z2,&z2,&t0);
|
|
|
|
FP4_FP256BN_pmul(&t0,&(w->c),&(y->c).b);
|
|
FP4_FP256BN_times_i(&t0);
|
|
FP4_FP256BN_neg(&t1,&t0);
|
|
FP4_FP256BN_times_i(&t0);
|
|
|
|
FP4_FP256BN_add(&(w->c),&z2,&t1);
|
|
FP4_FP256BN_add(&z3,&z3,&t1);
|
|
|
|
FP4_FP256BN_add(&(w->b),&(w->b),&t0);
|
|
FP4_FP256BN_norm(&z3);
|
|
FP4_FP256BN_times_i(&z3);
|
|
FP4_FP256BN_add(&(w->a),&z0,&z3);
|
|
}
|
|
FP12_FP256BN_norm(w);
|
|
}
|
|
|
|
/* Set w=1/x */
|
|
/* SU= 600 */
|
|
void FP12_FP256BN_inv(FP12_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
FP4_FP256BN f0,f1,f2,f3;
|
|
// FP12_FP256BN_norm(x);
|
|
|
|
FP4_FP256BN_sqr(&f0,&(x->a));
|
|
FP4_FP256BN_mul(&f1,&(x->b),&(x->c));
|
|
FP4_FP256BN_times_i(&f1);
|
|
FP4_FP256BN_sub(&f0,&f0,&f1); /* y.a */
|
|
FP4_FP256BN_norm(&f0);
|
|
|
|
FP4_FP256BN_sqr(&f1,&(x->c));
|
|
FP4_FP256BN_times_i(&f1);
|
|
FP4_FP256BN_mul(&f2,&(x->a),&(x->b));
|
|
FP4_FP256BN_sub(&f1,&f1,&f2); /* y.b */
|
|
FP4_FP256BN_norm(&f1);
|
|
|
|
FP4_FP256BN_sqr(&f2,&(x->b));
|
|
FP4_FP256BN_mul(&f3,&(x->a),&(x->c));
|
|
FP4_FP256BN_sub(&f2,&f2,&f3); /* y.c */
|
|
FP4_FP256BN_norm(&f2);
|
|
|
|
FP4_FP256BN_mul(&f3,&(x->b),&f2);
|
|
FP4_FP256BN_times_i(&f3);
|
|
FP4_FP256BN_mul(&(w->a),&f0,&(x->a));
|
|
FP4_FP256BN_add(&f3,&(w->a),&f3);
|
|
FP4_FP256BN_mul(&(w->c),&f1,&(x->c));
|
|
FP4_FP256BN_times_i(&(w->c));
|
|
|
|
FP4_FP256BN_add(&f3,&(w->c),&f3);
|
|
FP4_FP256BN_norm(&f3);
|
|
|
|
FP4_FP256BN_inv(&f3,&f3);
|
|
|
|
FP4_FP256BN_mul(&(w->a),&f0,&f3);
|
|
FP4_FP256BN_mul(&(w->b),&f1,&f3);
|
|
FP4_FP256BN_mul(&(w->c),&f2,&f3);
|
|
|
|
}
|
|
|
|
/* constant time powering by small integer of max length bts */
|
|
|
|
void FP12_FP256BN_pinpow(FP12_FP256BN *r,int e,int bts)
|
|
{
|
|
int i,b;
|
|
FP12_FP256BN R[2];
|
|
|
|
FP12_FP256BN_one(&R[0]);
|
|
FP12_FP256BN_copy(&R[1],r);
|
|
|
|
for (i=bts-1; i>=0; i--)
|
|
{
|
|
b=(e>>i)&1;
|
|
FP12_FP256BN_mul(&R[1-b],&R[b]);
|
|
FP12_FP256BN_usqr(&R[b],&R[b]);
|
|
}
|
|
FP12_FP256BN_copy(r,&R[0]);
|
|
}
|
|
|
|
/* Compressed powering of unitary elements y=x^(e mod r) */
|
|
|
|
void FP12_FP256BN_compow(FP4_FP256BN *c,FP12_FP256BN *x,BIG_256_56 e,BIG_256_56 r)
|
|
{
|
|
FP12_FP256BN g1,g2;
|
|
FP4_FP256BN cp,cpm1,cpm2;
|
|
FP2_FP256BN f;
|
|
BIG_256_56 q,a,b,m;
|
|
|
|
BIG_256_56_rcopy(a,Fra_FP256BN);
|
|
BIG_256_56_rcopy(b,Frb_FP256BN);
|
|
FP2_FP256BN_from_BIGs(&f,a,b);
|
|
|
|
BIG_256_56_rcopy(q,Modulus_FP256BN);
|
|
|
|
FP12_FP256BN_copy(&g1,x);
|
|
FP12_FP256BN_copy(&g2,x);
|
|
|
|
BIG_256_56_copy(m,q);
|
|
BIG_256_56_mod(m,r);
|
|
|
|
BIG_256_56_copy(a,e);
|
|
BIG_256_56_mod(a,m);
|
|
|
|
BIG_256_56_copy(b,e);
|
|
BIG_256_56_sdiv(b,m);
|
|
|
|
FP12_FP256BN_trace(c,&g1);
|
|
|
|
if (BIG_256_56_iszilch(b))
|
|
{
|
|
FP4_FP256BN_xtr_pow(c,c,e);
|
|
return;
|
|
}
|
|
|
|
|
|
FP12_FP256BN_frob(&g2,&f);
|
|
FP12_FP256BN_trace(&cp,&g2);
|
|
|
|
FP12_FP256BN_conj(&g1,&g1);
|
|
FP12_FP256BN_mul(&g2,&g1);
|
|
FP12_FP256BN_trace(&cpm1,&g2);
|
|
FP12_FP256BN_mul(&g2,&g1);
|
|
FP12_FP256BN_trace(&cpm2,&g2);
|
|
|
|
FP4_FP256BN_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
|
|
|
|
}
|
|
|
|
|
|
/* SU= 528 */
|
|
/* set r=a^b */
|
|
/* Note this is simple square and multiply, so not side-channel safe */
|
|
|
|
void FP12_FP256BN_pow(FP12_FP256BN *r,FP12_FP256BN *a,BIG_256_56 b)
|
|
{
|
|
FP12_FP256BN w;
|
|
BIG_256_56 b3;
|
|
int i,nb,bt;
|
|
BIG_256_56_norm(b);
|
|
BIG_256_56_pmul(b3,b,3);
|
|
BIG_256_56_norm(b3);
|
|
|
|
FP12_FP256BN_copy(&w,a);
|
|
|
|
nb=BIG_256_56_nbits(b3);
|
|
for (i=nb-2; i>=1; i--)
|
|
{
|
|
FP12_FP256BN_usqr(&w,&w);
|
|
bt=BIG_256_56_bit(b3,i)-BIG_256_56_bit(b,i);
|
|
if (bt==1)
|
|
FP12_FP256BN_mul(&w,a);
|
|
if (bt==-1)
|
|
{
|
|
FP12_FP256BN_conj(a,a);
|
|
FP12_FP256BN_mul(&w,a);
|
|
FP12_FP256BN_conj(a,a);
|
|
}
|
|
}
|
|
|
|
FP12_FP256BN_copy(r,&w);
|
|
FP12_FP256BN_reduce(r);
|
|
|
|
/*
|
|
while(1)
|
|
{
|
|
bt=BIG_256_56_parity(z);
|
|
BIG_256_56_shr(z,1);
|
|
if (bt)
|
|
FP12_FP256BN_mul(r,&w);
|
|
if (BIG_256_56_comp(z,zilch)==0) break;
|
|
FP12_FP256BN_usqr(&w,&w);
|
|
}
|
|
|
|
FP12_FP256BN_reduce(r); */
|
|
}
|
|
|
|
/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
|
|
/* Timing attack secure, but not cache attack secure */
|
|
|
|
void FP12_FP256BN_pow4(FP12_FP256BN *p,FP12_FP256BN *q,BIG_256_56 u[4])
|
|
{
|
|
int i,j,a[4],nb,m;
|
|
FP12_FP256BN g[8],c,s[2];
|
|
BIG_256_56 t[4],mt;
|
|
sign8 w[NLEN_256_56*BASEBITS_256_56+1];
|
|
|
|
for (i=0; i<4; i++)
|
|
BIG_256_56_copy(t[i],u[i]);
|
|
|
|
FP12_FP256BN_copy(&g[0],&q[0]);
|
|
FP12_FP256BN_conj(&s[0],&q[1]);
|
|
FP12_FP256BN_mul(&g[0],&s[0]); /* P/Q */
|
|
FP12_FP256BN_copy(&g[1],&g[0]);
|
|
FP12_FP256BN_copy(&g[2],&g[0]);
|
|
FP12_FP256BN_copy(&g[3],&g[0]);
|
|
FP12_FP256BN_copy(&g[4],&q[0]);
|
|
FP12_FP256BN_mul(&g[4],&q[1]); /* P*Q */
|
|
FP12_FP256BN_copy(&g[5],&g[4]);
|
|
FP12_FP256BN_copy(&g[6],&g[4]);
|
|
FP12_FP256BN_copy(&g[7],&g[4]);
|
|
|
|
FP12_FP256BN_copy(&s[1],&q[2]);
|
|
FP12_FP256BN_conj(&s[0],&q[3]);
|
|
FP12_FP256BN_mul(&s[1],&s[0]); /* R/S */
|
|
FP12_FP256BN_conj(&s[0],&s[1]);
|
|
FP12_FP256BN_mul(&g[1],&s[0]);
|
|
FP12_FP256BN_mul(&g[2],&s[1]);
|
|
FP12_FP256BN_mul(&g[5],&s[0]);
|
|
FP12_FP256BN_mul(&g[6],&s[1]);
|
|
FP12_FP256BN_copy(&s[1],&q[2]);
|
|
FP12_FP256BN_mul(&s[1],&q[3]); /* R*S */
|
|
FP12_FP256BN_conj(&s[0],&s[1]);
|
|
FP12_FP256BN_mul(&g[0],&s[0]);
|
|
FP12_FP256BN_mul(&g[3],&s[1]);
|
|
FP12_FP256BN_mul(&g[4],&s[0]);
|
|
FP12_FP256BN_mul(&g[7],&s[1]);
|
|
|
|
/* if power is even add 1 to power, and add q to correction */
|
|
FP12_FP256BN_one(&c);
|
|
|
|
BIG_256_56_zero(mt);
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if (BIG_256_56_parity(t[i])==0)
|
|
{
|
|
BIG_256_56_inc(t[i],1);
|
|
BIG_256_56_norm(t[i]);
|
|
FP12_FP256BN_mul(&c,&q[i]);
|
|
}
|
|
BIG_256_56_add(mt,mt,t[i]);
|
|
BIG_256_56_norm(mt);
|
|
}
|
|
|
|
FP12_FP256BN_conj(&c,&c);
|
|
nb=1+BIG_256_56_nbits(mt);
|
|
|
|
/* convert exponent to signed 1-bit window */
|
|
for (j=0; j<nb; j++)
|
|
{
|
|
for (i=0; i<4; i++)
|
|
{
|
|
a[i]=BIG_256_56_lastbits(t[i],2)-2;
|
|
BIG_256_56_dec(t[i],a[i]);
|
|
BIG_256_56_norm(t[i]);
|
|
BIG_256_56_fshr(t[i],1);
|
|
}
|
|
w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
|
|
}
|
|
w[nb]=8*BIG_256_56_lastbits(t[0],2)+4*BIG_256_56_lastbits(t[1],2)+2*BIG_256_56_lastbits(t[2],2)+BIG_256_56_lastbits(t[3],2);
|
|
FP12_FP256BN_copy(p,&g[(w[nb]-1)/2]);
|
|
|
|
for (i=nb-1; i>=0; i--)
|
|
{
|
|
m=w[i]>>7;
|
|
j=(w[i]^m)-m; /* j=abs(w[i]) */
|
|
j=(j-1)/2;
|
|
FP12_FP256BN_copy(&s[0],&g[j]);
|
|
FP12_FP256BN_conj(&s[1],&g[j]);
|
|
FP12_FP256BN_usqr(p,p);
|
|
FP12_FP256BN_mul(p,&s[m&1]);
|
|
}
|
|
FP12_FP256BN_mul(p,&c); /* apply correction */
|
|
FP12_FP256BN_reduce(p);
|
|
}
|
|
|
|
/* Set w=w^p using Frobenius */
|
|
/* SU= 160 */
|
|
void FP12_FP256BN_frob(FP12_FP256BN *w,FP2_FP256BN *f)
|
|
{
|
|
FP2_FP256BN f2,f3;
|
|
FP2_FP256BN_sqr(&f2,f); /* f2=f^2 */
|
|
FP2_FP256BN_mul(&f3,&f2,f); /* f3=f^3 */
|
|
|
|
FP4_FP256BN_frob(&(w->a),&f3);
|
|
FP4_FP256BN_frob(&(w->b),&f3);
|
|
FP4_FP256BN_frob(&(w->c),&f3);
|
|
|
|
FP4_FP256BN_pmul(&(w->b),&(w->b),f);
|
|
FP4_FP256BN_pmul(&(w->c),&(w->c),&f2);
|
|
}
|
|
|
|
/* SU= 8 */
|
|
/* normalise all components of w */
|
|
void FP12_FP256BN_norm(FP12_FP256BN *w)
|
|
{
|
|
FP4_FP256BN_norm(&(w->a));
|
|
FP4_FP256BN_norm(&(w->b));
|
|
FP4_FP256BN_norm(&(w->c));
|
|
}
|
|
|
|
/* SU= 8 */
|
|
/* reduce all components of w */
|
|
void FP12_FP256BN_reduce(FP12_FP256BN *w)
|
|
{
|
|
FP4_FP256BN_reduce(&(w->a));
|
|
FP4_FP256BN_reduce(&(w->b));
|
|
FP4_FP256BN_reduce(&(w->c));
|
|
}
|
|
|
|
/* trace function w=trace(x) */
|
|
/* SU= 8 */
|
|
void FP12_FP256BN_trace(FP4_FP256BN *w,FP12_FP256BN *x)
|
|
{
|
|
FP4_FP256BN_imul(w,&(x->a),3);
|
|
FP4_FP256BN_reduce(w);
|
|
}
|
|
|
|
/* SU= 8 */
|
|
/* Output w in hex */
|
|
void FP12_FP256BN_output(FP12_FP256BN *w)
|
|
{
|
|
printf("[");
|
|
FP4_FP256BN_output(&(w->a));
|
|
printf(",");
|
|
FP4_FP256BN_output(&(w->b));
|
|
printf(",");
|
|
FP4_FP256BN_output(&(w->c));
|
|
printf("]");
|
|
}
|
|
|
|
/* SU= 64 */
|
|
/* Convert g to octet string w */
|
|
void FP12_FP256BN_toOctet(octet *W,FP12_FP256BN *g)
|
|
{
|
|
BIG_256_56 a;
|
|
W->len=12*MODBYTES_256_56;
|
|
|
|
FP_FP256BN_redc(a,&(g->a.a.a));
|
|
BIG_256_56_toBytes(&(W->val[0]),a);
|
|
FP_FP256BN_redc(a,&(g->a.a.b));
|
|
BIG_256_56_toBytes(&(W->val[MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->a.b.a));
|
|
BIG_256_56_toBytes(&(W->val[2*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->a.b.b));
|
|
BIG_256_56_toBytes(&(W->val[3*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->b.a.a));
|
|
BIG_256_56_toBytes(&(W->val[4*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->b.a.b));
|
|
BIG_256_56_toBytes(&(W->val[5*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->b.b.a));
|
|
BIG_256_56_toBytes(&(W->val[6*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->b.b.b));
|
|
BIG_256_56_toBytes(&(W->val[7*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->c.a.a));
|
|
BIG_256_56_toBytes(&(W->val[8*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->c.a.b));
|
|
BIG_256_56_toBytes(&(W->val[9*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->c.b.a));
|
|
BIG_256_56_toBytes(&(W->val[10*MODBYTES_256_56]),a);
|
|
FP_FP256BN_redc(a,&(g->c.b.b));
|
|
BIG_256_56_toBytes(&(W->val[11*MODBYTES_256_56]),a);
|
|
}
|
|
|
|
/* SU= 24 */
|
|
/* Restore g from octet string w */
|
|
void FP12_FP256BN_fromOctet(FP12_FP256BN *g,octet *W)
|
|
{
|
|
BIG_256_56 b;
|
|
BIG_256_56_fromBytes(b,&W->val[0]);
|
|
FP_FP256BN_nres(&(g->a.a.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->a.a.b),b);
|
|
BIG_256_56_fromBytes(b,&W->val[2*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->a.b.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[3*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->a.b.b),b);
|
|
BIG_256_56_fromBytes(b,&W->val[4*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->b.a.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[5*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->b.a.b),b);
|
|
BIG_256_56_fromBytes(b,&W->val[6*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->b.b.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[7*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->b.b.b),b);
|
|
BIG_256_56_fromBytes(b,&W->val[8*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->c.a.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[9*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->c.a.b),b);
|
|
BIG_256_56_fromBytes(b,&W->val[10*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->c.b.a),b);
|
|
BIG_256_56_fromBytes(b,&W->val[11*MODBYTES_256_56]);
|
|
FP_FP256BN_nres(&(g->c.b.b),b);
|
|
}
|
|
|
|
/*
|
|
int main(){
|
|
FP2_FP256BN f,w0,w1;
|
|
FP4_FP256BN t0,t1,t2;
|
|
FP12_FP256BN w,t,lv;
|
|
BIG_256_56 a,b;
|
|
BIG_256_56 p;
|
|
|
|
//Test w^(P^4) = w mod p^2
|
|
// BIG_256_56_randomnum(a);
|
|
// BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,1); BIG_256_56_inc(b,2); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w0,a,b);
|
|
|
|
// BIG_256_56_randomnum(a); BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,3); BIG_256_56_inc(b,4); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w1,a,b);
|
|
|
|
FP4_FP256BN_from_FP2s(&t0,&w0,&w1);
|
|
FP4_FP256BN_reduce(&t0);
|
|
|
|
// BIG_256_56_randomnum(a);
|
|
// BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,5); BIG_256_56_inc(b,6); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w0,a,b);
|
|
|
|
// BIG_256_56_randomnum(a); BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,7); BIG_256_56_inc(b,8); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w1,a,b);
|
|
|
|
FP4_FP256BN_from_FP2s(&t1,&w0,&w1);
|
|
FP4_FP256BN_reduce(&t1);
|
|
|
|
// BIG_256_56_randomnum(a);
|
|
// BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,9); BIG_256_56_inc(b,10); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w0,a,b);
|
|
|
|
// BIG_256_56_randomnum(a); BIG_256_56_randomnum(b);
|
|
// BIG_256_56_mod(a,Modulus); BIG_256_56_mod(b,Modulus);
|
|
BIG_256_56_zero(a); BIG_256_56_zero(b); BIG_256_56_inc(a,11); BIG_256_56_inc(b,12); FP_FP256BN_nres(a); FP_FP256BN_nres(b);
|
|
FP2_FP256BN_from_zps(&w1,a,b);
|
|
|
|
FP4_FP256BN_from_FP2s(&t2,&w0,&w1);
|
|
FP4_FP256BN_reduce(&t2);
|
|
|
|
FP12_FP256BN_from_FP4s(&w,&t0,&t1,&t2);
|
|
|
|
FP12_FP256BN_copy(&t,&w);
|
|
|
|
printf("w= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
|
|
BIG_256_56_rcopy(p,Modulus);
|
|
//BIG_256_56_zero(p); BIG_256_56_inc(p,7);
|
|
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
|
|
printf("w^p= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
|
|
FP2_FP256BN_gfc(&f,12);
|
|
FP12_FP256BN_frob(&t,&f);
|
|
printf("w^p= ");
|
|
FP12_FP256BN_output(&t);
|
|
printf("\n");
|
|
|
|
//exit(0);
|
|
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
//printf("w^p^2= ");
|
|
//FP12_FP256BN_output(&w);
|
|
//printf("\n");
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
//printf("w^p^3= ");
|
|
//FP12_FP256BN_output(&w);
|
|
//printf("\n");
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
printf("w^p^6= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
printf("w^p^8= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
printf("w^p^11= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
|
|
// BIG_256_56_zero(p); BIG_256_56_inc(p,7); BIG_256_56_norm(p);
|
|
FP12_FP256BN_pow(&w,&w,p);
|
|
|
|
printf("w^p12= ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
//exit(0);
|
|
|
|
FP12_FP256BN_inv(&t,&w);
|
|
printf("1/w mod p^4 = ");
|
|
FP12_FP256BN_output(&t);
|
|
printf("\n");
|
|
|
|
FP12_FP256BN_inv(&w,&t);
|
|
printf("1/(1/w) mod p^4 = ");
|
|
FP12_FP256BN_output(&w);
|
|
printf("\n");
|
|
|
|
|
|
|
|
FP12_FP256BN_inv(&lv,&w);
|
|
//printf("w= "); FP12_FP256BN_output(&w); printf("\n");
|
|
FP12_FP256BN_conj(&w,&w);
|
|
//printf("w= "); FP12_FP256BN_output(&w); printf("\n");
|
|
//exit(0);
|
|
FP12_FP256BN_mul(&w,&w,&lv);
|
|
//printf("w= "); FP12_FP256BN_output(&w); printf("\n");
|
|
FP12_FP256BN_copy(&lv,&w);
|
|
FP12_FP256BN_frob(&w,&f);
|
|
FP12_FP256BN_frob(&w,&f);
|
|
FP12_FP256BN_mul(&w,&w,&lv);
|
|
|
|
//printf("w= "); FP12_FP256BN_output(&w); printf("\n");
|
|
//exit(0);
|
|
|
|
w.unitary=0;
|
|
FP12_FP256BN_conj(&lv,&w);
|
|
printf("rx= "); FP12_FP256BN_output(&lv); printf("\n");
|
|
FP12_FP256BN_inv(&lv,&w);
|
|
printf("ry= "); FP12_FP256BN_output(&lv); printf("\n");
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
*/
|
|
|