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
NewPairingState(EcGroup const * ga,EcGroup const * gb,FiniteField * ff,BigNumStr const * t,bool neg,PairingState ** ps)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
DeletePairingState(PairingState ** ps)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
Pairing(PairingState * ps,EcPoint const * a,EcPoint const * b,FfElement * d)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 */
FinalExp(PairingState * ps,FfElement * d,FfElement const * h)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 */
PiOp(PairingState * ps,FfElement * x_out,FfElement * y_out,FfElement const * x,FfElement const * y,const int e)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 */
FrobeniusOp(PairingState * ps,FfElement * d_out,FfElement const * a,const int e)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 */
Line(FiniteField * gt,FfElement * f,FfElement * x_out,FfElement * y_out,FfElement * z_out,FfElement * z2_out,FfElement const * px,FfElement const * py,FfElement const * x,FfElement const * y,FfElement const * z,FfElement const * z2,FfElement const * qx,FfElement const * qy)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 */
Tangent(FiniteField * gt,FfElement * f,FfElement * x_out,FfElement * y_out,FfElement * z_out,FfElement * z2_out,FfElement const * px,FfElement const * py,FfElement const * x,FfElement const * y,FfElement const * z,FfElement const * z2)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 */
Ternary(int * s,int * n,int max_elements,BigNum const * x)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
Bit(Ipp32u const * num,Ipp32u bit_index)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 */
MulXiFast(FfElement * e,FfElement const * a,PairingState * ps)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 */
MulV(FfElement * e,FfElement * a,PairingState * ps)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 */
Fq6MulGFpE2(FfElement * e,FfElement * a,FfElement * b0,FfElement * b1,PairingState * ps)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 */
MulSpecial(FfElement * e,FfElement const * a,FfElement const * b,PairingState * ps)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 */
SquareForFq4(PairingState * ps,FfElement * e0,FfElement * e1,FfElement const * a0,FfElement const * a1)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 */
SquareCyclotomic(PairingState * ps,FfElement * e_out,FfElement const * a_in)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 */
ExpCyclotomic(PairingState * ps,FfElement * e,FfElement const * a,BigNum const * b)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