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; }
EpidStatus CreatePrivKey(PrivKey const* priv_key_str, EcGroup* G1, FiniteField* Fp, PrivKey_** priv_key) { EpidStatus result = kEpidErr; PrivKey_* priv_key_ = NULL; // check parameters if (!priv_key_str || !G1 || !Fp || !priv_key) return kEpidBadArgErr; do { priv_key_ = SAFE_ALLOC(sizeof(*priv_key_)); if (!priv_key_) { result = kEpidMemAllocErr; break; } result = NewEcPoint(G1, &priv_key_->A); if (kEpidNoErr != result) break; result = NewFfElement(Fp, &priv_key_->x); if (kEpidNoErr != result) break; result = NewFfElement(Fp, &priv_key_->f); if (kEpidNoErr != result) break; if (0 != memcpy_S(&priv_key_->gid, sizeof(priv_key_->gid), &priv_key_str->gid, sizeof(priv_key_str->gid))) { result = kEpidBadArgErr; break; } result = ReadEcPoint(G1, &priv_key_str->A, sizeof(priv_key_str->A), priv_key_->A); if (kEpidNoErr != result) break; result = ReadFfElement(Fp, &priv_key_str->x, sizeof(priv_key_str->x), priv_key_->x); if (kEpidNoErr != result) break; result = ReadFfElement(Fp, &priv_key_str->f, sizeof(priv_key_str->f), priv_key_->f); if (kEpidNoErr != result) break; *priv_key = priv_key_; result = kEpidNoErr; } while (0); if (kEpidNoErr != result) { DeletePrivKey(&priv_key_); } return (result); }
EpidStatus Tpm2CreatePrimary(Tpm2Ctx* ctx, G1ElemStr* p_str) { EpidStatus sts = kEpidErr; FfElement* ff_elem; FpElemStr ff_elem_str; if (!ctx || !ctx->epid2_params) { return kEpidBadArgErr; } (void)p_str; do { const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; FiniteField* Fp = ctx->epid2_params->Fp; sts = NewFfElement(Fp, &ff_elem); BREAK_ON_EPID_ERROR(sts); sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, ff_elem); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, ff_elem, &ff_elem_str, sizeof(ff_elem_str)); BREAK_ON_EPID_ERROR(sts); } while (0); DeleteFfElement(&ff_elem); if (kEpidNoErr == sts) { sts = Tpm2LoadExternal(ctx, &ff_elem_str); } return sts; }
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 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 EpidSignBasic(MemberCtx const* ctx, void const* msg, size_t msg_len, void const* basename, size_t basename_len, BasicSignature* sig, BigNumStr* rnd_bsn) { EpidStatus sts = kEpidErr; EcPoint* B = NULL; EcPoint* t = NULL; // temp value in G1 EcPoint* k = NULL; EcPoint* e = NULL; FfElement* R2 = NULL; FfElement* p2y = NULL; FfElement* t1 = NULL; FfElement* t2 = NULL; FfElement* a = NULL; FfElement* b = NULL; FfElement* rx = NULL; FfElement* ra = NULL; FfElement* rb = NULL; struct p2x_t { uint32_t i; uint8_t bsn[1]; }* p2x = NULL; FfElement* t3 = NULL; // temporary for multiplication FfElement* c = NULL; uint8_t* digest = NULL; PreComputedSignature curr_presig = {0}; if (!ctx || !sig) { return kEpidBadArgErr; } if (!msg && (0 != msg_len)) { // if message is non-empty it must have both length and content return kEpidBadArgErr; } if (!basename && (0 != basename_len)) { // if basename is non-empty it must have both length and content return kEpidBadArgErr; } if (!ctx->epid2_params) { return kEpidBadArgErr; } do { FiniteField* Fp = ctx->epid2_params->Fp; SignCommitOutput commit_out = {0}; FpElemStr c_str = {0}; EcGroup* G1 = ctx->epid2_params->G1; FiniteField* GT = ctx->epid2_params->GT; FiniteField* Fq = ctx->epid2_params->Fq; PairingState* ps_ctx = ctx->epid2_params->pairing_state; const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; BigNumStr t1_str = {0}; BigNumStr t2_str = {0}; size_t digest_size = 0; uint16_t* rf_ctr = (uint16_t*)&ctx->rf_ctr; FfElement const* x = ctx->x; if (basename) { if (!IsBasenameAllowed(ctx->allowed_basenames, basename, basename_len)) { sts = kEpidBadArgErr; BREAK_ON_EPID_ERROR(sts); } } sts = NewEcPoint(G1, &B); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(G1, &k); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(G1, &t); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(G1, &e); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(GT, &R2); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fq, &p2y); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &t1); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &t2); BREAK_ON_EPID_ERROR(sts); p2x = (struct p2x_t*)SAFE_ALLOC(sizeof(struct p2x_t) + basename_len - 1); if (!p2x) { sts = kEpidMemAllocErr; break; } sts = NewFfElement(Fp, &a); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &b); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &rx); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &ra); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &rb); BREAK_ON_EPID_ERROR(sts); sts = MemberGetPreSig((MemberCtx*)ctx, &curr_presig); BREAK_ON_EPID_ERROR(sts); // 3. If the pre-computed signature pre-sigma exists, the member // loads (B, K, T, a, b, rx, rf, ra, rb, R1, R2) from // pre-sigma. Refer to Section 4.4 for the computation of // these values. sts = ReadFfElement(Fp, &curr_presig.a, sizeof(curr_presig.a), a); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fp, &curr_presig.b, sizeof(curr_presig.b), b); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fp, &curr_presig.rx, sizeof(curr_presig.rx), rx); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fp, &curr_presig.ra, sizeof(curr_presig.ra), ra); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fp, &curr_presig.rb, sizeof(curr_presig.rb), rb); BREAK_ON_EPID_ERROR(sts); // If the basename is provided, use it, otherwise use presig B if (basename) { // 3.a. The member computes (B, i2, y2) = G1.tpmHash(bsn). sts = EcHash(G1, basename, basename_len, ctx->hash_alg, B, &p2x->i); BREAK_ON_EPID_ERROR(sts); p2x->i = htonl(p2x->i); sts = WriteEcPoint(G1, B, &commit_out.B, sizeof(commit_out.B)); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fq, &commit_out.B.y, sizeof(commit_out.B.y), p2y); BREAK_ON_EPID_ERROR(sts); // b.i. (KTPM, LTPM, ETPM, counterTPM) = TPM2_Commit(P1=h1,(s2, y2) = (i2 // || bsn, y2)). // b.ii.K = KTPM. if (0 != memcpy_S((void*)p2x->bsn, basename_len, basename, basename_len)) { sts = kEpidBadArgErr; break; } sts = Tpm2Commit(ctx->tpm2_ctx, ctx->h1, p2x, sizeof(p2x->i) + basename_len, p2y, k, t, e, (uint16_t*)&ctx->rf_ctr); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(G1, k, &commit_out.K, sizeof(commit_out.K)); BREAK_ON_EPID_ERROR(sts); // c.i. The member computes R1 = LTPM. sts = WriteEcPoint(G1, t, &commit_out.R1, sizeof(commit_out.R1)); BREAK_ON_EPID_ERROR(sts); // c.ii. e12rf = pairing(ETPM, g2) sts = Pairing(ps_ctx, e, ctx->epid2_params->g2, R2); BREAK_ON_EPID_ERROR(sts); // c.iii. R2 = GT.sscmMultiExp(ea2, t1, e12rf, 1, e22, t2, e2w,ra). // 4.i. The member computes t1 = (- rx) mod p. sts = FfNeg(Fp, rx, t1); BREAK_ON_EPID_ERROR(sts); // 4.j. The member computes t2 = (rb - a * rx) mod p. sts = FfMul(Fp, a, rx, t2); BREAK_ON_EPID_ERROR(sts); sts = FfNeg(Fp, t2, t2); BREAK_ON_EPID_ERROR(sts); sts = FfAdd(Fp, rb, t2, t2); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t1, &t1_str, sizeof(t1_str)); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t2, &t2_str, sizeof(t2_str)); BREAK_ON_EPID_ERROR(sts); { FfElement const* points[4]; BigNumStr const* exponents[4]; points[0] = ctx->ea2; points[1] = R2; points[2] = ctx->e22; points[3] = ctx->e2w; exponents[0] = &t1_str; exponents[1] = &kOne; exponents[2] = &t2_str; exponents[3] = (BigNumStr*)&curr_presig.ra; sts = FfMultiExp(GT, points, exponents, COUNT_OF(points), R2); BREAK_ON_EPID_ERROR(sts); } sts = WriteFfElement(GT, R2, &commit_out.R2, sizeof(commit_out.R2)); BREAK_ON_EPID_ERROR(sts); // d. The member over-writes the counterTPM, B, K, R1 and R2 values. } else { if (!rnd_bsn) { sts = kEpidBadArgErr; break; } sts = ReadEcPoint(G1, &curr_presig.B, sizeof(curr_presig.B), B); BREAK_ON_EPID_ERROR(sts); commit_out.B = curr_presig.B; commit_out.K = curr_presig.K; commit_out.R1 = curr_presig.R1; ((MemberCtx*)ctx)->rf_ctr = curr_presig.rf_ctr; commit_out.R2 = curr_presig.R2; *rnd_bsn = curr_presig.rnd_bsn; } commit_out.T = curr_presig.T; sts = HashSignCommitment(Fp, ctx->hash_alg, &ctx->pub_key, &commit_out, msg, msg_len, &c_str); BREAK_ON_EPID_ERROR(sts); digest_size = EpidGetHashSize(ctx->hash_alg); digest = (uint8_t*)SAFE_ALLOC(digest_size); if (!digest) { sts = kEpidNoMemErr; break; } memcpy_S(digest + digest_size - sizeof(c_str), sizeof(c_str), &c_str, sizeof(c_str)); sts = NewFfElement(Fp, &t3); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(Fp, &c); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(Fp, &c_str, sizeof(c_str), c); BREAK_ON_EPID_ERROR(sts); // 7. The member computes sx = (rx + c * x) mod p. sts = FfMul(Fp, c, x, t3); BREAK_ON_EPID_ERROR(sts); sts = FfAdd(Fp, rx, t3, t3); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t3, &sig->sx, sizeof(sig->sx)); BREAK_ON_EPID_ERROR(sts); // 8. The member computes sf = (rf + c * f) mod p. sts = Tpm2Sign(ctx->tpm2_ctx, digest, digest_size, *rf_ctr, NULL, t3); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t3, &sig->sf, sizeof(sig->sf)); BREAK_ON_EPID_ERROR(sts); // 9. The member computes sa = (ra + c * a) mod p. sts = FfMul(Fp, c, a, t3); BREAK_ON_EPID_ERROR(sts); sts = FfAdd(Fp, ra, t3, t3); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t3, &sig->sa, sizeof(sig->sa)); BREAK_ON_EPID_ERROR(sts); // 10. The member computes sb = (rb + c * b) mod p. sts = FfMul(Fp, c, b, t3); BREAK_ON_EPID_ERROR(sts); sts = FfAdd(Fp, rb, t3, t3); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(Fp, t3, &sig->sb, sizeof(sig->sb)); BREAK_ON_EPID_ERROR(sts); sig->B = commit_out.B; sig->K = commit_out.K; sig->T = commit_out.T; sig->c = c_str; sts = kEpidNoErr; } while (0); if (sts != kEpidNoErr) { (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, (uint16_t)ctx->rf_ctr); (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr); } else if (basename) { (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr); } EpidZeroMemory(&curr_presig, sizeof(curr_presig)); DeleteEcPoint(&B); DeleteEcPoint(&k); DeleteEcPoint(&t); DeleteEcPoint(&e); DeleteFfElement(&R2); DeleteFfElement(&p2y); DeleteFfElement(&t1); DeleteFfElement(&t2); DeleteFfElement(&a); DeleteFfElement(&b); DeleteFfElement(&rx); DeleteFfElement(&ra); DeleteFfElement(&rb); SAFE_FREE(p2x); DeleteFfElement(&t3); DeleteFfElement(&c); SAFE_FREE(digest); return sts; }
EpidStatus EpidCheckPrivRlEntry(VerifierCtx const* ctx, BasicSignature const* sig, FpElemStr const* f) { EpidStatus result = kEpidErr; EcPoint* b = NULL; EcPoint* k = NULL; EcPoint* t4 = NULL; EcGroup* G1 = NULL; FfElement* ff_elem = NULL; if (!ctx || !sig || !f) { return kEpidBadArgErr; } if (!ctx->epid2_params || !ctx->epid2_params->G1) { return kEpidBadArgErr; } do { // Section 4.1.2 Step 4.b For i = 0, ... , n1-1, the verifier computes t4 // =G1.exp(B, f[i]) and verifies that G1.isEqual(t4, K) = false. bool compare_result = false; FiniteField* Fp = ctx->epid2_params->Fp; G1 = ctx->epid2_params->G1; result = NewFfElement(Fp, &ff_elem); if (kEpidNoErr != result) { break; } result = NewEcPoint(G1, &b); if (kEpidNoErr != result) { break; } result = NewEcPoint(G1, &k); if (kEpidNoErr != result) { break; } result = NewEcPoint(G1, &t4); if (kEpidNoErr != result) { break; } // ReadFfElement checks that the value f is in the field result = ReadFfElement(Fp, (BigNumStr const*)f, sizeof(BigNumStr), ff_elem); if (kEpidNoErr != result) { break; } result = ReadEcPoint(G1, &sig->B, sizeof(sig->B), b); if (kEpidNoErr != result) { break; } result = ReadEcPoint(G1, &sig->K, sizeof(sig->K), k); if (kEpidNoErr != result) { break; } result = EcExp(G1, b, (BigNumStr const*)f, t4); if (kEpidNoErr != result) { break; } result = EcIsEqual(G1, t4, k, &compare_result); if (kEpidNoErr != result) { break; } // if t4 == k, sig revoked in PrivRl if (compare_result) { result = kEpidSigRevokedInPrivRl; } else { result = kEpidNoErr; } } while (0); DeleteFfElement(&ff_elem); DeleteEcPoint(&t4); DeleteEcPoint(&k); DeleteEcPoint(&b); return result; }
EpidStatus EpidComputePreSig(MemberCtx const* ctx, PreComputedSignature* precompsig) { EpidStatus res = kEpidNotImpl; EcPoint* B = NULL; EcPoint* K = NULL; EcPoint* T = NULL; EcPoint* R1 = NULL; FfElement* R2 = NULL; FfElement* a = NULL; FfElement* b = NULL; FfElement* rx = NULL; FfElement* rf = NULL; FfElement* ra = NULL; FfElement* rb = NULL; FfElement* t1 = NULL; FfElement* t2 = NULL; FfElement* f = NULL; if (!ctx || !precompsig) return kEpidBadArgErr; if (!ctx->epid2_params || !ctx->pub_key || !ctx->priv_key) return kEpidBadArgErr; do { // handy shorthands: EcGroup* G1 = ctx->epid2_params->G1; FiniteField* GT = ctx->epid2_params->GT; FiniteField* Fp = ctx->epid2_params->Fp; EcPoint* h2 = ctx->pub_key->h2; EcPoint* A = ctx->priv_key->A; FfElement* x = ctx->priv_key->x; BigNumStr f_str = {0}; BigNumStr a_str = {0}; BigNumStr t1_str = {0}; BigNumStr rf_str = {0}; BigNumStr t2_str = {0}; BigNumStr ra_str = {0}; static const BigNumStr one = { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}}; if (!G1 || !GT || !Fp || !h2 || !A || !x || !ctx->priv_key->f || !ctx->e12 || !ctx->e22 || !ctx->e2w || !ctx->ea2) { res = kEpidBadArgErr; BREAK_ON_EPID_ERROR(res); } f = ctx->priv_key->f; // The following variables B, K, T, R1 (elements of G1), R2 // (elements of GT), a, b, rx, rf, ra, rb, t1, t2 (256-bit // integers) are used. res = NewEcPoint(G1, &B); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &K); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &T); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &R1); BREAK_ON_EPID_ERROR(res); res = NewFfElement(GT, &R2); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &a); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &b); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &rx); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &rf); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &ra); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &rb); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &t1); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &t2); BREAK_ON_EPID_ERROR(res); // 1. The member expects the pre-computation is done (e12, e22, e2w, // ea2). Refer to Section 3.5 for the computation of these // values. // 2. The member verifies gid in public key matches gid in private // key. // 3. The member computes B = G1.getRandom(). res = EcGetRandom(G1, ctx->rnd_func, ctx->rnd_param, B); BREAK_ON_EPID_ERROR(res); // 4. The member computes K = G1.sscmExp(B, f). res = WriteFfElement(Fp, f, &f_str, sizeof(f_str)); BREAK_ON_EPID_ERROR(res); res = EcExp(G1, B, &f_str, K); BREAK_ON_EPID_ERROR(res); // 5. The member chooses randomly an integers a from [1, p-1]. res = FfGetRandom(Fp, &one, ctx->rnd_func, ctx->rnd_param, a); BREAK_ON_EPID_ERROR(res); // 6. The member computes T = G1.sscmExp(h2, a). res = WriteFfElement(Fp, a, &a_str, sizeof(a_str)); BREAK_ON_EPID_ERROR(res); res = EcExp(G1, h2, &a_str, T); BREAK_ON_EPID_ERROR(res); // 7. The member computes T = G1.mul(T, A). res = EcMul(G1, T, A, T); BREAK_ON_EPID_ERROR(res); // 8. The member computes b = (a * x) mod p. res = FfMul(Fp, a, x, b); BREAK_ON_EPID_ERROR(res); // 9. The member chooses rx, rf, ra, rb randomly from [1, p-1]. res = FfGetRandom(Fp, &one, ctx->rnd_func, ctx->rnd_param, rx); BREAK_ON_EPID_ERROR(res); res = FfGetRandom(Fp, &one, ctx->rnd_func, ctx->rnd_param, rf); BREAK_ON_EPID_ERROR(res); res = FfGetRandom(Fp, &one, ctx->rnd_func, ctx->rnd_param, ra); BREAK_ON_EPID_ERROR(res); res = FfGetRandom(Fp, &one, ctx->rnd_func, ctx->rnd_param, rb); BREAK_ON_EPID_ERROR(res); // 10. The member computes t1 = (- rx) mod p. res = FfNeg(Fp, rx, t1); BREAK_ON_EPID_ERROR(res); // 11. The member computes t2 = (rb - a * rx) mod p. res = FfMul(Fp, a, rx, t2); BREAK_ON_EPID_ERROR(res); res = FfNeg(Fp, t2, t2); BREAK_ON_EPID_ERROR(res); res = FfAdd(Fp, rb, t2, t2); BREAK_ON_EPID_ERROR(res); // 12. The member computes R1 = G1.sscmExp(B, rf). res = WriteFfElement(Fp, rf, &rf_str, sizeof(rf_str)); BREAK_ON_EPID_ERROR(res); res = EcExp(G1, B, &rf_str, R1); BREAK_ON_EPID_ERROR(res); // 13. The member computes R2 = GT.sscmMultiExp(ea2, t1, e12, rf, // e22, t2, e2w, ra). res = WriteFfElement(Fp, t1, &t1_str, sizeof(t1_str)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, t2, &t2_str, sizeof(t2_str)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, ra, &ra_str, sizeof(ra_str)); BREAK_ON_EPID_ERROR(res); { FfElement const* points[4]; BigNumStr const* exponents[4]; points[0] = ctx->ea2; points[1] = ctx->e12; points[2] = ctx->e22; points[3] = ctx->e2w; exponents[0] = &t1_str; exponents[1] = &rf_str; exponents[2] = &t2_str; exponents[3] = &ra_str; res = FfMultiExp(GT, points, exponents, COUNT_OF(points), R2); BREAK_ON_EPID_ERROR(res); } // 14. The member sets and outputs pre-sigma = (B, K, T, a, b, rx, // rf, ra, rb, R1, R2). res = WriteEcPoint(G1, B, &precompsig->B, sizeof(precompsig->B)); BREAK_ON_EPID_ERROR(res); res = WriteEcPoint(G1, K, &precompsig->K, sizeof(precompsig->K)); BREAK_ON_EPID_ERROR(res); res = WriteEcPoint(G1, T, &precompsig->T, sizeof(precompsig->T)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, a, &precompsig->a, sizeof(precompsig->a)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, b, &precompsig->b, sizeof(precompsig->b)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, rx, &precompsig->rx, sizeof(precompsig->rx)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, rf, &precompsig->rf, sizeof(precompsig->rf)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, ra, &precompsig->ra, sizeof(precompsig->ra)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, rb, &precompsig->rb, sizeof(precompsig->rb)); BREAK_ON_EPID_ERROR(res); res = WriteEcPoint(G1, R1, &precompsig->R1, sizeof(precompsig->R1)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(GT, R2, &precompsig->R2, sizeof(precompsig->R2)); BREAK_ON_EPID_ERROR(res); // 15. The member stores pre-sigma in the secure storage of the // member. res = kEpidNoErr; } while (0); f = NULL; DeleteEcPoint(&B); DeleteEcPoint(&K); DeleteEcPoint(&T); DeleteEcPoint(&R1); DeleteFfElement(&R2); DeleteFfElement(&a); DeleteFfElement(&b); DeleteFfElement(&rx); DeleteFfElement(&rf); DeleteFfElement(&ra); DeleteFfElement(&rb); DeleteFfElement(&t1); DeleteFfElement(&t2); return (res); }
EpidStatus EpidRequestJoin(GroupPubKey const* pub_key, IssuerNonce const* ni, FpElemStr const* f, BitSupplier rnd_func, void* rnd_param, HashAlg hash_alg, JoinRequest* join_request) { EpidStatus sts; static const BigNumStr one = { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}}; BigNumStr r_str; JoinPCommitValues commit_values; Epid2Params_* params = NULL; FfElement* r_el = NULL; FfElement* f_el = NULL; FfElement* c_el = NULL; FfElement* cf_el = NULL; FfElement* s_el = NULL; EcPoint* f_pt = NULL; EcPoint* r_pt = NULL; EcPoint* h1_pt = NULL; if (!pub_key || !ni || !f || !rnd_func || !join_request) { return kEpidBadArgErr; } if (kSha256 != hash_alg && kSha384 != hash_alg && kSha512 != hash_alg) { return kEpidBadArgErr; } do { sts = CreateEpid2Params(¶ms); BREAK_ON_EPID_ERROR(sts); if (!params->Fp || !params->G1) { sts = kEpidBadArgErr; break; } sts = NewFfElement(params->Fp, &r_el); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(params->Fp, &f_el); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(params->Fp, &c_el); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(params->Fp, &cf_el); BREAK_ON_EPID_ERROR(sts); sts = NewFfElement(params->Fp, &s_el); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(params->G1, &f_pt); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(params->G1, &h1_pt); BREAK_ON_EPID_ERROR(sts); sts = NewEcPoint(params->G1, &r_pt); BREAK_ON_EPID_ERROR(sts); sts = ReadFfElement(params->Fp, (uint8_t const*)f, sizeof(*f), f_el); BREAK_ON_EPID_ERROR(sts); sts = ReadEcPoint(params->G1, (uint8_t*)&pub_key->h1, sizeof(pub_key->h1), h1_pt); BREAK_ON_EPID_ERROR(sts); // Step 1. The member chooses a random integer r from [1, p-1]. sts = FfGetRandom(params->Fp, &one, rnd_func, rnd_param, r_el); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(params->Fp, r_el, (uint8_t*)&r_str, sizeof(r_str)); // Step 2. The member computes F = G1.sscmExp(h1, f). sts = EcExp(params->G1, h1_pt, (BigNumStr const*)f, f_pt); BREAK_ON_EPID_ERROR(sts); // Step 3. The member computes R = G1.sscmExp(h1, r). sts = EcExp(params->G1, h1_pt, (BigNumStr const*)&r_str, r_pt); BREAK_ON_EPID_ERROR(sts); // Step 4. The member computes c = Fp.hash(p || g1 || g2 || h1 || h2 || w || // F || R || NI). Refer to Section 7.1 for hash operation over a prime // field. sts = WriteBigNum(params->p, sizeof(commit_values.p), (uint8_t*)&commit_values.p); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(params->G1, params->g1, (uint8_t*)&commit_values.g1, sizeof(commit_values.g1)); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(params->G2, params->g2, (uint8_t*)&commit_values.g2, sizeof(commit_values.g2)); BREAK_ON_EPID_ERROR(sts); commit_values.h1 = pub_key->h1; commit_values.h2 = pub_key->h2; commit_values.w = pub_key->w; sts = WriteEcPoint(params->G1, f_pt, (uint8_t*)&commit_values.F, sizeof(commit_values.F)); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(params->G1, r_pt, (uint8_t*)&commit_values.R, sizeof(commit_values.R)); BREAK_ON_EPID_ERROR(sts); commit_values.NI = *ni; sts = FfHash(params->Fp, (uint8_t*)&commit_values, sizeof(commit_values), hash_alg, c_el); BREAK_ON_EPID_ERROR(sts); // Step 5. The member computes s = (r + c * f) mod p. sts = FfMul(params->Fp, c_el, f_el, cf_el); BREAK_ON_EPID_ERROR(sts); sts = FfAdd(params->Fp, r_el, cf_el, s_el); BREAK_ON_EPID_ERROR(sts); // Step 6. The output join request is (F, c, s). sts = WriteFfElement(params->Fp, c_el, (uint8_t*)&join_request->c, sizeof(join_request->c)); BREAK_ON_EPID_ERROR(sts); sts = WriteFfElement(params->Fp, s_el, (uint8_t*)&join_request->s, sizeof(join_request->s)); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(params->G1, f_pt, (uint8_t*)&join_request->F, sizeof(join_request->F)); BREAK_ON_EPID_ERROR(sts); sts = kEpidNoErr; } while (0); DeleteEcPoint(&h1_pt); DeleteEcPoint(&r_pt); DeleteEcPoint(&f_pt); DeleteFfElement(&s_el); DeleteFfElement(&cf_el); DeleteFfElement(&c_el); DeleteFfElement(&f_el); DeleteFfElement(&r_el); DeleteEpid2Params(¶ms); return sts; }
// implements section 3.2.2 "Validation of Private Key" from // Intel(R) EPID 2.0 Spec bool EpidIsPrivKeyInGroup(GroupPubKey const* pub_key, PrivKey const* priv_key) { bool result; // Intel(R) EPID Parameters Epid2Params_* params = NULL; PairingState* ps = NULL; // private key EcPoint* a_pt = NULL; // an element in G1 FfElement* x_el = NULL; // an integer between [1, p-1] FfElement* f_el = NULL; // an integer between [1, p-1] // public key EcPoint* h1_pt = NULL; // an element in G1 EcPoint* h2_pt = NULL; // an element in G1 EcPoint* w_pt = NULL; // an element in G2 // local variables EcPoint* t1_pt = NULL; // an element in G2 EcPoint* t2_pt = NULL; // an element in G1 FfElement* t3_el = NULL; // an element in GT FfElement* t4_el = NULL; // an element in GT if (!pub_key || !priv_key) { return false; } do { EpidStatus sts; EcGroup* G1 = NULL; EcGroup* G2 = NULL; FiniteField* GT = NULL; FiniteField* Fp = NULL; BigNumStr t_str = {0}; sts = CreateEpid2Params(¶ms); if (kEpidNoErr != sts) { result = false; break; } G1 = params->G1; G2 = params->G2; GT = params->GT; Fp = params->Fp; sts = WriteBigNum(params->t, sizeof(t_str), &t_str); if (kEpidNoErr != sts) { result = false; break; } sts = NewPairingState(G1, G2, GT, &t_str, params->neg, &ps); if (kEpidNoErr != sts) { result = false; break; } // Load private key sts = NewEcPoint(G1, &a_pt); if (kEpidNoErr != sts) { result = false; break; } sts = ReadEcPoint(G1, &priv_key->A, sizeof(priv_key->A), a_pt); if (kEpidNoErr != sts) { result = false; break; } sts = NewFfElement(Fp, &x_el); if (kEpidNoErr != sts) { result = false; break; } sts = ReadFfElement(Fp, &priv_key->x, sizeof(priv_key->x), x_el); if (kEpidNoErr != sts) { result = false; break; } sts = NewFfElement(Fp, &f_el); if (kEpidNoErr != sts) { result = false; break; } sts = ReadFfElement(Fp, &priv_key->f, sizeof(priv_key->f), f_el); if (kEpidNoErr != sts) { result = false; break; } // Load public key sts = NewEcPoint(G1, &h1_pt); if (kEpidNoErr != sts) { result = false; break; } sts = ReadEcPoint(G1, &pub_key->h1, sizeof(pub_key->h1), h1_pt); if (kEpidNoErr != sts) { result = false; break; } sts = NewEcPoint(G1, &h2_pt); if (kEpidNoErr != sts) { result = false; break; } sts = ReadEcPoint(G1, &pub_key->h2, sizeof(pub_key->h2), h2_pt); if (kEpidNoErr != sts) { result = false; break; } sts = NewEcPoint(G2, &w_pt); if (kEpidNoErr != sts) { result = false; break; } sts = ReadEcPoint(G2, &pub_key->w, sizeof(pub_key->w), w_pt); if (kEpidNoErr != sts) { result = false; break; } // local variables sts = NewEcPoint(G2, &t1_pt); if (kEpidNoErr != sts) { result = false; break; } sts = NewEcPoint(G1, &t2_pt); if (kEpidNoErr != sts) { result = false; break; } sts = NewFfElement(GT, &t3_el); if (kEpidNoErr != sts) { result = false; break; } sts = NewFfElement(GT, &t4_el); if (kEpidNoErr != sts) { result = false; break; } // Step 1. The member verifies that the gid in the public key matches the // gid in the private key. if (0 != memcmp(&pub_key->gid, &priv_key->gid, sizeof(priv_key->gid))) { result = false; break; } // Step 2. The member computes t1 = G2.sscmExp(g2, x). sts = EcSscmExp(G2, params->g2, (BigNumStr const*)&priv_key->x, t1_pt); if (kEpidNoErr != sts) { result = false; break; } // Step 3. The member computes t1 = G2.mul(t1, w). sts = EcMul(G2, t1_pt, w_pt, t1_pt); if (kEpidNoErr != sts) { result = false; break; } // Step 4. The member computes t3 = pairing(A, t1). sts = Pairing(ps, t3_el, a_pt, t1_pt); if (kEpidNoErr != sts) { result = false; break; } // Step 5. The member computes t2 = G1.sscmExp(h1, f). sts = EcSscmExp(G1, h1_pt, (BigNumStr const*)&priv_key->f, t2_pt); if (kEpidNoErr != sts) { result = false; break; } // Step 6. The member computes t2 = G1.mul(t2, g1). sts = EcMul(G1, t2_pt, params->g1, t2_pt); if (kEpidNoErr != sts) { result = false; break; } // Step 7. The member computes t4 = pairing(t2, g2). sts = WriteBigNum(params->t, sizeof(t_str), &t_str); if (kEpidNoErr != sts) { result = false; break; } sts = Pairing(ps, t4_el, t2_pt, params->g2); if (kEpidNoErr != sts) { result = false; break; } // Step 8. If GT.isEqual(t3, t4) = false, reports bad private key. sts = FfIsEqual(GT, t3_el, t4_el, &result); if (kEpidNoErr != sts) { result = false; break; } } while (0); // local variables DeleteFfElement(&t4_el); DeleteFfElement(&t3_el); DeleteEcPoint(&t2_pt); DeleteEcPoint(&t1_pt); // public key DeleteEcPoint(&w_pt); DeleteEcPoint(&h2_pt); DeleteEcPoint(&h1_pt); // private key DeleteFfElement(&f_el); DeleteFfElement(&x_el); DeleteEcPoint(&a_pt); // Intel(R) EPID Parameters DeletePairingState(&ps); DeleteEpid2Params(¶ms); return result; }
EpidStatus Tpm2LoadExternal(Tpm2Ctx* ctx, FpElemStr const* f_str) { EpidStatus sts = kEpidErr; TPM_RC rc = TPM_RC_SUCCESS; EcPoint* pub = NULL; FfElement* f = NULL; TPMI_ALG_HASH tpm_hash_alg = TPM_ALG_NULL; if (!ctx || !ctx->epid2_params || !f_str) { return kEpidBadArgErr; } do { LoadExternal_In in = {0}; LoadExternal_Out out; G1ElemStr pub_str = {0}; TPMS_ECC_PARMS* ecc_details = &in.inPublic.publicArea.parameters.eccDetail; EcGroup* G1 = ctx->epid2_params->G1; EcPoint* g1 = ctx->epid2_params->g1; sts = NewFfElement(ctx->epid2_params->Fp, &f); BREAK_ON_EPID_ERROR(sts); // verify that f is valid sts = ReadFfElement(ctx->epid2_params->Fp, f_str, sizeof(*f_str), f); BREAK_ON_EPID_ERROR(sts); if (ctx->key_handle) { FlushContext_In in_fc; in_fc.flushHandle = ctx->key_handle; TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in_fc, NULL, TPM_CC_FlushContext, TPM_RH_NULL, NULL, 0); if (rc != TPM_RC_SUCCESS) { print_tpm2_response_code("TPM2_FlushContext", rc); } ctx->key_handle = 0; } sts = NewEcPoint(G1, &pub); BREAK_ON_EPID_ERROR(sts); sts = EcExp(G1, g1, (BigNumStr const*)f_str, pub); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(G1, pub, &pub_str, sizeof(pub_str)); BREAK_ON_EPID_ERROR(sts); tpm_hash_alg = EpidtoTpm2HashAlg(ctx->hash_alg); if (tpm_hash_alg == TPM_ALG_NULL) { sts = kEpidHashAlgorithmNotSupported; break; } in.hierarchy = TPM_RH_NULL; in.inPublic.size = sizeof(TPM2B_PUBLIC); in.inPublic.publicArea.type = TPM_ALG_ECC; in.inPublic.publicArea.nameAlg = tpm_hash_alg; in.inPublic.publicArea.objectAttributes.val = TPMA_OBJECT_NODA | TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN; in.inPublic.publicArea.authPolicy.t.size = 0; ecc_details->symmetric.algorithm = TPM_ALG_NULL; ecc_details->scheme.scheme = TPM_ALG_ECDAA; ecc_details->scheme.details.ecdaa.hashAlg = tpm_hash_alg; ecc_details->scheme.details.ecdaa.count = 0; ecc_details->curveID = TPM_ECC_BN_P256; ecc_details->kdf.scheme = TPM_ALG_NULL; sts = ReadTpm2FfElement(&pub_str.x.data, &in.inPublic.publicArea.unique.ecc.x); BREAK_ON_EPID_ERROR(sts); sts = ReadTpm2FfElement(&pub_str.y.data, &in.inPublic.publicArea.unique.ecc.y); BREAK_ON_EPID_ERROR(sts); in.inPrivate.t.size = sizeof(in.inPrivate.t.sensitiveArea); in.inPrivate.t.sensitiveArea.sensitiveType = TPM_ALG_ECC; sts = ReadTpm2FfElement(&f_str->data, &in.inPrivate.t.sensitiveArea.sensitive.ecc); BREAK_ON_EPID_ERROR(sts); rc = TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out, (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_LoadExternal, TPM_RH_NULL, NULL, 0); if (rc != TPM_RC_SUCCESS) { print_tpm2_response_code("TPM2_LoadExternal", rc); if (TPM_RC_BINDING == rc || TPM_RC_ECC_POINT == rc || TPM_RC_KEY_SIZE == rc) sts = kEpidBadArgErr; else sts = kEpidErr; break; } ctx->key_handle = out.objectHandle; } while (0); DeleteEcPoint(&pub); DeleteFfElement(&f); return sts; }
void PrintEcPoint(EcGroup const* g, EcPoint const* ec_point, char const* var_name, PrintUtilFormat format) { FiniteField fp; FfElement* fp_x = NULL; FfElement* fp_y = NULL; uint8_t ec_point_str[sizeof(G2ElemStr)]; if (!var_name) { var_name = "<no name>"; } if (!ec_point || !g) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<null>\n"); return; } if (!ec_point->ipp_ec_pt || !g->ipp_ec) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); return; } do { IppStatus sts = ippStsNoErr; int ipp_half_strlen; // get finite field sts = ippsGFpECGet(g->ipp_ec, (const IppsGFpState**)&(fp.ipp_ff), 0, 0, 0, 0, 0, 0, 0, 0); if (ippStsNoErr != sts) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } // create element X if (kEpidNoErr != NewFfElement(&fp, &fp_x)) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } // create element Y if (kEpidNoErr != NewFfElement(&fp, &fp_y)) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } ipp_half_strlen = fp_x->info.elementLen * sizeof(Ipp32u); // get elements from point sts = ippsGFpECGetPoint(ec_point->ipp_ec_pt, fp_x->ipp_ff_elem, fp_y->ipp_ff_elem, g->ipp_ec); // check return codes if (ippStsNoErr != sts) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } // get element X data sts = ippsGFpGetElementOctString(fp_x->ipp_ff_elem, (Ipp8u*)&ec_point_str, ipp_half_strlen, fp.ipp_ff); // check return codes if (ippStsNoErr != sts) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } // get element Y data sts = ippsGFpGetElementOctString(fp_y->ipp_ff_elem, (Ipp8u*)&ec_point_str + ipp_half_strlen, ipp_half_strlen, fp.ipp_ff); // check return codes if (ippStsNoErr != sts) { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } if (2 * ipp_half_strlen == sizeof(G1ElemStr)) { PrintG1ElemStr((const G1ElemStr*)&ec_point_str, var_name, format); } else if (2 * ipp_half_strlen == sizeof(G2ElemStr)) { PrintG2ElemStr((const G2ElemStr*)&ec_point_str, var_name, format); } else { PRINT("%s (EcPoint):\n", var_name); MAKE_INDENT(); PRINT("<invalid>\n"); break; } } while (0); DeleteFfElement(&fp_x); DeleteFfElement(&fp_y); }
EpidStatus EpidVerifierCreate(GroupPubKey const* pubkey, VerifierPrecomp const* precomp, VerifierCtx** ctx) { EpidStatus result = kEpidErr; VerifierCtx* verifier_ctx = NULL; if (!pubkey || !ctx) { return kEpidBadArgErr; } do { // Allocate memory for VerifierCtx verifier_ctx = SAFE_ALLOC(sizeof(VerifierCtx)); if (!verifier_ctx) { result = kEpidMemAllocErr; break; } // set SHA512 as the default hash algorithm verifier_ctx->hash_alg = kSha512; // Internal representation of Epid2Params result = CreateEpid2Params(&verifier_ctx->epid2_params); if (kEpidNoErr != result) { break; } // Internal representation of Group Pub Key result = CreateGroupPubKey(pubkey, verifier_ctx->epid2_params->G1, verifier_ctx->epid2_params->G2, &verifier_ctx->pub_key); if (kEpidNoErr != result) { break; } // Store group public key strings for later use result = SetKeySpecificCommitValues(pubkey, &verifier_ctx->commit_values); if (kEpidNoErr != result) { break; } // Allocate verifier_ctx->e12 result = NewFfElement(verifier_ctx->epid2_params->GT, &verifier_ctx->e12); if (kEpidNoErr != result) { break; } // Allocate verifier_ctx->e22 result = NewFfElement(verifier_ctx->epid2_params->GT, &verifier_ctx->e22); if (kEpidNoErr != result) { break; } // Allocate verifier_ctx->e2w result = NewFfElement(verifier_ctx->epid2_params->GT, &verifier_ctx->e2w); if (kEpidNoErr != result) { break; } // Allocate verifier_ctx->eg12 result = NewFfElement(verifier_ctx->epid2_params->GT, &verifier_ctx->eg12); if (kEpidNoErr != result) { break; } // precomputation if (precomp != NULL) { result = ReadPrecomputation(precomp, verifier_ctx); } else { result = DoPrecomputation(verifier_ctx); } if (kEpidNoErr != result) { break; } verifier_ctx->sig_rl = NULL; verifier_ctx->group_rl = NULL; verifier_ctx->priv_rl = NULL; verifier_ctx->verifier_rl = NULL; *ctx = verifier_ctx; result = kEpidNoErr; } while (0); if (kEpidNoErr != result && verifier_ctx) { DeleteFfElement(&verifier_ctx->eg12); DeleteFfElement(&verifier_ctx->e2w); DeleteFfElement(&verifier_ctx->e22); DeleteFfElement(&verifier_ctx->e12); DeleteEpid2Params(&verifier_ctx->epid2_params); DeleteGroupPubKey(&verifier_ctx->pub_key); SAFE_FREE(verifier_ctx); } return result; }
EpidStatus CreateEpid2Params(Epid2Params_** params) { EpidStatus result = kEpidErr; Epid2Params_* internal_param = NULL; BigNumStr t_str = {0}; Epid2Params params_str = { #include "epid/common/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->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); 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; }
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 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; }