summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/rng.cc20
-rw-r--r--crawl-ref/source/sha256.cc63
-rw-r--r--crawl-ref/source/sha256.h4
3 files changed, 82 insertions, 5 deletions
diff --git a/crawl-ref/source/rng.cc b/crawl-ref/source/rng.cc
index 8c856e7229..4b7200093c 100644
--- a/crawl-ref/source/rng.cc
+++ b/crawl-ref/source/rng.cc
@@ -29,6 +29,12 @@ void seed_rng(unsigned long* seed_key, size_t num_keys)
// MT19937 -- see mt19937ar.cc for details/licence
init_by_array(seed_key, num_keys);
+ // Reset the sha256 generator to get predictable random numbers in case
+ // of a saved rng state.
+#ifdef MORE_HARDENED_PRNG
+ reset_sha256_state();
+#endif
+
// for std::random_shuffle()
srand(seed_key[0]);
}
@@ -38,6 +44,12 @@ void seed_rng(long seed)
// MT19937 -- see mt19937ar.cc for details/licence
init_genrand(seed);
+ // Reset the sha256 generator to get predictable random numbers in case
+ // of a saved rng state.
+#ifdef MORE_HARDENED_PRNG
+ reset_sha256_state();
+#endif
+
// for std::random_shuffle()
srand(seed);
}
@@ -87,11 +99,19 @@ unsigned long random_int( void )
void push_rng_state()
{
+#ifndef MORE_HARDENED_PRNG
push_mt_state();
+#else
+ push_sha256_state();
+#endif
}
void pop_rng_state()
{
+#ifndef MORE_HARDENED_PRNG
pop_mt_state();
+#else
+ pop_sha256_state();
+#endif
}
diff --git a/crawl-ref/source/sha256.cc b/crawl-ref/source/sha256.cc
index a36d316d92..96443587a0 100644
--- a/crawl-ref/source/sha256.cc
+++ b/crawl-ref/source/sha256.cc
@@ -11,12 +11,13 @@
#include <stdint.h>
typedef uint32_t u32;
-typedef uint64_t u64;
#include "mt19937ar.h"
#ifdef MORE_HARDENED_PRNG
+#include <stack>
+
#include <cstring>
#include <cstdio>
#include <cstdlib>
@@ -137,12 +138,50 @@ void sha256chunk(const char* chunk, sha256state* ss)
}
}
-// 256 bits
-u32 mt_sha256_block[8], mt_block[8];
-u32 mt_block_index = 0;
+struct sha256mt_state
+{
+ // 256 bits
+ u32 mt_sha256_block[8], mt_block[8];
+ u32 mt_block_index;
+
+ sha256mt_state()
+ {
+ mt_block_index = 0;
+ }
+};
+
+sha256mt_state effective_state;
+
+std::stack<sha256mt_state> sha256mt_state_stack;
+
+void reset_sha256_state()
+{
+ effective_state.mt_block_index = 0;
+}
+
+void push_sha256_state()
+{
+ sha256mt_state_stack.push(effective_state);
+ push_mt_state();
+}
+
+void pop_sha256_state()
+{
+ if (sha256mt_state_stack.empty())
+ return;
+
+ effective_state = sha256mt_state_stack.top();
+
+ sha256mt_state_stack.pop();
+ pop_mt_state();
+}
unsigned long sha256_genrand()
{
+ u32 &mt_block_index = effective_state.mt_block_index;
+ u32 *mt_sha256_block = effective_state.mt_sha256_block;
+ u32 *mt_block = effective_state.mt_block;
+
// Needs some hashing
if (!(mt_block_index % 8))
{
@@ -166,7 +205,21 @@ unsigned long sha256_genrand()
return mt_sha256_block[mt_block_index++];
}
#else // MORE_HARDENED_PRNG
-// Stub this to MT function
+// Stub these to MT functions
+void push_sha256_state()
+{
+ push_mt_state();
+}
+
+void pop_sha256_state()
+{
+ pop_mt_state();
+}
+
+void reset_sha256_state()
+{
+}
+
unsigned long sha256_genrand()
{
return genrand_int32();
diff --git a/crawl-ref/source/sha256.h b/crawl-ref/source/sha256.h
index 44986adc6b..6ddbb0a0c6 100644
--- a/crawl-ref/source/sha256.h
+++ b/crawl-ref/source/sha256.h
@@ -2,6 +2,10 @@
#define sha256_h
unsigned long sha256_genrand();
+void push_sha256_state();
+void pop_sha256_state();
+
+void reset_sha256_state();
#endif