diff --git a/include/mcl/bn.hpp b/include/mcl/bn.hpp index 1e526f5..2927ec2 100644 --- a/include/mcl/bn.hpp +++ b/include/mcl/bn.hpp @@ -802,18 +802,26 @@ struct GLV2 { } } template - void mul(T& Q, const T& P, mpz_class x, bool constTime = false) const + void mul(T& Q, const T& P, const mpz_class& x, bool constTime = false) const { - (void)constTime; - mulVecNGLV(Q, &P, &x, 1); + mulVecNGLV(Q, &P, &x, 1, constTime); } template - size_t mulVecNGLV(T& z, const T *xVec, const mpz_class *yVec, size_t n) const + static void mulLambda(T& Q, const T& P) { + Frobenius(Q, P); + } + template + size_t mulVecNGLV(T& z, const T *xVec, const mpz_class *yVec, size_t n, bool constTime) const + { + if (n == 1 && constTime) { + ec::local::mul1CT, T, Fr, 4, 4>(*this, z, *xVec, *yVec); + return 1; + } const mpz_class& r = Fr::getOp().mp; const size_t N = mcl::fp::maxMulVecNGLV; if (n > N) n = N; - const int w = 5; + const int w = 4; const size_t tblSize = 1 << (w - 2); const int splitN = 4; NafArray naf[N][splitN]; @@ -1060,17 +1068,17 @@ inline void powArrayGLV2(Fp12& z, const Fp12& x, const mcl::fp::Unit *y, size_t BN::param.glv2.pow(z, x, s, constTime); } -inline size_t mulVecNGLV2(G2& z, const G2 *xVec, const mpz_class *yVec, size_t n) +inline size_t mulVecNGLV2(G2& z, const G2 *xVec, const mpz_class *yVec, size_t n, bool constTime) { - return BN::param.glv2.mulVecNGLV(z, xVec, yVec, n); + return BN::param.glv2.mulVecNGLV(z, xVec, yVec, n, constTime); } -inline size_t powVecNGLV2(Fp12& z, const Fp12 *xVec, const mpz_class *yVec, size_t n) +inline size_t powVecNGLV2(Fp12& z, const Fp12 *xVec, const mpz_class *yVec, size_t n, bool constTime) { typedef GroupMtoA AG; // as additive group AG& _z = static_cast(z); const AG *_xVec = static_cast(xVec); - return BN::param.glv2.mulVecNGLV(_z, _xVec, yVec, n); + return BN::param.glv2.mulVecNGLV(_z, _xVec, yVec, n, constTime); } /* diff --git a/include/mcl/ec.hpp b/include/mcl/ec.hpp index 20cc7ab..3678993 100644 --- a/include/mcl/ec.hpp +++ b/include/mcl/ec.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(push) @@ -71,6 +72,76 @@ bool get_a_flag(const mcl::Fp2T& x) return get_a_flag(x.b); // x = a + bi } +template +void mul1CT(const GLV& glv, G& Q, const G& P, const mpz_class& x) +{ + const mpz_class& r = F::getOp().mp; + const size_t tblSize = 1 << w; + G tbl[splitN][tblSize]; + bool negTbl[splitN]; + mpz_class u[splitN]; + mpz_class y = x % r; + if (y < 0) { + y += r; + } + glv.split(u, y); + for (int i = 0; i < splitN; i++) { + if (u[i] < 0) { + gmp::neg(u[i], u[i]); + negTbl[i] = true; + } else { + negTbl[i] = false; + } + tbl[i][0].clear(); + } + tbl[0][1] = P; + for (size_t j = 2; j < tblSize; j++) { + G::add(tbl[0][j], tbl[0][j - 1], P); + } + for (int i = 1; i < splitN; i++) { + for (size_t j = 1; j < tblSize; j++) { + GLV::mulLambda(tbl[i][j], tbl[i - 1][j]); + } + } + for (int i = 0; i < splitN; i++) { + if (negTbl[i]) { + for (size_t j = 0; j < tblSize; j++) { + G::neg(tbl[i][j], tbl[i][j]); + } + } + } + mcl::FixedArray vTbl[splitN]; + size_t bitSizeTbl[splitN]; + size_t maxBitSize = 0; + for (size_t i = 0; i < splitN; i++) { + size_t bitSize = gmp::getBitSize(u[i]); + bitSizeTbl[i] = bitSize; + if (bitSize > maxBitSize) { + maxBitSize = bitSize; + } + } + int loopN = (maxBitSize + w - 1) / w; + for (int i = 0; i < splitN; i++) { + fp::ArrayIterator itr(gmp::getUnit(u[i]), bitSizeTbl[i], w); + bool b = vTbl[i].resize(loopN); + assert(b); + (void)b; + for (int j = 0; j < loopN; j++) { + vTbl[i][loopN - 1 - j] = itr.getNext(); + } + } + Q.clear(); + for (int k = 0; k < loopN; k++) { + for (size_t i = 0; i < w; i++) { + G::dbl(Q, Q); + } + for (size_t i = 0; i < splitN; i++) { + uint8_t v = vTbl[i][k]; + G::add(Q, Q, tbl[i][v]); + } + } +} + } // mcl::ec::local template @@ -567,7 +638,7 @@ public: static bool verifyOrder_; static mpz_class order_; static void (*mulArrayGLV)(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime); - static size_t (*mulVecNGLV)(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn); + static size_t (*mulVecNGLV)(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn, bool constTime); /* default constructor is undefined value */ EcT() {} EcT(const Fp& _x, const Fp& _y) @@ -633,7 +704,7 @@ public: // don't clear order_ because it is used for isValidOrder() } } - static void setMulArrayGLV(void f(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn) = 0) + static void setMulArrayGLV(void f(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn, bool constTime) = 0) { mulArrayGLV = f; mulVecNGLV = g; @@ -1342,7 +1413,7 @@ private: public: templateclass FpT> - static inline void mulVec(EcT& z, const EcT *xVec, const FpT *yVec, size_t n) + static inline void mulVec(EcT& z, const EcT *xVec, const FpT *yVec, size_t n, bool constTime = false) { /* mulVecNGLV is a little slow for large n @@ -1354,7 +1425,7 @@ public: yVec[i].getMpz(&b, myVec[i]); assert(b); (void)b; } - size_t done = mulVecNGLV(z, xVec, myVec, n); + size_t done = mulVecNGLV(z, xVec, myVec, n, constTime); assert(done == n); (void)done; return; } @@ -1424,7 +1495,7 @@ template int EcT::ioMode_; template bool EcT::verifyOrder_; template mpz_class EcT::order_; template void (*EcT::mulArrayGLV)(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime); -template size_t (*EcT::mulVecNGLV)(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn); +template size_t (*EcT::mulVecNGLV)(EcT& z, const EcT *xVec, const mpz_class *yVec, size_t yn, bool constTime); template int EcT::mode_; // r = the order of Ec @@ -1471,11 +1542,11 @@ public: a = x - (t * B[0][0] + b * B[1][0]); b = - (t * B[0][1] + b * B[1][1]); } - static void mul(Ec& Q, const Ec& P, const mpz_class& x, bool /*constTime*/ = false) + static void mul(Ec& Q, const Ec& P, const mpz_class& x, bool constTime = false) { - mulVecNGLV(Q, &P, &x, 1); + mulVecNGLV(Q, &P, &x, 1, constTime); } - static inline size_t mulVecNGLV(Ec& z, const Ec *xVec, const mpz_class *yVec, size_t n) + static inline size_t mulVecNGLV(Ec& z, const Ec *xVec, const mpz_class *yVec, size_t n, bool /*constTime*/ = false) { const size_t N = mcl::fp::maxMulVecNGLV; if (n > N) n = N; diff --git a/include/mcl/operator.hpp b/include/mcl/operator.hpp index 84df77f..1658c2d 100644 --- a/include/mcl/operator.hpp +++ b/include/mcl/operator.hpp @@ -84,14 +84,14 @@ struct Operator : public E { { powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true); } - static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n) = 0) + static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n, bool constTime) = 0) { powArrayGLV = f; powVecNGLV = g; } static const size_t powVecMaxN = 16; templateclass FpT> - static void powVec(T& z, const T* xVec, const FpT *yVec, size_t n) + static void powVec(T& z, const T* xVec, const FpT *yVec, size_t n, bool constTime = false) { assert(powVecNGLV); T r; @@ -106,7 +106,7 @@ struct Operator : public E { yVec[i].getMpz(&b, myVec[i]); assert(b); (void)b; } - size_t done = powVecNGLV(t, xVec, myVec, tn); + size_t done = powVecNGLV(t, xVec, myVec, tn, constTime); r *= t; xVec += done; yVec += done; @@ -116,7 +116,7 @@ struct Operator : public E { } private: static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime); - static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n); + static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n, bool constTime); static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime) { if (powArrayGLV && (constTime || yn > 1)) { @@ -145,7 +145,7 @@ template void (*Operator::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime); template -size_t (*Operator::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n); +size_t (*Operator::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n, bool constTime); /* T must have save and load diff --git a/test/common_test.hpp b/test/common_test.hpp index f6d1dcd..54d3bed 100644 --- a/test/common_test.hpp +++ b/test/common_test.hpp @@ -89,12 +89,27 @@ inline void testPowVec(const G& e) } } +template +void testMulCT(const G& P) +{ + cybozu::XorShift rg; + G Q1, Q2; + for (int i = 0; i < 100; i++) { + Fr x; + x.setByCSPRNG(rg); + G::mul(Q1, P, x); + G::mulCT(Q2, P, x); + CYBOZU_TEST_EQUAL(Q1, Q2); + } +} + void testCommon(const G1& P, const G2& Q) { puts("G1"); testMulVec(P); puts("G2"); testMulVec(Q); + testMulCT(Q); GT e; mcl::bn::pairing(e, P, Q); puts("GT");