1 /*############################################################################ 2 # Copyright 2016-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 17 /*! 18 * \file 19 * \brief Pairing implementation. 20 */ 21 22 #include "epid/common/math/pairing.h" 23 #include <limits.h> 24 #include "epid/common/math/src/bignum-internal.h" 25 #include "epid/common/math/src/ecgroup-internal.h" 26 #include "epid/common/math/src/finitefield-internal.h" 27 #include "epid/common/math/src/pairing-internal.h" 28 #include "epid/common/src/memory.h" 29 #include "ext/ipp/include/ippcp.h" 30 31 /// Handle Ipp Errors with Break 32 #define BREAK_ON_IPP_ERROR(sts, ret) \ 33 { \ 34 IppStatus temp_sts = (sts); \ 35 if (ippStsNoErr != temp_sts) { \ 36 if (ippStsContextMatchErr == temp_sts) { \ 37 (ret) = kEpidMathErr; \ 38 } else { \ 39 (ret) = kEpidBadArgErr; \ 40 } \ 41 break; \ 42 } \ 43 } 44 /// Handle Ipp Errors with Return 45 #define RETURN_ON_IPP_ERROR(sts) \ 46 { \ 47 IppStatus temp_sts = (sts); \ 48 if (ippStsNoErr != temp_sts) { \ 49 if (ippStsContextMatchErr == temp_sts) { \ 50 return kEpidMathErr; \ 51 } else { \ 52 return kEpidBadArgErr; \ 53 } \ 54 } \ 55 } 56 /// Handle SDK Error with Break 57 #define BREAK_ON_EPID_ERROR(ret) \ 58 if (kEpidNoErr != (ret)) { \ 59 break; \ 60 } 61 62 #pragma pack(1) 63 /// Data for element in Fq 64 typedef struct FqElemDat { 65 Ipp32u x[sizeof(FqElemStr) / sizeof(Ipp32u)]; ///< element in Fq 66 } FqElemDat; 67 /// Data for element in Fq2 68 typedef struct Fq2ElemDat { 69 FqElemDat x[2]; ///< element in Fq2 70 } Fq2ElemDat; 71 /// Data for element in Fq2^3 72 typedef struct Fq6ElemDat { 73 Fq2ElemDat x[3]; ///< element in Fq6 74 } Fq6ElemDat; 75 /// Data for element in Fq2^3^2 76 typedef struct Fq12ElemDat { 77 Fq6ElemDat x[2]; ///< element in Fq12 78 } Fq12ElemDat; 79 #pragma pack() 80 81 // Forward Declarations 82 static EpidStatus FinalExp(PairingState* ps, FfElement* d, FfElement const* h); 83 84 static EpidStatus PiOp(PairingState* ps, FfElement* x_out, FfElement* y_out, 85 FfElement const* x, FfElement const* y, const int e); 86 87 static EpidStatus FrobeniusOp(PairingState* ps, FfElement* d_out, 88 FfElement const* a, const int e); 89 90 static EpidStatus Line(FiniteField* gt, FfElement* f, FfElement* x_out, 91 FfElement* y_out, FfElement* z_out, FfElement* z2_out, 92 FfElement const* px, FfElement const* py, 93 FfElement const* x, FfElement const* y, 94 FfElement const* z, FfElement const* z2, 95 FfElement const* qx, FfElement const* qy); 96 97 static EpidStatus Tangent(FiniteField* gt, FfElement* f, FfElement* x_out, 98 FfElement* y_out, FfElement* z_out, FfElement* z2_out, 99 FfElement const* px, FfElement const* py, 100 FfElement const* x, FfElement const* y, 101 FfElement const* z, FfElement const* z2); 102 103 static EpidStatus Ternary(int* s, int* n, int max_elements, BigNum const* x); 104 105 static int Bit(Ipp32u const* num, Ipp32u bit_index); 106 107 static EpidStatus MulXiFast(FfElement* e, FfElement const* a, PairingState* ps); 108 109 static EpidStatus MulV(FfElement* e, FfElement* a, PairingState* ps); 110 111 static EpidStatus Fq6MulGFpE2(FfElement* e, FfElement* a, FfElement* b0, 112 FfElement* b1, PairingState* ps); 113 114 static EpidStatus MulSpecial(FfElement* e, FfElement const* a, 115 FfElement const* b, PairingState* ps); 116 117 static EpidStatus SquareCyclotomic(PairingState* ps, FfElement* e_out, 118 FfElement const* a_in); 119 120 static EpidStatus ExpCyclotomic(PairingState* ps, FfElement* e, 121 FfElement const* a, BigNum const* b); 122 123 // Implementation 124 125 EpidStatus NewPairingState(EcGroup const* ga, EcGroup const* gb, 126 FiniteField* ff, BigNumStr const* t, bool neg, 127 PairingState** ps) { 128 EpidStatus result = kEpidErr; 129 FfElement* xi = NULL; 130 PairingState* pairing_state_ctx = NULL; 131 BigNum* e = NULL; 132 BigNum* one = NULL; 133 BigNum* six = NULL; 134 OctStr scratch_buffer = NULL; 135 do { 136 IppStatus sts = ippStsNoErr; 137 IppsGFpState* Fq6 = NULL; 138 IppsGFpState* Fq2 = NULL; 139 IppsGFpState* Fq = NULL; 140 FiniteField* Ffq6 = NULL; 141 FiniteField* Ffq2 = NULL; 142 FiniteField* Ffq = NULL; 143 Fq2ElemDat Fq6IrrPolynomial = {0}; 144 uint8_t one_str[] = {1}; 145 uint8_t six_str[] = {6}; 146 int i = 0; 147 int j = 0; 148 int bufferSize = 0; 149 int bitSize = 0; 150 // validate inputs 151 if (!ga || !gb || !ff || !t || !ps) { 152 result = kEpidBadArgErr; 153 break; 154 } 155 if (!ga->ipp_ec || !gb->ipp_ec || !ff->ipp_ff) { 156 result = kEpidBadArgErr; 157 break; 158 } 159 // get Fq6, Fq2, Fq 160 Ffq6 = ff->ground_ff; 161 if (!Ffq6) { 162 result = kEpidBadArgErr; 163 break; 164 } 165 Fq6 = Ffq6->ipp_ff; 166 Ffq2 = Ffq6->ground_ff; 167 if (!Ffq2) { 168 result = kEpidBadArgErr; 169 break; 170 } 171 Fq2 = Ffq2->ipp_ff; 172 Ffq = Ffq2->ground_ff; 173 if (!Ffq) { 174 result = kEpidBadArgErr; 175 break; 176 } 177 Fq = Ffq->ipp_ff; 178 // extract xi from Fq6 irr poly 179 result = NewFfElement(Ffq2, &xi); 180 BREAK_ON_EPID_ERROR(result); 181 result = WriteBigNum(Ffq6->modulus_0, sizeof(Fq6IrrPolynomial), 182 &Fq6IrrPolynomial); 183 BREAK_ON_EPID_ERROR(result); 184 result = SetFfElementOctString(&Fq6IrrPolynomial, sizeof(Fq6IrrPolynomial), 185 xi, Ffq2); 186 BREAK_ON_EPID_ERROR(result); 187 // first coefficent is -xi 188 sts = ippsGFpNeg(xi->ipp_ff_elem, xi->ipp_ff_elem, Fq2); 189 BREAK_ON_IPP_ERROR(sts, result); 190 191 pairing_state_ctx = (PairingState*)SAFE_ALLOC(sizeof(PairingState)); 192 if (!pairing_state_ctx) { 193 result = kEpidMemAllocErr; 194 break; 195 } 196 197 // 1. Set param(pairing) = (param(G1), param(G2), param(GT), t, neg) 198 pairing_state_ctx->ga = (EcGroup*)ga; 199 pairing_state_ctx->gb = (EcGroup*)gb; 200 pairing_state_ctx->ff = ff; 201 result = NewBigNum(sizeof(BigNumStr), &pairing_state_ctx->t); 202 BREAK_ON_EPID_ERROR(result); 203 result = ReadBigNum(t, sizeof(BigNumStr), pairing_state_ctx->t); 204 BREAK_ON_EPID_ERROR(result); 205 pairing_state_ctx->neg = neg; 206 pairing_state_ctx->Fq6 = Ffq6; 207 pairing_state_ctx->Fq2 = Ffq2; 208 pairing_state_ctx->Fq = Ffq; 209 // 2. Let g[0][0], ..., g[0][4], g[1][0], ..., g[1][4], g[2][0], ..., 210 // g[2][4] be 15 elements in Fq2. 211 for (i = 0; i < 3; i++) { 212 for (j = 0; j < 5; j++) { 213 result = NewFfElement(Ffq2, &pairing_state_ctx->g[i][j]); 214 BREAK_ON_EPID_ERROR(result); 215 } 216 } 217 // 3. Compute a big integer e = (q - 1)/6. 218 result = NewBigNum(sizeof(BigNumStr), &one); 219 BREAK_ON_EPID_ERROR(result); 220 result = ReadBigNum(one_str, sizeof(one_str), one); 221 BREAK_ON_EPID_ERROR(result); 222 result = NewBigNum(sizeof(BigNumStr), &e); 223 BREAK_ON_EPID_ERROR(result); 224 // q - 1 225 sts = ippsSub_BN(Ffq->modulus_0->ipp_bn, one->ipp_bn, e->ipp_bn); 226 BREAK_ON_IPP_ERROR(sts, result); 227 result = NewBigNum(sizeof(BigNumStr), &six); 228 BREAK_ON_EPID_ERROR(result); 229 result = ReadBigNum(six_str, sizeof(six_str), six); 230 BREAK_ON_EPID_ERROR(result); 231 // e = (q - 1)/6 232 // reusing one as remainder here 233 sts = ippsDiv_BN(e->ipp_bn, six->ipp_bn, e->ipp_bn, one->ipp_bn); 234 BREAK_ON_IPP_ERROR(sts, result); 235 // 4. Compute g[0][0] = Fq2.exp(xi, e). 236 sts = ippsRef_BN(0, &bitSize, 0, e->ipp_bn); 237 BREAK_ON_IPP_ERROR(sts, result); 238 sts = ippsGFpScratchBufferSize(1, bitSize, Fq2, &bufferSize); 239 BREAK_ON_IPP_ERROR(sts, result); 240 scratch_buffer = (OctStr)SAFE_ALLOC(bufferSize); 241 if (!scratch_buffer) { 242 result = kEpidMemAllocErr; 243 break; 244 } 245 sts = ippsGFpExp(xi->ipp_ff_elem, e->ipp_bn, 246 pairing_state_ctx->g[0][0]->ipp_ff_elem, Fq2, 247 scratch_buffer); 248 BREAK_ON_IPP_ERROR(sts, result); 249 // 5. For i = 0, ..., 4, compute 250 for (i = 0; i < 5; i++) { 251 // a. If i > 0, compute g[0][i] = Fq2.mul(g[0][i-1], g[0][0]). 252 if (i > 0) { 253 sts = ippsGFpMul(pairing_state_ctx->g[0][i - 1]->ipp_ff_elem, 254 pairing_state_ctx->g[0][0]->ipp_ff_elem, 255 pairing_state_ctx->g[0][i]->ipp_ff_elem, Fq2); 256 } 257 // b. Compute g[1][i] = Fq2.conjugate(g[0][i]), 258 sts = ippsGFpConj(pairing_state_ctx->g[0][i]->ipp_ff_elem, 259 pairing_state_ctx->g[1][i]->ipp_ff_elem, Fq2); 260 // c. Compute g[1][i] = Fq2.mul(g[0][i], g[1][i]), 261 sts = ippsGFpMul(pairing_state_ctx->g[0][i]->ipp_ff_elem, 262 pairing_state_ctx->g[1][i]->ipp_ff_elem, 263 pairing_state_ctx->g[1][i]->ipp_ff_elem, Fq2); 264 // d. Compute g[2][i] = Fq2.mul(g[0][i], g[1][i]). 265 sts = ippsGFpMul(pairing_state_ctx->g[0][i]->ipp_ff_elem, 266 pairing_state_ctx->g[1][i]->ipp_ff_elem, 267 pairing_state_ctx->g[2][i]->ipp_ff_elem, Fq2); 268 } 269 // 6. Save g[0][0], ..., g[0][4], g[1][0], ..., g[1][4], g[2][0], ..., 270 // g[2][4] 271 // for the pairing operations. 272 *ps = pairing_state_ctx; 273 result = kEpidNoErr; 274 } while (0); 275 SAFE_FREE(scratch_buffer) 276 DeleteBigNum(&six); 277 DeleteBigNum(&e); 278 DeleteBigNum(&one); 279 DeleteFfElement(&xi); 280 if (kEpidNoErr != result) { 281 if (pairing_state_ctx) { 282 int i = 0; 283 int j = 0; 284 for (i = 0; i < 3; i++) { 285 for (j = 0; j < 5; j++) { 286 DeleteFfElement(&pairing_state_ctx->g[i][j]); 287 } 288 } 289 DeleteBigNum(&pairing_state_ctx->t); 290 SAFE_FREE(pairing_state_ctx); 291 } 292 } 293 return result; 294 } 295 296 void DeletePairingState(PairingState** ps) { 297 if (!ps) { 298 return; 299 } 300 if (!*ps) { 301 return; 302 } 303 if (ps) { 304 if (*ps) { 305 int i = 0; 306 int j = 0; 307 for (i = 0; i < 3; i++) { 308 for (j = 0; j < 5; j++) { 309 DeleteFfElement(&(*ps)->g[i][j]); 310 } 311 } 312 DeleteBigNum(&(*ps)->t); 313 (*ps)->ga = NULL; 314 (*ps)->gb = NULL; 315 (*ps)->ff = NULL; 316 } 317 SAFE_FREE(*ps); 318 } 319 } 320 321 EpidStatus Pairing(PairingState* ps, EcPoint const* a, EcPoint const* b, 322 FfElement* d) { 323 EpidStatus result = kEpidErr; 324 FfElement* ax = NULL; 325 FfElement* ay = NULL; 326 FfElement* bx = NULL; 327 FfElement* by = NULL; 328 FfElement* x = NULL; 329 FfElement* y = NULL; 330 FfElement* z = NULL; 331 FfElement* z2 = NULL; 332 FfElement* bx_ = NULL; 333 FfElement* by_ = NULL; 334 FfElement* f = NULL; 335 BigNum* s = NULL; 336 BigNum* two = NULL; 337 BigNum* six = NULL; 338 FfElement* neg_qy = NULL; 339 340 do { 341 IppStatus sts = ippStsNoErr; 342 Ipp32u two_dat[] = {2}; 343 Ipp32u six_dat[] = {6}; 344 Ipp32u one_dat[] = {1}; 345 G1ElemStr first_val_str = {0}; 346 G2ElemStr second_val_str = {0}; 347 bool in_group = true; 348 int s_ternary[sizeof(BigNumStr) * CHAR_BIT] = {0}; 349 int i = 0; 350 int n = 0; 351 // check parameters 352 if (!ps || !d || !a || !b) { 353 result = kEpidBadArgErr; 354 break; 355 } 356 if (!ps->Fq || !ps->Fq2) { 357 result = kEpidBadArgErr; 358 break; 359 } 360 if (!d->ipp_ff_elem || !a->ipp_ec_pt || !b->ipp_ec_pt || !ps->ff || 361 !ps->ff->ipp_ff || !ps->Fq->ipp_ff || !ps->Fq2->ipp_ff || !ps->t || 362 !ps->t->ipp_bn || !ps->ga || !ps->ga->ipp_ec || !ps->gb || 363 !ps->gb->ipp_ec) { 364 result = kEpidBadArgErr; 365 break; 366 } 367 // Let ax, ay be elements in Fq. Let bx, by, x, y, z, z2, bx', by' 368 // be elements in Fq2. Let f be a variable in GT. 369 result = NewFfElement(ps->Fq, &ax); 370 BREAK_ON_EPID_ERROR(result); 371 result = NewFfElement(ps->Fq, &ay); 372 BREAK_ON_EPID_ERROR(result); 373 result = NewFfElement(ps->Fq2, &bx); 374 BREAK_ON_EPID_ERROR(result); 375 result = NewFfElement(ps->Fq2, &by); 376 BREAK_ON_EPID_ERROR(result); 377 result = NewFfElement(ps->Fq2, &x); 378 BREAK_ON_EPID_ERROR(result); 379 result = NewFfElement(ps->Fq2, &y); 380 BREAK_ON_EPID_ERROR(result); 381 result = NewFfElement(ps->Fq2, &z); 382 BREAK_ON_EPID_ERROR(result); 383 result = NewFfElement(ps->Fq2, &z2); 384 BREAK_ON_EPID_ERROR(result); 385 result = NewFfElement(ps->Fq2, &bx_); 386 BREAK_ON_EPID_ERROR(result); 387 result = NewFfElement(ps->Fq2, &by_); 388 BREAK_ON_EPID_ERROR(result); 389 result = NewFfElement(ps->ff, &f); 390 BREAK_ON_EPID_ERROR(result); 391 result = NewFfElement(ps->Fq2, &neg_qy); 392 BREAK_ON_EPID_ERROR(result); 393 394 // 1. If neg = 0, compute integer s = 6t + 2, otherwise, compute 395 // s = 6t - 2 396 result = NewBigNum(sizeof(BigNumStr), &s); 397 BREAK_ON_EPID_ERROR(result); 398 result = NewBigNum(sizeof(BigNumStr), &two); 399 BREAK_ON_EPID_ERROR(result); 400 sts = ippsSet_BN(IppsBigNumPOS, sizeof(two_dat) / sizeof(Ipp32u), two_dat, 401 two->ipp_bn); 402 BREAK_ON_IPP_ERROR(sts, result); 403 result = NewBigNum(sizeof(BigNumStr), &six); 404 BREAK_ON_EPID_ERROR(result); 405 sts = ippsSet_BN(IppsBigNumPOS, sizeof(six_dat) / sizeof(Ipp32u), six_dat, 406 six->ipp_bn); 407 BREAK_ON_IPP_ERROR(sts, result); 408 sts = ippsMul_BN(six->ipp_bn, ps->t->ipp_bn, s->ipp_bn); 409 BREAK_ON_IPP_ERROR(sts, result); 410 if (ps->neg) { 411 sts = ippsSub_BN(s->ipp_bn, two->ipp_bn, s->ipp_bn); 412 BREAK_ON_IPP_ERROR(sts, result); 413 } else { 414 sts = ippsAdd_BN(s->ipp_bn, two->ipp_bn, s->ipp_bn); 415 BREAK_ON_IPP_ERROR(sts, result); 416 } 417 // 2. Let sn...s1s0 be the ternary representation of s, that is s = 418 // s0 + 2*s1 + ... + 2^n*sn, where si is in {-1, 0, 1}. 419 result = 420 Ternary(s_ternary, &n, sizeof(s_ternary) / sizeof(s_ternary[0]), s); 421 BREAK_ON_EPID_ERROR(result); 422 // 3. Set (ax, ay) = E(Fq).outputPoint(a) 423 // check if a is in ga that was used to create ps 424 result = WriteEcPoint(ps->ga, a, &first_val_str, sizeof(first_val_str)); 425 BREAK_ON_EPID_ERROR(result); 426 result = 427 EcInGroup(ps->ga, &first_val_str, sizeof(first_val_str), &in_group); 428 BREAK_ON_EPID_ERROR(result); 429 if (false == in_group) { 430 result = kEpidBadArgErr; 431 break; 432 } 433 sts = ippsGFpECGetPoint(a->ipp_ec_pt, ax->ipp_ff_elem, ay->ipp_ff_elem, 434 ps->ga->ipp_ec); 435 BREAK_ON_IPP_ERROR(sts, result); 436 // 4. Set (bx, by) = E(Fq2).outputPoint(b). 437 // check if b is in gb that was used to create ps 438 result = WriteEcPoint(ps->gb, b, &second_val_str, sizeof(second_val_str)); 439 BREAK_ON_EPID_ERROR(result); 440 result = 441 EcInGroup(ps->gb, &second_val_str, sizeof(second_val_str), &in_group); 442 BREAK_ON_EPID_ERROR(result); 443 if (false == in_group) { 444 result = kEpidBadArgErr; 445 break; 446 } 447 sts = ippsGFpECGetPoint(b->ipp_ec_pt, bx->ipp_ff_elem, by->ipp_ff_elem, 448 ps->gb->ipp_ec); 449 BREAK_ON_IPP_ERROR(sts, result); 450 // 5. Set X = bx, Y = by, Z = Z2 = 1. 451 sts = ippsGFpCpyElement(bx->ipp_ff_elem, x->ipp_ff_elem, ps->Fq2->ipp_ff); 452 BREAK_ON_IPP_ERROR(sts, result); 453 sts = ippsGFpCpyElement(by->ipp_ff_elem, y->ipp_ff_elem, ps->Fq2->ipp_ff); 454 BREAK_ON_IPP_ERROR(sts, result); 455 sts = ippsGFpSetElement(one_dat, sizeof(one_dat) / sizeof(Ipp32u), 456 z->ipp_ff_elem, ps->Fq2->ipp_ff); 457 BREAK_ON_IPP_ERROR(sts, result); 458 sts = ippsGFpSetElement(one_dat, sizeof(one_dat) / sizeof(Ipp32u), 459 z2->ipp_ff_elem, ps->Fq2->ipp_ff); 460 BREAK_ON_IPP_ERROR(sts, result); 461 // 6. Set d = 1. 462 sts = ippsGFpSetElement(one_dat, sizeof(one_dat) / sizeof(Ipp32u), 463 d->ipp_ff_elem, ps->ff->ipp_ff); 464 BREAK_ON_IPP_ERROR(sts, result); 465 // 7. For i = n-1, ..., 0, do the following: 466 for (i = n - 1; i >= 0; i--) { 467 // a. Set (f, x, y, z, z2) = tangent(ax, ay, x, y, z, z2), 468 result = Tangent(ps->ff, f, x, y, z, z2, ax, ay, x, y, z, z2); 469 BREAK_ON_EPID_ERROR(result); 470 // b. Set d = Fq12.square(d), 471 sts = ippsGFpMul(d->ipp_ff_elem, d->ipp_ff_elem, d->ipp_ff_elem, 472 ps->ff->ipp_ff); 473 BREAK_ON_IPP_ERROR(sts, result); 474 // c. Set d = Fq12.mulSpecial(d, f), 475 result = MulSpecial(d, d, f, ps); 476 BREAK_ON_EPID_ERROR(result); 477 // d. If s[i] = -1 then 478 if (-1 == s_ternary[i]) { 479 // i. Set (f, x, y, z, z2) = line(ax, ay, x, y, z, z2, bx, 480 // -by), 481 BREAK_ON_EPID_ERROR(result); 482 sts = ippsGFpNeg(by->ipp_ff_elem, neg_qy->ipp_ff_elem, ps->Fq2->ipp_ff); 483 BREAK_ON_IPP_ERROR(sts, result); 484 result = Line(ps->ff, f, x, y, z, z2, ax, ay, x, y, z, z2, bx, neg_qy); 485 BREAK_ON_EPID_ERROR(result); 486 // ii. Set d = Fq12.mulSpecial(d, f). 487 result = MulSpecial(d, d, f, ps); 488 BREAK_ON_EPID_ERROR(result); 489 } 490 // e. If s[i] = 1 then 491 if (1 == s_ternary[i]) { 492 // i. Set (f, x, y, z, z2) = line(ax, ay, x, y, z, z2, bx, 493 // by), 494 result = Line(ps->ff, f, x, y, z, z2, ax, ay, x, y, z, z2, bx, by); 495 BREAK_ON_EPID_ERROR(result); 496 // ii. Set d = Fq12.mulSpecial(d, f). 497 result = MulSpecial(d, d, f, ps); 498 BREAK_ON_EPID_ERROR(result); 499 } 500 } 501 502 // 8. if neg = true, 503 if (ps->neg) { 504 // a. Set Y = Fq2.negate(y), 505 sts = ippsGFpNeg(y->ipp_ff_elem, y->ipp_ff_elem, ps->Fq2->ipp_ff); 506 BREAK_ON_IPP_ERROR(sts, result); 507 // b. Set d = Fq12.conjugate(d). 508 sts = ippsGFpConj(d->ipp_ff_elem, d->ipp_ff_elem, ps->ff->ipp_ff); 509 BREAK_ON_IPP_ERROR(sts, result); 510 } 511 // 9. Set (bx', by') = Pi-op(bx, by, 1). 512 result = PiOp(ps, bx_, by_, bx, by, 1); 513 BREAK_ON_EPID_ERROR(result); 514 // 10. Set (f, x, y, z, z2) = line(ax, ay, x, y, z, z2, bx', by'). 515 result = Line(ps->ff, f, x, y, z, z2, ax, ay, x, y, z, z2, bx_, by_); 516 BREAK_ON_EPID_ERROR(result); 517 // 11. Set d = Fq12.mulSpecial(d, f). 518 result = MulSpecial(d, d, f, ps); 519 BREAK_ON_EPID_ERROR(result); 520 // 12. Set (bx', by') = piOp(bx, by, 2). 521 result = PiOp(ps, bx_, by_, bx, by, 2); 522 BREAK_ON_EPID_ERROR(result); 523 // 13. Set by' = Fq2.negate(by'). 524 sts = ippsGFpNeg(by_->ipp_ff_elem, by_->ipp_ff_elem, ps->Fq2->ipp_ff); 525 BREAK_ON_IPP_ERROR(sts, result); 526 // 14. Set (f, x, y, z, z2) = line(ax, ay, x, y, z, z2, bx', by'). 527 result = Line(ps->ff, f, x, y, z, z2, ax, ay, x, y, z, z2, bx_, by_); 528 BREAK_ON_EPID_ERROR(result); 529 // 15. Set d = Fq12.mulSpecial(d, f). 530 result = MulSpecial(d, d, f, ps); 531 BREAK_ON_EPID_ERROR(result); 532 // 16. Set d = finalExp(d). 533 result = FinalExp(ps, d, d); 534 BREAK_ON_EPID_ERROR(result); 535 // 17. Return d. 536 result = kEpidNoErr; 537 } while (0); 538 539 DeleteFfElement(&ax); 540 DeleteFfElement(&ay); 541 DeleteFfElement(&bx); 542 DeleteFfElement(&by); 543 DeleteFfElement(&x); 544 DeleteFfElement(&y); 545 DeleteFfElement(&z); 546 DeleteFfElement(&z2); 547 DeleteFfElement(&bx_); 548 DeleteFfElement(&by_); 549 DeleteFfElement(&f); 550 DeleteFfElement(&neg_qy); 551 552 DeleteBigNum(&s); 553 DeleteBigNum(&two); 554 DeleteBigNum(&six); 555 556 return result; 557 } 558 559 /* 560 d = finalExp(h) 561 Input: h (an element in GT) 562 Output: d (an element in GT) where d = GT.exp(h, (q^12-1)/p) 563 */ 564 static EpidStatus FinalExp(PairingState* ps, FfElement* d, FfElement const* h) { 565 EpidStatus result = kEpidErr; 566 FfElement* f = NULL; 567 FfElement* f1 = NULL; 568 FfElement* f2 = NULL; 569 FfElement* f3 = NULL; 570 FfElement* ft1 = NULL; 571 FfElement* ft2 = NULL; 572 FfElement* ft3 = NULL; 573 FfElement* fp1 = NULL; 574 FfElement* fp2 = NULL; 575 FfElement* fp3 = NULL; 576 FfElement* y0 = NULL; 577 FfElement* y1 = NULL; 578 FfElement* y2 = NULL; 579 FfElement* y3 = NULL; 580 FfElement* y4 = NULL; 581 FfElement* y5 = NULL; 582 FfElement* y6 = NULL; 583 FfElement* t0 = NULL; 584 FfElement* t1 = NULL; 585 do { 586 IppStatus sts = ippStsNoErr; 587 // Check parameters 588 if (!ps || !d || !h) { 589 result = kEpidBadArgErr; 590 break; 591 } 592 if (!d->ipp_ff_elem || !h->ipp_ff_elem || !ps->ff || !ps->ff->ipp_ff || 593 !ps->t || !ps->t->ipp_bn) { 594 result = kEpidBadArgErr; 595 break; 596 } 597 // Let f, f1, f2, f3, ft1, ft2, ft3, fp1, fp2, fp3, y0, y1, y2, 598 // y3, y4, y5, y6, t0, t1 be temporary variables in GT. All the 599 // following operations are computed in Fq12 unless explicitly 600 // specified. 601 result = NewFfElement(ps->ff, &f); 602 BREAK_ON_EPID_ERROR(result); 603 result = NewFfElement(ps->ff, &f1); 604 BREAK_ON_EPID_ERROR(result); 605 result = NewFfElement(ps->ff, &f2); 606 BREAK_ON_EPID_ERROR(result); 607 result = NewFfElement(ps->ff, &f3); 608 BREAK_ON_EPID_ERROR(result); 609 result = NewFfElement(ps->ff, &ft1); 610 BREAK_ON_EPID_ERROR(result); 611 result = NewFfElement(ps->ff, &ft2); 612 BREAK_ON_EPID_ERROR(result); 613 result = NewFfElement(ps->ff, &ft3); 614 BREAK_ON_EPID_ERROR(result); 615 result = NewFfElement(ps->ff, &fp1); 616 BREAK_ON_EPID_ERROR(result); 617 result = NewFfElement(ps->ff, &fp2); 618 BREAK_ON_EPID_ERROR(result); 619 result = NewFfElement(ps->ff, &fp3); 620 BREAK_ON_EPID_ERROR(result); 621 result = NewFfElement(ps->ff, &y0); 622 BREAK_ON_EPID_ERROR(result); 623 result = NewFfElement(ps->ff, &y1); 624 BREAK_ON_EPID_ERROR(result); 625 result = NewFfElement(ps->ff, &y2); 626 BREAK_ON_EPID_ERROR(result); 627 result = NewFfElement(ps->ff, &y3); 628 BREAK_ON_EPID_ERROR(result); 629 result = NewFfElement(ps->ff, &y4); 630 BREAK_ON_EPID_ERROR(result); 631 result = NewFfElement(ps->ff, &y5); 632 BREAK_ON_EPID_ERROR(result); 633 result = NewFfElement(ps->ff, &y6); 634 BREAK_ON_EPID_ERROR(result); 635 result = NewFfElement(ps->ff, &t0); 636 BREAK_ON_EPID_ERROR(result); 637 result = NewFfElement(ps->ff, &t1); 638 BREAK_ON_EPID_ERROR(result); 639 // 1. Set f1 = Fq12.conjugate(h). 640 sts = ippsGFpConj(h->ipp_ff_elem, f1->ipp_ff_elem, ps->ff->ipp_ff); 641 BREAK_ON_IPP_ERROR(sts, result); 642 // 2. Set f2 = Fq12.inverse(h). 643 sts = ippsGFpInv(h->ipp_ff_elem, f2->ipp_ff_elem, ps->ff->ipp_ff); 644 BREAK_ON_IPP_ERROR(sts, result); 645 // 3. Set f = f1 * f2. 646 sts = ippsGFpMul(f1->ipp_ff_elem, f2->ipp_ff_elem, f->ipp_ff_elem, 647 ps->ff->ipp_ff); 648 BREAK_ON_IPP_ERROR(sts, result); 649 // 4. Set f3 = frobeniusOp(f, 2). 650 result = FrobeniusOp(ps, f3, f, 2); 651 BREAK_ON_EPID_ERROR(result); 652 // 5. Set f = f3 * f. 653 sts = ippsGFpMul(f3->ipp_ff_elem, f->ipp_ff_elem, f->ipp_ff_elem, 654 ps->ff->ipp_ff); 655 BREAK_ON_IPP_ERROR(sts, result); 656 // 6. Set ft1 = Fq12.expCyclotomic (f, t). 657 result = ExpCyclotomic(ps, ft1, f, ps->t); 658 BREAK_ON_EPID_ERROR(result); 659 // 7. If neg = true, ft1 = Fq12.conjugate(ft1). 660 if (ps->neg) { 661 sts = ippsGFpConj(ft1->ipp_ff_elem, ft1->ipp_ff_elem, ps->ff->ipp_ff); 662 BREAK_ON_IPP_ERROR(sts, result); 663 } 664 // 8. Set ft2 = Fq12.expCyclotomic (ft1, t). 665 result = ExpCyclotomic(ps, ft2, ft1, ps->t); 666 BREAK_ON_EPID_ERROR(result); 667 // 9. If neg = true, ft2 = Fq12.conjugate(ft2). 668 if (ps->neg) { 669 sts = ippsGFpConj(ft2->ipp_ff_elem, ft2->ipp_ff_elem, ps->ff->ipp_ff); 670 BREAK_ON_IPP_ERROR(sts, result); 671 } 672 // 10. Set ft3 = Fq12.expCyclotomic (ft2, t). 673 result = ExpCyclotomic(ps, ft3, ft2, ps->t); 674 BREAK_ON_EPID_ERROR(result); 675 // 11. If neg = true, ft3 = Fq12.conjugate(ft3). 676 if (ps->neg) { 677 sts = ippsGFpConj(ft3->ipp_ff_elem, ft3->ipp_ff_elem, ps->ff->ipp_ff); 678 BREAK_ON_IPP_ERROR(sts, result); 679 } 680 // 12. Set fp1 = frobeniusOp(f, 1). 681 result = FrobeniusOp(ps, fp1, f, 1); 682 BREAK_ON_EPID_ERROR(result); 683 // 13. Set fp2 = frobeniusOp(f, 2). 684 result = FrobeniusOp(ps, fp2, f, 2); 685 BREAK_ON_EPID_ERROR(result); 686 // 14. Set fp3 = frobeniusOp(f, 3). 687 result = FrobeniusOp(ps, fp3, f, 3); 688 BREAK_ON_EPID_ERROR(result); 689 // 15. Set y0 = fp1 * fp2 * fp3. 690 sts = ippsGFpMul(fp1->ipp_ff_elem, fp2->ipp_ff_elem, y0->ipp_ff_elem, 691 ps->ff->ipp_ff); 692 BREAK_ON_IPP_ERROR(sts, result); 693 sts = ippsGFpMul(y0->ipp_ff_elem, fp3->ipp_ff_elem, y0->ipp_ff_elem, 694 ps->ff->ipp_ff); 695 BREAK_ON_IPP_ERROR(sts, result); 696 // 16. Set y1 = Fq12.conjugate(f). 697 sts = ippsGFpConj(f->ipp_ff_elem, y1->ipp_ff_elem, ps->ff->ipp_ff); 698 BREAK_ON_IPP_ERROR(sts, result); 699 // 17. Set y2 = frobeniusOp(ft2, 2). 700 result = FrobeniusOp(ps, y2, ft2, 2); 701 BREAK_ON_EPID_ERROR(result); 702 // 18. Set y3 = frobeniusOp(ft1, 1). 703 result = FrobeniusOp(ps, y3, ft1, 1); 704 BREAK_ON_EPID_ERROR(result); 705 // 19. Set y3 = Fq12.conjugate(y3). 706 sts = ippsGFpConj(y3->ipp_ff_elem, y3->ipp_ff_elem, ps->ff->ipp_ff); 707 BREAK_ON_IPP_ERROR(sts, result); 708 // 20. Set y4 = frobeniusOp(ft2, 1). 709 result = FrobeniusOp(ps, y4, ft2, 1); 710 BREAK_ON_EPID_ERROR(result); 711 // 21. Set y4 = y4 * ft1. 712 sts = ippsGFpMul(y4->ipp_ff_elem, ft1->ipp_ff_elem, y4->ipp_ff_elem, 713 ps->ff->ipp_ff); 714 BREAK_ON_IPP_ERROR(sts, result); 715 // 22. Set y4 = Fq12.conjugate(y4). 716 sts = ippsGFpConj(y4->ipp_ff_elem, y4->ipp_ff_elem, ps->ff->ipp_ff); 717 BREAK_ON_IPP_ERROR(sts, result); 718 // 23. Set y5 = Fq12.conjugate(ft2). 719 sts = ippsGFpConj(ft2->ipp_ff_elem, y5->ipp_ff_elem, ps->ff->ipp_ff); 720 BREAK_ON_IPP_ERROR(sts, result); 721 // 24. Set y6 = frobeniusOp(ft3, 1). 722 result = FrobeniusOp(ps, y6, ft3, 1); 723 BREAK_ON_EPID_ERROR(result); 724 // 25. Set y6 = y6 * ft3. 725 sts = ippsGFpMul(y6->ipp_ff_elem, ft3->ipp_ff_elem, y6->ipp_ff_elem, 726 ps->ff->ipp_ff); 727 BREAK_ON_IPP_ERROR(sts, result); 728 // 26. Set y6 = Fq12.conjugate(y6). 729 sts = ippsGFpConj(y6->ipp_ff_elem, y6->ipp_ff_elem, ps->ff->ipp_ff); 730 BREAK_ON_IPP_ERROR(sts, result); 731 // 27. Set t0 = Fq12.squareCyclotomic(y6). 732 result = SquareCyclotomic(ps, t0, y6); 733 BREAK_ON_EPID_ERROR(result); 734 // 28. Set t0 = t0 * y4 * y5. 735 sts = ippsGFpMul(t0->ipp_ff_elem, y4->ipp_ff_elem, t0->ipp_ff_elem, 736 ps->ff->ipp_ff); 737 BREAK_ON_IPP_ERROR(sts, result); 738 sts = ippsGFpMul(t0->ipp_ff_elem, y5->ipp_ff_elem, t0->ipp_ff_elem, 739 ps->ff->ipp_ff); 740 BREAK_ON_IPP_ERROR(sts, result); 741 // 29. Set t1 = y3 * y5 * t0. 742 sts = ippsGFpMul(y3->ipp_ff_elem, y5->ipp_ff_elem, t1->ipp_ff_elem, 743 ps->ff->ipp_ff); 744 BREAK_ON_IPP_ERROR(sts, result); 745 sts = ippsGFpMul(t1->ipp_ff_elem, t0->ipp_ff_elem, t1->ipp_ff_elem, 746 ps->ff->ipp_ff); 747 BREAK_ON_IPP_ERROR(sts, result); 748 // 30. Set t0 = t0 * y2. 749 sts = ippsGFpMul(t0->ipp_ff_elem, y2->ipp_ff_elem, t0->ipp_ff_elem, 750 ps->ff->ipp_ff); 751 BREAK_ON_IPP_ERROR(sts, result); 752 // 31. Set t1 = Fq12.squareCyclotomic(t1). 753 result = SquareCyclotomic(ps, t1, t1); 754 BREAK_ON_EPID_ERROR(result); 755 // 32. Set t1 = t1 * t0. 756 sts = ippsGFpMul(t1->ipp_ff_elem, t0->ipp_ff_elem, t1->ipp_ff_elem, 757 ps->ff->ipp_ff); 758 BREAK_ON_IPP_ERROR(sts, result); 759 // 33. Set t1 = Fq12.squareCyclotomic(t1). 760 result = SquareCyclotomic(ps, t1, t1); 761 BREAK_ON_EPID_ERROR(result); 762 // 34. Set t0 = t1 * y1. 763 sts = ippsGFpMul(t1->ipp_ff_elem, y1->ipp_ff_elem, t0->ipp_ff_elem, 764 ps->ff->ipp_ff); 765 BREAK_ON_IPP_ERROR(sts, result); 766 // 35. Set t1 = t1 * y0. 767 sts = ippsGFpMul(t1->ipp_ff_elem, y0->ipp_ff_elem, t1->ipp_ff_elem, 768 ps->ff->ipp_ff); 769 BREAK_ON_IPP_ERROR(sts, result); 770 // 36. Set t0 = Fq12.squareCyclotomic(t0). 771 result = SquareCyclotomic(ps, t0, t0); 772 BREAK_ON_EPID_ERROR(result); 773 // 37. Set d = t1 * t0. 774 sts = ippsGFpMul(t1->ipp_ff_elem, t0->ipp_ff_elem, d->ipp_ff_elem, 775 ps->ff->ipp_ff); 776 BREAK_ON_IPP_ERROR(sts, result); 777 // 38. Return d. 778 result = kEpidNoErr; 779 } while (0); 780 781 DeleteFfElement(&f); 782 DeleteFfElement(&f1); 783 DeleteFfElement(&f2); 784 DeleteFfElement(&f3); 785 DeleteFfElement(&ft1); 786 DeleteFfElement(&ft2); 787 DeleteFfElement(&ft3); 788 DeleteFfElement(&fp1); 789 DeleteFfElement(&fp2); 790 DeleteFfElement(&fp3); 791 DeleteFfElement(&y0); 792 DeleteFfElement(&y1); 793 DeleteFfElement(&y2); 794 DeleteFfElement(&y3); 795 DeleteFfElement(&y4); 796 DeleteFfElement(&y5); 797 DeleteFfElement(&y6); 798 DeleteFfElement(&t0); 799 DeleteFfElement(&t1); 800 801 return result; 802 } 803 804 /* 805 (x', y') = piOp(x, y, e) 806 Input: x, y (elements in Fq2), e (an integer of value 1 or 2) 807 Output: x', y' (elements in Fq2) 808 */ 809 static EpidStatus PiOp(PairingState* ps, FfElement* x_out, FfElement* y_out, 810 FfElement const* x, FfElement const* y, const int e) { 811 IppStatus sts = ippStsNoErr; 812 IppsGFpState* Fq2 = 0; 813 IppsGFpState* Fq6 = 0; 814 FiniteField* Ffq12 = 0; 815 FiniteField* Ffq6 = 0; 816 FiniteField* Ffq2 = 0; 817 // check parameters 818 if (!ps || !x_out || !y_out || !x || !y) { 819 return kEpidBadArgErr; 820 } 821 if (e < 1 || e > 3) { 822 return kEpidBadArgErr; 823 } 824 Ffq12 = ps->ff; 825 // get Fq6, Fq2 826 if (!Ffq12) { 827 return kEpidBadArgErr; 828 } 829 Ffq6 = Ffq12->ground_ff; 830 if (!Ffq6) { 831 return kEpidBadArgErr; 832 } 833 Fq6 = Ffq6->ipp_ff; 834 Ffq2 = Ffq6->ground_ff; 835 if (!Ffq2) { 836 return kEpidBadArgErr; 837 } 838 Fq2 = Ffq2->ipp_ff; 839 // 1. Set x' = x and y' = y. 840 sts = ippsGFpCpyElement(x->ipp_ff_elem, x_out->ipp_ff_elem, Fq2); 841 RETURN_ON_IPP_ERROR(sts); 842 sts = ippsGFpCpyElement(y->ipp_ff_elem, y_out->ipp_ff_elem, Fq2); 843 RETURN_ON_IPP_ERROR(sts); 844 if (1 == e) { 845 // 2. If e = 1, 846 // a. Compute x' = Fq2.conjugate(x'). 847 sts = ippsGFpConj(x_out->ipp_ff_elem, x_out->ipp_ff_elem, Fq2); 848 RETURN_ON_IPP_ERROR(sts); 849 // b. Compute y' = Fq2.conjugate(y'). 850 sts = ippsGFpConj(y_out->ipp_ff_elem, y_out->ipp_ff_elem, Fq2); 851 RETURN_ON_IPP_ERROR(sts); 852 } 853 // 3. Compute x' = Fq2.mul(x', g[e-1][1]). 854 sts = ippsGFpMul(x_out->ipp_ff_elem, ps->g[e - 1][1]->ipp_ff_elem, 855 x_out->ipp_ff_elem, Fq2); 856 RETURN_ON_IPP_ERROR(sts); 857 // 4. Compute y' = Fq2.mul(y', g[e-1][2]). 858 sts = ippsGFpMul(y_out->ipp_ff_elem, ps->g[e - 1][2]->ipp_ff_elem, 859 y_out->ipp_ff_elem, Fq2); 860 RETURN_ON_IPP_ERROR(sts); 861 // 5. Return (x', y'). 862 return kEpidNoErr; 863 } 864 865 /* 866 d = frobeniusOp(a, e) 867 Input: a (an element in GT), e (an integer of value 1, 2, or 3) 868 Output: d (an element in GT) such that d = GT.exp(a, qe) 869 870 */ 871 static EpidStatus FrobeniusOp(PairingState* ps, FfElement* d_out, 872 FfElement const* a, const int e) { 873 EpidStatus result = kEpidErr; 874 FfElement* d[6] = {0}; 875 size_t i = 0; 876 Fq12ElemDat a_dat = {0}; 877 Fq12ElemDat d_dat = {0}; 878 do { 879 IppStatus sts = ippStsNoErr; 880 // check parameters 881 if (!ps || !d_out || !a) { 882 return kEpidBadArgErr; 883 } 884 if (!ps->ff || !ps->Fq2) { 885 return kEpidBadArgErr; 886 } 887 if (e < 1 || e > 3 || !d_out->ipp_ff_elem || !a->ipp_ff_elem || 888 !ps->ff->ipp_ff || !ps->Fq2->ipp_ff) { 889 return kEpidBadArgErr; 890 } 891 892 for (i = 0; i < sizeof(d) / sizeof(FfElement*); i++) { 893 result = NewFfElement(ps->Fq2, &d[i]); 894 BREAK_ON_EPID_ERROR(result); 895 } 896 897 // 1. Let a = ((a[0], a[2], a[4]), (a[1], a[3], a[5])). 898 sts = ippsGFpGetElement(a->ipp_ff_elem, (BNU)&a_dat, 899 sizeof(a_dat) / sizeof(Ipp32u), ps->ff->ipp_ff); 900 BREAK_ON_IPP_ERROR(sts, result); 901 // 2. Let d = ((d[0], d[2], d[4]), (d[1], d[3], d[5])). 902 // 3. For i = 0, ..., 5, 903 // a. set d[i] = a[i]. 904 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0].x[0], 905 sizeof(a_dat.x[0].x[0]) / sizeof(Ipp32u), 906 d[0]->ipp_ff_elem, ps->Fq2->ipp_ff); 907 BREAK_ON_IPP_ERROR(sts, result); 908 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0].x[1], 909 sizeof(a_dat.x[0].x[1]) / sizeof(Ipp32u), 910 d[2]->ipp_ff_elem, ps->Fq2->ipp_ff); 911 BREAK_ON_IPP_ERROR(sts, result); 912 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0].x[2], 913 sizeof(a_dat.x[0].x[2]) / sizeof(Ipp32u), 914 d[4]->ipp_ff_elem, ps->Fq2->ipp_ff); 915 BREAK_ON_IPP_ERROR(sts, result); 916 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1].x[0], 917 sizeof(a_dat.x[1].x[0]) / sizeof(Ipp32u), 918 d[1]->ipp_ff_elem, ps->Fq2->ipp_ff); 919 BREAK_ON_IPP_ERROR(sts, result); 920 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1].x[1], 921 sizeof(a_dat.x[1].x[1]) / sizeof(Ipp32u), 922 d[3]->ipp_ff_elem, ps->Fq2->ipp_ff); 923 BREAK_ON_IPP_ERROR(sts, result); 924 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1].x[2], 925 sizeof(a_dat.x[1].x[2]) / sizeof(Ipp32u), 926 d[5]->ipp_ff_elem, ps->Fq2->ipp_ff); 927 BREAK_ON_IPP_ERROR(sts, result); 928 929 // b. If e = 1 or 3, set d[i] = Fq2.conjugate(d[i]). 930 if (1 == e || 3 == e) { 931 for (i = 0; i < sizeof(d) / sizeof(FfElement*); i++) { 932 sts = 933 ippsGFpConj(d[i]->ipp_ff_elem, d[i]->ipp_ff_elem, ps->Fq2->ipp_ff); 934 BREAK_ON_IPP_ERROR(sts, result); 935 } 936 } 937 // 4. For i = 1, ..., 5, compute d[i] = Fq2.mul(d[i], g[e-1][i-1]). 938 for (i = 1; i < sizeof(d) / sizeof(FfElement*); i++) { 939 sts = ippsGFpMul(d[i]->ipp_ff_elem, ps->g[e - 1][i - 1]->ipp_ff_elem, 940 d[i]->ipp_ff_elem, ps->Fq2->ipp_ff); 941 BREAK_ON_IPP_ERROR(sts, result); 942 } 943 // 5. Return d. 944 sts = ippsGFpGetElement(d[0]->ipp_ff_elem, (BNU)&d_dat.x[0].x[0], 945 sizeof(d_dat.x[0].x[0]) / sizeof(Ipp32u), 946 ps->Fq2->ipp_ff); 947 BREAK_ON_IPP_ERROR(sts, result); 948 sts = ippsGFpGetElement(d[2]->ipp_ff_elem, (BNU)&d_dat.x[0].x[1], 949 sizeof(d_dat.x[0].x[0]) / sizeof(Ipp32u), 950 ps->Fq2->ipp_ff); 951 BREAK_ON_IPP_ERROR(sts, result); 952 sts = ippsGFpGetElement(d[4]->ipp_ff_elem, (BNU)&d_dat.x[0].x[2], 953 sizeof(d_dat.x[0].x[0]) / sizeof(Ipp32u), 954 ps->Fq2->ipp_ff); 955 BREAK_ON_IPP_ERROR(sts, result); 956 sts = ippsGFpGetElement(d[1]->ipp_ff_elem, (BNU)&d_dat.x[1].x[0], 957 sizeof(d_dat.x[1].x[0]) / sizeof(Ipp32u), 958 ps->Fq2->ipp_ff); 959 BREAK_ON_IPP_ERROR(sts, result); 960 sts = ippsGFpGetElement(d[3]->ipp_ff_elem, (BNU)&d_dat.x[1].x[1], 961 sizeof(d_dat.x[1].x[0]) / sizeof(Ipp32u), 962 ps->Fq2->ipp_ff); 963 BREAK_ON_IPP_ERROR(sts, result); 964 sts = ippsGFpGetElement(d[5]->ipp_ff_elem, (BNU)&d_dat.x[1].x[2], 965 sizeof(d_dat.x[1].x[0]) / sizeof(Ipp32u), 966 ps->Fq2->ipp_ff); 967 BREAK_ON_IPP_ERROR(sts, result); 968 sts = ippsGFpSetElement((Ipp32u*)&d_dat, sizeof(d_dat) / sizeof(Ipp32u), 969 d_out->ipp_ff_elem, ps->ff->ipp_ff); 970 BREAK_ON_IPP_ERROR(sts, result); 971 result = kEpidNoErr; 972 } while (0); 973 974 EpidZeroMemory(&a_dat, sizeof(a_dat)); 975 EpidZeroMemory(&d_dat, sizeof(d_dat)); 976 for (i = 0; i < sizeof(d) / sizeof(FfElement*); i++) { 977 DeleteFfElement(&d[i]); 978 } 979 980 return result; 981 } 982 983 /* 984 (f, X', Y', Z', Z2') = line(Px, Py, X, Y, Z, Z2, Qx, Qy) 985 Input: Px, Py (elements in Fq), X, Y, Z, Z2, Qx, Qy (elements in Fq2) 986 Output: f (an element in GT), X', Y', Z', Z2' (elements in Fq2) 987 */ 988 static EpidStatus Line(FiniteField* gt, FfElement* f, FfElement* x_out, 989 FfElement* y_out, FfElement* z_out, FfElement* z2_out, 990 FfElement const* px, FfElement const* py, 991 FfElement const* x, FfElement const* y, 992 FfElement const* z, FfElement const* z2, 993 FfElement const* qx, FfElement const* qy) { 994 EpidStatus result = kEpidNotImpl; 995 FfElement* t0 = NULL; 996 FfElement* t1 = NULL; 997 FfElement* t2 = NULL; 998 FfElement* t3 = NULL; 999 FfElement* t4 = NULL; 1000 FfElement* t5 = NULL; 1001 FfElement* t6 = NULL; 1002 FfElement* t7 = NULL; 1003 FfElement* t8 = NULL; 1004 FfElement* t9 = NULL; 1005 FfElement* t10 = NULL; 1006 FfElement* t = NULL; 1007 Fq12ElemDat fDat = {0}; 1008 do { 1009 IppStatus sts = ippStsNoErr; 1010 IppsGFpState* Fq2 = 0; 1011 IppsGFpState* Fq6 = 0; 1012 FiniteField* Ffq6 = 0; 1013 FiniteField* Ffq2 = 0; 1014 1015 // check parameters 1016 if (!f || !x_out || !y_out || !z_out || !z2_out || !px || !py || !x || !y || 1017 !z || !z2 || !qx || !qy || !gt) { 1018 result = kEpidBadArgErr; 1019 break; 1020 } 1021 if (!f->ipp_ff_elem || !x_out->ipp_ff_elem || !y_out->ipp_ff_elem || 1022 !z_out->ipp_ff_elem || !z2_out->ipp_ff_elem || !px->ipp_ff_elem || 1023 !py->ipp_ff_elem || !x->ipp_ff_elem || !y->ipp_ff_elem || 1024 !z->ipp_ff_elem || !z2->ipp_ff_elem || !qx->ipp_ff_elem || 1025 !qy->ipp_ff_elem || !gt->ipp_ff) { 1026 result = kEpidBadArgErr; 1027 break; 1028 } 1029 // get Fq6, Fq2 1030 Ffq6 = gt->ground_ff; 1031 if (!Ffq6) { 1032 return kEpidBadArgErr; 1033 } 1034 Fq6 = Ffq6->ipp_ff; 1035 Ffq2 = Ffq6->ground_ff; 1036 if (!Ffq2) { 1037 return kEpidBadArgErr; 1038 } 1039 Fq2 = Ffq2->ipp_ff; 1040 // Let t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 be temporary 1041 // elements in Fq2. All the following operations are computed in 1042 // Fq2 unless explicitly specified. 1043 result = NewFfElement(Ffq2, &t0); 1044 if (kEpidNoErr != result) { 1045 break; 1046 } 1047 result = NewFfElement(Ffq2, &t1); 1048 if (kEpidNoErr != result) { 1049 break; 1050 } 1051 result = NewFfElement(Ffq2, &t2); 1052 if (kEpidNoErr != result) { 1053 break; 1054 } 1055 result = NewFfElement(Ffq2, &t3); 1056 if (kEpidNoErr != result) { 1057 break; 1058 } 1059 result = NewFfElement(Ffq2, &t4); 1060 if (kEpidNoErr != result) { 1061 break; 1062 } 1063 result = NewFfElement(Ffq2, &t5); 1064 if (kEpidNoErr != result) { 1065 break; 1066 } 1067 result = NewFfElement(Ffq2, &t6); 1068 if (kEpidNoErr != result) { 1069 break; 1070 } 1071 result = NewFfElement(Ffq2, &t7); 1072 if (kEpidNoErr != result) { 1073 break; 1074 } 1075 result = NewFfElement(Ffq2, &t8); 1076 if (kEpidNoErr != result) { 1077 break; 1078 } 1079 result = NewFfElement(Ffq2, &t9); 1080 if (kEpidNoErr != result) { 1081 break; 1082 } 1083 result = NewFfElement(Ffq2, &t10); 1084 if (kEpidNoErr != result) { 1085 break; 1086 } 1087 result = NewFfElement(Ffq2, &t); 1088 if (kEpidNoErr != result) { 1089 break; 1090 } 1091 // 1. Set t0 = Qx * Z2. 1092 sts = 1093 ippsGFpMul(qx->ipp_ff_elem, z2_out->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1094 BREAK_ON_IPP_ERROR(sts, result); 1095 // 2. Set t1 = (Qy + Z)^2 - Qy * Qy - Z2. 1096 sts = ippsGFpAdd(qy->ipp_ff_elem, z->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1097 BREAK_ON_IPP_ERROR(sts, result); 1098 sts = ippsGFpMul(t1->ipp_ff_elem, t1->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1099 BREAK_ON_IPP_ERROR(sts, result); 1100 sts = ippsGFpMul(qy->ipp_ff_elem, qy->ipp_ff_elem, t->ipp_ff_elem, Fq2); 1101 BREAK_ON_IPP_ERROR(sts, result); 1102 sts = ippsGFpSub(t1->ipp_ff_elem, t->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1103 BREAK_ON_IPP_ERROR(sts, result); 1104 sts = ippsGFpSub(t1->ipp_ff_elem, z2->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1105 BREAK_ON_IPP_ERROR(sts, result); 1106 // 3. Set t1 = t1 * Z2. 1107 sts = 1108 ippsGFpMul(t1->ipp_ff_elem, z2_out->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1109 BREAK_ON_IPP_ERROR(sts, result); 1110 // 4. Set t2 = t0 - X. 1111 sts = ippsGFpSub(t0->ipp_ff_elem, x->ipp_ff_elem, t2->ipp_ff_elem, Fq2); 1112 BREAK_ON_IPP_ERROR(sts, result); 1113 // 5. Set t3 = t2 * t2. 1114 sts = ippsGFpMul(t2->ipp_ff_elem, t2->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1115 BREAK_ON_IPP_ERROR(sts, result); 1116 // 6. Set t4 = 4 * t3. 1117 sts = ippsGFpAdd(t3->ipp_ff_elem, t3->ipp_ff_elem, t4->ipp_ff_elem, Fq2); 1118 BREAK_ON_IPP_ERROR(sts, result); 1119 sts = ippsGFpAdd(t4->ipp_ff_elem, t4->ipp_ff_elem, t4->ipp_ff_elem, Fq2); 1120 BREAK_ON_IPP_ERROR(sts, result); 1121 // 7. Set t5 = t4 * t2. 1122 sts = ippsGFpMul(t4->ipp_ff_elem, t2->ipp_ff_elem, t5->ipp_ff_elem, Fq2); 1123 BREAK_ON_IPP_ERROR(sts, result); 1124 // 8. Set t6 = t1 - Y - Y. 1125 sts = ippsGFpSub(t1->ipp_ff_elem, y->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1126 BREAK_ON_IPP_ERROR(sts, result); 1127 sts = ippsGFpSub(t6->ipp_ff_elem, y->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1128 BREAK_ON_IPP_ERROR(sts, result); 1129 // 9. Set t9 = t6 * Qx. 1130 sts = ippsGFpMul(t6->ipp_ff_elem, qx->ipp_ff_elem, t9->ipp_ff_elem, Fq2); 1131 BREAK_ON_IPP_ERROR(sts, result); 1132 // 10. Set t7 = X * t4. 1133 sts = ippsGFpMul(x->ipp_ff_elem, t4->ipp_ff_elem, t7->ipp_ff_elem, Fq2); 1134 BREAK_ON_IPP_ERROR(sts, result); 1135 // 11. X' = t6 * t6 - t5 - t7 - t7. 1136 sts = ippsGFpMul(t6->ipp_ff_elem, t6->ipp_ff_elem, x_out->ipp_ff_elem, Fq2); 1137 BREAK_ON_IPP_ERROR(sts, result); 1138 sts = ippsGFpSub(x_out->ipp_ff_elem, t5->ipp_ff_elem, x_out->ipp_ff_elem, 1139 Fq2); 1140 BREAK_ON_IPP_ERROR(sts, result); 1141 sts = ippsGFpSub(x_out->ipp_ff_elem, t7->ipp_ff_elem, x_out->ipp_ff_elem, 1142 Fq2); 1143 BREAK_ON_IPP_ERROR(sts, result); 1144 sts = ippsGFpSub(x_out->ipp_ff_elem, t7->ipp_ff_elem, x_out->ipp_ff_elem, 1145 Fq2); 1146 BREAK_ON_IPP_ERROR(sts, result); 1147 // 12. Set Z' = (Z + t2)^2 - Z2 - t3. 1148 sts = ippsGFpAdd(z->ipp_ff_elem, t2->ipp_ff_elem, z_out->ipp_ff_elem, Fq2); 1149 BREAK_ON_IPP_ERROR(sts, result); 1150 sts = ippsGFpMul(z_out->ipp_ff_elem, z_out->ipp_ff_elem, z_out->ipp_ff_elem, 1151 Fq2); 1152 BREAK_ON_IPP_ERROR(sts, result); 1153 sts = ippsGFpSub(z_out->ipp_ff_elem, z2->ipp_ff_elem, z_out->ipp_ff_elem, 1154 Fq2); 1155 BREAK_ON_IPP_ERROR(sts, result); 1156 sts = ippsGFpSub(z_out->ipp_ff_elem, t3->ipp_ff_elem, z_out->ipp_ff_elem, 1157 Fq2); 1158 BREAK_ON_IPP_ERROR(sts, result); 1159 // 13. Set t10 = Qy + Z'. 1160 sts = 1161 ippsGFpAdd(qy->ipp_ff_elem, z_out->ipp_ff_elem, t10->ipp_ff_elem, Fq2); 1162 BREAK_ON_IPP_ERROR(sts, result); 1163 // 14. Set t8 = (t7 - X') * t6. 1164 sts = ippsGFpSub(t7->ipp_ff_elem, x_out->ipp_ff_elem, t8->ipp_ff_elem, Fq2); 1165 BREAK_ON_IPP_ERROR(sts, result); 1166 sts = ippsGFpMul(t8->ipp_ff_elem, t6->ipp_ff_elem, t8->ipp_ff_elem, Fq2); 1167 BREAK_ON_IPP_ERROR(sts, result); 1168 // 15. Set t0 = 2 * Y * t5. 1169 sts = ippsGFpMul(y->ipp_ff_elem, t5->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1170 BREAK_ON_IPP_ERROR(sts, result); 1171 sts = ippsGFpAdd(t0->ipp_ff_elem, t0->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1172 BREAK_ON_IPP_ERROR(sts, result); 1173 // 16. Set Y' = t8 - t0. 1174 sts = ippsGFpSub(t8->ipp_ff_elem, t0->ipp_ff_elem, y_out->ipp_ff_elem, Fq2); 1175 BREAK_ON_IPP_ERROR(sts, result); 1176 // 17. Set Z2' = Z' * Z'. 1177 sts = ippsGFpMul(z_out->ipp_ff_elem, z_out->ipp_ff_elem, 1178 z2_out->ipp_ff_elem, Fq2); 1179 BREAK_ON_IPP_ERROR(sts, result); 1180 // 18. Set t10 = t10 * t10 - Qy * Qy - Z2'. 1181 sts = ippsGFpMul(t10->ipp_ff_elem, t10->ipp_ff_elem, t10->ipp_ff_elem, Fq2); 1182 BREAK_ON_IPP_ERROR(sts, result); 1183 sts = ippsGFpSub(t10->ipp_ff_elem, t->ipp_ff_elem, t10->ipp_ff_elem, 1184 Fq2); // t still Qy*Qy 1185 BREAK_ON_IPP_ERROR(sts, result); 1186 sts = ippsGFpSub(t10->ipp_ff_elem, z2_out->ipp_ff_elem, t10->ipp_ff_elem, 1187 Fq2); 1188 BREAK_ON_IPP_ERROR(sts, result); 1189 // 19. Set t9 = t9 + t9 - t10. 1190 sts = ippsGFpAdd(t9->ipp_ff_elem, t9->ipp_ff_elem, t9->ipp_ff_elem, Fq2); 1191 BREAK_ON_IPP_ERROR(sts, result); 1192 sts = ippsGFpSub(t9->ipp_ff_elem, t10->ipp_ff_elem, t9->ipp_ff_elem, Fq2); 1193 BREAK_ON_IPP_ERROR(sts, result); 1194 // 20. Set t10 = Fq2.mul(Z', Py). 1195 sts = ippsGFpMul_PE(z_out->ipp_ff_elem, py->ipp_ff_elem, t10->ipp_ff_elem, 1196 Fq2); 1197 BREAK_ON_IPP_ERROR(sts, result); 1198 // 21. Set t10 = t10 + t10. 1199 sts = ippsGFpAdd(t10->ipp_ff_elem, t10->ipp_ff_elem, t10->ipp_ff_elem, Fq2); 1200 BREAK_ON_IPP_ERROR(sts, result); 1201 // 22. Set t6 = -t6. 1202 sts = ippsGFpNeg(t6->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1203 BREAK_ON_IPP_ERROR(sts, result); 1204 // 23. Set t1 = Fq2.mul(t6, Px). 1205 sts = ippsGFpMul_PE(t6->ipp_ff_elem, px->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1206 BREAK_ON_IPP_ERROR(sts, result); 1207 // 24. Set t1 = t1 + t1. 1208 sts = ippsGFpAdd(t1->ipp_ff_elem, t1->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1209 BREAK_ON_IPP_ERROR(sts, result); 1210 // 25. Set f = ((t10, 0, 0), (t1, t9, 0)). 1211 sts = ippsGFpGetElement(t10->ipp_ff_elem, (BNU)&fDat.x[0].x[0], 1212 sizeof(fDat.x[0].x[0]) / sizeof(Ipp32u), Fq2); 1213 BREAK_ON_IPP_ERROR(sts, result); 1214 sts = ippsGFpGetElement(t1->ipp_ff_elem, (BNU)&fDat.x[1].x[0], 1215 sizeof(fDat.x[1].x[0]) / sizeof(Ipp32u), Fq2); 1216 BREAK_ON_IPP_ERROR(sts, result); 1217 sts = ippsGFpGetElement(t9->ipp_ff_elem, (BNU)&fDat.x[1].x[1], 1218 sizeof(fDat.x[1].x[1]) / sizeof(Ipp32u), Fq2); 1219 BREAK_ON_IPP_ERROR(sts, result); 1220 sts = ippsGFpSetElement((Ipp32u*)&fDat, sizeof(fDat) / sizeof(Ipp32u), 1221 f->ipp_ff_elem, gt->ipp_ff); 1222 BREAK_ON_IPP_ERROR(sts, result); 1223 // 26. Return (f, X', Y', Z', Z2'). 1224 } while (0); 1225 EpidZeroMemory(&fDat, sizeof(fDat)); 1226 DeleteFfElement(&t); 1227 DeleteFfElement(&t10); 1228 DeleteFfElement(&t9); 1229 DeleteFfElement(&t8); 1230 DeleteFfElement(&t7); 1231 DeleteFfElement(&t6); 1232 DeleteFfElement(&t5); 1233 DeleteFfElement(&t4); 1234 DeleteFfElement(&t3); 1235 DeleteFfElement(&t2); 1236 DeleteFfElement(&t1); 1237 DeleteFfElement(&t0); 1238 1239 return (result); 1240 } 1241 1242 /* 1243 (f, X', Y', Z', Z2') = tangent(Px, Py, X, Y, Z, Z2) 1244 Input: Px, Py (elements in Fq), X, Y, Z, Z2 (elements in Fq2) 1245 Output: f (an element in GT), X', Y', Z', Z2' (elements in Fq2) 1246 Steps: 1247 */ 1248 static EpidStatus Tangent(FiniteField* gt, FfElement* f, FfElement* x_out, 1249 FfElement* y_out, FfElement* z_out, FfElement* z2_out, 1250 FfElement const* px, FfElement const* py, 1251 FfElement const* x, FfElement const* y, 1252 FfElement const* z, FfElement const* z2) { 1253 EpidStatus result = kEpidErr; 1254 FfElement* t0 = NULL; 1255 FfElement* t1 = NULL; 1256 FfElement* t2 = NULL; 1257 FfElement* t3 = NULL; 1258 FfElement* t4 = NULL; 1259 FfElement* t5 = NULL; 1260 FfElement* t6 = NULL; 1261 Fq12ElemDat fDat = {0}; 1262 do { 1263 IppStatus sts = ippStsNoErr; 1264 IppsGFpState* Fq2 = NULL; 1265 IppsGFpState* Fq6 = NULL; 1266 FiniteField* Ffq2 = NULL; 1267 FiniteField* Ffq6 = NULL; 1268 1269 int i = 0; 1270 // validate input 1271 if (!gt || !f || !x_out || !y_out || !z_out || !z2_out || !px || !py || 1272 !x || !y || !z || !z2) { 1273 result = kEpidBadArgErr; 1274 break; 1275 } 1276 if (!gt->ipp_ff || !f->ipp_ff_elem || !x_out->ipp_ff_elem || 1277 !y_out->ipp_ff_elem || !z_out->ipp_ff_elem || !z2_out->ipp_ff_elem || 1278 !px->ipp_ff_elem || !py->ipp_ff_elem || !x->ipp_ff_elem || 1279 !y->ipp_ff_elem || !z->ipp_ff_elem || !z2->ipp_ff_elem) { 1280 result = kEpidBadArgErr; 1281 break; 1282 } 1283 // get Fq2, Fq6 1284 Ffq6 = gt->ground_ff; 1285 if (!Ffq6) { 1286 result = kEpidBadArgErr; 1287 break; 1288 } 1289 Fq6 = Ffq6->ipp_ff; 1290 Ffq2 = Ffq6->ground_ff; 1291 if (!Ffq2) { 1292 result = kEpidBadArgErr; 1293 break; 1294 } 1295 Fq2 = Ffq2->ipp_ff; 1296 // Let t0, t1, t2, t3, t4, t5, t6 be elements in Fq2. All the following 1297 // operations are computed in Fq2 unless explicitly specified. 1298 // 1. Set t0 = X * X. 1299 result = NewFfElement(Ffq2, &t0); 1300 BREAK_ON_EPID_ERROR(result); 1301 sts = ippsGFpMul(x->ipp_ff_elem, x->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1302 BREAK_ON_IPP_ERROR(sts, result); 1303 // 2. Set t1 = Y * Y. 1304 result = NewFfElement(Ffq2, &t1); 1305 BREAK_ON_EPID_ERROR(result); 1306 sts = ippsGFpMul(y->ipp_ff_elem, y->ipp_ff_elem, t1->ipp_ff_elem, Fq2); 1307 BREAK_ON_IPP_ERROR(sts, result); 1308 // 3. Set t2 = t1 * t1. 1309 result = NewFfElement(Ffq2, &t2); 1310 BREAK_ON_EPID_ERROR(result); 1311 sts = ippsGFpMul(t1->ipp_ff_elem, t1->ipp_ff_elem, t2->ipp_ff_elem, Fq2); 1312 BREAK_ON_IPP_ERROR(sts, result); 1313 // 4. Set t3 = (t1 + X)^2 - t0 - t2. 1314 result = NewFfElement(Ffq2, &t3); 1315 BREAK_ON_EPID_ERROR(result); 1316 sts = ippsGFpAdd(t1->ipp_ff_elem, x->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1317 BREAK_ON_IPP_ERROR(sts, result); 1318 sts = ippsGFpMul(t3->ipp_ff_elem, t3->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1319 BREAK_ON_IPP_ERROR(sts, result); 1320 sts = ippsGFpSub(t3->ipp_ff_elem, t0->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1321 BREAK_ON_IPP_ERROR(sts, result); 1322 sts = ippsGFpSub(t3->ipp_ff_elem, t2->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1323 BREAK_ON_IPP_ERROR(sts, result); 1324 // 5. Set t3 = t3 + t3. 1325 sts = ippsGFpAdd(t3->ipp_ff_elem, t3->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1326 BREAK_ON_IPP_ERROR(sts, result); 1327 // 6. Set t4 = 3 * t0. 1328 result = NewFfElement(Ffq2, &t4); 1329 BREAK_ON_EPID_ERROR(result); 1330 sts = ippsGFpAdd(t0->ipp_ff_elem, t0->ipp_ff_elem, t4->ipp_ff_elem, Fq2); 1331 BREAK_ON_IPP_ERROR(sts, result); 1332 sts = ippsGFpAdd(t4->ipp_ff_elem, t0->ipp_ff_elem, t4->ipp_ff_elem, Fq2); 1333 BREAK_ON_IPP_ERROR(sts, result); 1334 // 7. Set t6 = X + t4. 1335 result = NewFfElement(Ffq2, &t6); 1336 BREAK_ON_EPID_ERROR(result); 1337 sts = ippsGFpAdd(x->ipp_ff_elem, t4->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1338 BREAK_ON_IPP_ERROR(sts, result); 1339 // 8. Set t5 = t4 * t4. 1340 result = NewFfElement(Ffq2, &t5); 1341 BREAK_ON_EPID_ERROR(result); 1342 sts = ippsGFpMul(t4->ipp_ff_elem, t4->ipp_ff_elem, t5->ipp_ff_elem, Fq2); 1343 BREAK_ON_IPP_ERROR(sts, result); 1344 // 9. Set X' = t5 - t3 - t3. 1345 sts = ippsGFpSub(t5->ipp_ff_elem, t3->ipp_ff_elem, x_out->ipp_ff_elem, Fq2); 1346 BREAK_ON_IPP_ERROR(sts, result); 1347 sts = ippsGFpSub(x_out->ipp_ff_elem, t3->ipp_ff_elem, x_out->ipp_ff_elem, 1348 Fq2); 1349 BREAK_ON_IPP_ERROR(sts, result); 1350 // 10.Set Z' = (Y + Z)^2 - t1 - Z2. 1351 sts = ippsGFpAdd(y->ipp_ff_elem, z->ipp_ff_elem, z_out->ipp_ff_elem, Fq2); 1352 BREAK_ON_IPP_ERROR(sts, result); 1353 sts = ippsGFpMul(z_out->ipp_ff_elem, z_out->ipp_ff_elem, z_out->ipp_ff_elem, 1354 Fq2); 1355 BREAK_ON_IPP_ERROR(sts, result); 1356 sts = ippsGFpSub(z_out->ipp_ff_elem, t1->ipp_ff_elem, z_out->ipp_ff_elem, 1357 Fq2); 1358 BREAK_ON_IPP_ERROR(sts, result); 1359 sts = ippsGFpSub(z_out->ipp_ff_elem, z2->ipp_ff_elem, z_out->ipp_ff_elem, 1360 Fq2); 1361 BREAK_ON_IPP_ERROR(sts, result); 1362 // 11.Set Y' = (t3 - X') * t4 - 8 * t2. 1363 sts = ippsGFpSub(t3->ipp_ff_elem, x_out->ipp_ff_elem, y_out->ipp_ff_elem, 1364 Fq2); 1365 BREAK_ON_IPP_ERROR(sts, result); 1366 sts = ippsGFpMul(y_out->ipp_ff_elem, t4->ipp_ff_elem, y_out->ipp_ff_elem, 1367 Fq2); 1368 BREAK_ON_IPP_ERROR(sts, result); 1369 for (i = 0; i < 8; i++) { 1370 sts = ippsGFpSub(y_out->ipp_ff_elem, t2->ipp_ff_elem, y_out->ipp_ff_elem, 1371 Fq2); 1372 BREAK_ON_IPP_ERROR(sts, result); 1373 } 1374 // 12.Set t3 = -2 * (t4 * Z2). 1375 sts = ippsGFpMul(t4->ipp_ff_elem, z2->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1376 BREAK_ON_IPP_ERROR(sts, result); 1377 sts = ippsGFpAdd(t3->ipp_ff_elem, t3->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1378 BREAK_ON_IPP_ERROR(sts, result); 1379 sts = ippsGFpNeg(t3->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1380 BREAK_ON_IPP_ERROR(sts, result); 1381 // 13.Set t3 = Fq2.mul(t3, Px). 1382 sts = ippsGFpMul_PE(t3->ipp_ff_elem, px->ipp_ff_elem, t3->ipp_ff_elem, Fq2); 1383 BREAK_ON_IPP_ERROR(sts, result); 1384 // 14.Set t6 = t6 * t6 - t0 - t5 - 4 * t1. 1385 sts = ippsGFpMul(t6->ipp_ff_elem, t6->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1386 BREAK_ON_IPP_ERROR(sts, result); 1387 sts = ippsGFpSub(t6->ipp_ff_elem, t0->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1388 BREAK_ON_IPP_ERROR(sts, result); 1389 sts = ippsGFpSub(t6->ipp_ff_elem, t5->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1390 BREAK_ON_IPP_ERROR(sts, result); 1391 for (i = 0; i < 4; i++) { 1392 sts = ippsGFpSub(t6->ipp_ff_elem, t1->ipp_ff_elem, t6->ipp_ff_elem, Fq2); 1393 BREAK_ON_IPP_ERROR(sts, result); 1394 } 1395 // 15.Set t0 = 2 * (Z' * Z2). 1396 sts = ippsGFpMul(z_out->ipp_ff_elem, z2->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1397 BREAK_ON_IPP_ERROR(sts, result); 1398 sts = ippsGFpAdd(t0->ipp_ff_elem, t0->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1399 BREAK_ON_IPP_ERROR(sts, result); 1400 // 16.Set t0 = Fq2.mul(t0, Py). 1401 sts = ippsGFpMul_PE(t0->ipp_ff_elem, py->ipp_ff_elem, t0->ipp_ff_elem, Fq2); 1402 BREAK_ON_IPP_ERROR(sts, result); 1403 // 17.Set f = ((t0, 0, 0), (t3, t6, 0)). 1404 sts = ippsGFpGetElement(t0->ipp_ff_elem, (BNU)&fDat.x[0].x[0], 1405 sizeof(fDat.x[0].x[0]) / sizeof(Ipp32u), Fq2); 1406 BREAK_ON_IPP_ERROR(sts, result); 1407 sts = ippsGFpGetElement(t3->ipp_ff_elem, (BNU)&fDat.x[1].x[0], 1408 sizeof(fDat.x[1].x[0]) / sizeof(Ipp32u), Fq2); 1409 BREAK_ON_IPP_ERROR(sts, result); 1410 sts = ippsGFpGetElement(t6->ipp_ff_elem, (BNU)&fDat.x[1].x[1], 1411 sizeof(fDat.x[1].x[1]) / sizeof(Ipp32u), Fq2); 1412 BREAK_ON_IPP_ERROR(sts, result); 1413 sts = ippsGFpSetElement((Ipp32u*)&fDat, sizeof(fDat) / sizeof(Ipp32u), 1414 f->ipp_ff_elem, gt->ipp_ff); 1415 BREAK_ON_IPP_ERROR(sts, result); 1416 // 18.Set Z2' = Z' * Z'. 1417 sts = ippsGFpMul(z_out->ipp_ff_elem, z_out->ipp_ff_elem, 1418 z2_out->ipp_ff_elem, Fq2); 1419 BREAK_ON_IPP_ERROR(sts, result); 1420 // 19.Return (f, X', Y', Z', Z2'). 1421 } while (0); 1422 EpidZeroMemory(&fDat, sizeof(fDat)); 1423 DeleteFfElement(&t6); 1424 DeleteFfElement(&t5); 1425 DeleteFfElement(&t4); 1426 DeleteFfElement(&t3); 1427 DeleteFfElement(&t2); 1428 DeleteFfElement(&t1); 1429 DeleteFfElement(&t0); 1430 return result; 1431 } 1432 1433 /* 1434 (sn...s1s0) = ternary(s) 1435 Input: s (big integer) 1436 Output: sn...s1s0 (ternary representation of s) 1437 */ 1438 static EpidStatus Ternary(int* s, int* n, int max_elements, BigNum const* x) { 1439 /* 1440 Let xn...x1x0 be binary representation of s. 1441 Let flag be a Boolean variable. 1442 1. Set flag = false. 1443 2. For i = 0, ..., n, do the following: 1444 a. If xi = 1 1445 i. If flag = true, set si = 0, 1446 ii. Else 1447 1. If xi+1 = 1, set si = -1 and set flag = true, 1448 2. Else si = 1. 1449 b. Else 1450 i. If flag = true, set si = 1 and set flag = false, 1451 ii. Else set si = 0. 1452 3. If flag is true 1453 a. Set n = n+1, 1454 b. Set sn = 1. 1455 4. Return sn...s1s0. 1456 */ 1457 EpidStatus result = kEpidErr; 1458 1459 do { 1460 IppStatus sts = ippStsNoErr; 1461 int flag = 0; 1462 int i = 0; 1463 int num_bits = 0; 1464 IppBNU data = 0; 1465 1466 // check parameters 1467 if (!s || !n || !x || !x->ipp_bn) { 1468 result = kEpidBadArgErr; 1469 break; 1470 } 1471 1472 sts = ippsRef_BN(0, &num_bits, &data, x->ipp_bn); 1473 if (ippStsNoErr != sts) { 1474 result = kEpidMathErr; 1475 break; 1476 } 1477 1478 if (num_bits + 1 > max_elements) { 1479 // not enough room for ternary representation 1480 result = kEpidBadArgErr; 1481 break; 1482 } 1483 1484 // Let xn...x1x0 be binary representation of s. Let flag be a 1485 // Boolean variable. 1486 *n = num_bits - 1; 1487 // 1. Set flag = false. 1488 flag = 0; 1489 // 2. For i = 0, ..., n, do the following: 1490 for (i = 0; i < num_bits; i++) { 1491 if (1 == Bit(data, i)) { 1492 // a. If x[i] = 1 1493 if (flag) { 1494 // i. If flag = true, set si = 0, 1495 s[i] = 0; 1496 } else { 1497 // ii. Else 1498 if ((i < num_bits - 2) && Bit(data, i + 1)) { 1499 // 1. If x[i+1] = 1, set s[i] = -1 and set flag = true, 1500 s[i] = -1; 1501 flag = 1; 1502 } else { 1503 // 2. Else s[i] = 1. 1504 s[i] = 1; 1505 } 1506 } 1507 } else { 1508 // b. Else 1509 if (flag) { 1510 // i. If flag = true, set s[i] = 1 and set flag = false, 1511 s[i] = 1; 1512 flag = 0; 1513 } else { 1514 // ii. Else set s[i] = 0. 1515 s[i] = 0; 1516 } 1517 } 1518 } 1519 // 3. If flag is true 1520 if (flag) { 1521 // a. Set n = n+1, 1522 *n = *n + 1; 1523 // b. Set s[n] = 1. 1524 s[*n] = 1; 1525 } 1526 // 4. Return sn...s1s0. 1527 result = kEpidNoErr; 1528 } while (0); 1529 1530 return (result); 1531 } 1532 1533 static int Bit(Ipp32u const* num, Ipp32u bit_index) { 1534 return 0 != (num[bit_index >> 5] & (1 << (bit_index & 0x1F))); 1535 } 1536 1537 /* 1538 e = Fq2.mulXi(a) 1539 Input: a (an element in Fq2) 1540 Output: e (an element in Fq2) where e = a * xi 1541 1542 \note THIS IMPLEMENTATION ASSUMES xi[0] = 2, xi[1] = 1, beta = -1 1543 1544 \note only should work with Fq2 1545 1546 */ 1547 static EpidStatus MulXiFast(FfElement* e, FfElement const* a, 1548 PairingState* ps) { 1549 EpidStatus retvalue = kEpidNotImpl; 1550 FfElement* a0 = NULL; 1551 FfElement* a1 = NULL; 1552 FfElement* e0 = NULL; 1553 FfElement* e1 = NULL; 1554 Fq2ElemDat a_dat = {0}; 1555 Fq2ElemDat e_dat = {0}; 1556 1557 do { 1558 IppStatus sts = ippStsNoErr; 1559 // check parameters 1560 if (!e || !a || !ps) { 1561 retvalue = kEpidBadArgErr; 1562 BREAK_ON_EPID_ERROR(retvalue); 1563 } 1564 if (!ps->Fq || !ps->Fq2) { 1565 retvalue = kEpidBadArgErr; 1566 BREAK_ON_EPID_ERROR(retvalue); 1567 } 1568 if (!e->ipp_ff_elem || !a->ipp_ff_elem || !ps->Fq->ipp_ff || 1569 !ps->Fq2->ipp_ff) { 1570 retvalue = kEpidBadArgErr; 1571 BREAK_ON_EPID_ERROR(retvalue); 1572 } 1573 // All the following arithmetic operations are in ps->Fq. 1574 // 1. Let a = (a[0], a[1]), xi = (xi[0], xi[1]), and e = (e[0], e[1]). 1575 retvalue = NewFfElement(ps->Fq, &a0); 1576 BREAK_ON_EPID_ERROR(retvalue); 1577 retvalue = NewFfElement(ps->Fq, &a1); 1578 BREAK_ON_EPID_ERROR(retvalue); 1579 retvalue = NewFfElement(ps->Fq, &e0); 1580 BREAK_ON_EPID_ERROR(retvalue); 1581 retvalue = NewFfElement(ps->Fq, &e1); 1582 BREAK_ON_EPID_ERROR(retvalue); 1583 1584 sts = ippsGFpGetElement(a->ipp_ff_elem, (BNU)&a_dat, 1585 sizeof(a_dat) / sizeof(Ipp32u), ps->Fq2->ipp_ff); 1586 BREAK_ON_IPP_ERROR(sts, retvalue); 1587 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0], 1588 sizeof(a_dat.x[0]) / sizeof(Ipp32u), 1589 a0->ipp_ff_elem, ps->Fq->ipp_ff); 1590 BREAK_ON_IPP_ERROR(sts, retvalue); 1591 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1], 1592 sizeof(a_dat.x[1]) / sizeof(Ipp32u), 1593 a1->ipp_ff_elem, ps->Fq->ipp_ff); 1594 BREAK_ON_IPP_ERROR(sts, retvalue); 1595 1596 // 4. If xi[0] = 2, xi[1] = 1, beta = -1, then e[0] and e[1] can 1597 // be computed as 1598 // a. e[0] = a[0] + a[0] - a[1]. 1599 sts = ippsGFpAdd(a0->ipp_ff_elem, a0->ipp_ff_elem, e0->ipp_ff_elem, 1600 ps->Fq->ipp_ff); 1601 BREAK_ON_IPP_ERROR(sts, retvalue); 1602 sts = ippsGFpSub(e0->ipp_ff_elem, a1->ipp_ff_elem, e0->ipp_ff_elem, 1603 ps->Fq->ipp_ff); 1604 BREAK_ON_IPP_ERROR(sts, retvalue); 1605 // b. e[1] = a[0] + a[1] + a[1]. 1606 sts = ippsGFpAdd(a0->ipp_ff_elem, a1->ipp_ff_elem, e1->ipp_ff_elem, 1607 ps->Fq->ipp_ff); 1608 BREAK_ON_IPP_ERROR(sts, retvalue); 1609 sts = ippsGFpAdd(e1->ipp_ff_elem, a1->ipp_ff_elem, e1->ipp_ff_elem, 1610 ps->Fq->ipp_ff); 1611 BREAK_ON_IPP_ERROR(sts, retvalue); 1612 // 5. Return e = (e[0], e[1]). 1613 sts = 1614 ippsGFpGetElement(e0->ipp_ff_elem, (BNU)&e_dat.x[0], 1615 sizeof(e_dat.x[0]) / sizeof(Ipp32u), ps->Fq->ipp_ff); 1616 BREAK_ON_IPP_ERROR(sts, retvalue); 1617 sts = 1618 ippsGFpGetElement(e1->ipp_ff_elem, (BNU)&e_dat.x[1], 1619 sizeof(e_dat.x[1]) / sizeof(Ipp32u), ps->Fq->ipp_ff); 1620 BREAK_ON_IPP_ERROR(sts, retvalue); 1621 sts = ippsGFpSetElement((Ipp32u*)&e_dat, sizeof(e_dat) / sizeof(Ipp32u), 1622 e->ipp_ff_elem, ps->Fq2->ipp_ff); 1623 BREAK_ON_IPP_ERROR(sts, retvalue); 1624 retvalue = kEpidNoErr; 1625 } while (0); 1626 1627 EpidZeroMemory(&a_dat, sizeof(a_dat)); 1628 EpidZeroMemory(&e_dat, sizeof(e_dat)); 1629 DeleteFfElement(&a0); 1630 DeleteFfElement(&a1); 1631 DeleteFfElement(&e0); 1632 DeleteFfElement(&e1); 1633 1634 return (retvalue); 1635 } 1636 1637 /* 1638 e = Fq6.MulV(a) 1639 Input: a (element in Fq6) 1640 Output: e (an element in Fq6) where e = a * V, where V = 0 * v2 + 1 * v + 0 1641 1642 \note only should work with Fq6 1643 */ 1644 static EpidStatus MulV(FfElement* e, FfElement* a, PairingState* ps) { 1645 EpidStatus retvalue = kEpidNotImpl; 1646 FfElement* a2 = NULL; 1647 FfElement* e0 = NULL; 1648 FfElement* e1 = NULL; 1649 FfElement* e2 = NULL; 1650 Fq6ElemDat a_dat = {0}; 1651 Fq6ElemDat e_dat = {0}; 1652 do { 1653 IppStatus sts = ippStsNoErr; 1654 // check parameters 1655 if (!e || !a || !ps) { 1656 retvalue = kEpidBadArgErr; 1657 BREAK_ON_EPID_ERROR(retvalue); 1658 } 1659 if (!ps->Fq2 || !ps->Fq6) { 1660 retvalue = kEpidBadArgErr; 1661 BREAK_ON_EPID_ERROR(retvalue); 1662 } 1663 if (!e->ipp_ff_elem || !a->ipp_ff_elem || !ps->Fq2->ipp_ff || 1664 !ps->Fq6->ipp_ff) { 1665 retvalue = kEpidBadArgErr; 1666 BREAK_ON_EPID_ERROR(retvalue); 1667 } 1668 // 1. Let a = (a[0], a[1], a[2]) and e = (e[0], e[1], e[2]). 1669 retvalue = NewFfElement(ps->Fq2, &a2); 1670 BREAK_ON_EPID_ERROR(retvalue); 1671 retvalue = NewFfElement(ps->Fq2, &e0); 1672 BREAK_ON_EPID_ERROR(retvalue); 1673 retvalue = NewFfElement(ps->Fq2, &e1); 1674 BREAK_ON_EPID_ERROR(retvalue); 1675 retvalue = NewFfElement(ps->Fq2, &e2); 1676 BREAK_ON_EPID_ERROR(retvalue); 1677 1678 sts = ippsGFpGetElement(a->ipp_ff_elem, (BNU)&a_dat, 1679 sizeof(a_dat) / sizeof(Ipp32u), ps->Fq6->ipp_ff); 1680 BREAK_ON_IPP_ERROR(sts, retvalue); 1681 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[2], 1682 sizeof(a_dat.x[2]) / sizeof(Ipp32u), 1683 a2->ipp_ff_elem, ps->Fq2->ipp_ff); 1684 BREAK_ON_IPP_ERROR(sts, retvalue); 1685 // 2. e[0] = Fq2.mulXi(a[2]). 1686 retvalue = MulXiFast(e0, a2, ps); 1687 BREAK_ON_EPID_ERROR(retvalue); 1688 // 3. e[1] = a[0]. 1689 e_dat.x[1] = a_dat.x[0]; 1690 // 4. e[2] = a[1]. 1691 e_dat.x[2] = a_dat.x[1]; 1692 1693 sts = 1694 ippsGFpGetElement(e0->ipp_ff_elem, (BNU)&e_dat.x[0], 1695 sizeof(e_dat.x[0]) / sizeof(Ipp32u), ps->Fq2->ipp_ff); 1696 BREAK_ON_IPP_ERROR(sts, retvalue); 1697 sts = ippsGFpSetElement((Ipp32u*)&e_dat, sizeof(e_dat) / sizeof(Ipp32u), 1698 e->ipp_ff_elem, ps->Fq6->ipp_ff); 1699 BREAK_ON_IPP_ERROR(sts, retvalue); 1700 retvalue = kEpidNoErr; 1701 } while (0); 1702 1703 EpidZeroMemory(&a_dat, sizeof(a_dat)); 1704 EpidZeroMemory(&e_dat, sizeof(e_dat)); 1705 DeleteFfElement(&a2); 1706 DeleteFfElement(&e0); 1707 DeleteFfElement(&e1); 1708 DeleteFfElement(&e2); 1709 1710 return (retvalue); 1711 } 1712 1713 /* 1714 helper for MulSpecial, special args form of Fq6Mul 1715 1716 special args form of Fq6.mul(a,b[0],b[1]) 1717 Input: a (elements in Fq6), b[0], b[1] (elements in Fq2) 1718 Output: e (an element in Fq6) where e = a * b, and b = b[1] * v + b[0] 1719 1720 \note assumes a,e are Fq6 elements and b0,b1 are fq2 elements 1721 */ 1722 static EpidStatus Fq6MulGFpE2(FfElement* e, FfElement* a, FfElement* b0, 1723 FfElement* b1, PairingState* ps) { 1724 EpidStatus retvalue = kEpidNotImpl; 1725 FfElement* t0 = NULL; 1726 FfElement* t1 = NULL; 1727 FfElement* t2 = NULL; 1728 FfElement* t3 = NULL; 1729 FfElement* t4 = NULL; 1730 FfElement* a0 = NULL; 1731 FfElement* a1 = NULL; 1732 FfElement* a2 = NULL; 1733 FfElement* e0 = NULL; 1734 FfElement* e1 = NULL; 1735 FfElement* e2 = NULL; 1736 Fq6ElemDat a_dat = {0}; 1737 Fq6ElemDat e_dat = {0}; 1738 do { 1739 IppStatus sts = ippStsNoErr; 1740 // check parameters 1741 if (!e || !a || !b0 || !b1 || !ps) { 1742 retvalue = kEpidBadArgErr; 1743 BREAK_ON_EPID_ERROR(retvalue); 1744 } 1745 if (!ps->Fq2 || !ps->Fq6) { 1746 retvalue = kEpidBadArgErr; 1747 BREAK_ON_EPID_ERROR(retvalue); 1748 } 1749 if (!e->ipp_ff_elem || !a->ipp_ff_elem || !b0->ipp_ff_elem || 1750 !b1->ipp_ff_elem || !ps->Fq2->ipp_ff || !ps->Fq6->ipp_ff) { 1751 retvalue = kEpidBadArgErr; 1752 BREAK_ON_EPID_ERROR(retvalue); 1753 } 1754 1755 // Let t0, t1, t3, t4 be temporary variables in Fq2. All the 1756 // following arithmetic operations are in Fq2. 1757 retvalue = NewFfElement(ps->Fq2, &t0); 1758 BREAK_ON_EPID_ERROR(retvalue); 1759 retvalue = NewFfElement(ps->Fq2, &t1); 1760 BREAK_ON_EPID_ERROR(retvalue); 1761 retvalue = NewFfElement(ps->Fq2, &t2); 1762 BREAK_ON_EPID_ERROR(retvalue); 1763 retvalue = NewFfElement(ps->Fq2, &t3); 1764 BREAK_ON_EPID_ERROR(retvalue); 1765 retvalue = NewFfElement(ps->Fq2, &t4); 1766 BREAK_ON_EPID_ERROR(retvalue); 1767 // 1. Let a = (a[0], a[1], a[2]) and e = (e[0], e[1], e[2]). 1768 retvalue = NewFfElement(ps->Fq2, &a0); 1769 BREAK_ON_EPID_ERROR(retvalue); 1770 retvalue = NewFfElement(ps->Fq2, &a1); 1771 BREAK_ON_EPID_ERROR(retvalue); 1772 retvalue = NewFfElement(ps->Fq2, &a2); 1773 BREAK_ON_EPID_ERROR(retvalue); 1774 retvalue = NewFfElement(ps->Fq2, &e0); 1775 BREAK_ON_EPID_ERROR(retvalue); 1776 retvalue = NewFfElement(ps->Fq2, &e1); 1777 BREAK_ON_EPID_ERROR(retvalue); 1778 retvalue = NewFfElement(ps->Fq2, &e2); 1779 BREAK_ON_EPID_ERROR(retvalue); 1780 1781 sts = ippsGFpGetElement(a->ipp_ff_elem, (BNU)&a_dat, 1782 sizeof(a_dat) / sizeof(Ipp32u), ps->Fq6->ipp_ff); 1783 BREAK_ON_IPP_ERROR(sts, retvalue); 1784 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0], 1785 sizeof(a_dat.x[0]) / sizeof(Ipp32u), 1786 a0->ipp_ff_elem, ps->Fq2->ipp_ff); 1787 BREAK_ON_IPP_ERROR(sts, retvalue); 1788 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1], 1789 sizeof(a_dat.x[1]) / sizeof(Ipp32u), 1790 a1->ipp_ff_elem, ps->Fq2->ipp_ff); 1791 BREAK_ON_IPP_ERROR(sts, retvalue); 1792 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[2], 1793 sizeof(a_dat.x[2]) / sizeof(Ipp32u), 1794 a2->ipp_ff_elem, ps->Fq2->ipp_ff); 1795 BREAK_ON_IPP_ERROR(sts, retvalue); 1796 // 2. t0 = a[0] * b[0]. 1797 sts = ippsGFpMul(a0->ipp_ff_elem, b0->ipp_ff_elem, t0->ipp_ff_elem, 1798 ps->Fq2->ipp_ff); 1799 BREAK_ON_IPP_ERROR(sts, retvalue); 1800 // 3. t1 = a[1] * b[1]. 1801 sts = ippsGFpMul(a1->ipp_ff_elem, b1->ipp_ff_elem, t1->ipp_ff_elem, 1802 ps->Fq2->ipp_ff); 1803 BREAK_ON_IPP_ERROR(sts, retvalue); 1804 // 4. t3 = a[1] + a[2]. 1805 sts = ippsGFpAdd(a1->ipp_ff_elem, a2->ipp_ff_elem, t3->ipp_ff_elem, 1806 ps->Fq2->ipp_ff); 1807 BREAK_ON_IPP_ERROR(sts, retvalue); 1808 // 5. t3 = t3 * b[1]. 1809 sts = ippsGFpMul(t3->ipp_ff_elem, b1->ipp_ff_elem, t3->ipp_ff_elem, 1810 ps->Fq2->ipp_ff); 1811 BREAK_ON_IPP_ERROR(sts, retvalue); 1812 // 6. t3 = t3 - t1. 1813 sts = ippsGFpSub(t3->ipp_ff_elem, t1->ipp_ff_elem, t3->ipp_ff_elem, 1814 ps->Fq2->ipp_ff); 1815 BREAK_ON_IPP_ERROR(sts, retvalue); 1816 // 7. e[0] = Fq2.mulXi(t3) + t0. 1817 retvalue = MulXiFast(e0, t3, ps); 1818 BREAK_ON_EPID_ERROR(retvalue); 1819 sts = ippsGFpAdd(e0->ipp_ff_elem, t0->ipp_ff_elem, e0->ipp_ff_elem, 1820 ps->Fq2->ipp_ff); 1821 BREAK_ON_IPP_ERROR(sts, retvalue); 1822 // 8. t3 = a[0] + a[1]. 1823 sts = ippsGFpAdd(a0->ipp_ff_elem, a1->ipp_ff_elem, t3->ipp_ff_elem, 1824 ps->Fq2->ipp_ff); 1825 BREAK_ON_IPP_ERROR(sts, retvalue); 1826 // 9. t4 = b[0] + b[1]. 1827 sts = ippsGFpAdd(b0->ipp_ff_elem, b1->ipp_ff_elem, t4->ipp_ff_elem, 1828 ps->Fq2->ipp_ff); 1829 BREAK_ON_IPP_ERROR(sts, retvalue); 1830 // 10. t3 = t3 * t4. 1831 sts = ippsGFpMul(t3->ipp_ff_elem, t4->ipp_ff_elem, t3->ipp_ff_elem, 1832 ps->Fq2->ipp_ff); 1833 BREAK_ON_IPP_ERROR(sts, retvalue); 1834 // 11. e[1] = t3 - t0 - t1. 1835 sts = ippsGFpSub(t3->ipp_ff_elem, t0->ipp_ff_elem, e1->ipp_ff_elem, 1836 ps->Fq2->ipp_ff); 1837 BREAK_ON_IPP_ERROR(sts, retvalue); 1838 sts = ippsGFpSub(e1->ipp_ff_elem, t1->ipp_ff_elem, e1->ipp_ff_elem, 1839 ps->Fq2->ipp_ff); 1840 BREAK_ON_IPP_ERROR(sts, retvalue); 1841 // 12. t3 = a[2] * b[0]. 1842 sts = ippsGFpMul(a2->ipp_ff_elem, b0->ipp_ff_elem, t3->ipp_ff_elem, 1843 ps->Fq2->ipp_ff); 1844 BREAK_ON_IPP_ERROR(sts, retvalue); 1845 // 13. e[2] = t3 + t1. 1846 sts = ippsGFpAdd(t3->ipp_ff_elem, t1->ipp_ff_elem, e2->ipp_ff_elem, 1847 ps->Fq2->ipp_ff); 1848 BREAK_ON_IPP_ERROR(sts, retvalue); 1849 // 14. Return e. 1850 sts = 1851 ippsGFpGetElement(e0->ipp_ff_elem, (BNU)&e_dat.x[0], 1852 sizeof(e_dat.x[0]) / sizeof(Ipp32u), ps->Fq2->ipp_ff); 1853 BREAK_ON_IPP_ERROR(sts, retvalue); 1854 sts = 1855 ippsGFpGetElement(e1->ipp_ff_elem, (BNU)&e_dat.x[1], 1856 sizeof(e_dat.x[1]) / sizeof(Ipp32u), ps->Fq2->ipp_ff); 1857 BREAK_ON_IPP_ERROR(sts, retvalue); 1858 sts = 1859 ippsGFpGetElement(e2->ipp_ff_elem, (BNU)&e_dat.x[2], 1860 sizeof(e_dat.x[2]) / sizeof(Ipp32u), ps->Fq2->ipp_ff); 1861 BREAK_ON_IPP_ERROR(sts, retvalue); 1862 sts = ippsGFpSetElement((Ipp32u*)&e_dat, sizeof(e_dat) / sizeof(Ipp32u), 1863 e->ipp_ff_elem, ps->Fq6->ipp_ff); 1864 BREAK_ON_IPP_ERROR(sts, retvalue); 1865 retvalue = kEpidNoErr; 1866 } while (0); 1867 1868 EpidZeroMemory(&a_dat, sizeof(a_dat)); 1869 EpidZeroMemory(&e_dat, sizeof(e_dat)); 1870 DeleteFfElement(&t0); 1871 DeleteFfElement(&t1); 1872 DeleteFfElement(&t2); 1873 DeleteFfElement(&t3); 1874 DeleteFfElement(&t4); 1875 DeleteFfElement(&a0); 1876 DeleteFfElement(&a1); 1877 DeleteFfElement(&a2); 1878 DeleteFfElement(&e0); 1879 DeleteFfElement(&e1); 1880 DeleteFfElement(&e2); 1881 1882 return (retvalue); 1883 } 1884 1885 /* 1886 e = Fq12.MulSpecial(a, b) 1887 Input: a, b (elements in Fq12) where b = ((b[0], b[2], b[4]), (b[1], b[3], 1888 b[5])) and b[2] = b[4] = b[5] = 0 1889 Output: e (an element in Fq12) where e = a * b 1890 */ 1891 static EpidStatus MulSpecial(FfElement* e, FfElement const* a, 1892 FfElement const* b, PairingState* ps) { 1893 EpidStatus retvalue = kEpidNotImpl; 1894 FfElement* t0 = NULL; 1895 FfElement* t1 = NULL; 1896 FfElement* t2 = NULL; 1897 FfElement* a0 = NULL; 1898 FfElement* a1 = NULL; 1899 FfElement* b0 = NULL; 1900 FfElement* b1 = NULL; 1901 FfElement* b3 = NULL; 1902 FfElement* e0 = NULL; 1903 FfElement* e1 = NULL; 1904 FfElement* b0plusb1 = NULL; 1905 Fq12ElemDat a_dat = {0}; 1906 Fq12ElemDat b_dat = {0}; 1907 Fq12ElemDat e_dat = {0}; 1908 do { 1909 IppStatus sts = ippStsNoErr; 1910 1911 // check parameters 1912 if (!e || !a || !b || !ps) { 1913 retvalue = kEpidBadArgErr; 1914 BREAK_ON_EPID_ERROR(retvalue); 1915 } 1916 if (!ps->Fq2 || !ps->Fq6) { 1917 retvalue = kEpidBadArgErr; 1918 BREAK_ON_EPID_ERROR(retvalue); 1919 } 1920 if (!e->ipp_ff_elem || !a->ipp_ff_elem || !b->ipp_ff_elem || 1921 !ps->Fq2->ipp_ff || !ps->Fq6->ipp_ff || !ps->ff || !ps->ff->ipp_ff) { 1922 retvalue = kEpidBadArgErr; 1923 BREAK_ON_EPID_ERROR(retvalue); 1924 } 1925 1926 // Let t0, t1, t2 be temporary variables in ps->Fq6. 1927 retvalue = NewFfElement(ps->Fq6, &t0); 1928 BREAK_ON_EPID_ERROR(retvalue); 1929 retvalue = NewFfElement(ps->Fq6, &t1); 1930 BREAK_ON_EPID_ERROR(retvalue); 1931 retvalue = NewFfElement(ps->Fq6, &t2); 1932 BREAK_ON_EPID_ERROR(retvalue); 1933 retvalue = NewFfElement(ps->Fq2, &b0plusb1); 1934 BREAK_ON_EPID_ERROR(retvalue); 1935 1936 // 1. Let a = (a[0], a[1]) and e = (e[0], e[1]). 1937 retvalue = NewFfElement(ps->Fq6, &a0); 1938 BREAK_ON_EPID_ERROR(retvalue); 1939 retvalue = NewFfElement(ps->Fq6, &a1); 1940 BREAK_ON_EPID_ERROR(retvalue); 1941 retvalue = NewFfElement(ps->Fq6, &e0); 1942 BREAK_ON_EPID_ERROR(retvalue); 1943 retvalue = NewFfElement(ps->Fq6, &e1); 1944 BREAK_ON_EPID_ERROR(retvalue); 1945 1946 sts = ippsGFpGetElement(a->ipp_ff_elem, (BNU)&a_dat, 1947 sizeof(a_dat) / sizeof(Ipp32u), ps->ff->ipp_ff); 1948 BREAK_ON_IPP_ERROR(sts, retvalue); 1949 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[0], 1950 sizeof(a_dat.x[0]) / sizeof(Ipp32u), 1951 a0->ipp_ff_elem, ps->Fq6->ipp_ff); 1952 BREAK_ON_IPP_ERROR(sts, retvalue); 1953 sts = ippsGFpSetElement((Ipp32u*)&a_dat.x[1], 1954 sizeof(a_dat.x[1]) / sizeof(Ipp32u), 1955 a1->ipp_ff_elem, ps->Fq6->ipp_ff); 1956 BREAK_ON_IPP_ERROR(sts, retvalue); 1957 1958 // 2. Let b = ((b[0], b[2], b[4]), (b[1], b[3], b[5])) where 1959 // b[0], ..., b[5] are elements in ps->Fq2 and b[2] = b[4] = b[5] 1960 // = 0. 1961 retvalue = NewFfElement(ps->Fq2, &b0); 1962 BREAK_ON_EPID_ERROR(retvalue); 1963 retvalue = NewFfElement(ps->Fq2, &b1); 1964 BREAK_ON_EPID_ERROR(retvalue); 1965 retvalue = NewFfElement(ps->Fq2, &b3); 1966 BREAK_ON_EPID_ERROR(retvalue); 1967 1968 sts = ippsGFpGetElement(b->ipp_ff_elem, (BNU)&b_dat, 1969 sizeof(b_dat) / sizeof(Ipp32u), ps->ff->ipp_ff); 1970 BREAK_ON_IPP_ERROR(sts, retvalue); 1971 sts = ippsGFpSetElement((Ipp32u*)&b_dat.x[0].x[0], 1972 sizeof(a_dat.x[0].x[0]) / sizeof(Ipp32u), 1973 b0->ipp_ff_elem, ps->Fq2->ipp_ff); 1974 BREAK_ON_IPP_ERROR(sts, retvalue); 1975 sts = ippsGFpSetElement((Ipp32u*)&b_dat.x[1].x[0], 1976 sizeof(a_dat.x[1].x[0]) / sizeof(Ipp32u), 1977 b1->ipp_ff_elem, ps->Fq2->ipp_ff); 1978 BREAK_ON_IPP_ERROR(sts, retvalue); 1979 sts = ippsGFpSetElement((Ipp32u*)&b_dat.x[1].x[1], 1980 sizeof(a_dat.x[1].x[1]) / sizeof(Ipp32u), 1981 b3->ipp_ff_elem, ps->Fq2->ipp_ff); 1982 BREAK_ON_IPP_ERROR(sts, retvalue); 1983 1984 // 3. t0 = ps->Fq6.mul(a[0], b[0]). 1985 1986 sts = ippsGFpMul_PE(a0->ipp_ff_elem, b0->ipp_ff_elem, t0->ipp_ff_elem, 1987 ps->Fq6->ipp_ff); 1988 BREAK_ON_IPP_ERROR(sts, retvalue); 1989 // 4. t1 = ps->Fq6.mul(a[1], b[1], b[3]). 1990 retvalue = Fq6MulGFpE2(t1, a1, b1, b3, ps); 1991 BREAK_ON_EPID_ERROR(retvalue); 1992 // 5. e[0] = ps->Fq6.MulV(t1). 1993 retvalue = MulV(e0, t1, ps); 1994 BREAK_ON_EPID_ERROR(retvalue); 1995 // 6. e[0] = ps->Fq6.add(t0, e[0]). 1996 sts = ippsGFpAdd(t0->ipp_ff_elem, e0->ipp_ff_elem, e0->ipp_ff_elem, 1997 ps->Fq6->ipp_ff); 1998 BREAK_ON_IPP_ERROR(sts, retvalue); 1999 // 7. t2 = ps->Fq6.add(a[0], a[1]). 2000 sts = ippsGFpAdd(a0->ipp_ff_elem, a1->ipp_ff_elem, t2->ipp_ff_elem, 2001 ps->Fq6->ipp_ff); 2002 BREAK_ON_IPP_ERROR(sts, retvalue); 2003 // 8. e[1] = ps->Fq6.mul(t2, b[0] + b[1], b[3]). 2004 sts = ippsGFpAdd(b0->ipp_ff_elem, b1->ipp_ff_elem, b0plusb1->ipp_ff_elem, 2005 ps->Fq2->ipp_ff); 2006 BREAK_ON_IPP_ERROR(sts, retvalue); 2007 retvalue = Fq6MulGFpE2(e1, t2, b0plusb1, b3, ps); 2008 BREAK_ON_EPID_ERROR(retvalue); 2009 // 9. e[1] = ps->Fq6.subtract(e[1], t0). 2010 sts = ippsGFpSub(e1->ipp_ff_elem, t0->ipp_ff_elem, e1->ipp_ff_elem, 2011 ps->Fq6->ipp_ff); 2012 BREAK_ON_IPP_ERROR(sts, retvalue); 2013 // 10. e[1] = ps->Fq6.subtract(e[1], t1). 2014 sts = ippsGFpSub(e1->ipp_ff_elem, t1->ipp_ff_elem, e1->ipp_ff_elem, 2015 ps->Fq6->ipp_ff); 2016 BREAK_ON_IPP_ERROR(sts, retvalue); 2017 // 11. Return e. 2018 sts = 2019 ippsGFpGetElement(e0->ipp_ff_elem, (BNU)&e_dat.x[0], 2020 sizeof(e_dat.x[0]) / sizeof(Ipp32u), ps->Fq6->ipp_ff); 2021 BREAK_ON_IPP_ERROR(sts, retvalue); 2022 sts = 2023 ippsGFpGetElement(e1->ipp_ff_elem, (BNU)&e_dat.x[1], 2024 sizeof(e_dat.x[1]) / sizeof(Ipp32u), ps->Fq6->ipp_ff); 2025 BREAK_ON_IPP_ERROR(sts, retvalue); 2026 sts = ippsGFpSetElement((Ipp32u*)&e_dat, sizeof(e_dat) / sizeof(Ipp32u), 2027 e->ipp_ff_elem, ps->ff->ipp_ff); 2028 BREAK_ON_IPP_ERROR(sts, retvalue); 2029 retvalue = kEpidNoErr; 2030 } while (0); 2031 EpidZeroMemory(&a_dat, sizeof(a_dat)); 2032 EpidZeroMemory(&b_dat, sizeof(b_dat)); 2033 EpidZeroMemory(&e_dat, sizeof(e_dat)); 2034 DeleteFfElement(&t0); 2035 DeleteFfElement(&t1); 2036 DeleteFfElement(&t2); 2037 DeleteFfElement(&a0); 2038 DeleteFfElement(&a1); 2039 DeleteFfElement(&b0); 2040 DeleteFfElement(&b1); 2041 DeleteFfElement(&b3); 2042 DeleteFfElement(&e0); 2043 DeleteFfElement(&e1); 2044 DeleteFfElement(&b0plusb1); 2045 2046 return (retvalue); 2047 } 2048 2049 /* 2050 (e0, e1) = Fq12.SquareForFq4(a0, a1) 2051 Input: a0, a1 (elements in Fq2) 2052 Output: e0, e1 (elements in Fq2) where e = a * a in Fq4 2053 */ 2054 static EpidStatus SquareForFq4(PairingState* ps, FfElement* e0, FfElement* e1, 2055 FfElement const* a0, FfElement const* a1) { 2056 EpidStatus result = kEpidErr; 2057 FfElement* t0 = NULL; 2058 FfElement* t1 = NULL; 2059 FfElement* xi = NULL; 2060 Fq2ElemStr Fq6IrrPolynomial = {0}; 2061 2062 // check parameters 2063 if (!e0 || !e1 || !a0 || !a1 || !ps) return kEpidBadArgErr; 2064 if (!ps->Fq2 || !ps->Fq6) { 2065 return kEpidBadArgErr; 2066 } 2067 if (!e0->ipp_ff_elem || !e1->ipp_ff_elem || !a0->ipp_ff_elem || 2068 !a1->ipp_ff_elem || !ps->ff || !ps->ff->ipp_ff || !ps->Fq2->ipp_ff || 2069 !ps->Fq6->ipp_ff) 2070 return kEpidBadArgErr; 2071 2072 do { 2073 IppStatus sts = ippStsNoErr; 2074 2075 // extract xi from Fq6 irr poly 2076 result = NewFfElement(ps->Fq2, &xi); 2077 BREAK_ON_EPID_ERROR(result); 2078 result = WriteBigNum(ps->Fq6->modulus_0, sizeof(Fq6IrrPolynomial), 2079 &Fq6IrrPolynomial); 2080 BREAK_ON_EPID_ERROR(result); 2081 result = SetFfElementOctString(&Fq6IrrPolynomial, sizeof(Fq6IrrPolynomial), 2082 xi, ps->Fq2); 2083 BREAK_ON_EPID_ERROR(result); 2084 // first coefficent is -xi 2085 sts = ippsGFpNeg(xi->ipp_ff_elem, xi->ipp_ff_elem, ps->Fq2->ipp_ff); 2086 BREAK_ON_IPP_ERROR(sts, result); 2087 2088 // Let t0, t1 be temporary variables in Fq2. All the following 2089 // operations are computed in Fq2. 2090 result = NewFfElement(ps->Fq2, &t0); 2091 BREAK_ON_EPID_ERROR(result); 2092 result = NewFfElement(ps->Fq2, &t1); 2093 BREAK_ON_EPID_ERROR(result); 2094 2095 // 1. Set t0 = a0 * a0. 2096 sts = ippsGFpMul(a0->ipp_ff_elem, a0->ipp_ff_elem, t0->ipp_ff_elem, 2097 ps->Fq2->ipp_ff); 2098 BREAK_ON_IPP_ERROR(sts, result); 2099 // 2. Set t1 = a1 * a1. 2100 sts = ippsGFpMul(a1->ipp_ff_elem, a1->ipp_ff_elem, t1->ipp_ff_elem, 2101 ps->Fq2->ipp_ff); 2102 BREAK_ON_IPP_ERROR(sts, result); 2103 // 3. Set e0 = t1 * xi. 2104 sts = ippsGFpMul(t1->ipp_ff_elem, xi->ipp_ff_elem, e0->ipp_ff_elem, 2105 ps->Fq2->ipp_ff); 2106 BREAK_ON_IPP_ERROR(sts, result); 2107 // 4. Set e0 = e0 + t0. 2108 sts = ippsGFpAdd(e0->ipp_ff_elem, t0->ipp_ff_elem, e0->ipp_ff_elem, 2109 ps->Fq2->ipp_ff); 2110 BREAK_ON_IPP_ERROR(sts, result); 2111 // 5. Set e1 = a0 + a1. 2112 sts = ippsGFpAdd(a0->ipp_ff_elem, a1->ipp_ff_elem, e1->ipp_ff_elem, 2113 ps->Fq2->ipp_ff); 2114 BREAK_ON_IPP_ERROR(sts, result); 2115 // 6. Set e1 = e1 * e1 - t0 - t1. 2116 sts = ippsGFpMul(e1->ipp_ff_elem, e1->ipp_ff_elem, e1->ipp_ff_elem, 2117 ps->Fq2->ipp_ff); 2118 BREAK_ON_IPP_ERROR(sts, result); 2119 sts = ippsGFpSub(e1->ipp_ff_elem, t0->ipp_ff_elem, e1->ipp_ff_elem, 2120 ps->Fq2->ipp_ff); 2121 BREAK_ON_IPP_ERROR(sts, result); 2122 sts = ippsGFpSub(e1->ipp_ff_elem, t1->ipp_ff_elem, e1->ipp_ff_elem, 2123 ps->Fq2->ipp_ff); 2124 BREAK_ON_IPP_ERROR(sts, result); 2125 // 7. Return (e0, e1). 2126 result = kEpidNoErr; 2127 } while (0); 2128 2129 EpidZeroMemory(&Fq6IrrPolynomial, sizeof(Fq6IrrPolynomial)); 2130 DeleteFfElement(&t0); 2131 DeleteFfElement(&t1); 2132 DeleteFfElement(&xi); 2133 2134 return (result); 2135 } 2136 2137 /* 2138 e = Fq12.squareCyclotomic(a) 2139 Input: a (an element in Fq12) 2140 Output: e (an element in Fq12) where e = a * a 2141 */ 2142 static EpidStatus SquareCyclotomic(PairingState* ps, FfElement* e_out, 2143 FfElement const* a_in) { 2144 EpidStatus result = kEpidErr; 2145 FfElement* t00 = NULL; 2146 FfElement* t01 = NULL; 2147 FfElement* t02 = NULL; 2148 FfElement* t10 = NULL; 2149 FfElement* t11 = NULL; 2150 FfElement* t12 = NULL; 2151 2152 FfElement* a[6] = {0}; 2153 FfElement* e[6] = {0}; 2154 2155 FfElement* xi = NULL; 2156 int i = 0; 2157 Fq12ElemStr a_str = {0}; 2158 Fq12ElemStr e_str = {0}; 2159 Fq2ElemStr Fq6IrrPolynomial = {0}; 2160 2161 // check parameters 2162 if (!e_out || !a_in || !ps) return kEpidBadArgErr; 2163 if (!ps->Fq || !ps->Fq2 || !ps->Fq6) { 2164 return kEpidBadArgErr; 2165 } 2166 if (!e_out->ipp_ff_elem || !a_in->ipp_ff_elem || !ps->ff || !ps->ff->ipp_ff || 2167 !ps->Fq->ipp_ff || !ps->Fq2->ipp_ff || !ps->Fq6->ipp_ff) 2168 return kEpidBadArgErr; 2169 2170 do { 2171 IppStatus sts = ippStsNoErr; 2172 2173 // extract xi from Fq6 irr poly 2174 result = NewFfElement(ps->Fq2, &xi); 2175 BREAK_ON_EPID_ERROR(result); 2176 result = WriteBigNum(ps->Fq6->modulus_0, sizeof(Fq6IrrPolynomial), 2177 &Fq6IrrPolynomial); 2178 BREAK_ON_EPID_ERROR(result); 2179 result = SetFfElementOctString(&Fq6IrrPolynomial, sizeof(Fq6IrrPolynomial), 2180 xi, ps->Fq2); 2181 BREAK_ON_EPID_ERROR(result); 2182 // first coefficent is -xi 2183 sts = ippsGFpNeg(xi->ipp_ff_elem, xi->ipp_ff_elem, ps->Fq2->ipp_ff); 2184 BREAK_ON_IPP_ERROR(sts, result); 2185 2186 // Let t00, t01, t02, t10, t11, t12 be temporary variables in 2187 // Fq2. All the following operations are computed in Fq2 unless 2188 // specified otherwise. 2189 result = NewFfElement(ps->Fq2, &t00); 2190 BREAK_ON_EPID_ERROR(result); 2191 result = NewFfElement(ps->Fq2, &t01); 2192 BREAK_ON_EPID_ERROR(result); 2193 result = NewFfElement(ps->Fq2, &t02); 2194 BREAK_ON_EPID_ERROR(result); 2195 result = NewFfElement(ps->Fq2, &t10); 2196 BREAK_ON_EPID_ERROR(result); 2197 result = NewFfElement(ps->Fq2, &t11); 2198 BREAK_ON_EPID_ERROR(result); 2199 result = NewFfElement(ps->Fq2, &t12); 2200 BREAK_ON_EPID_ERROR(result); 2201 for (i = 0; i < 6; i++) { 2202 result = NewFfElement(ps->Fq2, &a[i]); 2203 BREAK_ON_EPID_ERROR(result); 2204 result = NewFfElement(ps->Fq2, &e[i]); 2205 BREAK_ON_EPID_ERROR(result); 2206 } 2207 BREAK_ON_EPID_ERROR(result); 2208 // 1. Let a = ((a[0], a[2], a[4]), (a[1], a[3], a[5])). 2209 sts = ippsGFpGetElement(a_in->ipp_ff_elem, (BNU)&a_str, 2210 sizeof(a_str) / sizeof(Ipp32u), ps->ff->ipp_ff); 2211 BREAK_ON_IPP_ERROR(sts, result); 2212 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[0].a[0], 2213 sizeof(a_str.a[0].a[0]) / sizeof(Ipp32u), 2214 a[0]->ipp_ff_elem, ps->Fq2->ipp_ff); 2215 BREAK_ON_IPP_ERROR(sts, result); 2216 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[0].a[1], 2217 sizeof(a_str.a[0].a[1]) / sizeof(Ipp32u), 2218 a[2]->ipp_ff_elem, ps->Fq2->ipp_ff); 2219 BREAK_ON_IPP_ERROR(sts, result); 2220 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[0].a[2], 2221 sizeof(a_str.a[0].a[2]) / sizeof(Ipp32u), 2222 a[4]->ipp_ff_elem, ps->Fq2->ipp_ff); 2223 BREAK_ON_IPP_ERROR(sts, result); 2224 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[1].a[0], 2225 sizeof(a_str.a[1].a[0]) / sizeof(Ipp32u), 2226 a[1]->ipp_ff_elem, ps->Fq2->ipp_ff); 2227 BREAK_ON_IPP_ERROR(sts, result); 2228 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[1].a[1], 2229 sizeof(a_str.a[1].a[1]) / sizeof(Ipp32u), 2230 a[3]->ipp_ff_elem, ps->Fq2->ipp_ff); 2231 BREAK_ON_IPP_ERROR(sts, result); 2232 sts = ippsGFpSetElement((Ipp32u*)&a_str.a[1].a[2], 2233 sizeof(a_str.a[1].a[2]) / sizeof(Ipp32u), 2234 a[5]->ipp_ff_elem, ps->Fq2->ipp_ff); 2235 BREAK_ON_IPP_ERROR(sts, result); 2236 // 2. Let e = ((e[0], e[2], e[4]), (e[1], e[3], e[5])). 2237 2238 // 3. (t00, t11) = Fq12.SquareForFq4(a[0], a[3]). 2239 result = SquareForFq4(ps, t00, t11, a[0], a[3]); 2240 BREAK_ON_EPID_ERROR(result); 2241 // 4. (t01, t12) = Fq12.SquareForFq4(a[1], a[4]). 2242 result = SquareForFq4(ps, t01, t12, a[1], a[4]); 2243 BREAK_ON_EPID_ERROR(result); 2244 // 5. (t02, t10) = Fq12.SquareForFq4(a[2], a[5]). 2245 result = SquareForFq4(ps, t02, t10, a[2], a[5]); 2246 BREAK_ON_EPID_ERROR(result); 2247 // 6. Set t10 = t10 * xi. 2248 sts = ippsGFpMul(t10->ipp_ff_elem, xi->ipp_ff_elem, t10->ipp_ff_elem, 2249 ps->Fq2->ipp_ff); 2250 BREAK_ON_IPP_ERROR(sts, result); 2251 // 7. Set e[0] = 3 * t00 - 2 * a[0]. 2252 sts = ippsGFpAdd(t00->ipp_ff_elem, t00->ipp_ff_elem, e[0]->ipp_ff_elem, 2253 ps->Fq2->ipp_ff); 2254 BREAK_ON_IPP_ERROR(sts, result); 2255 sts = ippsGFpAdd(e[0]->ipp_ff_elem, t00->ipp_ff_elem, e[0]->ipp_ff_elem, 2256 ps->Fq2->ipp_ff); 2257 BREAK_ON_IPP_ERROR(sts, result); 2258 sts = ippsGFpSub(e[0]->ipp_ff_elem, a[0]->ipp_ff_elem, e[0]->ipp_ff_elem, 2259 ps->Fq2->ipp_ff); 2260 BREAK_ON_IPP_ERROR(sts, result); 2261 sts = ippsGFpSub(e[0]->ipp_ff_elem, a[0]->ipp_ff_elem, e[0]->ipp_ff_elem, 2262 ps->Fq2->ipp_ff); 2263 BREAK_ON_IPP_ERROR(sts, result); 2264 // 8. Set e[2] = 3 * t01 - 2 * a[2]. 2265 sts = ippsGFpAdd(t01->ipp_ff_elem, t01->ipp_ff_elem, e[2]->ipp_ff_elem, 2266 ps->Fq2->ipp_ff); 2267 BREAK_ON_IPP_ERROR(sts, result); 2268 sts = ippsGFpAdd(e[2]->ipp_ff_elem, t01->ipp_ff_elem, e[2]->ipp_ff_elem, 2269 ps->Fq2->ipp_ff); 2270 BREAK_ON_IPP_ERROR(sts, result); 2271 sts = ippsGFpSub(e[2]->ipp_ff_elem, a[2]->ipp_ff_elem, e[2]->ipp_ff_elem, 2272 ps->Fq2->ipp_ff); 2273 BREAK_ON_IPP_ERROR(sts, result); 2274 sts = ippsGFpSub(e[2]->ipp_ff_elem, a[2]->ipp_ff_elem, e[2]->ipp_ff_elem, 2275 ps->Fq2->ipp_ff); 2276 BREAK_ON_IPP_ERROR(sts, result); 2277 // 9. Set e[4] = 3 * t02 - 2 * a[4]. 2278 sts = ippsGFpAdd(t02->ipp_ff_elem, t02->ipp_ff_elem, e[4]->ipp_ff_elem, 2279 ps->Fq2->ipp_ff); 2280 BREAK_ON_IPP_ERROR(sts, result); 2281 sts = ippsGFpAdd(e[4]->ipp_ff_elem, t02->ipp_ff_elem, e[4]->ipp_ff_elem, 2282 ps->Fq2->ipp_ff); 2283 BREAK_ON_IPP_ERROR(sts, result); 2284 sts = ippsGFpSub(e[4]->ipp_ff_elem, a[4]->ipp_ff_elem, e[4]->ipp_ff_elem, 2285 ps->Fq2->ipp_ff); 2286 BREAK_ON_IPP_ERROR(sts, result); 2287 sts = ippsGFpSub(e[4]->ipp_ff_elem, a[4]->ipp_ff_elem, e[4]->ipp_ff_elem, 2288 ps->Fq2->ipp_ff); 2289 BREAK_ON_IPP_ERROR(sts, result); 2290 // 10. Set e[1] = 3 * t10 + 2 * a[1]. 2291 sts = ippsGFpAdd(t10->ipp_ff_elem, t10->ipp_ff_elem, e[1]->ipp_ff_elem, 2292 ps->Fq2->ipp_ff); 2293 BREAK_ON_IPP_ERROR(sts, result); 2294 sts = ippsGFpAdd(e[1]->ipp_ff_elem, t10->ipp_ff_elem, e[1]->ipp_ff_elem, 2295 ps->Fq2->ipp_ff); 2296 BREAK_ON_IPP_ERROR(sts, result); 2297 sts = ippsGFpAdd(e[1]->ipp_ff_elem, a[1]->ipp_ff_elem, e[1]->ipp_ff_elem, 2298 ps->Fq2->ipp_ff); 2299 BREAK_ON_IPP_ERROR(sts, result); 2300 sts = ippsGFpAdd(e[1]->ipp_ff_elem, a[1]->ipp_ff_elem, e[1]->ipp_ff_elem, 2301 ps->Fq2->ipp_ff); 2302 BREAK_ON_IPP_ERROR(sts, result); 2303 // 11. Set e[3] = 3 * t11 + 2 * a[3]. 2304 sts = ippsGFpAdd(t11->ipp_ff_elem, t11->ipp_ff_elem, e[3]->ipp_ff_elem, 2305 ps->Fq2->ipp_ff); 2306 BREAK_ON_IPP_ERROR(sts, result); 2307 sts = ippsGFpAdd(e[3]->ipp_ff_elem, t11->ipp_ff_elem, e[3]->ipp_ff_elem, 2308 ps->Fq2->ipp_ff); 2309 BREAK_ON_IPP_ERROR(sts, result); 2310 sts = ippsGFpAdd(e[3]->ipp_ff_elem, a[3]->ipp_ff_elem, e[3]->ipp_ff_elem, 2311 ps->Fq2->ipp_ff); 2312 BREAK_ON_IPP_ERROR(sts, result); 2313 sts = ippsGFpAdd(e[3]->ipp_ff_elem, a[3]->ipp_ff_elem, e[3]->ipp_ff_elem, 2314 ps->Fq2->ipp_ff); 2315 BREAK_ON_IPP_ERROR(sts, result); 2316 // 12. Set e[5] = 3 * t12 + 2 * a[5]. 2317 sts = ippsGFpAdd(t12->ipp_ff_elem, t12->ipp_ff_elem, e[5]->ipp_ff_elem, 2318 ps->Fq2->ipp_ff); 2319 BREAK_ON_IPP_ERROR(sts, result); 2320 sts = ippsGFpAdd(e[5]->ipp_ff_elem, t12->ipp_ff_elem, e[5]->ipp_ff_elem, 2321 ps->Fq2->ipp_ff); 2322 BREAK_ON_IPP_ERROR(sts, result); 2323 sts = ippsGFpAdd(e[5]->ipp_ff_elem, a[5]->ipp_ff_elem, e[5]->ipp_ff_elem, 2324 ps->Fq2->ipp_ff); 2325 BREAK_ON_IPP_ERROR(sts, result); 2326 sts = ippsGFpAdd(e[5]->ipp_ff_elem, a[5]->ipp_ff_elem, e[5]->ipp_ff_elem, 2327 ps->Fq2->ipp_ff); 2328 BREAK_ON_IPP_ERROR(sts, result); 2329 // 13. Return e. 2330 sts = ippsGFpGetElement(e[0]->ipp_ff_elem, (BNU)&e_str.a[0].a[0], 2331 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2332 ps->Fq2->ipp_ff); 2333 BREAK_ON_IPP_ERROR(sts, result); 2334 sts = ippsGFpGetElement(e[2]->ipp_ff_elem, (BNU)&e_str.a[0].a[1], 2335 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2336 ps->Fq2->ipp_ff); 2337 BREAK_ON_IPP_ERROR(sts, result); 2338 sts = ippsGFpGetElement(e[4]->ipp_ff_elem, (BNU)&e_str.a[0].a[2], 2339 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2340 ps->Fq2->ipp_ff); 2341 BREAK_ON_IPP_ERROR(sts, result); 2342 sts = ippsGFpGetElement(e[1]->ipp_ff_elem, (BNU)&e_str.a[1].a[0], 2343 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2344 ps->Fq2->ipp_ff); 2345 BREAK_ON_IPP_ERROR(sts, result); 2346 sts = ippsGFpGetElement(e[3]->ipp_ff_elem, (BNU)&e_str.a[1].a[1], 2347 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2348 ps->Fq2->ipp_ff); 2349 BREAK_ON_IPP_ERROR(sts, result); 2350 sts = ippsGFpGetElement(e[5]->ipp_ff_elem, (BNU)&e_str.a[1].a[2], 2351 sizeof(e_str.a[0].a[0]) / sizeof(Ipp32u), 2352 ps->Fq2->ipp_ff); 2353 BREAK_ON_IPP_ERROR(sts, result); 2354 sts = ippsGFpSetElement((Ipp32u*)&e_str, sizeof(e_str) / sizeof(Ipp32u), 2355 e_out->ipp_ff_elem, ps->ff->ipp_ff); 2356 BREAK_ON_IPP_ERROR(sts, result); 2357 result = kEpidNoErr; 2358 } while (0); 2359 2360 EpidZeroMemory(&a_str, sizeof(a_str)); 2361 EpidZeroMemory(&e_str, sizeof(e_str)); 2362 EpidZeroMemory(&Fq6IrrPolynomial, sizeof(Fq6IrrPolynomial)); 2363 DeleteFfElement(&t00); 2364 DeleteFfElement(&t01); 2365 DeleteFfElement(&t02); 2366 DeleteFfElement(&t10); 2367 DeleteFfElement(&t11); 2368 DeleteFfElement(&t12); 2369 2370 for (i = 0; i < 6; i++) { 2371 DeleteFfElement(&a[i]); 2372 DeleteFfElement(&e[i]); 2373 } 2374 2375 DeleteFfElement(&xi); 2376 2377 return (result); 2378 } 2379 2380 /* 2381 e = Fq12.expCyclotomic(a, b) 2382 Input: a (an element in Fq12), b (a non-negative integer) 2383 Output: e (an element in Fq12) where e = a^b 2384 Steps: 2385 2386 2. Set e = a. 2387 3. For i = n-1, ..., 0, do the following: 2388 e = Fq12.squareCyclotomic(e, e), 2389 If bi = 1, compute e = Fq12.mul(e, a). 2390 4. Return e. 2391 */ 2392 static EpidStatus ExpCyclotomic(PairingState* ps, FfElement* e, 2393 FfElement const* a, BigNum const* b) { 2394 EpidStatus result = kEpidErr; 2395 2396 // check parameters 2397 if (!e || !a || !b || !ps) return kEpidBadArgErr; 2398 if (!ps->Fq || !ps->Fq2) { 2399 return kEpidBadArgErr; 2400 } 2401 if (!e->ipp_ff_elem || !a->ipp_ff_elem || !ps->Fq->ipp_ff || 2402 !ps->Fq2->ipp_ff || !b->ipp_bn) 2403 return kEpidBadArgErr; 2404 2405 do { 2406 IppStatus sts = ippStsNoErr; 2407 int num_bits = 0; 2408 IppBNU b_str = 0; 2409 int i = 0; 2410 2411 // 1. Let bn...b1b0 be the binary representation of b. 2412 sts = ippsRef_BN(0, &num_bits, &b_str, b->ipp_bn); 2413 BREAK_ON_IPP_ERROR(sts, result); 2414 // 2. Set e = a. 2415 sts = ippsGFpCpyElement(a->ipp_ff_elem, e->ipp_ff_elem, ps->ff->ipp_ff); 2416 BREAK_ON_IPP_ERROR(sts, result); 2417 // 3. For i = n-1, ..., 0, do the following: 2418 for (i = num_bits - 2; i >= 0; i--) { 2419 // e = Fq12.squareCyclotomic(e, e), 2420 result = SquareCyclotomic(ps, e, e); 2421 BREAK_ON_EPID_ERROR(result); 2422 // If bi = 1, compute e = Fq12.mul(e, a). 2423 if (1 == Bit(b_str, i)) { 2424 sts = ippsGFpMul(e->ipp_ff_elem, a->ipp_ff_elem, e->ipp_ff_elem, 2425 ps->ff->ipp_ff); 2426 BREAK_ON_IPP_ERROR(sts, result); 2427 } 2428 // 4. Return e. 2429 } 2430 result = kEpidNoErr; 2431 } while (0); 2432 2433 return (result); 2434 } 2435