/*############################################################################ # 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 1.1 constant parameters implementation. */ #include "epid/common/1.1/src/epid11params.h" #include "epid/common/math/tatepairing.h" #include "epid/common/src/memory.h" /// Handle SDK Error with Break #define BREAK_ON_EPID_ERROR(ret) \ if (kEpidNoErr != (ret)) { \ break; \ } /// Count of elements in array #define COUNT_OF(a) (sizeof(a) / sizeof((a)[0])) /// create a new Finite Field Fqd static EpidStatus NewFqd(Epid11Params const* params, FiniteField* Fq, FiniteField** Fqd); /// create a new Finite Field Fqk EpidStatus NewFqk(Epid11Params const* params, FiniteField* Fq, FiniteField* Fqd, FiniteField** Fqk); /// create a new Elliptic curve group G1 over Fq static EpidStatus NewG1(Epid11Params const* params, FiniteField* Fq, EcGroup** G1); /// create a new Elliptic curve group G2 over Fqd static EpidStatus NewG2(Epid11Params const* params, FiniteField* Fq, FiniteField* Fqd, EcGroup** G2); /// create a new Elliptic curve group G3 over Fq' static EpidStatus NewG3(Epid11Params const* params, FiniteField* Fq_tick, EcGroup** G3); EpidStatus CreateEpid11Params(Epid11Params_** params) { EpidStatus result = kEpidErr; Epid11Params_* _params = NULL; Epid11Params params_str = { #include "epid/common/1.1/src/epid11params_tate.inc" }; if (!params) return kEpidBadArgErr; do { _params = SAFE_ALLOC(sizeof(Epid11Params_)); if (!_params) { result = kEpidMemAllocErr; break; } // BigNum* p; result = NewBigNum(sizeof(params_str.p), &_params->p); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms_str.p, sizeof(params_str.p), _params->p); BREAK_ON_EPID_ERROR(result); // BigNum* p_tick; result = NewBigNum(sizeof(params_str.p_tick), &_params->p_tick); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms_str.p_tick, sizeof(params_str.p_tick), _params->p_tick); BREAK_ON_EPID_ERROR(result); // FiniteField* Fp; result = NewFiniteField(¶ms_str.p, &_params->Fp); BREAK_ON_EPID_ERROR(result); // FiniteField* Fq; result = NewFiniteField(¶ms_str.q, &_params->Fq); BREAK_ON_EPID_ERROR(result); // FiniteField* Fp_tick; result = NewFiniteField(¶ms_str.p_tick, &_params->Fp_tick); BREAK_ON_EPID_ERROR(result); // FiniteField* Fq_tick; result = NewFiniteField(¶ms_str.q_tick, &_params->Fq_tick); BREAK_ON_EPID_ERROR(result); // FiniteField* Fqd; result = NewFqd(¶ms_str, _params->Fq, &_params->Fqd); BREAK_ON_EPID_ERROR(result); // EcGroup* G1; result = NewG1(¶ms_str, _params->Fq, &_params->G1); BREAK_ON_EPID_ERROR(result); // EcGroup* G2; result = NewG2(¶ms_str, _params->Fq, _params->Fqd, &_params->G2); BREAK_ON_EPID_ERROR(result); // EcGroup* G3; result = NewG3(¶ms_str, _params->Fq_tick, &_params->G3); BREAK_ON_EPID_ERROR(result); // FiniteField* GT; result = NewFqk(¶ms_str, _params->Fq, _params->Fqd, &_params->GT); BREAK_ON_EPID_ERROR(result); // EcPoint* g1; result = NewEcPoint(_params->G1, &_params->g1); BREAK_ON_EPID_ERROR(result); result = ReadEcPoint(_params->G1, ¶ms_str.g1, sizeof(params_str.g1), _params->g1); BREAK_ON_EPID_ERROR(result); // EcPoint* g2; result = NewEcPoint(_params->G2, &_params->g2); BREAK_ON_EPID_ERROR(result); result = ReadEcPoint(_params->G2, ¶ms_str.g2, sizeof(params_str.g2), _params->g2); BREAK_ON_EPID_ERROR(result); // EcPoint* g3; result = NewEcPoint(_params->G3, &_params->g3); BREAK_ON_EPID_ERROR(result); result = ReadEcPoint(_params->G3, ¶ms_str.g3, sizeof(params_str.g3), _params->g3); BREAK_ON_EPID_ERROR(result); // Epid11PairingState* pairing_state; result = NewEpid11PairingState(_params->G1, _params->G2, _params->GT, &_params->pairing_state); BREAK_ON_EPID_ERROR(result); *params = _params; result = kEpidNoErr; } while (0); if (kEpidNoErr != result && _params) { DeleteEpid11PairingState(&_params->pairing_state); DeleteBigNum(&_params->p); DeleteBigNum(&_params->p_tick); DeleteEcPoint(&_params->g1); DeleteEcPoint(&_params->g2); DeleteEcPoint(&_params->g3); DeleteFiniteField(&_params->Fp); DeleteFiniteField(&_params->Fq); DeleteFiniteField(&_params->Fp_tick); DeleteFiniteField(&_params->Fq_tick); DeleteFiniteField(&_params->Fqd); DeleteFiniteField(&_params->GT); DeleteEcGroup(&_params->G1); DeleteEcGroup(&_params->G2); DeleteEcGroup(&_params->G3); SAFE_FREE(_params); } return result; } void DeleteEpid11Params(Epid11Params_** params) { if (params && *params) { DeleteEpid11PairingState(&(*params)->pairing_state); DeleteBigNum(&(*params)->p); DeleteBigNum(&(*params)->p_tick); DeleteEcPoint(&(*params)->g1); DeleteEcPoint(&(*params)->g2); DeleteEcPoint(&(*params)->g3); DeleteFiniteField(&(*params)->Fp); DeleteFiniteField(&(*params)->Fq); DeleteFiniteField(&(*params)->Fp_tick); DeleteFiniteField(&(*params)->Fq_tick); DeleteFiniteField(&(*params)->Fqd); DeleteFiniteField(&(*params)->GT); DeleteEcGroup(&(*params)->G1); DeleteEcGroup(&(*params)->G2); DeleteEcGroup(&(*params)->G3); SAFE_FREE(*params); } } EpidStatus NewFqd(Epid11Params const* params, FiniteField* Fq, FiniteField** Fqd) { if (!params || !Fq || !Fqd) return kEpidBadArgErr; return NewFiniteFieldViaPolynomialExtension(Fq, params->coeff, 3, Fqd); } EpidStatus NewFqk(Epid11Params const* params, FiniteField* Fq, FiniteField* Fqd, FiniteField** Fqk) { EpidStatus result = kEpidNoErr; FfElement* qnr = NULL; FfElement* neg_qnr = NULL; FfElement* ground_element = NULL; Fq3ElemStr ground_element_str = {0}; if (!params || !Fq || !Fqd || !Fqk) return kEpidBadArgErr; do { result = NewFfElement(Fq, &qnr); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, &(params->qnr), sizeof(params->qnr), qnr); BREAK_ON_EPID_ERROR(result); result = NewFfElement(Fq, &neg_qnr); BREAK_ON_EPID_ERROR(result); result = FfNeg(Fq, qnr, neg_qnr); BREAK_ON_EPID_ERROR(result); result = WriteFfElement(Fq, neg_qnr, &ground_element_str.a[0], sizeof(ground_element_str.a[0])); BREAK_ON_EPID_ERROR(result); result = NewFfElement(Fqd, &ground_element); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fqd, &(ground_element_str), sizeof(ground_element_str), ground_element); BREAK_ON_EPID_ERROR(result); result = NewFiniteFieldViaBinomalExtension(Fqd, ground_element, 2, Fqk); BREAK_ON_EPID_ERROR(result); } while (0); DeleteFfElement(&qnr); DeleteFfElement(&neg_qnr); DeleteFfElement(&ground_element); return result; } EpidStatus NewG1(Epid11Params const* params, 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* h = NULL; if (!params || !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, h, a, b, g1.x, g1.y). // a result = NewFfElement(Fq, &fq_a); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->a, sizeof(params->a), fq_a); BREAK_ON_EPID_ERROR(result); // b result = NewFfElement(Fq, &fq_b); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->b, sizeof(params->b), fq_b); BREAK_ON_EPID_ERROR(result); // g1.x result = NewFfElement(Fq, &g1_x); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->g1.x, sizeof(params->g1.x), g1_x); BREAK_ON_EPID_ERROR(result); // g1.y result = NewFfElement(Fq, &g1_y); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->g1.y, sizeof(params->g1.y), g1_y); BREAK_ON_EPID_ERROR(result); // order result = NewBigNum(sizeof(BigNumStr), &order); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->p, sizeof(params->p), order); BREAK_ON_EPID_ERROR(result); // h result = NewBigNum(sizeof(BigNumStr), &h); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->h, sizeof(params->h), h); BREAK_ON_EPID_ERROR(result); result = NewEcGroup(Fq, fq_a, fq_b, g1_x, g1_y, order, h, &ec); BREAK_ON_EPID_ERROR(result); *G1 = ec; result = kEpidNoErr; } while (0); DeleteBigNum(&h); DeleteBigNum(&order); DeleteFfElement(&g1_y); DeleteFfElement(&g1_x); DeleteFfElement(&fq_b); DeleteFfElement(&fq_a); return result; } EpidStatus NewG3(Epid11Params const* params, FiniteField* Fq_dash, EcGroup** G3) { EpidStatus result = kEpidErr; EcGroup* ec = NULL; FfElement* fq_a = NULL; FfElement* fq_b = NULL; FfElement* g3_x = NULL; FfElement* g3_y = NULL; BigNum* order = NULL; BigNum* h_tick = NULL; if (!params || !Fq_dash || !G3) return kEpidBadArgErr; do { // Create G3 // G3 is an elliptic curve group E(Fq').It can be initialized as follows: // 1. Set G3 = E(Fq').init(p', q', h', a', b', g3.x, g3.y). // a' result = NewFfElement(Fq_dash, &fq_a); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq_dash, ¶ms->a_tick, sizeof(params->a_tick), fq_a); BREAK_ON_EPID_ERROR(result); // b' result = NewFfElement(Fq_dash, &fq_b); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq_dash, ¶ms->b_tick, sizeof(params->b_tick), fq_b); BREAK_ON_EPID_ERROR(result); // g3.x result = NewFfElement(Fq_dash, &g3_x); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq_dash, ¶ms->g3.x, sizeof(params->g3.x), g3_x); BREAK_ON_EPID_ERROR(result); // g3.y result = NewFfElement(Fq_dash, &g3_y); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq_dash, ¶ms->g3.y, sizeof(params->g3.y), g3_y); BREAK_ON_EPID_ERROR(result); // order result = NewBigNum(sizeof(BigNumStr), &order); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->p_tick, sizeof(params->p_tick), order); BREAK_ON_EPID_ERROR(result); // h' result = NewBigNum(sizeof(BigNumStr), &h_tick); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->h_tick, sizeof(params->h_tick), h_tick); BREAK_ON_EPID_ERROR(result); result = NewEcGroup(Fq_dash, fq_a, fq_b, g3_x, g3_y, order, h_tick, &ec); BREAK_ON_EPID_ERROR(result); *G3 = ec; result = kEpidNoErr; } while (0); DeleteBigNum(&h_tick); DeleteBigNum(&order); DeleteFfElement(&g3_y); DeleteFfElement(&g3_x); DeleteFfElement(&fq_b); DeleteFfElement(&fq_a); return result; } EpidStatus NewG2(Epid11Params const* params, FiniteField* Fq, FiniteField* Fqd, EcGroup** G2) { EpidStatus result = kEpidErr; EcGroup* ec = NULL; FfElement* fq_twista = NULL; FfElement* fq_twistb = NULL; FfElement* fqd_twista = NULL; FfElement* fqd_twistb = NULL; FfElement* g2_x = NULL; FfElement* g2_y = NULL; FfElement* qnr = NULL; BigNum* order = NULL; BigNum* h = NULL; Fq3ElemStr tmp_Fq3_str = {0}; if (!params || !Fq || !Fqd || !G2) return kEpidBadArgErr; do { // Create G2 // G2 is an elliptic curve group E(Fqd).It can be initialized as follows: // 2. Set g2.x = (g2.x[0], g2.x[1], g2.x[2]) an element of Fqd result = NewFfElement(Fqd, &g2_x); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fqd, ¶ms->g2.x, sizeof(params->g2.x), g2_x); BREAK_ON_EPID_ERROR(result); // 3. Set g2.y = (g2.y[0], g2.y[1], g2.y[2]) an element of Fqd result = NewFfElement(Fqd, &g2_y); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fqd, ¶ms->g2.y, sizeof(params->g2.y), g2_y); BREAK_ON_EPID_ERROR(result); // qnr result = NewFfElement(Fq, &qnr); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->qnr, sizeof(params->qnr), qnr); BREAK_ON_EPID_ERROR(result); // 4. twista = (a * qnr * qnr) mod q result = NewFfElement(Fq, &fq_twista); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->a, sizeof(params->a), fq_twista); BREAK_ON_EPID_ERROR(result); result = FfMul(Fq, fq_twista, qnr, fq_twista); BREAK_ON_EPID_ERROR(result); result = FfMul(Fq, fq_twista, qnr, fq_twista); BREAK_ON_EPID_ERROR(result); // twista = {twista, 0, 0} result = WriteFfElement(Fq, fq_twista, &(tmp_Fq3_str.a[0]), sizeof(tmp_Fq3_str.a[0])); BREAK_ON_EPID_ERROR(result); result = NewFfElement(Fqd, &fqd_twista); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fqd, &tmp_Fq3_str, sizeof(tmp_Fq3_str), fqd_twista); BREAK_ON_EPID_ERROR(result); // 5. twistb = (b * qnr * qnr * qnr) mod q result = NewFfElement(Fq, &fq_twistb); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fq, ¶ms->b, sizeof(params->b), fq_twistb); BREAK_ON_EPID_ERROR(result); result = FfMul(Fq, fq_twistb, qnr, fq_twistb); BREAK_ON_EPID_ERROR(result); result = FfMul(Fq, fq_twistb, qnr, fq_twistb); BREAK_ON_EPID_ERROR(result); result = FfMul(Fq, fq_twistb, qnr, fq_twistb); BREAK_ON_EPID_ERROR(result); // twistb = {twistb, 0, 0} result = WriteFfElement(Fq, fq_twistb, &(tmp_Fq3_str.a[0]), sizeof(tmp_Fq3_str.a[0])); BREAK_ON_EPID_ERROR(result); result = NewFfElement(Fqd, &fqd_twistb); BREAK_ON_EPID_ERROR(result); result = ReadFfElement(Fqd, &tmp_Fq3_str, sizeof(tmp_Fq3_str), fqd_twistb); BREAK_ON_EPID_ERROR(result); // order result = NewBigNum(3 * sizeof(BigNumStr), &order); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->orderG2, sizeof(params->orderG2), order); BREAK_ON_EPID_ERROR(result); // h result = NewBigNum(sizeof(BigNumStr), &h); BREAK_ON_EPID_ERROR(result); result = ReadBigNum(¶ms->h, sizeof(params->h), h); BREAK_ON_EPID_ERROR(result); // 6. Set G2 = E(Fqd).init(orderG2, param(Fqd), twista, twistb, g2.x, g2.y) result = NewEcGroup(Fqd, fqd_twista, fqd_twistb, g2_x, g2_y, order, h, &ec); BREAK_ON_EPID_ERROR(result); *G2 = ec; result = kEpidNoErr; } while (0); DeleteBigNum(&h); DeleteBigNum(&order); DeleteFfElement(&qnr); DeleteFfElement(&fqd_twistb); DeleteFfElement(&fq_twistb); DeleteFfElement(&fqd_twista); DeleteFfElement(&fq_twista); DeleteFfElement(&g2_y); DeleteFfElement(&g2_x); return result; }