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; }
int MsClean(const MatrixSet_t *set, Matrix_t *mat) { int i; MatrixSetElement_t *l; /* Check the arguments. -------------------- */ if (!MsIsValid(set) || !MatIsValid(mat)) { return -1; } if (set->Len > 0) { Matrix_t *mat0 = set->List[0].Matrix; if ((mat->Field != mat0->Field) || (mat->Nor != mat0->Nor) || (mat->Noc != mat0->Noc)) { MTX_ERROR1("Cannot clean: %E",MTX_ERR_INCOMPAT); return -1; } } /* Clean the matrix. ----------------- */ for (i = 0, l = set->List; i < set->Len; ++i, ++l) { FEL f = FfExtract(MatGetPtr(mat,l->PivRow),l->PivCol); if (f != FF_ZERO) { MatAddMul(mat,l->Matrix,FfNeg(FfDiv(f,l->PivMark))); } } return 0; }
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; }
MTX_DEFINE_FILE_INFO //////////////////////////////////////////////////////////////////////////////////////////////////// static int zmatinv(PTR mat, PTR result) { PTR xj1, xj2, xk1, xk2; FEL f1 = FF_ZERO, f2; long j, k; // initialize result with identity matrix for (j = 0, xj1 = result; j < FfNoc; ++j, FfStepPtr(&xj1)) { FfMulRow(xj1,FF_ZERO); FfInsert(xj1,j,FF_ONE); } // matrix inversion xj1 = mat; xj2 = result; for (j = 0; j < FfNoc; ++j) { for (xk1 = xj1, k = j; k < FfNoc && (f1 = FfExtract(xk1,j)) == FF_ZERO; ++k, FfStepPtr(&xk1)) { } if (f1 == FF_ZERO) { MTX_ERROR1("%E",MTX_ERR_DIV0); return -1; } if (k > j) { /* Swap rows */ FfSwapRows(xk1,xj1); /* xk2 = FfGetPtr(xj2,k-j,FfNoc);*/ xk2 = (PTR)((char *)xj2 + (k - j) * FfCurrentRowSize); FfSwapRows(xk2,xj2); } f2 = FfInv(f1); FfMulRow(xj1,f2); FfMulRow(xj2,f2); xk1 = mat; xk2 = result; for (k = 0; k < FfNoc; ++k) { if (k != j) { f1 = FfNeg(FfExtract(xk1,j)); FfAddMulRow(xk1,xj1,f1); FfAddMulRow(xk2,xj2,f1); } FfStepPtr(&xk1); FfStepPtr(&xk2); } FfStepPtr(&xj1); FfStepPtr(&xj2); } return 0; }
static Matrix_t *makekernel(const Poly_t *pol) { Matrix_t *materg; PTR rowptr; FEL *xbuf, *pbuf = pol->Data; long pdeg = pol->Degree; int k, xshift; long fl = pol->Field; materg = MatAlloc(fl,pdeg,pdeg); rowptr = materg->Data; xbuf = NALLOC(FEL,pdeg+1); for (k = 0; k <= pdeg; ++k) xbuf[k] = FF_ZERO; xbuf[0] = FF_ONE; for (k = 0; k < pdeg; ++k) { int l; for (l = 0; l < pdeg; ++l) FfInsert(rowptr,l,xbuf[l]); FfInsert(rowptr,k,FfSub(xbuf[k],FF_ONE)); FfStepPtr(&rowptr); for (xshift = (int) fl; xshift > 0; ) { FEL f; int d; /* Find leading pos */ for (l = pdeg-1; xbuf[l] == FF_ZERO && l >= 0; --l); /* Shift left as much as possible */ if ((d = pdeg - l) > xshift) d = xshift; for (; l >= 0; l--) xbuf[l+d] = xbuf[l]; for (l = d-1; l >= 0; --l) xbuf[l] = FF_ZERO; xshift -= d; if (xbuf[pdeg] == FF_ZERO) continue; /* Reduce with pol */ f = FfNeg(FfDiv(xbuf[pdeg],pbuf[pdeg])); for (l = pdeg-1; l >= 0; --l) xbuf[l] = FfAdd(xbuf[l],FfMul(pbuf[l],f)); xbuf[pdeg] = FF_ZERO; } } SysFree(xbuf); return MatNullSpace__(materg); }
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; }
MTX_DEFINE_FILE_INFO /// @addtogroup mat /// @{ //////////////////////////////////////////////////////////////////////////////////////////////////// /// Null space. /// This function calculates the null-space of a matrix. The matrix is passed /// as first argument, |nor| is the number of rows, |piv| must be a pointer /// to an array of at least $|nor|+1$ integers, and |nsp| must be a pointer to /// a square matrix of size |nor|. /// /// If the function is successfull (non-negative return value), /// - |matrix| is reduced to echelon form, /// - |nsp| contains the null-space in echelon form, and /// - |piv| contains a pivot table for the null space. /// If |flags| is nonzero, the null-space is not reduced to echelon form, /// and the contents of |piv| are undefined. /// /// @return The dimension of the null-space, or -1 on error. static long znullsp(PTR matrix, long nor, int *piv, PTR nsp, int flags) { PTR x, y, a, b; int i; long noc = FfNoc; long dim; FEL f; // initialize result with identity if (FfSetNoc(nor) != 0) { return -1; } x = nsp; for (i = 0; i < nor; ++i) { piv[i] = -1; FfMulRow(x,FF_ZERO); FfInsert(x,i,FF_ONE); FfStepPtr(&x); } // gaussian elimination x = matrix; y = nsp; for (i = 0; i < nor; ++i) { PTR xx = matrix, yy = nsp; long k, p; for (k = 0; k < i; ++k) { FfSetNoc(noc); // not checked since we know noc is valid if (((p = piv[k]) >= 0) && ((f = FfExtract(x,p)) != FF_ZERO)) { f = FfNeg(FfDiv(f,FfExtract(xx,p))); FfSetNoc(noc); FfAddMulRow(x,xx,f); FfSetNoc(nor); FfAddMulRow(y,yy,f); } FfSetNoc(noc); FfStepPtr(&xx); FfSetNoc(nor); FfStepPtr(&yy); } FfSetNoc(noc); piv[i] = p = FfFindPivot(x,&f); FfSetNoc(noc); FfStepPtr(&x); FfSetNoc(nor); FfStepPtr(&y); } // step 2: reduce the null space to echelon form. dim = 0; x = y = nsp; a = b = matrix; for (i = 0; i < nor; ++i) { if (piv[i] == -1) { FfSetNoc(nor); if (y != x) { FfCopyRow(y,x); } if (flags) { ++dim; } else { FfCleanRow(y,nsp,dim,piv); piv[dim++] = FfFindPivot(y,&f); } FfStepPtr(&y); } else { FfSetNoc(noc); if (b != a) { FfCopyRow(b,a); } FfStepPtr(&b); } FfSetNoc(nor); FfStepPtr(&x); FfSetNoc(noc); FfStepPtr(&a); } return dim; }
static int ordmat() { PTR m1, v; PTR base, bend; int dim; int *piv; char *ispiv; int ord, i; FfSetField(ifile->Field); FfSetNoc(ifile->Noc); if (ifile->Nor != ifile->Noc) { MTX_ERROR2("%s: %E",iname,MTX_ERR_NOTSQUARE); return 1; } m1 = FfAlloc(FfNoc); base = FfAlloc(FfNoc+1); piv = NALLOC(int,FfNoc); ispiv = NALLOC(char,FfNoc); memset(ispiv,0,FfNoc); v = FfAlloc(1); if (MfReadRows(ifile,m1,FfNoc) != FfNoc) { MTX_ERROR("Error reading input file"); return -1; } ord = 1; bend = base; for (dim = 0; dim < FfNoc; ) { PTR start = bend; int tord = 0; int closed = 0; /* Find the next seed vector ------------------------- */ for (i = 0; i < FfNoc && ispiv[i]; ++i); MTX_ASSERT(i < FfNoc); FfMulRow(bend,FF_ZERO); FfInsert(bend,i,FF_ONE); /* Calculate order on the cyclic subspace -------------------------------------- */ do { PTR b; FEL f; int pv; /* Save the vector and extend the basis, if the vector is linearly independent. -------------------------------------- */ FfCopyRow(v,bend); if (!closed) { b = base; for (i = 0; i < dim; ++i) { f = FfExtract(bend,piv[i]); if (f != FF_ZERO) { FfAddMulRow(bend,b,FfNeg(FfDiv(f,FfExtract(b,piv[i])))); } FfStepPtr(&b); } pv = FfFindPivot(bend,&f); if (pv >= 0) { piv[dim++] = pv; ispiv[pv] = 1; FfStepPtr(&bend); } else closed = 1; } /* Apply the matrix. ----------------- */ if (++tord > MAXORDER_C) { MTX_ERROR1("zor: Partial order is over %d",MAXORDER_C); return 1; } FfMapRow(v,m1,FfNoc,bend); } while (FfCmpRows(bend,start)); /* Calculate l.c.m. of all tord's ------------------------------ */ for (i = ord; ord % tord != 0; ord += i); if (ord > MAXORDER) { MTX_ERROR1("zor: Order is over %d",MAXORDER); return 1; } if (opt_q && dim > FfNoc/10) break; if (maxord > 1) { if (ord > maxord) { fprintf(stderr,"zor: Order is over %d\n",maxord); exit(1); } if (ord == maxord) break; } } if (opt_q && ord != maxord) MESSAGE(0,("ORDER IS A MULTIPLE OF %d\n",ord)); else { if (opt_G) printf("MeatAxe.Order := %d;\n",ord); else printf("ORDER IS %d\n",ord); } return 0; }
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); }