<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />

Isogeny

sealed class Isogeny
namespace Org.BouncyCastle.Pqc.Crypto.Sike { internal sealed class Isogeny { private readonly SikeEngine engine; internal Isogeny(SikeEngine engine) { this.engine = engine; } internal void Double(PointProj P, PointProj Q, ulong[][] A24, uint k) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2copy(P.X, Q.X); engine.fpx.fp2copy(P.Z, Q.Z); for (int i = 0; i < k; i++) { engine.fpx.fp2add(Q.X, Q.Z, array2); engine.fpx.fp2sub(Q.X, Q.Z, array3); engine.fpx.fp2sqr_mont(array2, array5); engine.fpx.fp2sqr_mont(array3, array6); engine.fpx.fp2sub(array5, array6, array4); engine.fpx.fp2mul_mont(array5, array6, Q.X); engine.fpx.fp2mul_mont(A24, array4, array); engine.fpx.fp2add(array, array6, array); engine.fpx.fp2mul_mont(array4, array, Q.Z); } } internal void CompleteMPoint(ulong[][] A, PointProj P, PointProjFull R) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array7 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array8 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array9 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array2[0]); if (!Fpx.subarrayEquals(P.Z[0], array[0], engine.param.NWORDS_FIELD) || !Fpx.subarrayEquals(P.Z[1], array[1], engine.param.NWORDS_FIELD)) { engine.fpx.fp2mul_mont(P.X, P.Z, array3); engine.fpx.fpsubPRIME(P.X[0], P.Z[1], array8[0]); engine.fpx.fpaddPRIME(P.X[1], P.Z[0], array8[1]); engine.fpx.fpaddPRIME(P.X[0], P.Z[1], array9[0]); engine.fpx.fpsubPRIME(P.X[1], P.Z[0], array9[1]); engine.fpx.fp2mul_mont(array8, array9, array5); engine.fpx.fp2mul_mont(A, array3, array8); engine.fpx.fp2add(array8, array5, array9); engine.fpx.fp2mul_mont(array3, array9, array6); engine.fpx.sqrt_Fp2(array6, array4); engine.fpx.fp2copy(P.Z, array7); engine.fpx.fp2inv_mont_bingcd(array7); engine.fpx.fp2mul_mont(P.X, array7, R.X); engine.fpx.fp2sqr_mont(array7, array8); engine.fpx.fp2mul_mont(array4, array8, R.Y); engine.fpx.fp2copy(array2, R.Z); } else { engine.fpx.fp2copy(array, R.X); engine.fpx.fp2copy(array2, R.Y); engine.fpx.fp2copy(array, R.Z); } } internal void Ladder(PointProj P, ulong[] m, ulong[][] A, uint order_bits, PointProj R) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj q = new PointProj(engine.param.NWORDS_FIELD); ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); int num = 0; engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array[0]); engine.fpx.fpaddPRIME(array[0], array[0], array[0]); engine.fpx.fp2add(A, array, array); engine.fpx.fp2div2(array, array); engine.fpx.fp2div2(array, array); int num2 = (int)(order_bits - 1); for (uint num3 = (uint)((m[num2 >> (int)Internal.LOG2RADIX] >> (int)(num2 & (Internal.RADIX - 1))) & 1); num3 == 0; num3 = (uint)((m[num2 >> (int)Internal.LOG2RADIX] >> (int)(num2 & (Internal.RADIX - 1))) & 1)) { num2--; } engine.fpx.fp2copy(P.X, pointProj.X); engine.fpx.fp2copy(P.Z, pointProj.Z); XDblE(P, q, array, 1); int num5; ulong option; for (int num4 = num2 - 1; num4 >= 0; num4--) { uint num3 = (uint)((m[num4 >> (int)Internal.LOG2RADIX] >> (int)(num4 & (Internal.RADIX - 1))) & 1); num5 = (int)(num3 ^ num); num = (int)num3; option = (ulong)(-num5); SwapPoints(pointProj, q, option); XDblAddProj(pointProj, q, P.X, P.Z, array); } num5 = (0 ^ num); option = (ulong)(-num5); SwapPoints(pointProj, q, option); engine.fpx.fp2copy(pointProj.X, R.X); engine.fpx.fp2copy(pointProj.Z, R.Z); } private void XDblAddProj(PointProj P, PointProj Q, ulong[][] XPQ, ulong[][] ZPQ, ulong[][] A24) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2add(P.X, P.Z, array); engine.fpx.fp2sub(P.X, P.Z, array2); engine.fpx.fp2sqr_mont(array, P.X); engine.fpx.fp2sub(Q.X, Q.Z, array3); engine.fpx.fp2correction(array3); engine.fpx.fp2add(Q.X, Q.Z, Q.X); engine.fpx.fp2mul_mont(array, array3, array); engine.fpx.fp2sqr_mont(array2, P.Z); engine.fpx.fp2mul_mont(array2, Q.X, array2); engine.fpx.fp2sub(P.X, P.Z, array3); engine.fpx.fp2mul_mont(P.X, P.Z, P.X); engine.fpx.fp2mul_mont(array3, A24, Q.X); engine.fpx.fp2sub(array, array2, Q.Z); engine.fpx.fp2add(Q.X, P.Z, P.Z); engine.fpx.fp2add(array, array2, Q.X); engine.fpx.fp2mul_mont(P.Z, array3, P.Z); engine.fpx.fp2sqr_mont(Q.Z, Q.Z); engine.fpx.fp2sqr_mont(Q.X, Q.X); engine.fpx.fp2mul_mont(Q.X, ZPQ, Q.X); engine.fpx.fp2mul_mont(Q.Z, XPQ, Q.Z); } private void XDblE(PointProj P, PointProj Q, ulong[][] A24, int e) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2copy(P.X, Q.X); engine.fpx.fp2copy(P.Z, Q.Z); for (int i = 0; i < e; i++) { engine.fpx.fp2add(Q.X, Q.Z, array2); engine.fpx.fp2sub(Q.X, Q.Z, array3); engine.fpx.fp2sqr_mont(array2, array5); engine.fpx.fp2sqr_mont(array3, array6); engine.fpx.fp2sub(array5, array6, array4); engine.fpx.fp2mul_mont(array5, array6, Q.X); engine.fpx.fp2mul_mont(A24, array4, array); engine.fpx.fp2add(array, array6, array); engine.fpx.fp2mul_mont(array4, array, Q.Z); } } internal void XTplEFast(PointProj P, PointProj Q, ulong[][] A2, uint e) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); engine.fpx.copy_words(P, pointProj); for (int i = 0; i < e; i++) { XTplFast(pointProj, pointProj, A2); } engine.fpx.copy_words(pointProj, Q); } private void XTplFast(PointProj P, PointProj Q, ulong[][] A2) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2sqr_mont(P.X, array); engine.fpx.fp2sqr_mont(P.Z, array2); engine.fpx.fp2add(array, array2, array3); engine.fpx.fp2add(P.X, P.Z, array4); engine.fpx.fp2sqr_mont(array4, array4); engine.fpx.fp2sub(array4, array3, array4); engine.fpx.fp2mul_mont(A2, array4, array4); engine.fpx.fp2add(array3, array4, array4); engine.fpx.fp2sub(array, array2, array3); engine.fpx.fp2sqr_mont(array3, array3); engine.fpx.fp2mul_mont(array, array4, array); engine.fpx.fp2shl(array, 2, array); engine.fpx.fp2sub(array, array3, array); engine.fpx.fp2sqr_mont(array, array); engine.fpx.fp2mul_mont(array2, array4, array2); engine.fpx.fp2shl(array2, 2, array2); engine.fpx.fp2sub(array2, array3, array2); engine.fpx.fp2sqr_mont(array2, array2); engine.fpx.fp2mul_mont(P.X, array2, Q.X); engine.fpx.fp2mul_mont(P.Z, array, Q.Z); } internal void LADDER3PT(ulong[][] xP, ulong[][] xQ, ulong[][] xPQ, ulong[] m, uint AliceOrBob, PointProj R, ulong[][] A) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj2 = new PointProj(engine.param.NWORDS_FIELD); ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); uint num = 0; uint num2 = (AliceOrBob != engine.param.ALICE) ? (engine.param.OBOB_BITS - 1) : engine.param.OALICE_BITS; engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array[0]); engine.fpx.mp2_add(array, array, array); engine.fpx.mp2_add(A, array, array); engine.fpx.fp2div2(array, array); engine.fpx.fp2div2(array, array); engine.fpx.fp2copy(xQ, pointProj.X); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj.Z[0]); engine.fpx.fp2copy(xPQ, pointProj2.X); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj2.Z[0]); engine.fpx.fp2copy(xP, R.X); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, R.Z[0]); engine.fpx.fpzero(R.Z[1]); uint num5; ulong option; for (uint num3 = 0; num3 < num2; num3++) { int num4 = (int)((m[num3 >> (int)Internal.LOG2RADIX] >> (int)(num3 & (Internal.RADIX - 1))) & 1); num5 = (uint)(num4 ^ (int)num); num = (uint)num4; option = (ulong)(0 - (long)num5); SwapPoints(R, pointProj2, option); XDblAdd(pointProj, pointProj2, R.X, array); engine.fpx.fp2mul_mont(pointProj2.X, R.Z, pointProj2.X); } num5 = (0 ^ num); option = (ulong)(0 - (long)num5); SwapPoints(R, pointProj2, option); } internal void CompletePoint(PointProj P, PointProjFull R) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array7 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array8 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array8[0]); engine.fpx.fp2mul_mont(P.X, P.Z, array); engine.fpx.fpsubPRIME(P.X[0], P.Z[1], array6[0]); engine.fpx.fpaddPRIME(P.X[1], P.Z[0], array6[1]); engine.fpx.fpaddPRIME(P.X[0], P.Z[1], array7[0]); engine.fpx.fpsubPRIME(P.X[1], P.Z[0], array7[1]); engine.fpx.fp2mul_mont(array6, array7, array2); engine.fpx.fp2mul_mont(array, array2, array3); engine.fpx.sqrt_Fp2(array3, array4); engine.fpx.fp2copy(P.Z, array5); engine.fpx.fp2inv_mont_bingcd(array5); engine.fpx.fp2mul_mont(P.X, array5, R.X); engine.fpx.fp2sqr_mont(array5, array6); engine.fpx.fp2mul_mont(array4, array6, R.Y); engine.fpx.fp2copy(array8, R.Z); } internal void SwapPoints(PointProj P, PointProj Q, ulong option) { for (int i = 0; i < engine.param.NWORDS_FIELD; i++) { ulong num = option & (P.X[0][i] ^ Q.X[0][i]); P.X[0][i] = (num ^ P.X[0][i]); Q.X[0][i] = (num ^ Q.X[0][i]); num = (option & (P.X[1][i] ^ Q.X[1][i])); P.X[1][i] = (num ^ P.X[1][i]); Q.X[1][i] = (num ^ Q.X[1][i]); num = (option & (P.Z[0][i] ^ Q.Z[0][i])); P.Z[0][i] = (num ^ P.Z[0][i]); Q.Z[0][i] = (num ^ Q.Z[0][i]); num = (option & (P.Z[1][i] ^ Q.Z[1][i])); P.Z[1][i] = (num ^ P.Z[1][i]); Q.Z[1][i] = (num ^ Q.Z[1][i]); } } internal void XDblAdd(PointProj P, PointProj Q, ulong[][] xPQ, ulong[][] A24) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_add(P.X, P.Z, array); engine.fpx.mp2_sub_p2(P.X, P.Z, array2); engine.fpx.fp2sqr_mont(array, P.X); engine.fpx.mp2_sub_p2(Q.X, Q.Z, array3); engine.fpx.mp2_add(Q.X, Q.Z, Q.X); engine.fpx.fp2mul_mont(array, array3, array); engine.fpx.fp2sqr_mont(array2, P.Z); engine.fpx.fp2mul_mont(array2, Q.X, array2); engine.fpx.mp2_sub_p2(P.X, P.Z, array3); engine.fpx.fp2mul_mont(P.X, P.Z, P.X); engine.fpx.fp2mul_mont(A24, array3, Q.X); engine.fpx.mp2_sub_p2(array, array2, Q.Z); engine.fpx.mp2_add(Q.X, P.Z, P.Z); engine.fpx.mp2_add(array, array2, Q.X); engine.fpx.fp2mul_mont(P.Z, array3, P.Z); engine.fpx.fp2sqr_mont(Q.Z, Q.Z); engine.fpx.fp2sqr_mont(Q.X, Q.X); engine.fpx.fp2mul_mont(Q.Z, xPQ, Q.Z); } internal void XDblE(PointProj P, PointProj Q, ulong[][] A24plus, ulong[][] C24, uint e) { engine.fpx.copy_words(P, Q); for (int i = 0; i < e; i++) { XDbl(Q, Q, A24plus, C24); } } internal void XDbl(PointProj P, PointProj Q, ulong[][] A24plus, ulong[][] C24) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_sub_p2(P.X, P.Z, array); engine.fpx.mp2_add(P.X, P.Z, array2); engine.fpx.fp2sqr_mont(array, array); engine.fpx.fp2sqr_mont(array2, array2); engine.fpx.fp2mul_mont(C24, array, Q.Z); engine.fpx.fp2mul_mont(array2, Q.Z, Q.X); engine.fpx.mp2_sub_p2(array2, array, array2); engine.fpx.fp2mul_mont(A24plus, array2, array); engine.fpx.mp2_add(Q.Z, array, Q.Z); engine.fpx.fp2mul_mont(Q.Z, array2, Q.Z); } private void XTpl(PointProj P, PointProj Q, ulong[][] A24minus, ulong[][] A24plus) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array7 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_sub_p2(P.X, P.Z, array); engine.fpx.fp2sqr_mont(array, array3); engine.fpx.mp2_add(P.X, P.Z, array2); engine.fpx.fp2sqr_mont(array2, array4); engine.fpx.mp2_add(P.X, P.X, array5); engine.fpx.mp2_add(P.Z, P.Z, array); engine.fpx.fp2sqr_mont(array5, array2); engine.fpx.mp2_sub_p2(array2, array4, array2); engine.fpx.mp2_sub_p2(array2, array3, array2); engine.fpx.fp2mul_mont(A24plus, array4, array6); engine.fpx.fp2mul_mont(array4, array6, array4); engine.fpx.fp2mul_mont(A24minus, array3, array7); engine.fpx.fp2mul_mont(array3, array7, array3); engine.fpx.mp2_sub_p2(array3, array4, array4); engine.fpx.mp2_sub_p2(array6, array7, array3); engine.fpx.fp2mul_mont(array2, array3, array2); engine.fpx.fp2add(array4, array2, array3); engine.fpx.fp2sqr_mont(array3, array3); engine.fpx.fp2mul_mont(array5, array3, Q.X); engine.fpx.fp2sub(array4, array2, array2); engine.fpx.fp2sqr_mont(array2, array2); engine.fpx.fp2mul_mont(array, array2, Q.Z); } internal void XTplE(PointProj P, PointProj Q, ulong[][] A24minus, ulong[][] A24plus, uint e) { engine.fpx.copy_words(P, Q); for (int i = 0; i < e; i++) { XTpl(Q, Q, A24minus, A24plus); } } internal void GetA(ulong[][] xP, ulong[][] xQ, ulong[][] xR, ulong[][] A) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array3[0]); engine.fpx.fp2add(xP, xQ, array2); engine.fpx.fp2mul_mont(xP, xQ, array); engine.fpx.fp2mul_mont(xR, array2, A); engine.fpx.fp2add(array, A, A); engine.fpx.fp2mul_mont(array, xR, array); engine.fpx.fp2sub(A, array3, A); engine.fpx.fp2add(array, array, array); engine.fpx.fp2add(array2, xR, array2); engine.fpx.fp2add(array, array, array); engine.fpx.fp2sqr_mont(A, A); engine.fpx.fp2inv_mont(array); engine.fpx.fp2mul_mont(A, array, A); engine.fpx.fp2sub(A, array2, A); } internal void JInv(ulong[][] A, ulong[][] C, ulong[][] jinv) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2sqr_mont(A, jinv); engine.fpx.fp2sqr_mont(C, array2); engine.fpx.fp2add(array2, array2, array); engine.fpx.fp2sub(jinv, array, array); engine.fpx.fp2sub(array, array2, array); engine.fpx.fp2sub(array, array2, jinv); engine.fpx.fp2sqr_mont(array2, array2); engine.fpx.fp2mul_mont(jinv, array2, jinv); engine.fpx.fp2add(array, array, array); engine.fpx.fp2add(array, array, array); engine.fpx.fp2sqr_mont(array, array2); engine.fpx.fp2mul_mont(array, array2, array); engine.fpx.fp2add(array, array, array); engine.fpx.fp2add(array, array, array); engine.fpx.fp2inv_mont(jinv); engine.fpx.fp2mul_mont(jinv, array, jinv); } internal void Get3Isog(PointProj P, ulong[][] A24minus, ulong[][] A24plus, ulong[][][] coeff) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_sub_p2(P.X, P.Z, coeff[0]); engine.fpx.fp2sqr_mont(coeff[0], array); engine.fpx.mp2_add(P.X, P.Z, coeff[1]); engine.fpx.fp2sqr_mont(coeff[1], array2); engine.fpx.mp2_add(P.X, P.X, array4); engine.fpx.fp2sqr_mont(array4, array4); engine.fpx.fp2sub(array4, array, array3); engine.fpx.fp2sub(array4, array2, array4); engine.fpx.mp2_add(array, array4, array5); engine.fpx.mp2_add(array5, array5, array5); engine.fpx.mp2_add(array2, array5, array5); engine.fpx.fp2mul_mont(array3, array5, A24minus); engine.fpx.mp2_add(array2, array3, array5); engine.fpx.mp2_add(array5, array5, array5); engine.fpx.mp2_add(array, array5, array5); engine.fpx.fp2mul_mont(array4, array5, A24plus); } internal void Eval3Isog(PointProj Q, ulong[][][] coeff) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_add(Q.X, Q.Z, array); engine.fpx.mp2_sub_p2(Q.X, Q.Z, array2); engine.fpx.fp2mul_mont(coeff[0], array, array); engine.fpx.fp2mul_mont(coeff[1], array2, array2); engine.fpx.mp2_add(array, array2, array3); engine.fpx.mp2_sub_p2(array2, array, array); engine.fpx.fp2sqr_mont(array3, array3); engine.fpx.fp2sqr_mont(array, array); engine.fpx.fp2mul_mont(Q.X, array3, Q.X); engine.fpx.fp2mul_mont(Q.Z, array, Q.Z); } internal void Inv3Way(ulong[][] z1, ulong[][] z2, ulong[][] z3) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.fp2mul_mont(z1, z2, array); engine.fpx.fp2mul_mont(z3, array, array2); engine.fpx.fp2inv_mont(array2); engine.fpx.fp2mul_mont(z3, array2, array3); engine.fpx.fp2mul_mont(array3, z2, array4); engine.fpx.fp2mul_mont(array3, z1, z2); engine.fpx.fp2mul_mont(array, array2, z3); engine.fpx.fp2copy(array4, z1); } internal void Get2Isog(PointProj P, ulong[][] A, ulong[][] C) { engine.fpx.fp2sqr_mont(P.X, A); engine.fpx.fp2sqr_mont(P.Z, C); engine.fpx.mp2_sub_p2(C, A, A); } internal void Eval2Isog(PointProj P, PointProj Q) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_add(Q.X, Q.Z, array); engine.fpx.mp2_sub_p2(Q.X, Q.Z, array2); engine.fpx.mp2_add(P.X, P.Z, array3); engine.fpx.mp2_sub_p2(P.X, P.Z, array4); engine.fpx.fp2mul_mont(array, array4, array); engine.fpx.fp2mul_mont(array2, array3, array2); engine.fpx.mp2_add(array, array2, array3); engine.fpx.mp2_sub_p2(array, array2, array4); engine.fpx.fp2mul_mont(P.X, array3, P.X); engine.fpx.fp2mul_mont(P.Z, array4, P.Z); } internal void Get4Isog(PointProj P, ulong[][] A24plus, ulong[][] C24, ulong[][][] coeff) { engine.fpx.mp2_sub_p2(P.X, P.Z, coeff[1]); engine.fpx.mp2_add(P.X, P.Z, coeff[2]); engine.fpx.fp2sqr_mont(P.Z, coeff[0]); engine.fpx.mp2_add(coeff[0], coeff[0], coeff[0]); engine.fpx.fp2sqr_mont(coeff[0], C24); engine.fpx.mp2_add(coeff[0], coeff[0], coeff[0]); engine.fpx.fp2sqr_mont(P.X, A24plus); engine.fpx.mp2_add(A24plus, A24plus, A24plus); engine.fpx.fp2sqr_mont(A24plus, A24plus); } internal void Eval4Isog(PointProj P, ulong[][][] coeff) { ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); engine.fpx.mp2_add(P.X, P.Z, array); engine.fpx.mp2_sub_p2(P.X, P.Z, array2); engine.fpx.fp2mul_mont(array, coeff[1], P.X); engine.fpx.fp2mul_mont(array2, coeff[2], P.Z); engine.fpx.fp2mul_mont(array, array2, array); engine.fpx.fp2mul_mont(coeff[0], array, array); engine.fpx.mp2_add(P.X, P.Z, array2); engine.fpx.mp2_sub_p2(P.X, P.Z, P.Z); engine.fpx.fp2sqr_mont(array2, array2); engine.fpx.fp2sqr_mont(P.Z, P.Z); engine.fpx.mp2_add(array2, array, P.X); engine.fpx.mp2_sub_p2(P.Z, array, array); engine.fpx.fp2mul_mont(P.X, array2, P.X); engine.fpx.fp2mul_mont(P.Z, array, P.Z); } } }