void cpMontRedAdc_BNU(BNU_CHUNK_T* pR, BNU_CHUNK_T* pProduct, const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0) { BNU_CHUNK_T carry; BNU_CHUNK_T extension; cpSize n; for(n=0, carry = 0; n<(nsM-1); n++) { BNU_CHUNK_T u = pProduct[n]*m0; BNU_CHUNK_T t = pProduct[nsM +n +1] + carry; extension = cpAddMulDgt_BNU(pProduct+n, pModulus, nsM, u); ADD_AB(carry, pProduct[nsM+n], pProduct[nsM+n], extension); t += carry; carry = t<pProduct[nsM+n+1]; pProduct[nsM+n+1] = t; } m0 *= pProduct[nsM-1]; extension = cpAddMulDgt_BNU(pProduct+nsM-1, pModulus, nsM, m0); ADD_AB(extension, pProduct[2*nsM-1], pProduct[2*nsM-1], extension); carry |= extension; carry -= cpSub_BNU(pR, pProduct+nsM, pModulus, nsM); /* condition copy: R = carry? Product+mSize : R */ MASKED_COPY_BNU(pR, carry, pProduct+nsM, pR, nsM); }
int cpModInv_BNU(BNU_CHUNK_T* pInv, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pM, cpSize nsM, BNU_CHUNK_T* bufInv, BNU_CHUNK_T* bufA, BNU_CHUNK_T* bufM) { FIX_BNU(pA, nsA); FIX_BNU(pM, nsM); /* inv(1) = 1 */ if(nsA==1 && pA[0]==1) { pInv[0] = 1; return 1; } { cpSize moduloSize = nsM; BNU_CHUNK_T* X1 = pInv; BNU_CHUNK_T* X2 = bufM; BNU_CHUNK_T* Q = bufInv; cpSize nsX1 = 1; cpSize nsX2 = 1; cpSize nsQ; COPY_BNU(bufA, pA, nsA); ZEXPAND_BNU(X1, 0, moduloSize); ZEXPAND_BNU(X2, 0, moduloSize); X2[0] = 1; for(;;) { nsM = cpDiv_BNU(Q, &nsQ, (BNU_CHUNK_T*)pM, nsM, bufA, nsA); nsX1 = cpMac_BNU(X1,moduloSize, Q,nsQ, X2,nsX2); if (nsM==1 && pM[0]==1) { ////ZEXPAND_BNU(X2, nsX2, moduloSize); nsX2 = cpMac_BNU(X2,moduloSize, X1,nsX1, bufA, nsA); COPY_BNU((BNU_CHUNK_T*)pM, X2, moduloSize); cpSub_BNU(pInv, pM, X1, moduloSize); FIX_BNU(pInv, moduloSize); return moduloSize; } else if (nsM==1 && pM[0]==0) { cpMul_BNU_school((BNU_CHUNK_T*)pM, X1,nsX1, bufA, nsA); /* gcd = buf_a */ return 0; } nsA = cpDiv_BNU(Q, &nsQ, bufA, nsA, (BNU_CHUNK_T*)pM, nsM); nsX2 = cpMac_BNU(X2,moduloSize, Q,nsQ, X1,nsX1); if(nsA==1 && bufA[0]==1) { ////ZEXPAND_BNU(X1, nsX1, moduloSize); nsX1 = cpMac_BNU(X1, moduloSize, X2, nsX2, pM, nsM); COPY_BNU((BNU_CHUNK_T*)pM, X1, moduloSize); COPY_BNU(pInv, X2, nsX2); return nsX2; } else if (nsA==1 && bufA[0]==0) { /* gcd = m */ COPY_BNU(X1, pM, nsM); cpMul_BNU_school((BNU_CHUNK_T*)pM, X2, nsX2, X1, nsM); return 0; } } } }