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 EpidVerifierWritePrecomp(VerifierCtx const* ctx, VerifierPrecomp* precomp) { EpidStatus result = kEpidErr; FfElement* e12 = NULL; // an element in GT FfElement* e22 = NULL; // an element in GT FfElement* e2w = NULL; // an element in GT FfElement* eg12 = NULL; // an element in GT FiniteField* GT = NULL; // Finite field GT(Fq12 ) if (!ctx) { return kEpidBadArgErr; } if (!precomp) { return kEpidBadArgErr; } if (!ctx->e12 || !ctx->e22 || !ctx->e2w || !ctx->eg12 || !ctx->epid2_params || !(ctx->epid2_params->GT)) { return kEpidBadArgErr; } e12 = ctx->e12; e22 = ctx->e22; e2w = ctx->e2w; eg12 = ctx->eg12; GT = ctx->epid2_params->GT; result = WriteFfElement(GT, e12, &(precomp->e12), sizeof(precomp->e12)); if (kEpidNoErr != result) { return result; } result = WriteFfElement(GT, e22, &(precomp->e22), sizeof(precomp->e22)); if (kEpidNoErr != result) { return result; } result = WriteFfElement(GT, e2w, &(precomp->e2w), sizeof(precomp->e2w)); if (kEpidNoErr != result) { return result; } result = WriteFfElement(GT, eg12, &(precomp->eg12), sizeof(precomp->eg12)); if (kEpidNoErr != result) { return result; } 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 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; }