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 Intel(R) EPID 2.0 constant parameters implementation.
20 */
21 #include "epid/common/src/epid2params.h"
22 #include "epid/common/src/memory.h"
23
24 /// create a new Finite Field Fp
25 static EpidStatus NewFp(Epid2Params const* param, FiniteField** Fp);
26 /// create a new Finite Field Fq
27 static EpidStatus NewFq(Epid2Params const* param, FiniteField** Fq);
28 /// create a new Finite Field Fq2
29 static EpidStatus NewFq2(Epid2Params const* param, FiniteField* Fq,
30 FiniteField** Fq2);
31 /// create a new Finite Field Fq6
32 EpidStatus NewFq6(Epid2Params const* param, FiniteField* Fq2, FfElement* xi,
33 FiniteField** Fq6);
34 /// create a new Elliptic curve group G1 over Fq
35 static EpidStatus NewG1(Epid2Params const* param, FiniteField* Fq,
36 EcGroup** G1);
37 /// create a new Elliptic curve group G2 over Fq2
38 static EpidStatus NewG2(Epid2Params const* param, BigNum* p, BigNum* q,
39 FiniteField* Fq, FiniteField* Fq2, EcGroup** G2);
40 /// create a new Finite Field Fq12
41 static EpidStatus NewGT(FiniteField* Fq6, FiniteField** GT);
42 /// create a new pairing state
43
44 /// Deallocate Finite Field Fp
45 static void DeleteFp(FiniteField** Fp);
46
47 /// Deallocate Finite Field Fq
48 static void DeleteFq(FiniteField** Fq);
49 /// Deallocate Finite Field Fq2
50 static void DeleteFq2(FiniteField** Fq2);
51 /// Deallocate Finite Field Fq6
52 static void DeleteFq6(FiniteField** Fq6);
53 /// Deallocate Elliptic curve group G1 over Fq
54 static void DeleteG1(EcGroup** G1);
55 /// Deallocate Elliptic curve group G2 over Fq2
56 static void DeleteG2(EcGroup** G2);
57 /// Deallocate Finite Field Fq12
58 static void DeleteGT(FiniteField** GT);
59
CreateEpid2Params(Epid2Params_ ** params)60 EpidStatus CreateEpid2Params(Epid2Params_** params) {
61 EpidStatus result = kEpidErr;
62 Epid2Params_* internal_param = NULL;
63 BigNumStr t_str = {0};
64 Epid2Params params_str = {
65 #include "epid/common/src/epid2params_ate.inc"
66 };
67 if (!params) {
68 return kEpidBadArgErr;
69 }
70 do {
71 internal_param = SAFE_ALLOC(sizeof(Epid2Params_));
72 if (!internal_param) {
73 result = kEpidMemAllocErr;
74 break;
75 }
76 result = NewBigNum(sizeof(params_str.p), &internal_param->p);
77 if (kEpidNoErr != result) {
78 break;
79 }
80 result = ReadBigNum(¶ms_str.p, sizeof(params_str.p), internal_param->p);
81 if (kEpidNoErr != result) {
82 break;
83 }
84 result = NewBigNum(sizeof(params_str.q), &internal_param->q);
85 if (kEpidNoErr != result) {
86 break;
87 }
88 result = ReadBigNum(¶ms_str.q, sizeof(params_str.q), internal_param->q);
89 if (kEpidNoErr != result) {
90 break;
91 }
92 result = NewBigNum(sizeof(params_str.t), &internal_param->t);
93 if (kEpidNoErr != result) {
94 break;
95 }
96 result = ReadBigNum(¶ms_str.t, sizeof(params_str.t), internal_param->t);
97 if (kEpidNoErr != result) {
98 break;
99 }
100 internal_param->neg = (params_str.neg.data[0]) ? true : false;
101
102 result = NewFp(¶ms_str, &internal_param->Fp);
103 if (kEpidNoErr != result) {
104 break;
105 }
106 result = NewFq(¶ms_str, &internal_param->Fq);
107 if (kEpidNoErr != result) {
108 break;
109 }
110 result = NewFq2(¶ms_str, internal_param->Fq, &internal_param->Fq2);
111 if (kEpidNoErr != result) {
112 break;
113 }
114 result = NewFfElement(internal_param->Fq, &internal_param->b);
115 if (kEpidNoErr != result) {
116 break;
117 }
118 result = ReadFfElement(internal_param->Fq, ¶ms_str.b,
119 sizeof(params_str.b), internal_param->b);
120 if (kEpidNoErr != result) {
121 break;
122 }
123 result = NewFfElement(internal_param->Fq2, &internal_param->xi);
124 if (kEpidNoErr != result) {
125 break;
126 }
127 result = ReadFfElement(internal_param->Fq2, ¶ms_str.xi,
128 sizeof(params_str.xi), internal_param->xi);
129 if (kEpidNoErr != result) {
130 break;
131 }
132 result = NewFq6(¶ms_str, internal_param->Fq2, internal_param->xi,
133 &internal_param->Fq6);
134 if (kEpidNoErr != result) {
135 break;
136 }
137 result = NewGT(internal_param->Fq6, &internal_param->GT);
138 if (kEpidNoErr != result) {
139 break;
140 }
141 result = NewG1(¶ms_str, internal_param->Fq, &internal_param->G1);
142 if (kEpidNoErr != result) {
143 break;
144 }
145 result = NewEcPoint(internal_param->G1, &internal_param->g1);
146 if (kEpidNoErr != result) {
147 break;
148 }
149 result = ReadEcPoint(internal_param->G1, ¶ms_str.g1,
150 sizeof(params_str.g1), internal_param->g1);
151 if (kEpidNoErr != result) {
152 break;
153 }
154 result =
155 NewG2(¶ms_str, internal_param->p, internal_param->q,
156 internal_param->Fq, internal_param->Fq2, &internal_param->G2);
157 if (kEpidNoErr != result) {
158 break;
159 }
160 result = NewEcPoint(internal_param->G2, &internal_param->g2);
161 if (kEpidNoErr != result) {
162 break;
163 }
164 result = ReadEcPoint(internal_param->G2, ¶ms_str.g2,
165 sizeof(params_str.g2), internal_param->g2);
166 if (kEpidNoErr != result) {
167 break;
168 }
169 result = WriteBigNum(internal_param->t, sizeof(t_str), &t_str);
170 if (kEpidNoErr != result) {
171 break;
172 }
173 result = NewPairingState(internal_param->G1, internal_param->G2,
174 internal_param->GT, &t_str, internal_param->neg,
175 &internal_param->pairing_state);
176 if (kEpidNoErr != result) {
177 break;
178 }
179 *params = internal_param;
180 result = kEpidNoErr;
181 } while (0);
182 if (kEpidNoErr != result && internal_param) {
183 DeletePairingState(&internal_param->pairing_state);
184
185 DeleteEcPoint(&internal_param->g2);
186 DeleteEcPoint(&internal_param->g1);
187
188 DeleteBigNum(&internal_param->p);
189 DeleteBigNum(&internal_param->q);
190 DeleteFfElement(&internal_param->b);
191 DeleteBigNum(&internal_param->t);
192
193 DeleteFp(&internal_param->Fp);
194 DeleteFq(&internal_param->Fq);
195 DeleteFq2(&internal_param->Fq2);
196 DeleteFq6(&internal_param->Fq6);
197 DeleteGT(&internal_param->GT);
198
199 DeleteG1(&internal_param->G1);
200 DeleteG2(&internal_param->G2);
201
202 SAFE_FREE(internal_param);
203 }
204 return result;
205 }
206
DeleteEpid2Params(Epid2Params_ ** epid_params)207 void DeleteEpid2Params(Epid2Params_** epid_params) {
208 if (epid_params && *epid_params) {
209 DeletePairingState(&(*epid_params)->pairing_state);
210
211 DeleteBigNum(&(*epid_params)->p);
212 DeleteBigNum(&(*epid_params)->q);
213 DeleteFfElement(&(*epid_params)->b);
214 DeleteBigNum(&(*epid_params)->t);
215 DeleteFfElement(&(*epid_params)->xi);
216 DeleteEcPoint(&(*epid_params)->g1);
217 DeleteEcPoint(&(*epid_params)->g2);
218
219 DeleteFp(&(*epid_params)->Fp);
220 DeleteFq(&(*epid_params)->Fq);
221 DeleteFq2(&(*epid_params)->Fq2);
222 DeleteFq6(&(*epid_params)->Fq6);
223 DeleteGT(&(*epid_params)->GT);
224
225 DeleteG1(&(*epid_params)->G1);
226 DeleteG2(&(*epid_params)->G2);
227
228 SAFE_FREE(*epid_params);
229 }
230 }
231
NewFp(Epid2Params const * param,FiniteField ** Fp)232 static EpidStatus NewFp(Epid2Params const* param, FiniteField** Fp) {
233 EpidStatus result = kEpidErr;
234 if (!param || !Fp) {
235 return kEpidBadArgErr;
236 }
237 result = NewFiniteField(¶m->p, Fp);
238 if (kEpidNoErr != result) {
239 return result;
240 }
241 return kEpidNoErr;
242 }
243
NewFq(Epid2Params const * param,FiniteField ** Fq)244 static EpidStatus NewFq(Epid2Params const* param, FiniteField** Fq) {
245 EpidStatus result = kEpidErr;
246 if (!param || !Fq) {
247 return kEpidBadArgErr;
248 }
249 result = NewFiniteField(¶m->q, Fq);
250 if (kEpidNoErr != result) {
251 return result;
252 }
253 return kEpidNoErr;
254 }
NewFq2(Epid2Params const * param,FiniteField * Fq,FiniteField ** Fq2)255 EpidStatus NewFq2(Epid2Params const* param, FiniteField* Fq,
256 FiniteField** Fq2) {
257 EpidStatus result = kEpidErr;
258 FiniteField* Ff = NULL;
259 FfElement* beta = NULL;
260 FfElement* neg_beta = NULL;
261 if (!param || !Fq || !Fq2) {
262 return kEpidBadArgErr;
263 }
264 do {
265 result = NewFfElement(Fq, &beta);
266 if (kEpidNoErr != result) {
267 break;
268 }
269 result = NewFfElement(Fq, &neg_beta);
270 if (kEpidNoErr != result) {
271 break;
272 }
273 result = ReadFfElement(Fq, ¶m->beta, sizeof(param->beta), beta);
274 if (kEpidNoErr != result) {
275 break;
276 }
277 result = FfNeg(Fq, beta, neg_beta);
278 if (kEpidNoErr != result) {
279 break;
280 }
281 result = NewFiniteFieldViaBinomalExtension(Fq, neg_beta, 2, &Ff);
282 if (kEpidNoErr != result) {
283 break;
284 }
285 *Fq2 = Ff;
286 result = kEpidNoErr;
287 } while (0);
288
289 DeleteFfElement(&neg_beta);
290 DeleteFfElement(&beta);
291
292 return result;
293 }
NewFq6(Epid2Params const * param,FiniteField * Fq2,FfElement * xi,FiniteField ** Fq6)294 EpidStatus NewFq6(Epid2Params const* param, FiniteField* Fq2, FfElement* xi,
295 FiniteField** Fq6) {
296 EpidStatus result = kEpidErr;
297 FiniteField* Ff = NULL;
298 FfElement* neg_xi = NULL;
299 if (!param || !Fq2 || !Fq6) {
300 return kEpidBadArgErr;
301 }
302 do {
303 result = NewFfElement(Fq2, &neg_xi);
304 if (kEpidNoErr != result) {
305 break;
306 }
307 result = FfNeg(Fq2, xi, neg_xi);
308 if (kEpidNoErr != result) {
309 break;
310 }
311 result = NewFiniteFieldViaBinomalExtension(Fq2, neg_xi, 3, &Ff);
312 if (kEpidNoErr != result) {
313 break;
314 }
315 *Fq6 = Ff;
316 result = kEpidNoErr;
317 } while (0);
318
319 DeleteFfElement(&neg_xi);
320
321 return result;
322 }
NewG1(Epid2Params const * param,FiniteField * Fq,EcGroup ** G1)323 EpidStatus NewG1(Epid2Params const* param, FiniteField* Fq, EcGroup** G1) {
324 EpidStatus result = kEpidErr;
325 EcGroup* ec = NULL;
326 FfElement* fq_a = NULL;
327 FfElement* fq_b = NULL;
328 FfElement* g1_x = NULL;
329 FfElement* g1_y = NULL;
330 BigNum* order = NULL;
331 BigNum* cofactor = NULL;
332 // h = 1;
333 const BigNumStr h1 = {
334 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}};
337
338 if (!param || !Fq || !G1) {
339 return kEpidBadArgErr;
340 }
341 do {
342 // Create G1
343 // G1 is an elliptic curve group E(Fq).It can be initialized as follows :
344 // 1. Set G1 = E(Fq).init(p, q, n = p, h = 1, a = 0, b, g1.x, g1.y).
345 // a = 0
346 // NewFfelement is Identidy
347 result = NewFfElement(Fq, &fq_a);
348 if (kEpidNoErr != result) {
349 break;
350 }
351 // b
352 result = NewFfElement(Fq, &fq_b);
353 if (kEpidNoErr != result) {
354 break;
355 }
356 result = ReadFfElement(Fq, ¶m->b, sizeof(param->b), fq_b);
357 if (kEpidNoErr != result) {
358 break;
359 }
360 // g1.x
361 result = NewFfElement(Fq, &g1_x);
362 if (kEpidNoErr != result) {
363 break;
364 }
365 result = ReadFfElement(Fq, ¶m->g1.x, sizeof(param->g1.x), g1_x);
366 if (kEpidNoErr != result) {
367 break;
368 }
369 // g1.y
370 result = NewFfElement(Fq, &g1_y);
371 if (kEpidNoErr != result) {
372 break;
373 }
374 result = ReadFfElement(Fq, ¶m->g1.y, sizeof(param->g1.y), g1_y);
375 if (kEpidNoErr != result) {
376 break;
377 }
378 // order
379 result = NewBigNum(sizeof(BigNumStr), &order);
380 if (kEpidNoErr != result) {
381 break;
382 }
383 result = ReadBigNum(¶m->p, sizeof(param->p), order);
384 if (kEpidNoErr != result) {
385 break;
386 }
387 // cofactor
388 result = NewBigNum(sizeof(BigNumStr), &cofactor);
389 if (kEpidNoErr != result) {
390 break;
391 }
392
393 result = ReadBigNum(&h1, sizeof(h1), cofactor);
394 if (kEpidNoErr != result) {
395 break;
396 }
397 result = NewEcGroup(Fq, fq_a, fq_b, g1_x, g1_y, order, cofactor, &ec);
398 if (kEpidNoErr != result) {
399 break;
400 }
401 *G1 = ec;
402 result = kEpidNoErr;
403 } while (0);
404
405 DeleteBigNum(&cofactor);
406 DeleteBigNum(&order);
407 DeleteFfElement(&g1_y);
408 DeleteFfElement(&g1_x);
409 DeleteFfElement(&fq_b);
410 DeleteFfElement(&fq_a);
411
412 return result;
413 }
NewG2(Epid2Params const * param,BigNum * p,BigNum * q,FiniteField * Fq,FiniteField * Fq2,EcGroup ** G2)414 EpidStatus NewG2(Epid2Params const* param, BigNum* p, BigNum* q,
415 FiniteField* Fq, FiniteField* Fq2, EcGroup** G2) {
416 EpidStatus result = kEpidErr;
417 EcGroup* ec = NULL;
418 FfElement* a = NULL;
419 FfElement* b = NULL;
420 FfElement* fq_param_b = NULL;
421 FfElement* x = NULL;
422 FfElement* y = NULL;
423 BigNum* order = NULL;
424 BigNum* cofactor = NULL;
425 if (!param || !Fq || !Fq2 || !G2) {
426 return kEpidBadArgErr;
427 }
428 do {
429 // 2. Set xi = (xi0, xi1) an element of Fq2.
430 // 3. Let b', xi' be a temporary variable in Fq2.
431 // 4. Compute xi' = Fq2.inverse(xi).
432 // 5. Compute b' = Fq2.mul(xi', b).
433 result = NewFfElement(Fq2, &b);
434 if (kEpidNoErr != result) {
435 break;
436 }
437 result = ReadFfElement(Fq2, ¶m->xi, sizeof(param->xi), b);
438 if (kEpidNoErr != result) {
439 break;
440 }
441 result = FfInv(Fq2, b, b);
442 if (kEpidNoErr != result) {
443 break;
444 }
445 result = NewFfElement(Fq, &fq_param_b);
446 if (kEpidNoErr != result) {
447 break;
448 }
449 result = ReadFfElement(Fq, ¶m->b, sizeof(param->b), fq_param_b);
450 if (kEpidNoErr != result) {
451 break;
452 }
453 result = FfMul(Fq2, b, fq_param_b, b); // ??? overflow fq2*fq
454 if (kEpidNoErr != result) {
455 break;
456 }
457 // 6. Set g2.x = (g2.x[0], g2.x[1]) an element of Fq2.
458 // 7. Set g2.y = (g2.y[0], g2.y[1]) an element of Fq2.
459 result = NewFfElement(Fq2, &x);
460 if (kEpidNoErr != result) {
461 break;
462 }
463 result = ReadFfElement(Fq2, ¶m->g2.x, sizeof(param->g2.x), x);
464 if (kEpidNoErr != result) {
465 break;
466 }
467 result = NewFfElement(Fq2, &y);
468 if (kEpidNoErr != result) {
469 break;
470 }
471 result = ReadFfElement(Fq2, ¶m->g2.y, sizeof(param->g2.y), y);
472 if (kEpidNoErr != result) {
473 break;
474 }
475 // 8. set h = 2q - p, aka cofactor
476 result = NewBigNum(2 * sizeof(param->q), &cofactor);
477 if (kEpidNoErr != result) {
478 break;
479 }
480 result = BigNumAdd(q, q, cofactor);
481 if (kEpidNoErr != result) {
482 break;
483 }
484 result = BigNumSub(cofactor, p, cofactor);
485 if (kEpidNoErr != result) {
486 break;
487 }
488 // 9. set n = p * h, AKA order
489 result = NewBigNum(2 * sizeof(param->q), &order);
490 if (kEpidNoErr != result) {
491 break;
492 }
493 result = BigNumMul(p, cofactor, order);
494 if (kEpidNoErr != result) {
495 break;
496 }
497 // set a to identity, NewFfElement does it by default
498 result = NewFfElement(Fq2, &a);
499 if (kEpidNoErr != result) {
500 break;
501 }
502 // 10. Set G2 = E(Fq2).init(p, param(Fq2), n, h, 0, b', g2.x, g2.y)
503 result = NewEcGroup(Fq2, a, b, x, y, order, cofactor, &ec);
504 if (kEpidNoErr != result) {
505 break;
506 }
507 *G2 = ec;
508 result = kEpidNoErr;
509 } while (0);
510
511 DeleteBigNum(&cofactor);
512 DeleteBigNum(&order);
513 DeleteFfElement(&y);
514 DeleteFfElement(&x);
515 DeleteFfElement(&b);
516 DeleteFfElement(&a);
517 DeleteFfElement(&fq_param_b);
518
519 return result;
520 }
NewGT(FiniteField * Fq6,FiniteField ** GT)521 EpidStatus NewGT(FiniteField* Fq6, FiniteField** GT) {
522 EpidStatus result = kEpidErr;
523 FiniteField* Ff = NULL;
524 FfElement* v = NULL;
525 FfElement* neg_v = NULL;
526
527 const Fq6ElemStr v_str = {
528 {{{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
531 {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}},
534 {{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}},
537 {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}},
540 {{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
543 {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}}}};
546
547 if (!Fq6 || !GT) {
548 return kEpidBadArgErr;
549 }
550 do {
551 result = NewFfElement(Fq6, &v);
552 if (kEpidNoErr != result) {
553 break;
554 }
555 result = NewFfElement(Fq6, &neg_v);
556 if (kEpidNoErr != result) {
557 break;
558 }
559 result = ReadFfElement(Fq6, &v_str, sizeof(v_str), v);
560 if (kEpidNoErr != result) {
561 break;
562 }
563 result = FfNeg(Fq6, v, neg_v);
564 if (kEpidNoErr != result) {
565 break;
566 }
567 result = NewFiniteFieldViaBinomalExtension(Fq6, neg_v, 2, &Ff);
568 if (kEpidNoErr != result) {
569 break;
570 }
571 *GT = Ff;
572 result = kEpidNoErr;
573 } while (0);
574
575 DeleteFfElement(&v);
576 DeleteFfElement(&neg_v);
577
578 return result;
579 }
DeleteFp(FiniteField ** Fp)580 static void DeleteFp(FiniteField** Fp) { DeleteFiniteField(Fp); }
DeleteFq(FiniteField ** Fq)581 static void DeleteFq(FiniteField** Fq) { DeleteFiniteField(Fq); }
DeleteFq2(FiniteField ** Fq2)582 static void DeleteFq2(FiniteField** Fq2) { DeleteFiniteField(Fq2); }
DeleteFq6(FiniteField ** Fq6)583 static void DeleteFq6(FiniteField** Fq6) { DeleteFiniteField(Fq6); }
DeleteG1(EcGroup ** G1)584 static void DeleteG1(EcGroup** G1) { DeleteEcGroup(G1); }
DeleteG2(EcGroup ** G2)585 static void DeleteG2(EcGroup** G2) { DeleteEcGroup(G2); }
DeleteGT(FiniteField ** GT)586 static void DeleteGT(FiniteField** GT) { DeleteFiniteField(GT); }
587