1 /*############################################################################ 2 # Copyright 2017 Intel Corporation 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 ############################################################################*/ 16 /// Implementation of EFq2 math 17 /*! \file */ 18 19 #include "epid/member/tiny/math/efq2.h" 20 21 #include "epid/member/tiny/math/fq.h" 22 #include "epid/member/tiny/math/fq2.h" 23 #include "epid/member/tiny/math/mathtypes.h" 24 #include "epid/member/tiny/math/vli.h" 25 26 static void EFq2CondSet(EccPointJacobiFq2* result, 27 EccPointJacobiFq2 const* true_val, 28 EccPointJacobiFq2 const* false_val, int truth_val) { 29 Fq2CondSet(&result->X, &true_val->X, &false_val->X, truth_val); 30 Fq2CondSet(&result->Y, &true_val->Y, &false_val->Y, truth_val); 31 Fq2CondSet(&result->Z, &true_val->Z, &false_val->Z, truth_val); 32 } 33 34 static void EFq2Cp(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { 35 Fq2Cp(&result->X, &in->X); 36 Fq2Cp(&result->Y, &in->Y); 37 Fq2Cp(&result->Z, &in->Z); 38 } 39 40 static void EFq2Inf(EccPointJacobiFq2* result) { 41 Fq2Set(&result->X, 0); 42 Fq2Set(&result->Y, 1); 43 Fq2Set(&result->Z, 0); 44 } 45 46 int EFq2IsInf(EccPointJacobiFq2 const* in) { 47 return Fq2IsZero(&in->X) && Fq2IsZero(&in->Z) && (!Fq2IsZero(&in->Y)); 48 } 49 50 void EFq2FromAffine(EccPointJacobiFq2* result, EccPointFq2 const* in) { 51 Fq2Cp(&result->X, &in->x); 52 Fq2Cp(&result->Y, &in->y); 53 Fq2Set(&result->Z, 1); 54 } 55 56 int EFq2ToAffine(EccPointFq2* result, EccPointJacobiFq2 const* in) { 57 Fq2Elem inverted_z; 58 if (EFq2IsInf(in)) { 59 return 0; 60 } 61 Fq2Inv(&inverted_z, &in->Z); 62 Fq2Mul(&result->x, &in->X, &inverted_z); 63 Fq2Mul(&result->x, &result->x, &inverted_z); 64 Fq2Mul(&result->y, &in->Y, &inverted_z); 65 Fq2Mul(&result->y, &result->y, &inverted_z); 66 Fq2Mul(&result->y, &result->y, &inverted_z); 67 return 1; 68 } 69 70 void EFq2Dbl(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { 71 Fq2Elem a; 72 Fq2Elem b; 73 // Z3 = 2Z1 74 Fq2Add(&(result->Z), &(in->Z), &(in->Z)); 75 // Z3 = 2*Z1*Y1 76 Fq2Mul(&(result->Z), &(result->Z), &(in->Y)); 77 // A = X1^2 78 Fq2Square(&a, &(in->X)); 79 // B = 2(X1^2) 80 Fq2Add(&b, &a, &a); 81 // B = 3(X1^2) 82 Fq2Add(&b, &b, &a); 83 // A = Y1^2 84 Fq2Square(&a, &(in->Y)); 85 // A = 2*(Y1^2) 86 Fq2Add(&a, &a, &a); 87 // Y3 = 4*(Y1^4) 88 Fq2Square(&(result->Y), &a); 89 // Y3 = 8*(Y1^4) 90 Fq2Add(&(result->Y), &(result->Y), &(result->Y)); 91 // A = 4(Y1^2) 92 Fq2Add(&a, &a, &a); 93 // A = 4(Y1^2)*X1 94 Fq2Mul(&a, &a, &(in->X)); 95 // X3 = B^2 96 Fq2Square(&(result->X), &b); 97 // X3 = (B^2) - A 98 Fq2Sub(&(result->X), &(result->X), &a); 99 // X3 = (B^2) - 2A 100 Fq2Sub(&(result->X), &(result->X), &a); 101 // A = A - X3 102 Fq2Sub(&a, &a, &(result->X)); 103 // A = B*(A-X3) 104 Fq2Mul(&a, &a, &b); 105 // Y3 = B*(A-X3) - 8*(Y1^4) 106 Fq2Sub(&(result->Y), &a, &(result->Y)); 107 } 108 109 void EFq2Add(EccPointJacobiFq2* result, EccPointJacobiFq2 const* left, 110 EccPointJacobiFq2 const* right) { 111 Fq2Elem A; 112 Fq2Elem B; 113 Fq2Elem C; 114 Fq2Elem D; 115 Fq2Elem W; 116 Fq2Elem V; 117 118 if (Fq2IsZero(&left->Z)) { 119 // If P = O, set R = Q and return 120 EFq2Cp(result, right); 121 return; 122 } 123 if (Fq2IsZero(&right->Z)) { 124 // If Q = O, set R = P and return. 125 EFq2Cp(result, left); 126 return; 127 } 128 // A = P.X * Q.Z^2 129 Fq2Square(&C, &right->Z); 130 Fq2Mul(&A, &left->X, &C); 131 // B = Q.X * P.Z^2 132 Fq2Square(&D, &left->Z); 133 Fq2Mul(&B, &right->X, &D); 134 // C = P.Y * Q.Z^3 135 Fq2Mul(&C, &right->Z, &C); 136 Fq2Mul(&C, &left->Y, &C); 137 // D = Q.Y * P.Z^3 138 Fq2Mul(&D, &left->Z, &D); 139 Fq2Mul(&D, &right->Y, &D); 140 // W = B - A 141 Fq2Sub(&W, &B, &A); 142 // V = D - C 143 Fq2Sub(&V, &D, &C); 144 if (Fq2IsZero(&W)) { 145 if (Fq2IsZero(&V)) { 146 EFq2Dbl(result, left); 147 return; 148 } else { 149 EFq2Inf(result); 150 return; 151 } 152 } 153 // R.Z = P.Z * Q.Z * W 154 Fq2Mul(&result->Z, &left->Z, &right->Z); 155 Fq2Mul(&result->Z, &result->Z, &W); 156 // R.X = V^2 - (A + B) * W^2 157 Fq2Square(&result->X, &V); 158 Fq2Add(&B, &A, &B); 159 // Before squaring W save (C * W) to use in compitation of R.Y 160 Fq2Mul(&C, &C, &W); 161 Fq2Square(&W, &W); 162 Fq2Mul(&B, &B, &W); 163 Fq2Sub(&result->X, &result->X, &B); 164 // R.Y = V * (A * W^2 - R.X) - C * W^3 165 Fq2Mul(&A, &A, &W); 166 Fq2Sub(&A, &A, &result->X); 167 Fq2Mul(&result->Y, &V, &A); 168 Fq2Mul(&C, &C, &W); 169 Fq2Sub(&result->Y, &result->Y, &C); 170 } 171 172 void EFq2Neg(EccPointJacobiFq2* result, EccPointJacobiFq2 const* in) { 173 Fq2Cp(&result->X, &in->X); 174 Fq2Neg(&result->Y, &in->Y); 175 Fq2Cp(&result->Z, &in->Z); 176 } 177 178 void EFq2MulSSCM(EccPointJacobiFq2* result, EccPointJacobiFq2 const* left, 179 FpElem const* right) { 180 int position; 181 EccPointJacobiFq2 nv; 182 EccPointJacobiFq2 mv; 183 EFq2Inf(&nv); 184 EFq2Cp(&mv, left); 185 for (position = 32 * NUM_ECC_DIGITS - 1; position >= 0; position--) { 186 EFq2Dbl(&nv, &nv); 187 EFq2Add(&mv, left, &nv); 188 EFq2CondSet(&nv, &mv, &nv, 189 (int)(VliTestBit(&right->limbs, (uint32_t)position))); 190 } 191 EFq2Cp(result, &nv); 192 } 193 194 int EFq2Eq(EccPointJacobiFq2 const* left, EccPointJacobiFq2 const* right) { 195 Fq2Elem t1; 196 Fq2Elem t2; 197 Fq2Elem t3; 198 Fq2Elem t4; 199 200 if (EFq2IsInf(left) && EFq2IsInf(right)) { 201 return 1; 202 } 203 // if either left or right equals to inf return 0 204 if (EFq2IsInf(left) || EFq2IsInf(right)) { 205 return 0; 206 } 207 Fq2Square(&t1, &(left->Z)); 208 Fq2Square(&t2, &(right->Z)); 209 Fq2Mul(&t3, &t1, &(right->X)); 210 Fq2Mul(&t4, &t2, &(left->X)); 211 Fq2Mul(&t1, &t1, &(left->Z)); 212 Fq2Mul(&t2, &t2, &(right->Z)); 213 Fq2Mul(&t1, &t1, &(right->Y)); 214 Fq2Mul(&t2, &t2, &(left->Y)); 215 return Fq2Eq(&t1, &t2) && Fq2Eq(&t3, &t4); 216 } 217 218 int EFq2OnCurve(EccPointFq2 const* in) { 219 // test that Y^2 mod q == (X^3 + a*Z^4*X + b'*Z^6) mod q 220 // This simplifies to: Y^2 mod q == (X^3 + b') mod q 221 // since: Z = 1 222 // a = 0 223 // b = 3 224 Fq2Elem t1; 225 Fq2Elem t2; 226 FqElem three; 227 // Fq2xi 228 Fq2Elem bp = {{{{0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 229 0x00000000, 0x00000000, 0x00000000}}}, 230 {{{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 231 0x00000000, 0x00000000, 0x00000000}}}}; 232 Fq2Elem const* x = &in->x; 233 Fq2Elem const* y = &in->y; 234 235 // b' = b * inv(x1) 236 FqSet(&three, 3); 237 Fq2Inv(&bp, &bp); 238 Fq2MulScalar(&bp, &bp, &three); 239 240 // set t2 = X^3 241 Fq2Square(&t1, x); 242 Fq2Mul(&t2, x, &t1); 243 // set t2 = X^3 + b' 244 Fq2Add(&t2, &t2, &bp); 245 246 // set t1 = Y^2 247 Fq2Square(&t1, y); 248 249 // set t1 = Y^2 - (X^3 + b') 250 Fq2Sub(&t1, &t1, &t2); 251 // return if t1 is zero 252 return Fq2IsZero(&t1); 253 } 254