730 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			730 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2012-2020 MIRACL UK Ltd.
 | |
|  *
 | |
|  * This file is part of MIRACL Core
 | |
|  * (see https://github.com/miracl/core).
 | |
|  *
 | |
|  * Licensed 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.
 | |
|  */
 | |
| 
 | |
| /* CORE Fp^4 functions */
 | |
| /* SU=m, m is Stack Usage (no lazy )*/
 | |
| 
 | |
| /* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
 | |
| 
 | |
| #include "fp4_YYY.h"
 | |
| 
 | |
| using namespace XXX;
 | |
| 
 | |
| /* test x==0 ? */
 | |
| /* SU= 8 */
 | |
| int YYY::FP4_iszilch(FP4 *x)
 | |
| {
 | |
|     return (FP2_iszilch(&(x->a)) & FP2_iszilch(&(x->b)));
 | |
| }
 | |
| 
 | |
| /* test x==1 ? */
 | |
| /* SU= 8 */
 | |
| int YYY::FP4_isunity(FP4 *x)
 | |
| {
 | |
|     return (FP2_isunity(&(x->a)) & FP2_iszilch(&(x->b)));
 | |
| }
 | |
| 
 | |
| /* test is w real? That is in a+ib test b is zero */
 | |
| int YYY::FP4_isreal(FP4 *w)
 | |
| {
 | |
|     return FP2_iszilch(&(w->b));
 | |
| }
 | |
| 
 | |
| 
 | |
| // Is x lexically larger than p-x?
 | |
| // return -1 for no, 0 if x=0, 1 for yes
 | |
| int YYY::FP4_islarger(FP4 *x)
 | |
| {
 | |
|     int cmp;
 | |
|     if (FP4_iszilch(x)) return 0;
 | |
|     cmp=FP2_islarger(&(x->b));
 | |
|     if (cmp!=0) return cmp;
 | |
|     return FP2_islarger(&(x->a));
 | |
| }
 | |
| 
 | |
| void YYY::FP4_toBytes(char *b,FP4 *x)
 | |
| {
 | |
|     FP2_toBytes(b,&(x->b));
 | |
|     FP2_toBytes(&b[2*MODBYTES_XXX],&(x->a));
 | |
| }
 | |
| 
 | |
| void YYY::FP4_fromBytes(FP4 *x,char *b)
 | |
| {
 | |
|     FP2_fromBytes(&(x->b),b);
 | |
|     FP2_fromBytes(&(x->a),&b[2*MODBYTES_XXX]);
 | |
| }
 | |
| 
 | |
| /* return 1 if x==y, else 0 */
 | |
| /* SU= 16 */
 | |
| int YYY::FP4_equals(FP4 *x, FP4 *y)
 | |
| {
 | |
|     return (FP2_equals(&(x->a), &(y->a)) & FP2_equals(&(x->b), &(y->b)));
 | |
| }
 | |
| 
 | |
| /* set FP4 from two FP2s */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_from_FP2s(FP4 *w, FP2 * x, FP2* y)
 | |
| {
 | |
|     FP2_copy(&(w->a), x);
 | |
|     FP2_copy(&(w->b), y);
 | |
| }
 | |
| 
 | |
| /* set FP4 from FP2 */
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_from_FP2(FP4 *w, FP2 *x)
 | |
| {
 | |
|     FP2_copy(&(w->a), x);
 | |
|     FP2_zero(&(w->b));
 | |
| }
 | |
| 
 | |
| /* set high part of FP4 from FP2 */
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_from_FP2H(FP4 *w, FP2 *x)
 | |
| {
 | |
|     FP2_copy(&(w->b), x);
 | |
|     FP2_zero(&(w->a));
 | |
| }
 | |
| 
 | |
| /* set FP4 from FP */
 | |
| void YYY::FP4_from_FP(FP4 *w, FP *x)
 | |
| {
 | |
|     FP2 t;
 | |
|     FP2_from_FP(&t, x);
 | |
|     FP4_from_FP2(w, &t);
 | |
| }
 | |
| 
 | |
| /* FP4 copy w=x */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_copy(FP4 *w, FP4 *x)
 | |
| {
 | |
|     if (w == x) return;
 | |
|     FP2_copy(&(w->a), &(x->a));
 | |
|     FP2_copy(&(w->b), &(x->b));
 | |
| }
 | |
| 
 | |
| /* FP4 w=0 */
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_zero(FP4 *w)
 | |
| {
 | |
|     FP2_zero(&(w->a));
 | |
|     FP2_zero(&(w->b));
 | |
| }
 | |
| 
 | |
| /* FP4 w=1 */
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_one(FP4 *w)
 | |
| {
 | |
|     FP2_one(&(w->a));
 | |
|     FP2_zero(&(w->b));
 | |
| }
 | |
| 
 | |
| int YYY::FP4_sign(FP4 *w)
 | |
| {
 | |
|     int p1,p2;
 | |
|     p1=FP2_sign(&(w->a));
 | |
|     p2=FP2_sign(&(w->b));
 | |
| #ifdef BIG_ENDIAN_SIGN_YYY
 | |
|     p2 ^= (p1 ^ p2)&FP2_iszilch(&(w->b));
 | |
|     return p2;
 | |
| #else
 | |
|     p1 ^= (p1 ^ p2)&FP2_iszilch(&(w->a));
 | |
|     return p1;
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
| /* Set w=-x */
 | |
| /* SU= 160 */
 | |
| void YYY::FP4_neg(FP4 *w, FP4 *x)
 | |
| {
 | |
|     /* Just one field neg */
 | |
|     FP2 m, t;
 | |
|     FP4_norm(x);
 | |
| 
 | |
|     FP2_add(&m, &(x->a), &(x->b));
 | |
|     FP2_neg(&m, &m);
 | |
|     FP2_add(&t, &m, &(x->b));
 | |
|     FP2_add(&(w->b), &m, &(x->a));
 | |
|     FP2_copy(&(w->a), &t);
 | |
|     FP4_norm(w);
 | |
| }
 | |
| 
 | |
| /* Set w=conj(x) */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_conj(FP4 *w, FP4 *x)
 | |
| {
 | |
|     FP2_copy(&(w->a), &(x->a));
 | |
|     FP2_neg(&(w->b), &(x->b));
 | |
|     FP4_norm(w);
 | |
| }
 | |
| 
 | |
| /* Set w=-conj(x) */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_nconj(FP4 *w, FP4 *x)
 | |
| {
 | |
|     FP2_copy(&(w->b), &(x->b));
 | |
|     FP2_neg(&(w->a), &(x->a));
 | |
|     FP4_norm(w);
 | |
| }
 | |
| 
 | |
| /* Set w=x+y */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_add(FP4 *w, FP4 *x, FP4 *y)
 | |
| {
 | |
|     FP2_add(&(w->a), &(x->a), &(y->a));
 | |
|     FP2_add(&(w->b), &(x->b), &(y->b));
 | |
| }
 | |
| 
 | |
| /* Set w=x-y */
 | |
| /* Input y MUST be normed */
 | |
| void YYY::FP4_sub(FP4 *w, FP4 *x, FP4 *y)
 | |
| {
 | |
|     FP4 my;
 | |
|     FP4_neg(&my, y);
 | |
|     FP4_add(w, x, &my);
 | |
| }
 | |
| /* SU= 8 */
 | |
| /* reduce all components of w mod Modulus */
 | |
| void YYY::FP4_reduce(FP4 *w)
 | |
| {
 | |
|     FP2_reduce(&(w->a));
 | |
|     FP2_reduce(&(w->b));
 | |
| }
 | |
| 
 | |
| /* SU= 8 */
 | |
| /* normalise all elements of w */
 | |
| void YYY::FP4_norm(FP4 *w)
 | |
| {
 | |
|     FP2_norm(&(w->a));
 | |
|     FP2_norm(&(w->b));
 | |
| }
 | |
| 
 | |
| /* Set w=s*x, where s is FP2 */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_pmul(FP4 *w, FP4 *x, FP2 *s)
 | |
| {
 | |
|     FP2_mul(&(w->a), &(x->a), s);
 | |
|     FP2_mul(&(w->b), &(x->b), s);
 | |
| }
 | |
| 
 | |
| /* Set w=s*x, where s is FP */
 | |
| void YYY::FP4_qmul(FP4 *w, FP4 *x, FP *s)
 | |
| {
 | |
|     FP2_pmul(&(w->a), &(x->a), s);
 | |
|     FP2_pmul(&(w->b), &(x->b), s);
 | |
| }
 | |
| 
 | |
| /* SU= 16 */
 | |
| /* Set w=s*x, where s is int */
 | |
| void YYY::FP4_imul(FP4 *w, FP4 *x, int s)
 | |
| {
 | |
|     FP2_imul(&(w->a), &(x->a), s);
 | |
|     FP2_imul(&(w->b), &(x->b), s);
 | |
| }
 | |
| 
 | |
| /* Set w=x^2 */
 | |
| /* Input MUST be normed  */
 | |
| void YYY::FP4_sqr(FP4 *w, FP4 *x)
 | |
| {
 | |
|     FP2 t1, t2, t3;
 | |
| 
 | |
|     FP2_mul(&t3, &(x->a), &(x->b)); /* norms x */
 | |
|     FP2_copy(&t2, &(x->b));
 | |
|     FP2_add(&t1, &(x->a), &(x->b));
 | |
|     FP2_mul_ip(&t2);
 | |
| 
 | |
|     FP2_add(&t2, &(x->a), &t2);
 | |
| 
 | |
|     FP2_norm(&t1);  // 2
 | |
|     FP2_norm(&t2);  // 2
 | |
| 
 | |
|     FP2_mul(&(w->a), &t1, &t2);
 | |
| 
 | |
|     FP2_copy(&t2, &t3);
 | |
|     FP2_mul_ip(&t2);
 | |
| 
 | |
|     FP2_add(&t2, &t2, &t3);
 | |
| 
 | |
|     FP2_norm(&t2);  // 2
 | |
|     FP2_neg(&t2, &t2);
 | |
|     FP2_add(&(w->a), &(w->a), &t2); /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
 | |
|     FP2_add(&(w->b), &t3, &t3); /* b=2ab */
 | |
| 
 | |
|     FP4_norm(w);
 | |
| }
 | |
| 
 | |
| /* Set w=x*y */
 | |
| /* Inputs MUST be normed  */
 | |
| void YYY::FP4_mul(FP4 *w, FP4 *x, FP4 *y)
 | |
| {
 | |
| 
 | |
|     FP2 t1, t2, t3, t4;
 | |
| 
 | |
|     FP2_mul(&t1, &(x->a), &(y->a));
 | |
| 
 | |
|     FP2_mul(&t2, &(x->b), &(y->b));
 | |
|     FP2_add(&t3, &(y->b), &(y->a));
 | |
|     FP2_add(&t4, &(x->b), &(x->a));
 | |
| 
 | |
|     FP2_norm(&t4); // 2
 | |
|     FP2_norm(&t3); // 2
 | |
| 
 | |
|     FP2_mul(&t4, &t4, &t3); /* (xa+xb)(ya+yb) */
 | |
| 
 | |
|     FP2_neg(&t3, &t1); // 1
 | |
|     FP2_add(&t4, &t4, &t3); //t4E=3
 | |
|     FP2_norm(&t4);
 | |
| 
 | |
|     FP2_neg(&t3, &t2); // 1
 | |
|     FP2_add(&(w->b), &t4, &t3); //wbE=3
 | |
| 
 | |
|     FP2_mul_ip(&t2);
 | |
|     FP2_add(&(w->a), &t2, &t1);
 | |
| 
 | |
|     FP4_norm(w);
 | |
| }
 | |
| 
 | |
| /* output FP4 in format [a,b] */
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_output(FP4 *w)
 | |
| {
 | |
|     printf("[");
 | |
|     FP2_output(&(w->a));
 | |
|     printf(",");
 | |
|     FP2_output(&(w->b));
 | |
|     printf("]");
 | |
| }
 | |
| 
 | |
| /* SU= 8 */
 | |
| void YYY::FP4_rawoutput(FP4 *w)
 | |
| {
 | |
|     printf("[");
 | |
|     FP2_rawoutput(&(w->a));
 | |
|     printf(",");
 | |
|     FP2_rawoutput(&(w->b));
 | |
|     printf("]");
 | |
| }
 | |
| 
 | |
| /* Set w=1/x */
 | |
| /* SU= 160 */
 | |
| void YYY::FP4_inv(FP4 *w, FP4 *x, FP *h)
 | |
| {
 | |
|     FP2 t1, t2;
 | |
|     FP2_sqr(&t1, &(x->a));
 | |
|     FP2_sqr(&t2, &(x->b));
 | |
|     FP2_mul_ip(&t2);
 | |
|     FP2_norm(&t2);
 | |
|     FP2_sub(&t1, &t1, &t2);
 | |
|     FP2_inv(&t1, &t1, h);
 | |
|     FP2_mul(&(w->a), &t1, &(x->a));
 | |
|     FP2_neg(&t1, &t1);
 | |
|     FP2_norm(&t1);
 | |
|     FP2_mul(&(w->b), &t1, &(x->b));
 | |
| }
 | |
| 
 | |
| /* w*=i where i = sqrt(2^i+sqrt(-1)) */
 | |
| /* SU= 200 */
 | |
| void YYY::FP4_times_i(FP4 *w)
 | |
| {
 | |
|     FP2 t;
 | |
|     FP2_copy(&t, &(w->b));
 | |
|     FP2_copy(&(w->b), &(w->a));
 | |
|     FP2_mul_ip(&t);
 | |
|     FP2_copy(&(w->a), &t);
 | |
|     FP4_norm(w);
 | |
| #if TOWER_YYY == POSITOWER
 | |
|     FP4_neg(w, w);  // ***
 | |
|     FP4_norm(w);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /* Set w=w^p using Frobenius */
 | |
| /* SU= 16 */
 | |
| void YYY::FP4_frob(FP4 *w, FP2 *f)
 | |
| {
 | |
|     FP2_conj(&(w->a), &(w->a));
 | |
|     FP2_conj(&(w->b), &(w->b));
 | |
|     FP2_mul( &(w->b), f, &(w->b));
 | |
| }
 | |
| 
 | |
| /* Set r=a^b mod m */
 | |
| /* SU= 240 */
 | |
| /*
 | |
| void YYY::FP4_pow(FP4 *r, FP4* a, BIG b)
 | |
| {
 | |
|     FP4 w;
 | |
|     BIG z, zilch;
 | |
|     int bt;
 | |
| 
 | |
|     BIG_zero(zilch);
 | |
|     BIG_copy(z, b);
 | |
|     BIG_norm(z);
 | |
|     FP4_copy(&w, a);
 | |
|     FP4_norm(&w);
 | |
|     FP4_one(r);
 | |
| 
 | |
|     while (1)
 | |
|     {
 | |
|         bt = BIG_parity(z);
 | |
|         BIG_shr(z, 1);
 | |
|         if (bt) FP4_mul(r, r, &w);
 | |
|         if (BIG_comp(z, zilch) == 0) break;
 | |
|         FP4_sqr(&w, &w);
 | |
|     }
 | |
|     FP4_reduce(r);
 | |
| }
 | |
| */
 | |
| #if CURVE_SECURITY_ZZZ == 128
 | |
| 
 | |
| /* SU= 304 */
 | |
| /* XTR xtr_a function */
 | |
| void YYY::FP4_xtr_A(FP4 *r, FP4 *w, FP4 *x, FP4 *y, FP4 *z)
 | |
| {
 | |
|     FP4 t1, t2;
 | |
| 
 | |
|     FP4_copy(r, x);
 | |
|     FP4_sub(&t1, w, y);
 | |
|     FP4_norm(&t1);
 | |
|     FP4_pmul(&t1, &t1, &(r->a));
 | |
|     FP4_add(&t2, w, y);
 | |
|     FP4_norm(&t2);
 | |
|     FP4_pmul(&t2, &t2, &(r->b));
 | |
|     FP4_times_i(&t2);
 | |
| 
 | |
|     FP4_add(r, &t1, &t2);
 | |
|     FP4_add(r, r, z);
 | |
| 
 | |
|     FP4_reduce(r);
 | |
| }
 | |
| 
 | |
| /* SU= 152 */
 | |
| /* XTR xtr_d function */
 | |
| void YYY::FP4_xtr_D(FP4 *r, FP4 *x)
 | |
| {
 | |
|     FP4 w;
 | |
|     FP4_copy(r, x);
 | |
|     FP4_conj(&w, r);
 | |
|     FP4_add(&w, &w, &w);
 | |
|     FP4_sqr(r, r);
 | |
|     FP4_norm(&w);
 | |
|     FP4_sub(r, r, &w);
 | |
|     FP4_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
 | |
| }
 | |
| 
 | |
| /* SU= 728 */
 | |
| /* r=x^n using XTR method on traces of FP12s */
 | |
| void YYY::FP4_xtr_pow(FP4 *r, FP4 *x, BIG n)
 | |
| {
 | |
|     int i, par, nb;
 | |
|     BIG v;
 | |
|     FP2 w;
 | |
|     FP4 t, a, b, c, sf;
 | |
| 
 | |
|     BIG_zero(v);
 | |
|     BIG_inc(v, 3);
 | |
|     BIG_norm(v);
 | |
|     FP2_from_BIG(&w, v);
 | |
|     FP4_from_FP2(&a, &w);
 | |
|     FP4_copy(&sf, x);
 | |
|     FP4_norm(&sf);
 | |
|     FP4_copy(&b, &sf);
 | |
|     FP4_xtr_D(&c, &sf);
 | |
| 
 | |
|     par = BIG_parity(n);
 | |
|     BIG_copy(v, n);
 | |
|     BIG_norm(v);
 | |
|     BIG_shr(v, 1);
 | |
|     if (par == 0)
 | |
|     {
 | |
|         BIG_dec(v, 1);
 | |
|         BIG_norm(v);
 | |
|     }
 | |
| 
 | |
|     nb = BIG_nbits(v);
 | |
|     for (i = nb - 1; i >= 0; i--)
 | |
|     {
 | |
|         if (!BIG_bit(v, i))
 | |
|         {
 | |
|             FP4_copy(&t, &b);
 | |
|             FP4_conj(&sf, &sf);
 | |
|             FP4_conj(&c, &c);
 | |
|             FP4_xtr_A(&b, &a, &b, &sf, &c);
 | |
|             FP4_conj(&sf, &sf);
 | |
|             FP4_xtr_D(&c, &t);
 | |
|             FP4_xtr_D(&a, &a);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             FP4_conj(&t, &a);
 | |
|             FP4_xtr_D(&a, &b);
 | |
|             FP4_xtr_A(&b, &c, &b, &sf, &t);
 | |
|             FP4_xtr_D(&c, &c);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (par == 0) FP4_copy(r, &c);
 | |
|     else FP4_copy(r, &b);
 | |
|     FP4_reduce(r);
 | |
| }
 | |
| 
 | |
| /* SU= 872 */
 | |
| /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
 | |
| void YYY::FP4_xtr_pow2(FP4 *r, FP4 *ck, FP4 *cl, FP4 *ckml, FP4 *ckm2l, BIG a, BIG b)
 | |
| {
 | |
|     int i, f2;
 | |
|     BIG d, e, w;
 | |
|     FP4 t, cu, cv, cumv, cum2v;
 | |
| 
 | |
| 
 | |
|     BIG_copy(e, a);
 | |
|     BIG_copy(d, b);
 | |
|     BIG_norm(e);
 | |
|     BIG_norm(d);
 | |
|     FP4_copy(&cu, ck);
 | |
|     FP4_copy(&cv, cl);
 | |
|     FP4_copy(&cumv, ckml);
 | |
|     FP4_copy(&cum2v, ckm2l);
 | |
| 
 | |
|     f2 = 0;
 | |
|     while (BIG_parity(d) == 0 && BIG_parity(e) == 0)
 | |
|     {
 | |
|         BIG_shr(d, 1);
 | |
|         BIG_shr(e, 1);
 | |
|         f2++;
 | |
|     }
 | |
|     while (BIG_comp(d, e) != 0)
 | |
|     {
 | |
|         if (BIG_comp(d, e) > 0)
 | |
|         {
 | |
|             BIG_imul(w, e, 4);
 | |
|             BIG_norm(w);
 | |
|             if (BIG_comp(d, w) <= 0)
 | |
|             {
 | |
|                 BIG_copy(w, d);
 | |
|                 BIG_copy(d, e);
 | |
|                 BIG_sub(e, w, e);
 | |
|                 BIG_norm(e);
 | |
|                 FP4_xtr_A(&t, &cu, &cv, &cumv, &cum2v);
 | |
|                 FP4_conj(&cum2v, &cumv);
 | |
|                 FP4_copy(&cumv, &cv);
 | |
|                 FP4_copy(&cv, &cu);
 | |
|                 FP4_copy(&cu, &t);
 | |
|             }
 | |
|             else if (BIG_parity(d) == 0)
 | |
|             {
 | |
|                 BIG_shr(d, 1);
 | |
|                 FP4_conj(r, &cum2v);
 | |
|                 FP4_xtr_A(&t, &cu, &cumv, &cv, r);
 | |
|                 FP4_xtr_D(&cum2v, &cumv);
 | |
|                 FP4_copy(&cumv, &t);
 | |
|                 FP4_xtr_D(&cu, &cu);
 | |
|             }
 | |
|             else if (BIG_parity(e) == 1)
 | |
|             {
 | |
|                 BIG_sub(d, d, e);
 | |
|                 BIG_norm(d);
 | |
|                 BIG_shr(d, 1);
 | |
|                 FP4_xtr_A(&t, &cu, &cv, &cumv, &cum2v);
 | |
|                 FP4_xtr_D(&cu, &cu);
 | |
|                 FP4_xtr_D(&cum2v, &cv);
 | |
|                 FP4_conj(&cum2v, &cum2v);
 | |
|                 FP4_copy(&cv, &t);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 BIG_copy(w, d);
 | |
|                 BIG_copy(d, e);
 | |
|                 BIG_shr(d, 1);
 | |
|                 BIG_copy(e, w);
 | |
|                 FP4_xtr_D(&t, &cumv);
 | |
|                 FP4_conj(&cumv, &cum2v);
 | |
|                 FP4_conj(&cum2v, &t);
 | |
|                 FP4_xtr_D(&t, &cv);
 | |
|                 FP4_copy(&cv, &cu);
 | |
|                 FP4_copy(&cu, &t);
 | |
|             }
 | |
|         }
 | |
|         if (BIG_comp(d, e) < 0)
 | |
|         {
 | |
|             BIG_imul(w, d, 4);
 | |
|             BIG_norm(w);
 | |
|             if (BIG_comp(e, w) <= 0)
 | |
|             {
 | |
|                 BIG_sub(e, e, d);
 | |
|                 BIG_norm(e);
 | |
|                 FP4_xtr_A(&t, &cu, &cv, &cumv, &cum2v);
 | |
|                 FP4_copy(&cum2v, &cumv);
 | |
|                 FP4_copy(&cumv, &cu);
 | |
|                 FP4_copy(&cu, &t);
 | |
|             }
 | |
|             else if (BIG_parity(e) == 0)
 | |
|             {
 | |
|                 BIG_copy(w, d);
 | |
|                 BIG_copy(d, e);
 | |
|                 BIG_shr(d, 1);
 | |
|                 BIG_copy(e, w);
 | |
|                 FP4_xtr_D(&t, &cumv);
 | |
|                 FP4_conj(&cumv, &cum2v);
 | |
|                 FP4_conj(&cum2v, &t);
 | |
|                 FP4_xtr_D(&t, &cv);
 | |
|                 FP4_copy(&cv, &cu);
 | |
|                 FP4_copy(&cu, &t);
 | |
|             }
 | |
|             else if (BIG_parity(d) == 1)
 | |
|             {
 | |
|                 BIG_copy(w, e);
 | |
|                 BIG_copy(e, d);
 | |
|                 BIG_sub(w, w, d);
 | |
|                 BIG_norm(w);
 | |
|                 BIG_copy(d, w);
 | |
|                 BIG_shr(d, 1);
 | |
|                 FP4_xtr_A(&t, &cu, &cv, &cumv, &cum2v);
 | |
|                 FP4_conj(&cumv, &cumv);
 | |
|                 FP4_xtr_D(&cum2v, &cu);
 | |
|                 FP4_conj(&cum2v, &cum2v);
 | |
|                 FP4_xtr_D(&cu, &cv);
 | |
|                 FP4_copy(&cv, &t);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 BIG_shr(d, 1);
 | |
|                 FP4_conj(r, &cum2v);
 | |
|                 FP4_xtr_A(&t, &cu, &cumv, &cv, r);
 | |
|                 FP4_xtr_D(&cum2v, &cumv);
 | |
|                 FP4_copy(&cumv, &t);
 | |
|                 FP4_xtr_D(&cu, &cu);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     FP4_xtr_A(r, &cu, &cv, &cumv, &cum2v);
 | |
|     for (i = 0; i < f2; i++)    FP4_xtr_D(r, r);
 | |
|     FP4_xtr_pow(r, r, d);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /* New stuff for ECp4 support */
 | |
| 
 | |
| /* Set w=x/2 */
 | |
| void YYY::FP4_div2(FP4 *w, FP4 *x)
 | |
| {
 | |
|     FP2_div2(&(w->a), &(x->a));
 | |
|     FP2_div2(&(w->b), &(x->b));
 | |
| }
 | |
| 
 | |
| /* Move b to a if d=1 */
 | |
| void YYY::FP4_cmove(FP4 *f, FP4 *g, int d)
 | |
| {
 | |
|     FP2_cmove(&(f->a), &(g->a), d);
 | |
|     FP2_cmove(&(f->b), &(g->b), d);
 | |
| }
 | |
| 
 | |
| void YYY::FP4_rand(FP4 *x,csprng *rng)
 | |
| {
 | |
|     FP2_rand(&(x->a),rng);
 | |
|     FP2_rand(&(x->b),rng);
 | |
| }
 | |
| 
 | |
| #if PAIRING_FRIENDLY_ZZZ >= BLS24_CURVE
 | |
| 
 | |
| /* test for x a QR */
 | |
| int YYY::FP4_qr(FP4 *x, FP *h)
 | |
| { /* test x^(p^4-1)/2 = 1 */
 | |
|     
 | |
|     FP4 c;
 | |
|     FP4_conj(&c,x);
 | |
|     FP4_mul(&c,&c,x);
 | |
| 
 | |
|     return FP2_qr(&(c.a),h);
 | |
| }
 | |
| 
 | |
| /* sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) */
 | |
| 
 | |
| void YYY::FP4_sqrt(FP4 *r, FP4* x, FP *h)
 | |
| {
 | |
|     FP2 a, b, s, t;
 | |
|     FP hint,twk;
 | |
|     FP4 nr;
 | |
|     int sgn,qr;
 | |
| 
 | |
|     FP4_copy(r, x);
 | |
|     if (FP4_iszilch(x)) return;
 | |
| 
 | |
|     FP2_copy(&a, &(x->a));
 | |
|     FP2_copy(&s, &(x->b));
 | |
| 
 | |
|     FP2_sqr(&s, &s); // s*=s
 | |
|     FP2_sqr(&a, &a); // a*=a
 | |
|     FP2_mul_ip(&s);
 | |
|     FP2_norm(&s);
 | |
|     FP2_sub(&a, &a, &s); // a-=txx(s)
 | |
|     FP2_norm(&a); // **
 | |
| 
 | |
|     FP2_sqrt(&s, &a, h);            // Cost = +1
 | |
| 
 | |
|     FP2_add(&a, &(r->a), &s);
 | |
|     FP2_norm(&a);
 | |
|     FP2_div2(&a, &a);
 | |
| 
 | |
|     FP2_div2(&b,&(r->b));                   // w1=b/2
 | |
|     qr=FP2_qr(&a,&hint);                    // only exp! Cost=+1
 | |
| 
 | |
| // tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial
 | |
|     FP2_copy(&s,&a);
 | |
|     FP_rcopy(&twk,TWK);
 | |
|     FP_mul(&twk,&twk,&hint);
 | |
|     FP2_div_ip(&s); FP2_norm(&s); // switch to other candidate
 | |
| 
 | |
|     FP2_cmove(&a,&s,1-qr);
 | |
|     FP_cmove(&hint,&twk,1-qr);
 | |
| 
 | |
|     FP2_sqrt(&(r->a),&a,&hint);             // a=sqrt(w2)  Cost=+1
 | |
|     FP2_inv(&s,&a,&hint);                  // w3=1/w2
 | |
|     FP2_mul(&s,&s,&(r->a));                // w3=1/sqrt(w2)
 | |
|     FP2_mul(&(r->b),&s,&b);                // b=(b/2)*1/sqrt(w2)
 | |
|     FP2_copy(&t,&(r->a));
 | |
| 
 | |
|     FP2_cmove(&(r->a),&(r->b),1-qr);
 | |
|     FP2_cmove(&(r->b),&t,1-qr);
 | |
| 
 | |
|     sgn=FP4_sign(r);
 | |
|     FP4_neg(&nr,r); FP4_norm(&nr);
 | |
|     FP4_cmove(r,&nr,sgn);
 | |
| }
 | |
| 
 | |
| void YYY::FP4_div_i(FP4 *f)
 | |
| {
 | |
|     FP2 u, v;
 | |
|     FP2_copy(&u, &(f->a));
 | |
|     FP2_copy(&v, &(f->b));
 | |
| 
 | |
|     FP2_div_ip(&u);
 | |
| 
 | |
|     FP2_copy(&(f->a), &v);
 | |
|     FP2_copy(&(f->b), &u);
 | |
| 
 | |
| #if TOWER_YYY == POSITOWER
 | |
|     FP4_neg(f, f);  // ***
 | |
|     FP4_norm(f);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| #endif
 |