forked from lthn/blockchain
crypto: safety improvement: use PRNG manipulation from Boolberry, explicitly require USE_INSECURE_RANDOM_RPNG_ROUTINES defined for using it
This commit is contained in:
parent
f5dbbfd1d4
commit
d742e6ea2d
4 changed files with 106 additions and 25 deletions
|
|
@ -10,14 +10,14 @@
|
|||
//#include "initializer.h"
|
||||
#include "random.h"
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result);
|
||||
static_assert(RANDOM_STATE_SIZE >= HASH_DATA_AREA, "Invalid RANDOM_STATE_SIZE");
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result) {
|
||||
void generate_system_random_bytes(size_t n, void *result) {
|
||||
HCRYPTPROV prov;
|
||||
#define must_succeed(x) do if (!(x)) assert(0); while (0)
|
||||
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
|
|
@ -40,7 +40,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result) {
|
||||
void generate_system_random_bytes(size_t n, void *result) {
|
||||
int fd;
|
||||
if ((fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) {
|
||||
err(EXIT_FAILURE, "open /dev/urandom");
|
||||
|
|
@ -68,7 +68,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
|||
|
||||
#endif
|
||||
|
||||
/* static */ union hash_state state; // NOTE: 'static' is commented out here to be able to store/load global random generator state in tests (see also random_helper.h)
|
||||
static union hash_state state;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static volatile int curstate; /* To catch thread safety problems. */
|
||||
|
|
@ -105,6 +105,57 @@ void grant_random_initialize(void)
|
|||
}
|
||||
}
|
||||
|
||||
void random_prng_initialize_with_seed(uint64_t seed)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 3;
|
||||
#endif
|
||||
memset(&state, 0, sizeof state);
|
||||
memcpy(&state, &seed, sizeof seed);
|
||||
for(size_t i = 0, count = seed & 31; i < count; ++i)
|
||||
hash_permutation(&state);
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 3);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void random_prng_get_state(void *state_buffer, const size_t buffer_size)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 4;
|
||||
#endif
|
||||
|
||||
assert(sizeof state == buffer_size);
|
||||
memcpy(state_buffer, &state, buffer_size);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 4);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void random_prng_set_state(const void *state_buffer, const size_t buffer_size)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 5;
|
||||
#endif
|
||||
|
||||
assert(sizeof state == buffer_size);
|
||||
memcpy(&state, state_buffer, buffer_size);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 5);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void generate_random_bytes(size_t n, void *result) {
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Copyright (c) 2014-2018 The Boolberry developers
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -5,6 +7,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// use the cryptographically secure Pseudo-Random Number Generator provided by the operating system
|
||||
void generate_system_random_bytes(size_t n, void *result);
|
||||
|
||||
void generate_random_bytes(size_t n, void *result);
|
||||
void grant_random_initialize(void);
|
||||
|
||||
// checks if PRNG is initialized and initializes it if necessary
|
||||
void grant_random_initialize(void);
|
||||
|
||||
#define RANDOM_STATE_SIZE 200
|
||||
|
||||
// explicitly define USE_INSECURE_RANDOM_RPNG_ROUTINES for using random_initialize_with_seed
|
||||
#ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
// reinitializes PRNG with the given seed
|
||||
// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH!
|
||||
// Use with care and ONLY for tests or debug purposes!
|
||||
void random_prng_initialize_with_seed(uint64_t seed);
|
||||
|
||||
// gets internal RPNG state (state_buffer should be 200 bytes long)
|
||||
void random_prng_get_state(void *state_buffer, const size_t buffer_size);
|
||||
|
||||
// sets internal RPNG state (state_buffer should be 200 bytes long)
|
||||
// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH!
|
||||
// Use with care and ONLY for tests or debug purposes!
|
||||
void random_prng_set_state(const void *state_buffer, const size_t buffer_size);
|
||||
|
||||
#endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
|
|
|
|||
|
|
@ -6,6 +6,21 @@
|
|||
#include "chaingen.h"
|
||||
#include "random_helper.h"
|
||||
|
||||
random_state_test_restorer::random_state_test_restorer()
|
||||
{
|
||||
crypto::random_prng_get_state(&m_state, sizeof m_state);
|
||||
}
|
||||
|
||||
random_state_test_restorer::~random_state_test_restorer()
|
||||
{
|
||||
crypto::random_prng_set_state(&m_state, sizeof m_state);
|
||||
}
|
||||
|
||||
void random_state_test_restorer::reset_random(uint64_t seed /* = 0 */)
|
||||
{
|
||||
crypto::random_prng_initialize_with_seed(seed);
|
||||
}
|
||||
|
||||
std::string get_random_text(size_t len)
|
||||
{
|
||||
static const char text_chars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "~!@#$%^&*()-=_+\\/?,.<>|{}[]`';:\" ";
|
||||
|
|
|
|||
|
|
@ -1,40 +1,28 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define RANDOM_STATE_SIZE 200
|
||||
extern "C" volatile union hash_state state; // field defined in random.c
|
||||
static_assert(RANDOM_STATE_SIZE >= HASH_DATA_AREA, "Invalid RANDOM_STATE_SIZE");
|
||||
|
||||
// DISCLAIMER: designed for tests puposes ONLY!
|
||||
// This class is not intended to be used neither in multi-threaded environment nor in production.
|
||||
|
||||
#ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
|
||||
// Remebers random state at ctor, restores it at dtor
|
||||
struct random_state_test_restorer
|
||||
{
|
||||
random_state_test_restorer()
|
||||
{
|
||||
memcpy(m_state, const_cast<hash_state*>(&::state), RANDOM_STATE_SIZE);
|
||||
}
|
||||
|
||||
~random_state_test_restorer()
|
||||
{
|
||||
memcpy(const_cast<hash_state*>(&::state), m_state, RANDOM_STATE_SIZE);
|
||||
}
|
||||
|
||||
static void reset_random(uint64_t seed = 0)
|
||||
{
|
||||
memset(const_cast<hash_state*>(&::state), 0, RANDOM_STATE_SIZE);
|
||||
memcpy(const_cast<hash_state*>(&::state), &seed, sizeof seed);
|
||||
}
|
||||
random_state_test_restorer();
|
||||
~random_state_test_restorer();
|
||||
static void reset_random(uint64_t seed = 0);
|
||||
|
||||
private:
|
||||
uint8_t m_state[RANDOM_STATE_SIZE];
|
||||
};
|
||||
|
||||
#endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
|
||||
std::string get_random_text(size_t len);
|
||||
|
||||
bool random_state_manupulation_test();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue