| /* |
| 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 mod p functions */ |
| /* Small Finite Field arithmetic */ |
| /* SU=m, SU is Stack Usage (NOT_SPECIAL Modulus) */ |
| |
| #include "fp_YYY.h" |
| |
| /* Fast Modular Reduction Methods */ |
| |
| /* r=d mod m */ |
| /* d MUST be normalised */ |
| /* Products must be less than pR in all cases !!! */ |
| /* So when multiplying two numbers, their product *must* be less than MODBITS+BASEBITS*NLEN */ |
| /* Results *may* be one bit bigger than MODBITS */ |
| |
| #if MODTYPE_YYY == PSEUDO_MERSENNE |
| /* r=d mod m */ |
| |
| /* Converts from BIG integer to residue form mod Modulus */ |
| void FP_YYY_nres(FP_YYY *y,BIG_XXX x) |
| { |
| BIG_XXX_copy(y->g,x); |
| y->XES=1; |
| } |
| |
| /* Converts from residue form back to BIG integer form */ |
| void FP_YYY_redc(BIG_XXX x,FP_YYY *y) |
| { |
| BIG_XXX_copy(x,y->g); |
| } |
| |
| /* reduce a DBIG to a BIG exploiting the special form of the modulus */ |
| void FP_YYY_mod(BIG_XXX r,DBIG_XXX d) |
| { |
| BIG_XXX t,b; |
| chunk v,tw; |
| BIG_XXX_split(t,b,d,MODBITS_YYY); |
| |
| /* Note that all of the excess gets pushed into t. So if squaring a value with a 4-bit excess, this results in |
| t getting all 8 bits of the excess product! So products must be less than pR which is Montgomery compatible */ |
| |
| if (MConst_YYY < NEXCESS_XXX) |
| { |
| BIG_XXX_imul(t,t,MConst_YYY); |
| BIG_XXX_norm(t); |
| BIG_XXX_add(r,t,b); |
| BIG_XXX_norm(r); |
| tw=r[NLEN_XXX-1]; |
| r[NLEN_XXX-1]&=TMASK_YYY; |
| r[0]+=MConst_YYY*((tw>>TBITS_YYY)); |
| } |
| else |
| { |
| v=BIG_XXX_pmul(t,t,MConst_YYY); |
| BIG_XXX_add(r,t,b); |
| BIG_XXX_norm(r); |
| tw=r[NLEN_XXX-1]; |
| r[NLEN_XXX-1]&=TMASK_YYY; |
| #if CHUNK == 16 |
| r[1]+=muladd_XXX(MConst_YYY,((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY))),0,&r[0]); |
| #else |
| r[0]+=MConst_YYY*((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY))); |
| #endif |
| } |
| BIG_XXX_norm(r); |
| } |
| #endif |
| |
| /* This only applies to Curve C448, so specialised (for now) */ |
| #if MODTYPE_YYY == GENERALISED_MERSENNE |
| |
| void FP_YYY_nres(FP_YYY *y,BIG_XXX x) |
| { |
| BIG_XXX_copy(y->g,x); |
| y->XES=1; |
| } |
| |
| /* Converts from residue form back to BIG integer form */ |
| void FP_YYY_redc(BIG_XXX x,FP_YYY *y) |
| { |
| BIG_XXX_copy(x,y->g); |
| } |
| |
| /* reduce a DBIG to a BIG exploiting the special form of the modulus */ |
| void FP_YYY_mod(BIG_XXX r,DBIG_XXX d) |
| { |
| BIG_XXX t,b; |
| chunk carry; |
| BIG_XXX_split(t,b,d,MBITS_YYY); |
| |
| BIG_XXX_add(r,t,b); |
| |
| BIG_XXX_dscopy(d,t); |
| BIG_XXX_dshl(d,MBITS_YYY/2); |
| |
| BIG_XXX_split(t,b,d,MBITS_YYY); |
| |
| BIG_XXX_add(r,r,t); |
| BIG_XXX_add(r,r,b); |
| BIG_XXX_norm(r); |
| BIG_XXX_shl(t,MBITS_YYY/2); |
| |
| BIG_XXX_add(r,r,t); |
| |
| carry=r[NLEN_XXX-1]>>TBITS_YYY; |
| |
| r[NLEN_XXX-1]&=TMASK_YYY; |
| r[0]+=carry; |
| |
| r[224/BASEBITS_XXX]+=carry<<(224%BASEBITS_XXX); /* need to check that this falls mid-word */ |
| BIG_XXX_norm(r); |
| } |
| |
| #endif |
| |
| #if MODTYPE_YYY == MONTGOMERY_FRIENDLY |
| |
| /* convert to Montgomery n-residue form */ |
| void FP_YYY_nres(FP_YYY *y,BIG_XXX x) |
| { |
| DBIG_XXX d; |
| BIG_XXX r; |
| BIG_XXX_rcopy(r,R2modp_YYY); |
| BIG_XXX_mul(d,x,r); |
| FP_YYY_mod(y->g,d); |
| y->XES=2; |
| } |
| |
| /* convert back to regular form */ |
| void FP_YYY_redc(BIG_XXX x,FP_YYY *y) |
| { |
| DBIG_XXX d; |
| BIG_XXX_dzero(d); |
| BIG_XXX_dscopy(d,y->g); |
| FP_YYY_mod(x,d); |
| } |
| |
| /* fast modular reduction from DBIG to BIG exploiting special form of the modulus */ |
| void FP_YYY_mod(BIG_XXX a,DBIG_XXX d) |
| { |
| int i; |
| |
| for (i=0; i<NLEN_XXX; i++) |
| d[NLEN_XXX+i]+=muladd_XXX(d[i],MConst_YYY-1,d[i],&d[NLEN_XXX+i-1]); |
| |
| BIG_XXX_sducopy(a,d); |
| BIG_XXX_norm(a); |
| } |
| |
| #endif |
| |
| #if MODTYPE_YYY == NOT_SPECIAL |
| |
| /* convert to Montgomery n-residue form */ |
| void FP_YYY_nres(FP_YYY *y,BIG_XXX x) |
| { |
| DBIG_XXX d; |
| BIG_XXX r; |
| BIG_XXX_rcopy(r,R2modp_YYY); |
| BIG_XXX_mul(d,x,r); |
| FP_YYY_mod(y->g,d); |
| y->XES=2; |
| } |
| |
| /* convert back to regular form */ |
| void FP_YYY_redc(BIG_XXX x,FP_YYY *y) |
| { |
| DBIG_XXX d; |
| BIG_XXX_dzero(d); |
| BIG_XXX_dscopy(d,y->g); |
| FP_YYY_mod(x,d); |
| } |
| |
| |
| /* reduce a DBIG to a BIG using Montgomery's no trial division method */ |
| /* d is expected to be dnormed before entry */ |
| /* SU= 112 */ |
| void FP_YYY_mod(BIG_XXX a,DBIG_XXX d) |
| { |
| BIG_XXX mdls; |
| BIG_XXX_rcopy(mdls,Modulus_YYY); |
| BIG_XXX_monty(a,mdls,MConst_YYY,d); |
| } |
| |
| #endif |
| |
| /* test x==0 ? */ |
| /* SU= 48 */ |
| int FP_YYY_iszilch(FP_YYY *x) |
| { |
| BIG_XXX m,t; |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| BIG_XXX_copy(t,x->g); |
| BIG_XXX_mod(t,m); |
| return BIG_XXX_iszilch(t); |
| } |
| |
| void FP_YYY_copy(FP_YYY *y,FP_YYY *x) |
| { |
| BIG_XXX_copy(y->g,x->g); |
| y->XES=x->XES; |
| } |
| |
| void FP_YYY_rcopy(FP_YYY *y, const BIG_XXX c) |
| { |
| BIG_XXX b; |
| BIG_XXX_rcopy(b,c); |
| FP_YYY_nres(y,b); |
| } |
| |
| /* Swap a and b if d=1 */ |
| void FP_YYY_cswap(FP_YYY *a,FP_YYY *b,int d) |
| { |
| sign32 t,c=d; |
| BIG_XXX_cswap(a->g,b->g,d); |
| |
| c=~(c-1); |
| t=c&((a->XES)^(b->XES)); |
| a->XES^=t; |
| b->XES^=t; |
| |
| } |
| |
| /* Move b to a if d=1 */ |
| void FP_YYY_cmove(FP_YYY *a,FP_YYY *b,int d) |
| { |
| sign32 c=-d; |
| |
| BIG_XXX_cmove(a->g,b->g,d); |
| a->XES^=(a->XES^b->XES)&c; |
| } |
| |
| void FP_YYY_zero(FP_YYY *x) |
| { |
| BIG_XXX_zero(x->g); |
| x->XES=1; |
| } |
| |
| int FP_YYY_equals(FP_YYY *x,FP_YYY *y) |
| { |
| FP_YYY xg,yg; |
| FP_YYY_copy(&xg,x); |
| FP_YYY_copy(&yg,y); |
| FP_YYY_reduce(&xg); |
| FP_YYY_reduce(&yg); |
| if (BIG_XXX_comp(xg.g,yg.g)==0) return 1; |
| return 0; |
| } |
| |
| /* output FP */ |
| /* SU= 48 */ |
| void FP_YYY_output(FP_YYY *r) |
| { |
| BIG_XXX c; |
| FP_YYY_redc(c,r); |
| BIG_XXX_output(c); |
| } |
| |
| void FP_YYY_rawoutput(FP_YYY *r) |
| { |
| BIG_XXX_rawoutput(r->g); |
| } |
| |
| #ifdef GET_STATS |
| int tsqr=0,rsqr=0,tmul=0,rmul=0; |
| int tadd=0,radd=0,tneg=0,rneg=0; |
| int tdadd=0,rdadd=0,tdneg=0,rdneg=0; |
| #endif |
| |
| #ifdef FUSED_MODMUL |
| |
| /* Insert fastest code here */ |
| |
| #endif |
| |
| /* r=a*b mod Modulus */ |
| /* product must be less that p.R - and we need to know this in advance! */ |
| /* SU= 88 */ |
| void FP_YYY_mul(FP_YYY *r,FP_YYY *a,FP_YYY *b) |
| { |
| DBIG_XXX d; |
| |
| if ((sign64)a->XES*b->XES>(sign64)FEXCESS_YYY) |
| { |
| #ifdef DEBUG_REDUCE |
| printf("Product too large - reducing it\n"); |
| #endif |
| FP_YYY_reduce(a); /* it is sufficient to fully reduce just one of them < p */ |
| } |
| |
| #ifdef FUSED_MODMUL |
| FP_YYY_modmul(r->g,a->g,b->g); |
| #else |
| BIG_XXX_mul(d,a->g,b->g); |
| FP_YYY_mod(r->g,d); |
| #endif |
| r->XES=2; |
| } |
| |
| |
| /* multiplication by an integer, r=a*c */ |
| /* SU= 136 */ |
| void FP_YYY_imul(FP_YYY *r,FP_YYY *a,int c) |
| { |
| int s=0; |
| |
| if (c<0) |
| { |
| c=-c; |
| s=1; |
| } |
| |
| #if MODTYPE_YYY==PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE |
| DBIG_XXX d; |
| BIG_XXX_pxmul(d,a->g,c); |
| FP_YYY_mod(r->g,d); |
| r->XES=2; |
| |
| #else |
| //Montgomery |
| BIG_XXX k; |
| FP_YYY f; |
| if (a->XES*c<=FEXCESS_YYY) |
| { |
| BIG_XXX_pmul(r->g,a->g,c); |
| r->XES=a->XES*c; // careful here - XES jumps! |
| } |
| else |
| { |
| // don't want to do this - only a problem for Montgomery modulus and larger constants |
| BIG_XXX_zero(k); |
| BIG_XXX_inc(k,c); |
| BIG_XXX_norm(k); |
| FP_YYY_nres(&f,k); |
| FP_YYY_mul(r,a,&f); |
| } |
| #endif |
| |
| if (s) |
| { |
| FP_YYY_neg(r,r); |
| FP_YYY_norm(r); |
| } |
| } |
| |
| /* Set r=a^2 mod m */ |
| /* SU= 88 */ |
| void FP_YYY_sqr(FP_YYY *r,FP_YYY *a) |
| { |
| DBIG_XXX d; |
| |
| if ((sign64)a->XES*a->XES>(sign64)FEXCESS_YYY) |
| { |
| #ifdef DEBUG_REDUCE |
| printf("Product too large - reducing it\n"); |
| #endif |
| FP_YYY_reduce(a); |
| } |
| |
| BIG_XXX_sqr(d,a->g); |
| FP_YYY_mod(r->g,d); |
| r->XES=2; |
| } |
| |
| /* SU= 16 */ |
| /* Set r=a+b */ |
| void FP_YYY_add(FP_YYY *r,FP_YYY *a,FP_YYY *b) |
| { |
| BIG_XXX_add(r->g,a->g,b->g); |
| r->XES=a->XES+b->XES; |
| if (r->XES>FEXCESS_YYY) |
| { |
| #ifdef DEBUG_REDUCE |
| printf("Sum too large - reducing it \n"); |
| #endif |
| FP_YYY_reduce(r); |
| } |
| } |
| |
| /* Set r=a-b mod m */ |
| /* SU= 56 */ |
| void FP_YYY_sub(FP_YYY *r,FP_YYY *a,FP_YYY *b) |
| { |
| FP_YYY n; |
| FP_YYY_neg(&n,b); |
| FP_YYY_add(r,a,&n); |
| } |
| |
| // https://graphics.stanford.edu/~seander/bithacks.html |
| // constant time log to base 2 (or number of bits in) |
| |
| static int logb2(unsign32 v) |
| { |
| int r; |
| v |= v >> 1; |
| v |= v >> 2; |
| v |= v >> 4; |
| v |= v >> 8; |
| v |= v >> 16; |
| |
| v = v - ((v >> 1) & 0x55555555); |
| v = (v & 0x33333333) + ((v >> 2) & 0x33333333); |
| r = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; |
| return r; |
| } |
| |
| // find appoximation to quotient of a/m |
| // Out by at most 2. |
| // Note that MAXXES is bounded to be 2-bits less than half a word |
| static int quo(BIG_XXX n,BIG_XXX m) |
| { |
| int sh; |
| chunk num,den; |
| int hb=CHUNK/2; |
| if (TBITS_YYY<hb) |
| { |
| sh=hb-TBITS_YYY; |
| num=(n[NLEN_XXX-1]<<sh)|(n[NLEN_XXX-2]>>(BASEBITS_XXX-sh)); |
| den=(m[NLEN_XXX-1]<<sh)|(m[NLEN_XXX-2]>>(BASEBITS_XXX-sh)); |
| } |
| else |
| { |
| num=n[NLEN_XXX-1]; |
| den=m[NLEN_XXX-1]; |
| } |
| return (int)(num/(den+1)); |
| } |
| |
| /* SU= 48 */ |
| /* Fully reduce a mod Modulus */ |
| void FP_YYY_reduce(FP_YYY *a) |
| { |
| BIG_XXX m,r; |
| int sr,sb,q; |
| chunk carry; |
| |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| |
| BIG_XXX_norm(a->g); |
| |
| if (a->XES>16) |
| { |
| q=quo(a->g,m); |
| carry=BIG_XXX_pmul(r,m,q); |
| r[NLEN_XXX-1]+=(carry<<BASEBITS_XXX); // correction - put any carry out back in again |
| BIG_XXX_sub(a->g,a->g,r); |
| BIG_XXX_norm(a->g); |
| sb=2; |
| } |
| else sb=logb2(a->XES-1); // sb does not depend on the actual data |
| |
| BIG_XXX_fshl(m,sb); |
| |
| while (sb>0) |
| { |
| // constant time... |
| sr=BIG_XXX_ssn(r,a->g,m); // optimized combined shift, subtract and norm |
| BIG_XXX_cmove(a->g,r,1-sr); |
| sb--; |
| } |
| |
| //BIG_XXX_mod(a->g,m); |
| a->XES=1; |
| } |
| |
| void FP_YYY_norm(FP_YYY *x) |
| { |
| BIG_XXX_norm(x->g); |
| } |
| |
| /* Set r=-a mod Modulus */ |
| /* SU= 64 */ |
| void FP_YYY_neg(FP_YYY *r,FP_YYY *a) |
| { |
| int sb; |
| BIG_XXX m; |
| |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| |
| sb=logb2(a->XES-1); |
| BIG_XXX_fshl(m,sb); |
| BIG_XXX_sub(r->g,m,a->g); |
| r->XES=((sign32)1<<sb)+1; |
| |
| if (r->XES>FEXCESS_YYY) |
| { |
| #ifdef DEBUG_REDUCE |
| printf("Negation too large - reducing it \n"); |
| #endif |
| FP_YYY_reduce(r); |
| } |
| |
| } |
| |
| /* Set r=a/2. */ |
| /* SU= 56 */ |
| void FP_YYY_div2(FP_YYY *r,FP_YYY *a) |
| { |
| BIG_XXX m; |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| FP_YYY_copy(r,a); |
| |
| if (BIG_XXX_parity(a->g)==0) |
| { |
| |
| BIG_XXX_fshr(r->g,1); |
| } |
| else |
| { |
| BIG_XXX_add(r->g,r->g,m); |
| BIG_XXX_norm(r->g); |
| BIG_XXX_fshr(r->g,1); |
| } |
| } |
| |
| #if MODTYPE_YYY == PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE |
| |
| // See eprint paper https://eprint.iacr.org/2018/1038 |
| // If p=3 mod 4 r= x^{(p-3)/4}, if p=5 mod 8 r=x^{(p-5)/8} |
| |
| static void FP_YYY_fpow(FP_YYY *r,FP_YYY *x) |
| { |
| int i,j,k,bw,w,c,nw,lo,m,n; |
| FP_YYY xp[11],t,key; |
| const int ac[]={1,2,3,6,12,15,30,60,120,240,255}; |
| // phase 1 |
| FP_YYY_copy(&xp[0],x); // 1 |
| FP_YYY_sqr(&xp[1],x); // 2 |
| FP_YYY_mul(&xp[2],&xp[1],x); //3 |
| FP_YYY_sqr(&xp[3],&xp[2]); // 6 |
| FP_YYY_sqr(&xp[4],&xp[3]); // 12 |
| FP_YYY_mul(&xp[5],&xp[4],&xp[2]); // 15 |
| FP_YYY_sqr(&xp[6],&xp[5]); // 30 |
| FP_YYY_sqr(&xp[7],&xp[6]); // 60 |
| FP_YYY_sqr(&xp[8],&xp[7]); // 120 |
| FP_YYY_sqr(&xp[9],&xp[8]); // 240 |
| FP_YYY_mul(&xp[10],&xp[9],&xp[5]); // 255 |
| |
| #if MODTYPE_YYY==PSEUDO_MERSENNE |
| n=MODBITS_YYY; |
| #endif |
| #if MODTYPE_YYY==GENERALISED_MERSENNE // Goldilocks ONLY |
| n=MODBITS_YYY/2; |
| #endif |
| |
| if (MOD8_YYY==5) |
| { |
| n-=3; |
| c=(MConst_YYY+5)/8; |
| } else { |
| n-=2; |
| c=(MConst_YYY+3)/4; |
| } |
| |
| bw=0; w=1; while (w<c) {w*=2; bw+=1;} |
| k=w-c; |
| |
| if (k!=0) |
| { |
| i=10; while (ac[i]>k) i--; |
| FP_YYY_copy(&key,&xp[i]); |
| k-=ac[i]; |
| } |
| while (k!=0) |
| { |
| i--; |
| if (ac[i]>k) continue; |
| FP_YYY_mul(&key,&key,&xp[i]); |
| k-=ac[i]; |
| } |
| |
| // phase 2 |
| FP_YYY_copy(&xp[1],&xp[2]); |
| FP_YYY_copy(&xp[2],&xp[5]); |
| FP_YYY_copy(&xp[3],&xp[10]); |
| |
| j=3; m=8; |
| nw=n-bw; |
| while (2*m<nw) |
| { |
| FP_YYY_copy(&t,&xp[j++]); |
| for (i=0;i<m;i++) |
| FP_YYY_sqr(&t,&t); |
| FP_YYY_mul(&xp[j],&xp[j-1],&t); |
| m*=2; |
| } |
| |
| lo=nw-m; |
| FP_YYY_copy(r,&xp[j]); |
| |
| while (lo!=0) |
| { |
| m/=2; j--; |
| if (lo<m) continue; |
| lo-=m; |
| FP_YYY_copy(&t,r); |
| for (i=0;i<m;i++) |
| FP_YYY_sqr(&t,&t); |
| FP_YYY_mul(r,&t,&xp[j]); |
| } |
| // phase 3 |
| |
| if (bw!=0) |
| { |
| for (i=0;i<bw;i++ ) |
| FP_YYY_sqr(r,r); |
| FP_YYY_mul(r,r,&key); |
| } |
| #if MODTYPE_YYY==GENERALISED_MERSENNE // Goldilocks ONLY |
| FP_YYY_copy(&key,r); |
| FP_YYY_sqr(&t,&key); |
| FP_YYY_mul(r,&t,x); |
| for (i=0;i<n+1;i++) |
| FP_YYY_sqr(r,r); |
| FP_YYY_mul(r,r,&key); |
| #endif |
| } |
| |
| void FP_YYY_inv(FP_YYY *r,FP_YYY *x) |
| { |
| FP_YYY y,t; |
| FP_YYY_fpow(&y,x); |
| if (MOD8_YYY==5) |
| { // r=x^3.y^8 |
| FP_YYY_sqr(&t,x); |
| FP_YYY_mul(&t,&t,x); |
| FP_YYY_sqr(&y,&y); |
| FP_YYY_sqr(&y,&y); |
| FP_YYY_sqr(&y,&y); |
| FP_YYY_mul(r,&t,&y); |
| } else { |
| FP_YYY_sqr(&y,&y); |
| FP_YYY_sqr(&y,&y); |
| FP_YYY_mul(r,&y,x); |
| } |
| } |
| |
| #else |
| |
| void FP_YYY_pow(FP_YYY *r,FP_YYY *a,BIG_XXX b) |
| { |
| sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4]; |
| FP_YYY tb[16]; |
| BIG_XXX t; |
| int i,nb; |
| |
| FP_YYY_norm(a); |
| BIG_XXX_norm(b); |
| BIG_XXX_copy(t,b); |
| nb=1+(BIG_XXX_nbits(t)+3)/4; |
| /* convert exponent to 4-bit window */ |
| for (i=0; i<nb; i++) |
| { |
| w[i]=BIG_XXX_lastbits(t,4); |
| BIG_XXX_dec(t,w[i]); |
| BIG_XXX_norm(t); |
| BIG_XXX_fshr(t,4); |
| } |
| |
| FP_YYY_one(&tb[0]); |
| FP_YYY_copy(&tb[1],a); |
| for (i=2;i<16;i++) |
| FP_YYY_mul(&tb[i],&tb[i-1],a); |
| |
| FP_YYY_copy(r,&tb[w[nb-1]]); |
| for (i=nb-2; i>=0; i--) |
| { |
| FP_YYY_sqr(r,r); |
| FP_YYY_sqr(r,r); |
| FP_YYY_sqr(r,r); |
| FP_YYY_sqr(r,r); |
| FP_YYY_mul(r,r,&tb[w[i]]); |
| } |
| FP_YYY_reduce(r); |
| } |
| |
| /* set w=1/x */ |
| void FP_YYY_inv(FP_YYY *w,FP_YYY *x) |
| { |
| |
| BIG_XXX m2; |
| BIG_XXX_rcopy(m2,Modulus_YYY); |
| BIG_XXX_dec(m2,2); |
| BIG_XXX_norm(m2); |
| FP_YYY_pow(w,x,m2); |
| } |
| #endif |
| |
| /* SU=8 */ |
| /* set n=1 */ |
| void FP_YYY_one(FP_YYY *n) |
| { |
| BIG_XXX b; |
| BIG_XXX_one(b); |
| FP_YYY_nres(n,b); |
| } |
| |
| /* is r a QR? */ |
| int FP_YYY_qr(FP_YYY *r) |
| { |
| int j; |
| BIG_XXX m; |
| BIG_XXX b; |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| FP_YYY_redc(b,r); |
| j=BIG_XXX_jacobi(b,m); |
| FP_YYY_nres(r,b); |
| if (j==1) return 1; |
| return 0; |
| |
| } |
| |
| /* Set a=sqrt(b) mod Modulus */ |
| /* SU= 160 */ |
| void FP_YYY_sqrt(FP_YYY *r,FP_YYY *a) |
| { |
| FP_YYY v,i; |
| BIG_XXX b; |
| BIG_XXX m; |
| BIG_XXX_rcopy(m,Modulus_YYY); |
| BIG_XXX_mod(a->g,m); |
| BIG_XXX_copy(b,m); |
| if (MOD8_YYY==5) |
| { |
| FP_YYY_copy(&i,a); // i=x |
| BIG_XXX_fshl(i.g,1); // i=2x |
| #if MODTYPE_YYY == PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE |
| FP_YYY_fpow(&v,&i); |
| #else |
| BIG_XXX_dec(b,5); |
| BIG_XXX_norm(b); |
| BIG_XXX_fshr(b,3); // (p-5)/8 |
| FP_YYY_pow(&v,&i,b); // v=(2x)^(p-5)/8 |
| #endif |
| FP_YYY_mul(&i,&i,&v); // i=(2x)^(p+3)/8 |
| FP_YYY_mul(&i,&i,&v); // i=(2x)^(p-1)/4 |
| BIG_XXX_dec(i.g,1); // i=(2x)^(p-1)/4 - 1 |
| FP_YYY_mul(r,a,&v); |
| FP_YYY_mul(r,r,&i); |
| FP_YYY_reduce(r); |
| } |
| if (MOD8_YYY==3 || MOD8_YYY==7) |
| { |
| #if MODTYPE_YYY == PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE |
| FP_YYY_fpow(r,a); |
| FP_YYY_mul(r,r,a); |
| #else |
| BIG_XXX_inc(b,1); |
| BIG_XXX_norm(b); |
| BIG_XXX_fshr(b,2); /* (p+1)/4 */ |
| FP_YYY_pow(r,a,b); |
| #endif |
| } |
| } |