1
0
Fork 0
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:
sowle 2019-09-11 13:35:40 +03:00
parent f5dbbfd1d4
commit d742e6ea2d
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
4 changed files with 106 additions and 25 deletions

View file

@ -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)

View file

@ -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

View file

@ -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" "~!@#$%^&*()-=_+\\/?,.<>|{}[]`';:\" ";

View file

@ -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();