diff options
author | MITSUNARI Shigeo <herumi@nifty.com> | 2018-10-28 14:10:57 +0800 |
---|---|---|
committer | MITSUNARI Shigeo <herumi@nifty.com> | 2018-10-28 14:10:57 +0800 |
commit | 494ebb1439b5942824f5cbe3a5ccf87406b45815 (patch) | |
tree | 0f5610c80ed4cc60fa7b4d7c071ebb88847d3959 | |
parent | 05dc2da2e222b691c662910ff902a72342067364 (diff) | |
download | tangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.tar.gz tangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.tar.zst tangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.zip |
add mclBn_setRandFunc
-rw-r--r-- | include/mcl/bn.h | 10 | ||||
-rw-r--r-- | include/mcl/fp.hpp | 23 | ||||
-rw-r--r-- | include/mcl/gmp_util.hpp | 3 | ||||
-rw-r--r-- | include/mcl/randgen.hpp | 58 | ||||
-rw-r--r-- | include/mcl/vint.hpp | 3 | ||||
-rw-r--r-- | src/bn_c_impl.hpp | 5 | ||||
-rw-r--r-- | src/fp.cpp | 6 | ||||
-rw-r--r-- | test/bn_c_test.hpp | 37 | ||||
-rw-r--r-- | test/fp_util_test.cpp | 14 |
9 files changed, 136 insertions, 23 deletions
diff --git a/include/mcl/bn.h b/include/mcl/bn.h index 9c78f92..c130004 100644 --- a/include/mcl/bn.h +++ b/include/mcl/bn.h @@ -219,6 +219,16 @@ MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x); #ifndef MCL_DONT_USE_CSRPNG // return 0 if success MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); + +/* + set user-defined random function for setByCSPRNG + @param self [in] user-defined pointer + @param readFunc [in] user-defined function, + which writes random bufSize bytes to buf and returns bufSize if success else returns 0 + @note if self == 0 and readFunc == 0 then set default random function + @note not threadsafe +*/ +MCLBN_DLL_API void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)); #endif // hash(s) and set x diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp index 4850012..dc8dc95 100644 --- a/include/mcl/fp.hpp +++ b/include/mcl/fp.hpp @@ -70,7 +70,15 @@ inline void dumpUnit(Unit x) bool isEnableJIT(); // 1st call is not threadsafe -void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize); +void getRandVal(bool *pb, void *p, RandGen& rg, const Unit *in, size_t bitSize); +#ifndef CYBOZU_DONT_USE_EXCEPTION +inline void getRandVal(void *p, RandGen& rg, const Unit *in, size_t bitSize) +{ + bool b; + getRandVal(&b, p, rg, in, bitSize); + if (!b) throw cybozu::Exception("getRandVal") << bitSize; +} +#endif uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); @@ -331,12 +339,21 @@ public: b.p = &v_[0]; } } - void setByCSPRNG(fp::RandGen rg = fp::RandGen()) + void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen()) { if (rg.isZero()) rg = fp::RandGen::get(); - fp::getRandVal(v_, rg, op_.p, op_.bitSize); + fp::getRandVal(pb, v_, rg, op_.p, op_.bitSize); + if (!*pb) return; toMont(); } +#ifndef CYBOZU_DONT_USE_EXCEPTION + void setByCSPRNG(fp::RandGen rg = fp::RandGen()) + { + bool b; + setByCSPRNG(&b, rg); + if (!b) throw cybozu::Exception("setByCSPRNG"); + } +#endif void setRand(fp::RandGen rg = fp::RandGen()) // old api { setByCSPRNG(rg); diff --git a/include/mcl/gmp_util.hpp b/include/mcl/gmp_util.hpp index 2dd71eb..a64bed4 100644 --- a/include/mcl/gmp_util.hpp +++ b/include/mcl/gmp_util.hpp @@ -450,7 +450,8 @@ inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp: *pb = false; return; } - rg.read(buf, n * sizeof(buf[0])); + rg.read(pb, buf, n * sizeof(buf[0])); + if (!*pb) return; uint32_t v = buf[n - 1]; if (rem == 0) { v |= 1U << 31; diff --git a/include/mcl/randgen.hpp b/include/mcl/randgen.hpp index 4bfb30b..30502fc 100644 --- a/include/mcl/randgen.hpp +++ b/include/mcl/randgen.hpp @@ -15,10 +15,16 @@ namespace mcl { struct RandomGeneratorJS { - void read(void *buf, size_t bufSize) + void read(bool *pb, void *buf, uint32_t byteSize) { + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues + if (byteSize > 65536) { + *pb = false; + return; + } // use crypto.getRandomValues - EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize); + EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, byteSize); + *pb = true; } }; } // mcl @@ -38,28 +44,33 @@ namespace mcl { namespace fp { namespace local { template<class RG> -void readWrapper(void *self, void *buf, uint32_t bufSize) +uint32_t readWrapper(void *self, void *buf, uint32_t byteSize) { - reinterpret_cast<RG*>(self)->read((uint8_t*)buf, bufSize); + bool b; + reinterpret_cast<RG*>(self)->read(&b, (uint8_t*)buf, byteSize); + if (b) return byteSize; + return 0; } #if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 template<> -inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufSize) +inline uint32_t readWrapper<std::random_device>(void *self, void *buf, uint32_t byteSize) { + const uint32_t keep = byteSize; std::random_device& rg = *reinterpret_cast<std::random_device*>(self); uint8_t *p = reinterpret_cast<uint8_t*>(buf); uint32_t v; - while (bufSize >= 4) { + while (byteSize >= 4) { v = rg(); memcpy(p, &v, 4); p += 4; - bufSize -= 4; + byteSize -= 4; } - if (bufSize > 0) { + if (byteSize > 0) { v = rg(); - memcpy(p, &v, bufSize); + memcpy(p, &v, byteSize); } + return keep; } #endif } // local @@ -67,7 +78,7 @@ inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufS wrapper of cryptographically secure pseudo random number generator */ class RandGen { - typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize); + typedef uint32_t (*readFuncType)(void *self, void *buf, uint32_t byteSize); void *self_; readFuncType readFunc_; public: @@ -87,16 +98,17 @@ public: , readFunc_(local::readWrapper<RG>) { } - void read(void *out, size_t byteSize) + void read(bool *pb, void *out, size_t byteSize) { - readFunc_(self_, out, static_cast<uint32_t>(byteSize)); + uint32_t size = readFunc_(self_, out, static_cast<uint32_t>(byteSize)); + *pb = size == byteSize; } #ifdef MCL_DONT_USE_CSPRNG bool isZero() const { return false; } /* return false to avoid copying default rg */ #else bool isZero() const { return self_ == 0 && readFunc_ == 0; } #endif - static RandGen& get() + static RandGen& getDefaultRandGen() { #ifdef MCL_DONT_USE_CSPRNG static RandGen wrg; @@ -109,14 +121,32 @@ public: #endif return wrg; } + static RandGen& get() + { + static RandGen wrg(getDefaultRandGen()); + return wrg; + } /* rg must be thread safe - rg.read(void *buf, size_t bufSize); + rg.read(void *buf, size_t byteSize); */ static void setRandGen(const RandGen& rg) { get() = rg; } + /* + set rand function + if self and readFunc are NULL then set default rand function + */ + static void setRandFunc(void *self, readFuncType readFunc) + { + if (self == 0 && readFunc == 0) { + setRandGen(getDefaultRandGen()); + } else { + RandGen rg(self, readFunc); + setRandGen(rg); + } + } }; } } // mcl::fp diff --git a/include/mcl/vint.hpp b/include/mcl/vint.hpp index 32a51bb..c2a7a10 100644 --- a/include/mcl/vint.hpp +++ b/include/mcl/vint.hpp @@ -1138,7 +1138,8 @@ public: size_t n = max.size(); buf_.alloc(pb, n); if (!*pb) return; - rg.read(&buf_[0], n * sizeof(buf_[0])); + rg.read(pb, &buf_[0], n * sizeof(buf_[0])); + if (!*pb) return; trim(n); *this %= max; } diff --git a/src/bn_c_impl.hpp b/src/bn_c_impl.hpp index bb0b4ba..497ae2b 100644 --- a/src/bn_c_impl.hpp +++ b/src/bn_c_impl.hpp @@ -84,6 +84,7 @@ mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize) { return Fp::getModulo(buf, maxBufSize); } + //////////////////////////////////////////////// // set zero void mclBnFr_clear(mclBnFr *x) @@ -138,6 +139,10 @@ int mclBnFr_setByCSPRNG(mclBnFr *x) cast(x)->setByCSPRNG(); return 0; } +void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)) +{ + mcl::fp::RandGen::setRandFunc(self, readFunc); +} #endif // hash(buf) and set x @@ -120,14 +120,16 @@ bool isEnableJIT() #endif } -void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize) +void getRandVal(bool *pb, void *p, RandGen& rg, const Unit *in, size_t bitSize) { if (rg.isZero()) rg = RandGen::get(); + Unit *out = reinterpret_cast<Unit*>(p); const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize; const size_t rem = bitSize & (UnitBitSize - 1); assert(n > 0); for (;;) { - rg.read(out, n * sizeof(Unit)); + rg.read(pb, out, n * sizeof(Unit)); // byte size + if (!*pb) return; if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1; if (isLessArray(out, in, n)) return; } diff --git a/test/bn_c_test.hpp b/test/bn_c_test.hpp index d33cdf5..fc81652 100644 --- a/test/bn_c_test.hpp +++ b/test/bn_c_test.hpp @@ -522,3 +522,40 @@ CYBOZU_TEST_AUTO(badG2) } #endif +struct Sequential { + uint32_t pos; + Sequential() : pos(0) {} + static uint32_t read(void *self, void *buf, uint32_t bufSize) + { + Sequential *seq = reinterpret_cast<Sequential*>(self); + uint8_t *p = reinterpret_cast<uint8_t*>(buf); + for (uint32_t i = 0; i < bufSize; i++) { + p[i] = uint8_t(seq->pos + i) & 0x1f; // mask is to make valid Fp + } + seq->pos += bufSize; + return bufSize; + } +}; + +CYBOZU_TEST_AUTO(setRandFunc) +{ + Sequential seq; + for (int j = 0; j < 3; j++) { + puts(j == 1 ? "sequential rand" : "true rand"); + for (int i = 0; i < 5; i++) { + mclBnFr x; + int ret; + char buf[1024]; + ret = mclBnFr_setByCSPRNG(&x); + CYBOZU_TEST_EQUAL(ret, 0); + ret = mclBnFr_getStr(buf, sizeof(buf), &x, 16); + CYBOZU_TEST_ASSERT(ret > 0); + printf("%d %s\n", i, buf); + } + if (j == 0) { + mclBn_setRandFunc(&seq, Sequential::read); + } else { + mclBn_setRandFunc(0, 0); + } + } +} diff --git a/test/fp_util_test.cpp b/test/fp_util_test.cpp index b11311b..b6d5efc 100644 --- a/test/fp_util_test.cpp +++ b/test/fp_util_test.cpp @@ -158,12 +158,22 @@ struct Rand { const uint8_t *p; size_t pos; size_t endPos; - void read(void *x, size_t n) + void read(bool *pb, void *x, size_t n) { - if (pos + n > endPos) throw cybozu::Exception("Rand:get:bad n") << pos << n << endPos; + if (pos + n > endPos) { + *pb = false; + return; + } uint8_t *dst = (uint8_t*)x; memcpy(dst, p + pos, n); pos += n; + *pb = true; + } + void read(void *x, size_t n) + { + bool b; + read(&b, x, n); + if (!b) throw cybozu::Exception("Rand") << n; } uint32_t operator()() { |