/*############################################################################ # Copyright 2016-2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################*/ /*! * \file * \brief Intel(R) EPID 2.0 constant parameters implementation. */ #include "epid/common/src/epid2params.h" #include "epid/common/src/memory.h" /// create a new Finite Field Fp static EpidStatus NewFp(Epid2Params const* param, FiniteField** Fp); /// create a new Finite Field Fq static EpidStatus NewFq(Epid2Params const* param, FiniteField** Fq); /// create a new Finite Field Fq2 static EpidStatus NewFq2(Epid2Params const* param, FiniteField* Fq, FiniteField** Fq2); /// create a new Finite Field Fq6 EpidStatus NewFq6(Epid2Params const* param, FiniteField* Fq2, FfElement* xi, FiniteField** Fq6); /// create a new Elliptic curve group G1 over Fq static EpidStatus NewG1(Epid2Params const* param, FiniteField* Fq, EcGroup** G1); /// create a new Elliptic curve group G2 over Fq2 static EpidStatus NewG2(Epid2Params const* param, BigNum* p, BigNum* q, FiniteField* Fq, FiniteField* Fq2, EcGroup** G2); /// create a new Finite Field Fq12 static EpidStatus NewGT(FiniteField* Fq6, FiniteField** GT); /// create a new pairing state /// Deallocate Finite Field Fp static void DeleteFp(FiniteField** Fp); /// Deallocate Finite Field Fq static void DeleteFq(FiniteField** Fq); /// Deallocate Finite Field Fq2 static void DeleteFq2(FiniteField** Fq2); /// Deallocate Finite Field Fq6 static void DeleteFq6(FiniteField** Fq6); /// Deallocate Elliptic curve group G1 over Fq static void DeleteG1(EcGroup** G1); /// Deallocate Elliptic curve group G2 over Fq2 static void DeleteG2(EcGroup** G2); /// Deallocate Finite Field Fq12 static void DeleteGT(FiniteField** GT); EpidStatus CreateEpid2Params(Epid2Params_** params) { EpidStatus result = kEpidErr; Epid2Params_* internal_param = NULL; BigNumStr t_str = {0}; Epid2Params params_str = { #include "epid/common/src/epid2params_ate.inc" }; if (!params) { return kEpidBadArgErr; } do { internal_param = SAFE_ALLOC(sizeof(Epid2Params_)); if (!internal_param) { result = kEpidMemAllocErr; break; } result = NewBigNum(sizeof(params_str.p), &internal_param->p); if (kEpidNoErr != result) { break; } result = ReadBigNum(¶ms_str.p, sizeof(params_str.p), internal_param->p); if (kEpidNoErr != result) { break; } result = NewBigNum(sizeof(params_str.q), &internal_param->q); if (kEpidNoErr != result) { break; } result = ReadBigNum(¶ms_str.q, sizeof(params_str.q), internal_param->q); if (kEpidNoErr != result) { break; } result = NewBigNum(sizeof(params_str.t), &internal_param->t); if (kEpidNoErr != result) { break; } result = ReadBigNum(¶ms_str.t, sizeof(params_str.t), internal_param->t); if (kEpidNoErr != result) { break; } internal_param->neg = (params_str.neg.data[0]) ? true : false; result = NewFp(¶ms_str, &internal_param->Fp); if (kEpidNoErr != result) { break; } result = NewFq(¶ms_str, &internal_param->Fq); if (kEpidNoErr != result) { break; } result = NewFq2(¶ms_str, internal_param->Fq, &internal_param->Fq2); if (kEpidNoErr != result) { break; } result = NewFfElement(internal_param->Fq, &internal_param->b); if (kEpidNoErr != result) { break; } result = ReadFfElement(internal_param->Fq, ¶ms_str.b, sizeof(params_str.b), internal_param->b); if (kEpidNoErr != result) { break; } result = NewFfElement(internal_param->Fq2, &internal_param->xi); if (kEpidNoErr != result) { break; } result = ReadFfElement(internal_param->Fq2, ¶ms_str.xi, sizeof(params_str.xi), internal_param->xi); if (kEpidNoErr != result) { break; } result = NewFq6(¶ms_str, internal_param->Fq2, internal_param->xi, &internal_param->Fq6); if (kEpidNoErr != result) { break; } result = NewGT(internal_param->Fq6, &internal_param->GT); if (kEpidNoErr != result) { break; } result = NewG1(¶ms_str, internal_param->Fq, &internal_param->G1); if (kEpidNoErr != result) { break; } result = NewEcPoint(internal_param->G1, &internal_param->g1); if (kEpidNoErr != result) { break; } result = ReadEcPoint(internal_param->G1, ¶ms_str.g1, sizeof(params_str.g1), internal_param->g1); if (kEpidNoErr != result) { break; } result = NewG2(¶ms_str, internal_param->p, internal_param->q, internal_param->Fq, internal_param->Fq2, &internal_param->G2); if (kEpidNoErr != result) { break; } result = NewEcPoint(internal_param->G2, &internal_param->g2); if (kEpidNoErr != result) { break; } result = ReadEcPoint(internal_param->G2, ¶ms_str.g2, sizeof(params_str.g2), internal_param->g2); if (kEpidNoErr != result) { break; } result = WriteBigNum(internal_param->t, sizeof(t_str), &t_str); if (kEpidNoErr != result) { break; } result = NewPairingState(internal_param->G1, internal_param->G2, internal_param->GT, &t_str, internal_param->neg, &internal_param->pairing_state); if (kEpidNoErr != result) { break; } *params = internal_param; result = kEpidNoErr; } while (0); if (kEpidNoErr != result && internal_param) { DeletePairingState(&internal_param->pairing_state); DeleteEcPoint(&internal_param->g2); DeleteEcPoint(&internal_param->g1); DeleteBigNum(&internal_param->p); DeleteBigNum(&internal_param->q); DeleteFfElement(&internal_param->b); DeleteBigNum(&internal_param->t); DeleteFp(&internal_param->Fp); DeleteFq(&internal_param->Fq); DeleteFq2(&internal_param->Fq2); DeleteFq6(&internal_param->Fq6); DeleteGT(&internal_param->GT); DeleteG1(&internal_param->G1); DeleteG2(&internal_param->G2); SAFE_FREE(internal_param); } return result; } void DeleteEpid2Params(Epid2Params_** epid_params) { if (epid_params && *epid_params) { DeletePairingState(&(*epid_params)->pairing_state); DeleteBigNum(&(*epid_params)->p); DeleteBigNum(&(*epid_params)->q); DeleteFfElement(&(*epid_params)->b); DeleteBigNum(&(*epid_params)->t); DeleteFfElement(&(*epid_params)->xi); DeleteEcPoint(&(*epid_params)->g1); DeleteEcPoint(&(*epid_params)->g2); DeleteFp(&(*epid_params)->Fp); DeleteFq(&(*epid_params)->Fq); DeleteFq2(&(*epid_params)->Fq2); DeleteFq6(&(*epid_params)->Fq6); DeleteGT(&(*epid_params)->GT); DeleteG1(&(*epid_params)->G1); DeleteG2(&(*epid_params)->G2); SAFE_FREE(*epid_params); } } static EpidStatus NewFp(Epid2Params const* param, FiniteField** Fp) { EpidStatus result = kEpidErr; if (!param || !Fp) { return kEpidBadArgErr; } result = NewFiniteField(¶m->p, Fp); if (kEpidNoErr != result) { return result; } return kEpidNoErr; } static EpidStatus NewFq(Epid2Params const* param, FiniteField** Fq) { EpidStatus result = kEpidErr; if (!param || !Fq) { return kEpidBadArgErr; } result = NewFiniteField(¶m->q, Fq); if (kEpidNoErr != result) { return result; } return kEpidNoErr; } EpidStatus NewFq2(Epid2Params const* param, FiniteField* Fq, FiniteField** Fq2) { EpidStatus result = kEpidErr; FiniteField* Ff = NULL; FfElement* beta = NULL; FfElement* neg_beta = NULL; if (!param || !Fq || !Fq2) { return kEpidBadArgErr; } do { result = NewFfElement(Fq, &beta); if (kEpidNoErr != result) { break; } result = NewFfElement(Fq, &neg_beta); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq, ¶m->beta, sizeof(param->beta), beta); if (kEpidNoErr != result) { break; } result = FfNeg(Fq, beta, neg_beta); if (kEpidNoErr != result) { break; } result = NewFiniteFieldViaBinomalExtension(Fq, neg_beta, 2, &Ff); if (kEpidNoErr != result) { break; } *Fq2 = Ff; result = kEpidNoErr; } while (0); DeleteFfElement(&neg_beta); DeleteFfElement(&beta); return result; } EpidStatus NewFq6(Epid2Params const* param, FiniteField* Fq2, FfElement* xi, FiniteField** Fq6) { EpidStatus result = kEpidErr; FiniteField* Ff = NULL; FfElement* neg_xi = NULL; if (!param || !Fq2 || !Fq6) { return kEpidBadArgErr; } do { result = NewFfElement(Fq2, &neg_xi); if (kEpidNoErr != result) { break; } result = FfNeg(Fq2, xi, neg_xi); if (kEpidNoErr != result) { break; } result = NewFiniteFieldViaBinomalExtension(Fq2, neg_xi, 3, &Ff); if (kEpidNoErr != result) { break; } *Fq6 = Ff; result = kEpidNoErr; } while (0); DeleteFfElement(&neg_xi); return result; } EpidStatus NewG1(Epid2Params const* param, FiniteField* Fq, EcGroup** G1) { EpidStatus result = kEpidErr; EcGroup* ec = NULL; FfElement* fq_a = NULL; FfElement* fq_b = NULL; FfElement* g1_x = NULL; FfElement* g1_y = NULL; BigNum* order = NULL; BigNum* cofactor = NULL; // h = 1; const BigNumStr h1 = { {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}}; if (!param || !Fq || !G1) { return kEpidBadArgErr; } do { // Create G1 // G1 is an elliptic curve group E(Fq).It can be initialized as follows : // 1. Set G1 = E(Fq).init(p, q, n = p, h = 1, a = 0, b, g1.x, g1.y). // a = 0 // NewFfelement is Identidy result = NewFfElement(Fq, &fq_a); if (kEpidNoErr != result) { break; } // b result = NewFfElement(Fq, &fq_b); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq, ¶m->b, sizeof(param->b), fq_b); if (kEpidNoErr != result) { break; } // g1.x result = NewFfElement(Fq, &g1_x); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq, ¶m->g1.x, sizeof(param->g1.x), g1_x); if (kEpidNoErr != result) { break; } // g1.y result = NewFfElement(Fq, &g1_y); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq, ¶m->g1.y, sizeof(param->g1.y), g1_y); if (kEpidNoErr != result) { break; } // order result = NewBigNum(sizeof(BigNumStr), &order); if (kEpidNoErr != result) { break; } result = ReadBigNum(¶m->p, sizeof(param->p), order); if (kEpidNoErr != result) { break; } // cofactor result = NewBigNum(sizeof(BigNumStr), &cofactor); if (kEpidNoErr != result) { break; } result = ReadBigNum(&h1, sizeof(h1), cofactor); if (kEpidNoErr != result) { break; } result = NewEcGroup(Fq, fq_a, fq_b, g1_x, g1_y, order, cofactor, &ec); if (kEpidNoErr != result) { break; } *G1 = ec; result = kEpidNoErr; } while (0); DeleteBigNum(&cofactor); DeleteBigNum(&order); DeleteFfElement(&g1_y); DeleteFfElement(&g1_x); DeleteFfElement(&fq_b); DeleteFfElement(&fq_a); return result; } EpidStatus NewG2(Epid2Params const* param, BigNum* p, BigNum* q, FiniteField* Fq, FiniteField* Fq2, EcGroup** G2) { EpidStatus result = kEpidErr; EcGroup* ec = NULL; FfElement* a = NULL; FfElement* b = NULL; FfElement* fq_param_b = NULL; FfElement* x = NULL; FfElement* y = NULL; BigNum* order = NULL; BigNum* cofactor = NULL; if (!param || !Fq || !Fq2 || !G2) { return kEpidBadArgErr; } do { // 2. Set xi = (xi0, xi1) an element of Fq2. // 3. Let b', xi' be a temporary variable in Fq2. // 4. Compute xi' = Fq2.inverse(xi). // 5. Compute b' = Fq2.mul(xi', b). result = NewFfElement(Fq2, &b); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq2, ¶m->xi, sizeof(param->xi), b); if (kEpidNoErr != result) { break; } result = FfInv(Fq2, b, b); if (kEpidNoErr != result) { break; } result = NewFfElement(Fq, &fq_param_b); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq, ¶m->b, sizeof(param->b), fq_param_b); if (kEpidNoErr != result) { break; } result = FfMul(Fq2, b, fq_param_b, b); // ??? overflow fq2*fq if (kEpidNoErr != result) { break; } // 6. Set g2.x = (g2.x[0], g2.x[1]) an element of Fq2. // 7. Set g2.y = (g2.y[0], g2.y[1]) an element of Fq2. result = NewFfElement(Fq2, &x); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq2, ¶m->g2.x, sizeof(param->g2.x), x); if (kEpidNoErr != result) { break; } result = NewFfElement(Fq2, &y); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq2, ¶m->g2.y, sizeof(param->g2.y), y); if (kEpidNoErr != result) { break; } // 8. set h = 2q - p, aka cofactor result = NewBigNum(2 * sizeof(param->q), &cofactor); if (kEpidNoErr != result) { break; } result = BigNumAdd(q, q, cofactor); if (kEpidNoErr != result) { break; } result = BigNumSub(cofactor, p, cofactor); if (kEpidNoErr != result) { break; } // 9. set n = p * h, AKA order result = NewBigNum(2 * sizeof(param->q), &order); if (kEpidNoErr != result) { break; } result = BigNumMul(p, cofactor, order); if (kEpidNoErr != result) { break; } // set a to identity, NewFfElement does it by default result = NewFfElement(Fq2, &a); if (kEpidNoErr != result) { break; } // 10. Set G2 = E(Fq2).init(p, param(Fq2), n, h, 0, b', g2.x, g2.y) result = NewEcGroup(Fq2, a, b, x, y, order, cofactor, &ec); if (kEpidNoErr != result) { break; } *G2 = ec; result = kEpidNoErr; } while (0); DeleteBigNum(&cofactor); DeleteBigNum(&order); DeleteFfElement(&y); DeleteFfElement(&x); DeleteFfElement(&b); DeleteFfElement(&a); DeleteFfElement(&fq_param_b); return result; } EpidStatus NewGT(FiniteField* Fq6, FiniteField** GT) { EpidStatus result = kEpidErr; FiniteField* Ff = NULL; FfElement* v = NULL; FfElement* neg_v = NULL; const Fq6ElemStr v_str = { {{{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}}, {{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}}, {{{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}}}}}; if (!Fq6 || !GT) { return kEpidBadArgErr; } do { result = NewFfElement(Fq6, &v); if (kEpidNoErr != result) { break; } result = NewFfElement(Fq6, &neg_v); if (kEpidNoErr != result) { break; } result = ReadFfElement(Fq6, &v_str, sizeof(v_str), v); if (kEpidNoErr != result) { break; } result = FfNeg(Fq6, v, neg_v); if (kEpidNoErr != result) { break; } result = NewFiniteFieldViaBinomalExtension(Fq6, neg_v, 2, &Ff); if (kEpidNoErr != result) { break; } *GT = Ff; result = kEpidNoErr; } while (0); DeleteFfElement(&v); DeleteFfElement(&neg_v); return result; } static void DeleteFp(FiniteField** Fp) { DeleteFiniteField(Fp); } static void DeleteFq(FiniteField** Fq) { DeleteFiniteField(Fq); } static void DeleteFq2(FiniteField** Fq2) { DeleteFiniteField(Fq2); } static void DeleteFq6(FiniteField** Fq6) { DeleteFiniteField(Fq6); } static void DeleteG1(EcGroup** G1) { DeleteEcGroup(G1); } static void DeleteG2(EcGroup** G2) { DeleteEcGroup(G2); } static void DeleteGT(FiniteField** GT) { DeleteFiniteField(GT); }