Rudimentary library unloading support
[lsnes.git] / src / core / random.cpp
blobe951f8ab3c80ee153b5ad0a83569dbf6e59a7360
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 buf[count++] = crandom::arch_get_tsc();
46 threads::alock h(seed_mutex);
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 threads::alock h(seed_mutex);
59 uint64_t buf[7];
60 uint8_t out[32];
61 timeval tv;
62 buf[3] = crandom::arch_get_random();
63 buf[4] = crandom::arch_get_random();
64 buf[5] = crandom::arch_get_random();
65 buf[6] = crandom::arch_get_random();
66 gettimeofday(&tv, NULL);
67 buf[0] = tv.tv_sec;
68 buf[1] = tv.tv_usec;
69 buf[2] = crandom::arch_get_tsc();
70 prng.write(buf, sizeof(buf));
71 prng.read(out, sizeof(out));
72 return hex::b_to(out, sizeof(out));
76 std::string get_random_hexstring(size_t length) throw(std::bad_alloc)
78 std::string out;
79 for(size_t i = 0; i < length; i += 64)
80 out = out + get_random_hexstring_64(i);
81 return out.substr(0, length);
84 void set_random_seed(const std::string& seed) throw(std::bad_alloc)
86 std::vector<char> x(seed.begin(), seed.end());
88 threads::alock h(seed_mutex);
89 prng.write(&x[0], x.size());
93 void set_random_seed() throw(std::bad_alloc)
95 char buf[128];
96 crandom::generate(buf, 128);
97 std::string s(buf, sizeof(buf));
98 set_random_seed(s);
101 void random_mix_timing_entropy()
103 do_mix_tsc();
106 //Generate highly random stuff.
107 void highrandom_256(uint8_t* buf)
109 uint8_t tmp[104];
110 std::string s = get_random_hexstring(64);
111 std::copy(s.begin(), s.end(), reinterpret_cast<char*>(tmp));
112 crandom::generate(tmp + 64, 32);
113 serialization::u64b(tmp + 96, crandom::arch_get_tsc());
114 skein::hash hsh(skein::hash::PIPE_1024, 256);
115 hsh.write(tmp, 104);
116 hsh.read(buf);