aboutsummaryrefslogtreecommitdiffstats
path: root/include/mcl/randgen.hpp
blob: d5a2e952cd69df427367f0cd6c33203bf8b66e6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma once
/**
    @file
    @brief definition of Op
    @author MITSUNARI Shigeo(@herumi)
    @license modified new BSD license
    http://opensource.org/licenses/BSD-3-Clause
*/
#ifdef MCL_DONT_USE_CSRPNG

// nothing

#elif defined(MCL_USE_WEB_CRYPTO_API)
#include <emscripten.h>

namespace mcl {
struct RandomGeneratorJS {
    void read(void *buf, size_t bufSize)
    {
        // use crypto.getRandomValues
        EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize);
    }
};
} // mcl

#else
#include <cybozu/random_generator.hpp>
#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#include <random>
#endif
#endif
#ifdef _MSC_VER
    #pragma warning(push)
    #pragma warning(disable : 4521)
#endif
namespace mcl { namespace fp {

namespace local {

template<class RG>
void readWrapper(void *self, void *buf, uint32_t bufSize)
{
    reinterpret_cast<RG*>(self)->read((uint8_t*)buf, bufSize);
}

#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
template<>
inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufSize)
{
    std::random_device& rg = *reinterpret_cast<std::random_device*>(self);
    uint8_t *p = reinterpret_cast<uint8_t*>(buf);
    uint32_t v;
    while (bufSize >= 4) {
        v = rg();
        memcpy(p, &v, 4);
        p += 4;
        bufSize -= 4;
    }
    if (bufSize > 0) {
        v = rg();
        memcpy(p, &v, bufSize);
    }
}
#endif
} // local
/*
    wrapper of cryptographically secure pseudo random number generator
*/
class RandGen {
    typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize);
    void *self_;
    readFuncType readFunc_;
public:
    RandGen() : self_(0), readFunc_(0) {}
    RandGen(void *self, readFuncType readFunc) : self_(self) , readFunc_(readFunc) {}
    RandGen(const RandGen& rhs) : self_(rhs.self_), readFunc_(rhs.readFunc_) {}
    RandGen(RandGen& rhs) : self_(rhs.self_), readFunc_(rhs.readFunc_) {}
    RandGen& operator=(const RandGen& rhs)
    {
        self_ = rhs.self_;
        readFunc_ = rhs.readFunc_;
        return *this;
    }
    template<class RG>
    RandGen(RG& rg)
        : self_(reinterpret_cast<void*>(&rg))
        , readFunc_(local::readWrapper<RG>)
    {
    }
    void read(void *out, size_t byteSize)
    {
        readFunc_(self_, out, static_cast<uint32_t>(byteSize));
    }
#ifdef MCL_DONT_USE_CSRPNG
    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()
    {
#ifdef MCL_DONT_USE_CSRPNG
        static RandGen wrg;
#elif defined(MCL_USE_WEB_CRYPTO_API)
        static mcl::RandomGeneratorJS rg;
        static RandGen wrg(rg);
#else
        static cybozu::RandomGenerator rg;
        static RandGen wrg(rg);
#endif
        return wrg;
    }
    /*
        rg must be thread safe
        rg.read(void *buf, size_t bufSize);
    */
    static void setRandGen(const RandGen& rg)
    {
        get() = rg;
    }
};

} } // mcl::fp

#ifdef _MSC_VER
    #pragma warning(pop)
#endif