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 EFq math 17 /*! \file */ 18 19 #include "epid/member/tiny/math/efq.h" 20 #include "epid/member/tiny/math/fq.h" 21 #include "epid/member/tiny/math/hashwrap.h" 22 #include "epid/member/tiny/math/mathtypes.h" 23 #include "epid/member/tiny/math/serialize.h" 24 #include "epid/member/tiny/math/vli.h" 25 #include "epid/member/tiny/stdlib/tiny_stdlib.h" 26 27 static int EFqMakePoint(EccPointFq* output, FqElem* in) { 28 FqElem fq_sqrt = {0}; 29 FqElem fq_tmp = {0}; 30 FqSet(&fq_tmp, 3); 31 FqSquare(&fq_sqrt, in); 32 FqMul(&fq_sqrt, &fq_sqrt, in); 33 FqAdd(&fq_sqrt, &fq_sqrt, &fq_tmp); 34 if (!FqSqrt(&output->y, &fq_sqrt)) { 35 return 0; 36 } 37 FqCp(&output->x, in); 38 39 return 1; 40 } 41 42 void EFqMulSSCM(EccPointJacobiFq* result, EccPointJacobiFq const* base, 43 FpElem const* exp) { 44 EccPointJacobiFq efqj_1; 45 EccPointJacobiFq efqj_2; 46 47 uint32_t position; 48 EFqInf(&efqj_1); 49 EFqJCp(&efqj_2, base); 50 for (position = 32 * NUM_ECC_DIGITS; position > 0; --position) { 51 EFqDbl(&efqj_1, &efqj_1); 52 EFqAdd(&efqj_2, base, &efqj_1); 53 EFqCondSet(&efqj_1, &efqj_2, &efqj_1, 54 VliTestBit(&(exp->limbs), position - 1)); 55 } 56 EFqJCp(result, &efqj_1); 57 } 58 59 int EFqAffineExp(EccPointFq* result, EccPointFq const* base, 60 FpElem const* exp) { 61 EccPointJacobiFq efqj; 62 EFqFromAffine(&efqj, base); 63 EFqMulSSCM(&efqj, &efqj, exp); 64 return EFqToAffine(result, &efqj); 65 } 66 67 int EFqAffineMultiExp(EccPointFq* result, EccPointFq const* base0, 68 FpElem const* exp0, EccPointFq const* base1, 69 FpElem const* exp1) { 70 EccPointJacobiFq efqj_base0; 71 EccPointJacobiFq efqj_base1; 72 EFqFromAffine(&efqj_base0, base0); 73 EFqFromAffine(&efqj_base1, base1); 74 EFqMultiExp(&efqj_base0, &efqj_base0, exp0, &efqj_base1, exp1); 75 return EFqToAffine(result, &efqj_base0); 76 } 77 78 void EFqMultiExp(EccPointJacobiFq* result, EccPointJacobiFq const* base0, 79 FpElem const* exp0, EccPointJacobiFq const* base1, 80 FpElem const* exp1) { 81 EccPointJacobiFq efqj_base0; 82 EccPointJacobiFq efqj_a; 83 EccPointJacobiFq efqj_b; 84 int i, j; 85 86 EFqAdd(&efqj_base0, base0, base1); 87 EFqInf(&efqj_a); 88 for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) { 89 for (j = 31; j >= 0; j--) { 90 EFqAdd(&efqj_a, &efqj_a, &efqj_a); 91 EFqInf(&efqj_b); 92 EFqJCp(&efqj_b, base0); 93 94 EFqCondSet(&efqj_b, base1, &efqj_b, 95 (int)((exp1->limbs.word[i] >> j) & (0x1))); 96 97 EFqCondSet(&efqj_b, &efqj_base0, &efqj_b, 98 (int)((exp0->limbs.word[i] >> j) & (exp1->limbs.word[i] >> j) & 99 (0x1))); 100 101 EFqAdd(&efqj_b, &efqj_a, &efqj_b); 102 103 EFqCondSet(&efqj_a, &efqj_b, &efqj_a, (int)(((exp0->limbs.word[i] >> j) | 104 (exp1->limbs.word[i] >> j)) & 105 (0x1))); 106 } 107 } 108 EFqJCp(result, &efqj_a); 109 } 110 111 int EFqAffineAdd(EccPointFq* result, EccPointFq const* left, 112 EccPointFq const* right) { 113 EccPointJacobiFq efqj_a; 114 EccPointJacobiFq efqj_b; 115 if (EFqEqAffine(left, right)) return EFqAffineDbl(result, left); 116 117 EFqFromAffine(&efqj_a, left); 118 EFqFromAffine(&efqj_b, right); 119 EFqAdd(&efqj_a, &efqj_a, &efqj_b); 120 121 return EFqToAffine(result, &efqj_a); 122 } 123 124 int EFqAffineDbl(EccPointFq* result, EccPointFq const* in) { 125 EccPointJacobiFq efqj_a; 126 EFqFromAffine(&efqj_a, in); 127 EFqAdd(&efqj_a, &efqj_a, &efqj_a); 128 129 return EFqToAffine(result, &efqj_a); 130 } 131 132 void EFqDbl(EccPointJacobiFq* result, EccPointJacobiFq const* in) { 133 FqElem fq_a; 134 FqElem fq_b; 135 136 FqAdd(&(result->Z), &(in->Z), &(in->Z)); 137 FqMul(&(result->Z), &(result->Z), &(in->Y)); 138 FqSquare(&fq_a, &(in->X)); 139 FqAdd(&fq_b, &fq_a, &fq_a); 140 FqAdd(&fq_b, &fq_b, &fq_a); 141 FqSquare(&fq_a, &(in->Y)); 142 FqAdd(&fq_a, &fq_a, &fq_a); 143 FqSquare(&(result->Y), &fq_a); 144 FqAdd(&(result->Y), &(result->Y), &(result->Y)); 145 FqAdd(&fq_a, &fq_a, &fq_a); 146 FqMul(&fq_a, &fq_a, &(in->X)); 147 FqSquare(&(result->X), &fq_b); 148 FqSub(&(result->X), &(result->X), &fq_a); 149 FqSub(&(result->X), &(result->X), &fq_a); 150 FqSub(&fq_a, &fq_a, &(result->X)); 151 FqMul(&fq_a, &fq_a, &fq_b); 152 FqSub(&(result->Y), &fq_a, &(result->Y)); 153 } 154 155 void EFqAdd(EccPointJacobiFq* result, EccPointJacobiFq const* left, 156 EccPointJacobiFq const* right) { 157 FqElem fq0; 158 FqElem fq1; 159 FqElem fq2; 160 FqElem fq3; 161 FqElem fq4; 162 FqElem fq5; 163 164 if (FqIsZero(&(left->Z))) { 165 EFqJCp(result, right); 166 return; 167 } 168 if (FqIsZero(&(right->Z))) { 169 EFqJCp(result, left); 170 return; 171 } 172 173 FqSquare(&fq2, &(right->Z)); 174 FqSquare(&fq3, &(left->Z)); 175 // P.X * Q.Z^2 176 FqMul(&fq0, &(left->X), &fq2); 177 // Q.X * P.Z^2 178 FqMul(&fq1, &(right->X), &fq3); 179 // Q.X*P.Z^2 - P*X+Q*Z^2 180 FqSub(&fq5, &fq1, &fq0); 181 FqMul(&fq3, &(right->Y), &fq3); 182 // P.Y * Q.Z^3 183 FqMul(&fq3, &(left->Z), &fq3); 184 FqMul(&fq2, &(left->Y), &fq2); 185 // Q.Y * P.Z^3 186 FqMul(&fq2, &(right->Z), &fq2); 187 FqSub(&fq4, &fq3, &fq2); 188 189 if (FqIsZero(&fq5)) { 190 if (FqIsZero(&fq4)) { 191 EFqDbl(result, left); 192 return; 193 } else { 194 EFqInf(result); 195 return; 196 } 197 } 198 FqMul(&(result->Z), &(left->Z), &(right->Z)); 199 FqMul(&(result->Z), &(result->Z), &fq5); 200 // Q.X*P.Z^2 + P*X+Q*Z^2 201 FqAdd(&fq1, &fq0, &fq1); 202 FqMul(&fq2, &fq2, &fq5); 203 FqSquare(&fq5, &fq5); 204 FqMul(&fq1, &fq1, &fq5); 205 FqSquare(&(result->X), &fq4); 206 FqSub(&(result->X), &(result->X), &fq1); 207 FqMul(&fq2, &fq2, &fq5); 208 FqMul(&fq0, &fq0, &fq5); 209 FqSub(&fq0, &fq0, &(result->X)); 210 FqMul(&(result->Y), &fq4, &fq0); 211 FqSub(&(result->Y), &(result->Y), &fq2); 212 } 213 214 int EFqRand(EccPointFq* result, BitSupplier rnd_func, void* rnd_param) { 215 FqElem fq; 216 do { 217 if (!FqRand(&fq, rnd_func, rnd_param)) { 218 return 0; 219 } 220 } while (!EFqMakePoint(result, &fq)); 221 return 1; 222 } 223 224 void EFqSet(EccPointJacobiFq* result, FqElem const* x, FqElem const* y) { 225 FqCp(&result->X, x); 226 FqCp(&result->Y, y); 227 FqSet(&result->Z, 1); 228 } 229 230 int EFqIsInf(EccPointJacobiFq const* in) { 231 return FqIsZero(&in->X) && FqIsZero(&in->Z) && (!FqIsZero(&in->Y)); 232 } 233 234 void EFqFromAffine(EccPointJacobiFq* result, EccPointFq const* in) { 235 FqCp(&result->X, &in->x); 236 FqCp(&result->Y, &in->y); 237 FqSet(&result->Z, 1); 238 } 239 240 int EFqToAffine(EccPointFq* result, EccPointJacobiFq const* in) { 241 FqElem fq_inv; 242 if (EFqIsInf(in)) { 243 return 0; 244 } 245 FqInv(&fq_inv, &in->Z); 246 FqMul(&result->x, &in->X, &fq_inv); 247 FqMul(&result->x, &result->x, &fq_inv); 248 FqMul(&result->y, &in->Y, &fq_inv); 249 FqMul(&result->y, &result->y, &fq_inv); 250 FqMul(&result->y, &result->y, &fq_inv); 251 252 return 1; 253 } 254 255 void EFqNeg(EccPointJacobiFq* result, EccPointJacobiFq const* in) { 256 FqCp(&result->X, &in->X); 257 FqNeg(&result->Y, &in->Y); 258 FqCp(&result->Z, &in->Z); 259 } 260 261 int EFqEq(EccPointJacobiFq const* left, EccPointJacobiFq const* right) { 262 FqElem fq1; 263 FqElem fq2; 264 FqElem fq3; 265 FqElem fq4; 266 if (EFqIsInf(left) && EFqIsInf(right)) { 267 return 1; 268 } 269 if (EFqIsInf(left) || EFqIsInf(right)) { 270 return 0; 271 } 272 // Z1^2 273 FqSquare(&fq1, &left->Z); 274 // Z2^2 275 FqSquare(&fq2, &right->Z); 276 // (Z1^2)*X2 277 FqMul(&fq3, &fq1, &right->X); 278 // (Z2^2)*X1 279 FqMul(&fq4, &fq2, &left->X); 280 // Z1^3 281 FqMul(&fq1, &fq1, &left->Z); 282 // Z2^3 283 FqMul(&fq2, &fq2, &right->Z); 284 // (Z1^3)*Y2 285 FqMul(&fq1, &fq1, &right->Y); 286 // (Z2^3)*Y1 287 FqMul(&fq2, &fq2, &left->Y); 288 // (Z1^2)*X2 == (Z2^2)*X1 && (Z1^3)*Y2 == (Z2^3)*Y1 289 return FqEq(&fq1, &fq2) && FqEq(&fq3, &fq4); 290 } 291 292 int EFqHash(EccPointFq* result, unsigned char const* msg, size_t len, 293 HashAlg hashalg) { 294 tiny_sha hash_context; 295 FqElem three; 296 FqElem tmp; 297 uint32_t hash_salt = 0; 298 uint32_t buf = 0; 299 sha_digest hash_buf; 300 // 1/q in Fq 301 FqElem montgomery_r = { 302 0x512ccfed, 0x2cd6d224, 0xed67f57d, 0xf3239a04, 303 0x118e5b60, 0xb91a0da1, 0x00030f32, 0, 304 }; 305 if ((kSha512 != hashalg) && (kSha256 != hashalg)) { 306 return 0; 307 } 308 FqSet(&three, 3); 309 310 for (hash_salt = 0; hash_salt < 0xFFFFFFFF; ++hash_salt) { 311 tinysha_init(hashalg, &hash_context); 312 313 Uint32Serialize((OctStr32*)&buf, hash_salt); 314 tinysha_update(&hash_context, &buf, sizeof(buf)); 315 tinysha_update(&hash_context, msg, len); 316 317 tinysha_final(hash_buf.digest, &hash_context); 318 319 FqFromHash(&result->x, hash_buf.digest, tinysha_digest_size(&hash_context)); 320 FqSquare(&tmp, &result->x); 321 FqMul(&tmp, &tmp, &result->x); 322 FqAdd(&tmp, &tmp, &three); 323 if (FqSqrt(&result->y, &tmp)) { 324 FqNeg(&tmp, &result->y); 325 // Verify and Non-tiny member use montgomery representation to determine 326 // if negation is needed: this is to be compatible with them 327 FqMul(&montgomery_r, &result->y, &montgomery_r); 328 FqCondSet(&result->y, &tmp, &result->y, montgomery_r.limbs.word[0] & 1); 329 return 1; 330 } 331 } 332 return 0; 333 } 334 335 void EFqCp(EccPointFq* result, EccPointFq const* in) { 336 FqCp(&result->x, &in->x); 337 FqCp(&result->y, &in->y); 338 } 339 340 int EFqEqAffine(EccPointFq const* left, EccPointFq const* right) { 341 return FqEq(&left->x, &right->x) && FqEq(&left->y, &right->y); 342 } 343 344 void EFqCondSet(EccPointJacobiFq* result, EccPointJacobiFq const* true_val, 345 EccPointJacobiFq const* false_val, int truth_val) { 346 FqCondSet(&result->X, &true_val->X, &false_val->X, truth_val); 347 FqCondSet(&result->Y, &true_val->Y, &false_val->Y, truth_val); 348 FqCondSet(&result->Z, &true_val->Z, &false_val->Z, truth_val); 349 } 350 351 void EFqJCp(EccPointJacobiFq* result, EccPointJacobiFq const* in) { 352 FqCp(&result->X, &in->X); 353 FqCp(&result->Y, &in->Y); 354 FqCp(&result->Z, &in->Z); 355 } 356 357 void EFqInf(EccPointJacobiFq* result) { 358 FqSet(&result->X, 0); 359 FqSet(&result->Y, 1); 360 FqSet(&result->Z, 0); 361 } 362 363 int EFqOnCurve(EccPointFq const* in) { 364 // test that Y^2 mod q == (X^3 + a*Z^4*X + b*Z^6) mod q 365 // This simplifies to: Y^2 mod q == (X^3 + 3) mod q 366 // since: Z = 1 367 // a = 0 368 // b = 3 369 FqElem t1; 370 FqElem t2; 371 FqSquare(&t1, &in->x); 372 FqMul(&t2, &in->x, &t1); 373 FqSquare(&t1, &in->y); 374 FqSub(&t1, &t1, &t2); 375 t1.limbs.word[0] -= 3; // check equal to curve b 376 // this operation will not always 377 // result in the same value as T1 - 3 378 // however it will always result in a correct 379 // value for the zero check below 380 return FqIsZero(&t1); 381 } 382 383 int EFqJOnCurve(EccPointJacobiFq const* in) { 384 FqElem fq1; 385 FqElem fq2; 386 387 FqSquare(&fq1, &in->Z); 388 FqSquare(&fq2, &fq1); 389 FqMul(&fq2, &fq2, &fq1); // T2 = Z^6 390 FqAdd(&fq1, &fq2, &fq2); 391 FqAdd(&fq1, &fq1, &fq2); // T1 = 3 * Z^6 392 FqSquare(&fq2, &in->X); 393 FqMul(&fq2, &fq2, &in->X); // T2 = X^3 394 FqAdd(&fq1, &fq1, &fq2); // T1 = X^3 + 3 Z^6 395 FqSquare(&fq2, &in->Y); 396 FqMul(&fq1, &fq1, &in->Z); 397 FqMul(&fq2, &fq2, &in->Z); 398 return FqEq(&fq1, &fq2); // check Y^2 = X^3 + 3 Z^6 399 } 400 401 int EFqJRand(EccPointJacobiFq* result, BitSupplier rnd_func, void* rnd_param) { 402 FqElem fq; 403 do { 404 if (!FqRand(&fq, rnd_func, rnd_param)) { 405 return 0; 406 } 407 } while (!EFqMakePoint((EccPointFq*)result, &fq)); 408 409 FqSet(&result->Z, 1); 410 411 return 1; 412 } 413