Lua: Fix type confusion between signed and unsigned
[lsnes.git] / src / core / random.cpp
blob7ce501e74af0570df246ae2e697df50d127961b2
1 #include "lsnes.hpp"
3 #include "core/random.hpp"
4 #include "library/crandom.hpp"
5 #include "library/hex.hpp"
6 #include "library/serialization.hpp"
7 #include "library/skein.hpp"
8 #include "library/string.hpp"
9 #include "library/threads.hpp"
11 #include <cstdlib>
12 #include <csignal>
13 #include <sstream>
14 #include <iostream>
15 #include <iomanip>
16 #include <fstream>
17 #include <string>
18 #include <vector>
19 #include <algorithm>
20 #include <ctime>
21 #include <cstdlib>
22 #include <cstring>
23 #include <sys/time.h>
24 #include <unistd.h>
25 #include <boost/filesystem.hpp>
26 #if defined(_WIN32) || defined(_WIN64)
27 #include <windows.h>
28 #endif
30 #ifdef USE_LIBGCRYPT_SHA256
31 #include <gcrypt.h>
32 #endif
34 namespace
36 skein::prng prng;
37 threads::lock seed_mutex;
39 void do_mix_tsc()
41 const unsigned slots = 32;
42 static unsigned count = 0;
43 static uint64_t last_reseed = 0;
44 static uint64_t buf[slots + 1];
45 threads::alock h(seed_mutex);
46 buf[count++] = crandom::arch_get_tsc();
47 if(count == 0) count = 1; //Shouldn't happen.
48 if(count == slots || buf[count - 1] - last_reseed > 300000000) {
49 last_reseed = buf[count - 1];
50 buf[slots] = crandom::arch_get_random();
51 prng.write(buf, sizeof(buf));
52 count = 0;
56 std::string get_random_hexstring_64(size_t index)
58 uint64_t buf[7];
59 uint8_t out[32];
60 timeval tv;
61 buf[3] = crandom::arch_get_random();
62 buf[4] = crandom::arch_get_random();
63 buf[5] = crandom::arch_get_random();
64 buf[6] = crandom::arch_get_random();
65 gettimeofday(&tv, NULL);
66 buf[0] = tv.tv_sec;
67 buf[1] = tv.tv_usec;
68 buf[2] = crandom::arch_get_tsc();
69 threads::alock h(seed_mutex);
70 prng.write(buf, sizeof(buf));
71 prng.read(out, sizeof(out));
72 return hex::b_to(out, sizeof(out));
76 void contribute_random_entropy(void* buf, size_t bytes)
78 do_mix_tsc();
79 threads::alock h(seed_mutex);
80 prng.write(buf, sizeof(buf));
83 std::string get_random_hexstring(size_t length) throw(std::bad_alloc)
85 std::string out;
86 for(size_t i = 0; i < length; i += 64)
87 out = out + get_random_hexstring_64(i);
88 return out.substr(0, length);
91 void set_random_seed(const std::string& seed) throw(std::bad_alloc)
93 std::vector<char> x(seed.begin(), seed.end());
95 threads::alock h(seed_mutex);
96 prng.write(&x[0], x.size());
100 void set_random_seed() throw(std::bad_alloc)
102 char buf[128];
103 crandom::generate(buf, 128);
104 std::string s(buf, sizeof(buf));
105 set_random_seed(s);
108 void random_mix_timing_entropy()
110 do_mix_tsc();
113 //Generate highly random stuff.
114 void highrandom_256(uint8_t* buf)
116 uint8_t tmp[104];
117 std::string s = get_random_hexstring(64);
118 std::copy(s.begin(), s.end(), reinterpret_cast<char*>(tmp));
119 crandom::generate(tmp + 64, 32);
120 serialization::u64b(tmp + 96, crandom::arch_get_tsc());
121 skein::hash hsh(skein::hash::PIPE_1024, 256);
122 hsh.write(tmp, 104);
123 hsh.read(buf);