Improve randomness of get_random_hexstring (on I386)
This commit is contained in:
parent
a271756c06
commit
2f301e1502
4 changed files with 117 additions and 5 deletions
|
@ -122,5 +122,14 @@ std::string safe_filename(const std::string& str);
|
|||
*/
|
||||
std::string mangle_name(const std::string& orig);
|
||||
|
||||
/**
|
||||
* Mix some entropy.
|
||||
*/
|
||||
void random_mix_timing_entropy();
|
||||
|
||||
/**
|
||||
* 256 bits of as high quality entropy as possible.
|
||||
*/
|
||||
void highrandom_256(uint8_t* buf);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1209,6 +1209,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_
|
|||
}
|
||||
frame_irq_time = get_utime() - time_x;
|
||||
our_rom.rtype->emulate();
|
||||
random_mix_timing_entropy();
|
||||
time_x = get_utime();
|
||||
if(amode == ADVANCE_AUTO)
|
||||
platform::wait(to_wait_frame(get_utime()));
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "core/window.hpp"
|
||||
#include "library/sha256.hpp"
|
||||
#include "library/string.hpp"
|
||||
#include "library/serialization.hpp"
|
||||
#include "library/arch-detect.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
@ -32,11 +34,78 @@ namespace
|
|||
std::string rseed;
|
||||
uint64_t rcounter = 0;
|
||||
bool reached_main_flag;
|
||||
mutex_class seed_mutex;
|
||||
|
||||
uint64_t arch_get_tsc()
|
||||
{
|
||||
#ifdef ARCH_IS_I386
|
||||
uint32_t a, b;
|
||||
asm volatile("rdtsc" : "=a"(a), "=d"(b));
|
||||
return ((uint64_t)b << 32) | a;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t arch_get_random()
|
||||
{
|
||||
#ifdef ARCH_IS_I386
|
||||
uint32_t r;
|
||||
asm volatile (".byte 0xb8, 0x01, 0x00, 0x00, 0x00, 0x0f, 0xa2, 0xf7, 0xc1, 0x00, 0x00, 0x00, 0x40, "
|
||||
"0x74, 0x03, 0x0f, 0xc7, 0xf0" : "=a"(r) : : "ebx", "ecx", "edx");
|
||||
return r;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//Returns 32 bytes.
|
||||
void arch_random_256(uint8_t* buf)
|
||||
{
|
||||
uint32_t tmp[1026];
|
||||
uint64_t tsc = arch_get_tsc();
|
||||
tmp[1024] = tsc;
|
||||
tmp[1025] = tsc >> 32;
|
||||
for(unsigned i = 0; i < 1024; i++)
|
||||
tmp[i] = arch_get_random();
|
||||
sha256::hash(buf, reinterpret_cast<uint8_t*>(buf), sizeof(buf));
|
||||
}
|
||||
|
||||
void do_mix_tsc()
|
||||
{
|
||||
const int slots = 32;
|
||||
static unsigned count = 0;
|
||||
static uint64_t last_reseed = 0;
|
||||
static uint64_t buf[slots];
|
||||
buf[count++] = arch_get_tsc();
|
||||
umutex_class h(seed_mutex);
|
||||
if(count == slots || buf[count - 1] - last_reseed > 300000000) {
|
||||
last_reseed = buf[count - 1];
|
||||
std::vector<char> x;
|
||||
x.resize(rseed.length() + slots * 8 + 8);
|
||||
std::copy(rseed.begin(), rseed.end(), x.begin());
|
||||
for(unsigned i = 0; i < slots; i++)
|
||||
write64ule(&x[rseed.length() + 8 * i], buf[i]);
|
||||
write64ule(&x[rseed.length() + 8 * slots], arch_get_random());
|
||||
rseed = "32 " + sha256::hash(reinterpret_cast<uint8_t*>(&x[0]), x.size());
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_random_hexstring_64(size_t index)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << rseed << " " << time(NULL) << " " << (rcounter++) << " " << index;
|
||||
{
|
||||
umutex_class h(seed_mutex);
|
||||
str << rseed << " ";
|
||||
str << time(NULL) << " ";
|
||||
str << arch_get_tsc() << " ";
|
||||
str << arch_get_random() << " ";
|
||||
str << arch_get_random() << " ";
|
||||
str << arch_get_random() << " ";
|
||||
str << arch_get_random() << " ";
|
||||
str << (rcounter++) << " " << index;
|
||||
}
|
||||
std::string s = str.str();
|
||||
std::vector<char> x;
|
||||
x.resize(s.length());
|
||||
|
@ -63,6 +132,9 @@ namespace
|
|||
}
|
||||
loops++;
|
||||
}
|
||||
str << arch_get_tsc() << " ";
|
||||
for(unsigned i = 0; i < 256; i++)
|
||||
str << arch_get_random() << " ";
|
||||
return str.str();
|
||||
}
|
||||
|
||||
|
@ -106,7 +178,10 @@ void set_random_seed(const std::string& seed) throw(std::bad_alloc)
|
|||
{
|
||||
std::ostringstream str;
|
||||
str << seed.length() << " " << seed;
|
||||
rseed = str.str();
|
||||
{
|
||||
umutex_class h(seed_mutex);
|
||||
rseed = str.str();
|
||||
}
|
||||
rrdata.set_internal(random_rrdata());
|
||||
}
|
||||
|
||||
|
@ -288,7 +363,27 @@ std::string mangle_name(const std::string& orig)
|
|||
return out.str();
|
||||
}
|
||||
|
||||
void random_mix_timing_entropy()
|
||||
{
|
||||
do_mix_tsc();
|
||||
}
|
||||
|
||||
//Generate highly random stuff.
|
||||
void highrandom_256(uint8_t* buf)
|
||||
{
|
||||
uint8_t tmp[104];
|
||||
std::string s = get_random_hexstring(0);
|
||||
std::copy(s.begin(), s.end(), reinterpret_cast<char*>(tmp));
|
||||
arch_random_256(tmp + 64);
|
||||
write64ube(tmp + 96, arch_get_tsc());
|
||||
sha256::hash(buf, tmp, 104);
|
||||
#ifdef USE_LIBGCRYPT_SHA256
|
||||
memset(tmp, 0, 32);
|
||||
gcry_randomize((unsigned char*)buf, 32, GCRY_STRONG_RANDOM);
|
||||
for(unsigned i = 0; i < 32; i++)
|
||||
buf[i] ^= tmp[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
function_ptr_command<const std::string&> macro_test(lsnes_cmd, "test-macro", "", "",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
|
|
|
@ -343,6 +343,7 @@ void platform::dummy_event_loop() throw()
|
|||
umutex_class h(queue_lock);
|
||||
internal_run_queues(true);
|
||||
cv_timed_wait(queue_condition, h, microsec_class(MAXWAIT));
|
||||
random_mix_timing_entropy();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,8 +395,10 @@ void platform::flush_command_queue() throw()
|
|||
waitleft = min(waitleft, on_idle_time - now);
|
||||
if(on_timer_time >= now)
|
||||
waitleft = min(waitleft, on_timer_time - now);
|
||||
if(waitleft > 0)
|
||||
if(waitleft > 0) {
|
||||
cv_timed_wait(queue_condition, h, microsec_class(waitleft));
|
||||
random_mix_timing_entropy();
|
||||
}
|
||||
} else
|
||||
break;
|
||||
//If we had to wait, check queues at least once more.
|
||||
|
@ -443,8 +446,10 @@ void platform::wait(uint64_t usec) throw()
|
|||
waitleft = min(waitleft, on_idle_time - now);
|
||||
if(on_timer_time >= now)
|
||||
waitleft = min(waitleft, on_timer_time - now);
|
||||
if(waitleft > 0)
|
||||
if(waitleft > 0) {
|
||||
cv_timed_wait(queue_condition, h, microsec_class(waitleft));
|
||||
random_mix_timing_entropy();
|
||||
}
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
@ -491,8 +496,10 @@ void platform::queue(void (*f)(void* arg), void* arg, bool sync) throw(std::bad_
|
|||
functions.push_back(std::make_pair(f, arg));
|
||||
queue_condition.notify_all();
|
||||
if(sync)
|
||||
while(functions_executed < next_function && _system_thread_available)
|
||||
while(functions_executed < next_function && _system_thread_available) {
|
||||
cv_timed_wait(queue_condition, h, microsec_class(10000));
|
||||
random_mix_timing_entropy();
|
||||
}
|
||||
}
|
||||
|
||||
void platform::run_queues() throw()
|
||||
|
|
Loading…
Add table
Reference in a new issue