/*############################################################################ # Copyright 2017 Intel Corporation # # 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. ############################################################################*/ /// Implementation of EFq2 math /*! \file */ #include "epid/member/tiny/math/efq2.h" #include "epid/member/tiny/math/fq.h" #include "epid/member/tiny/math/fq2.h" #include "epid/member/tiny/math/mathtypes.h" #include "epid/member/tiny/math/vli.h" static void EFq2CondSet(EccPointJacobiFq2* result, EccPointJacobiFq2 const* true_val, EccPointJacobiFq2 const* false_val, int truth_val) { Fq2CondSet(&result->X, &true_val->X, &false_val->X, truth_val); Fq2CondSet(&result->Y, &true_val->Y, &false_val->Y, truth_val); Fq2CondSet(&result->Z, &true_val->Z, &false_val->Z, truth_val); } static void EFq2Cp(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { Fq2Cp(&result->X, &in->X); Fq2Cp(&result->Y, &in->Y); Fq2Cp(&result->Z, &in->Z); } static void EFq2Inf(EccPointJacobiFq2* result) { Fq2Set(&result->X, 0); Fq2Set(&result->Y, 1); Fq2Set(&result->Z, 0); } int EFq2IsInf(EccPointJacobiFq2 const* in) { return Fq2IsZero(&in->X) && Fq2IsZero(&in->Z) && (!Fq2IsZero(&in->Y)); } void EFq2FromAffine(EccPointJacobiFq2* result, EccPointFq2 const* in) { Fq2Cp(&result->X, &in->x); Fq2Cp(&result->Y, &in->y); Fq2Set(&result->Z, 1); } int EFq2ToAffine(EccPointFq2* result, EccPointJacobiFq2 const* in) { Fq2Elem inverted_z; if (EFq2IsInf(in)) { return 0; } Fq2Inv(&inverted_z, &in->Z); Fq2Mul(&result->x, &in->X, &inverted_z); Fq2Mul(&result->x, &result->x, &inverted_z); Fq2Mul(&result->y, &in->Y, &inverted_z); Fq2Mul(&result->y, &result->y, &inverted_z); Fq2Mul(&result->y, &result->y, &inverted_z); return 1; } void EFq2Dbl(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { Fq2Elem a; Fq2Elem b; // Z3 = 2Z1 Fq2Add(&(result->Z), &(in->Z), &(in->Z)); // Z3 = 2*Z1*Y1 Fq2Mul(&(result->Z), &(result->Z), &(in->Y)); // A = X1^2 Fq2Square(&a, &(in->X)); // B = 2(X1^2) Fq2Add(&b, &a, &a); // B = 3(X1^2) Fq2Add(&b, &b, &a); // A = Y1^2 Fq2Square(&a, &(in->Y)); // A = 2*(Y1^2) Fq2Add(&a, &a, &a); // Y3 = 4*(Y1^4) Fq2Square(&(result->Y), &a); // Y3 = 8*(Y1^4) Fq2Add(&(result->Y), &(result->Y), &(result->Y)); // A = 4(Y1^2) Fq2Add(&a, &a, &a); // A = 4(Y1^2)*X1 Fq2Mul(&a, &a, &(in->X)); // X3 = B^2 Fq2Square(&(result->X), &b); // X3 = (B^2) - A Fq2Sub(&(result->X), &(result->X), &a); // X3 = (B^2) - 2A Fq2Sub(&(result->X), &(result->X), &a); // A = A - X3 Fq2Sub(&a, &a, &(result->X)); // A = B*(A-X3) Fq2Mul(&a, &a, &b); // Y3 = B*(A-X3) - 8*(Y1^4) Fq2Sub(&(result->Y), &a, &(result->Y)); } void EFq2Add(EccPointJacobiFq2* result, EccPointJacobiFq2 const* left, EccPointJacobiFq2 const* right) { Fq2Elem A; Fq2Elem B; Fq2Elem C; Fq2Elem D; Fq2Elem W; Fq2Elem V; if (Fq2IsZero(&left->Z)) { // If P = O, set R = Q and return EFq2Cp(result, right); return; } if (Fq2IsZero(&right->Z)) { // If Q = O, set R = P and return. EFq2Cp(result, left); return; } // A = P.X * Q.Z^2 Fq2Square(&C, &right->Z); Fq2Mul(&A, &left->X, &C); // B = Q.X * P.Z^2 Fq2Square(&D, &left->Z); Fq2Mul(&B, &right->X, &D); // C = P.Y * Q.Z^3 Fq2Mul(&C, &right->Z, &C); Fq2Mul(&C, &left->Y, &C); // D = Q.Y * P.Z^3 Fq2Mul(&D, &left->Z, &D); Fq2Mul(&D, &right->Y, &D); // W = B - A Fq2Sub(&W, &B, &A); // V = D - C Fq2Sub(&V, &D, &C); if (Fq2IsZero(&W)) { if (Fq2IsZero(&V)) { EFq2Dbl(result, left); return; } else { EFq2Inf(result); return; } } // R.Z = P.Z * Q.Z * W Fq2Mul(&result->Z, &left->Z, &right->Z); Fq2Mul(&result->Z, &result->Z, &W); // R.X = V^2 - (A + B) * W^2 Fq2Square(&result->X, &V); Fq2Add(&B, &A, &B); // Before squaring W save (C * W) to use in compitation of R.Y Fq2Mul(&C, &C, &W); Fq2Square(&W, &W); Fq2Mul(&B, &B, &W); Fq2Sub(&result->X, &result->X, &B); // R.Y = V * (A * W^2 - R.X) - C * W^3 Fq2Mul(&A, &A, &W); Fq2Sub(&A, &A, &result->X); Fq2Mul(&result->Y, &V, &A); Fq2Mul(&C, &C, &W); Fq2Sub(&result->Y, &result->Y, &C); } void EFq2Neg(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { Fq2Cp(&result->X, &in->X); Fq2Neg(&result->Y, &in->Y); Fq2Cp(&result->Z, &in->Z); } void EFq2MulSSCM(EccPointJacobiFq2* result, EccPointJacobiFq2 const* left, FpElem const* right) { int position; EccPointJacobiFq2 nv; EccPointJacobiFq2 mv; EFq2Inf(&nv); EFq2Cp(&mv, left); for (position = 32 * NUM_ECC_DIGITS - 1; position >= 0; position--) { EFq2Dbl(&nv, &nv); EFq2Add(&mv, left, &nv); EFq2CondSet(&nv, &mv, &nv, (int)(VliTestBit(&right->limbs, (uint32_t)position))); } EFq2Cp(result, &nv); } int EFq2Eq(EccPointJacobiFq2 const* left, EccPointJacobiFq2 const* right) { Fq2Elem t1; Fq2Elem t2; Fq2Elem t3; Fq2Elem t4; if (EFq2IsInf(left) && EFq2IsInf(right)) { return 1; } // if either left or right equals to inf return 0 if (EFq2IsInf(left) || EFq2IsInf(right)) { return 0; } Fq2Square(&t1, &(left->Z)); Fq2Square(&t2, &(right->Z)); Fq2Mul(&t3, &t1, &(right->X)); Fq2Mul(&t4, &t2, &(left->X)); Fq2Mul(&t1, &t1, &(left->Z)); Fq2Mul(&t2, &t2, &(right->Z)); Fq2Mul(&t1, &t1, &(right->Y)); Fq2Mul(&t2, &t2, &(left->Y)); return Fq2Eq(&t1, &t2) && Fq2Eq(&t3, &t4); } int EFq2OnCurve(EccPointFq2 const* in) { // test that Y^2 mod q == (X^3 + a*Z^4*X + b'*Z^6) mod q // This simplifies to: Y^2 mod q == (X^3 + b') mod q // since: Z = 1 // a = 0 // b = 3 Fq2Elem t1; Fq2Elem t2; FqElem three; // Fq2xi Fq2Elem bp = {{{{0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}, {{{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}}; Fq2Elem const* x = &in->x; Fq2Elem const* y = &in->y; // b' = b * inv(x1) FqSet(&three, 3); Fq2Inv(&bp, &bp); Fq2MulScalar(&bp, &bp, &three); // set t2 = X^3 Fq2Square(&t1, x); Fq2Mul(&t2, x, &t1); // set t2 = X^3 + b' Fq2Add(&t2, &t2, &bp); // set t1 = Y^2 Fq2Square(&t1, y); // set t1 = Y^2 - (X^3 + b') Fq2Sub(&t1, &t1, &t2); // return if t1 is zero return Fq2IsZero(&t1); }