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; }
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; }