mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
crypto: random and siphash static-init-safety
Co-authored-by: Thomas <thomas.giudici@proton.me> Co-authored-by: selsta <selsta@sent.at>
This commit is contained in:
co-authored by
Thomas
selsta
parent
f978eab613
commit
92582340a2
+13
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019-2024, The Monero Project
|
||||
// Copyright (c) 2019-2026, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -48,6 +48,12 @@
|
||||
#define CTHR_THREAD_JOIN(thr) do { WaitForSingleObject(thr, INFINITE); CloseHandle(thr); } while(0)
|
||||
#define CTHR_THREAD_CLOSE(thr) CloseHandle((HANDLE)thr);
|
||||
|
||||
#define CTHR_ONCE_FLAG INIT_ONCE
|
||||
#define CTHR_ONCE_INIT INIT_ONCE_STATIC_INIT
|
||||
#define CTHR_ONCE_CALL(flag, f) (0 != InitOnceExecuteOnce(flag, f, NULL, NULL))
|
||||
#define CTHR_ONCE_DECLARE_CB(name) BOOL CALLBACK name(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
#define CTHR_ONCE_CB_SUCCESS true
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
@@ -67,4 +73,10 @@
|
||||
#define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL)
|
||||
#define CTHR_THREAD_CLOSE(thr) pthread_detach(thr)
|
||||
|
||||
#define CTHR_ONCE_FLAG pthread_once_t
|
||||
#define CTHR_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
#define CTHR_ONCE_CALL(flag, f) (0 == pthread_once(flag, f))
|
||||
#define CTHR_ONCE_DECLARE_CB(name) void name(void)
|
||||
#define CTHR_ONCE_CB_SUCCESS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,12 +73,13 @@ namespace crypto { \
|
||||
|
||||
namespace crypto {
|
||||
inline std::size_t siphash_to_size_t(const void *data, std::size_t length) {
|
||||
static_assert(sizeof(crypto_siphash_key) == crypto_shorthash_siphash24_KEYBYTES,
|
||||
static_assert(16 == crypto_shorthash_siphash24_KEYBYTES,
|
||||
"crypto_siphash_key size must match the SipHash-2-4 key length");
|
||||
static_assert(sizeof(std::uint64_t) == crypto_shorthash_siphash24_BYTES,
|
||||
"std::uint64_t size must match the SipHash-2-4 digest length");
|
||||
std::uint64_t h;
|
||||
crypto_shorthash_siphash24(reinterpret_cast<unsigned char*>(&h), static_cast<const unsigned char*>(data), length, crypto_siphash_key);
|
||||
crypto_shorthash_siphash24(reinterpret_cast<unsigned char*>(&h), static_cast<const unsigned char*>(data), length,
|
||||
get_static_siphash_key());
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
+42
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2024, The Monero Project
|
||||
// Copyright (c) 2014-2026, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c_threads.h"
|
||||
#include "hash-ops.h"
|
||||
#include "initializer.h"
|
||||
#include "random.h"
|
||||
@@ -97,18 +98,22 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
||||
#endif
|
||||
|
||||
static union hash_state state;
|
||||
unsigned char crypto_siphash_key[16];
|
||||
static unsigned char crypto_siphash_key[16];
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static volatile int curstate; /* To catch thread safety problems. */
|
||||
#endif
|
||||
static CTHR_ONCE_FLAG init_random_once = CTHR_ONCE_INIT;
|
||||
|
||||
FINALIZER(deinit_random) {
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
assert(curstate == 1 || curstate == 0);
|
||||
curstate = 0;
|
||||
#endif
|
||||
memset(&state, 0, sizeof(union hash_state));
|
||||
}
|
||||
|
||||
FINALIZER(deinit_sip) {
|
||||
memset(crypto_siphash_key, 0, sizeof(crypto_siphash_key));
|
||||
}
|
||||
|
||||
@@ -122,19 +127,20 @@ static void lock_random_state(void) {
|
||||
|
||||
#define HASH_CAPACITY_AREA 64
|
||||
|
||||
INITIALIZER(init_random) {
|
||||
static CTHR_ONCE_DECLARE_CB(init_random) {
|
||||
static_assert(sizeof(state) == HASH_DATA_AREA + HASH_CAPACITY_AREA,
|
||||
"Keccak state is the wrong size");
|
||||
lock_random_state();
|
||||
generate_system_random_bytes(HASH_DATA_AREA, &state);
|
||||
hash_permutation(&state);
|
||||
|
||||
generate_system_random_bytes(sizeof(crypto_siphash_key), crypto_siphash_key);
|
||||
REGISTER_FINALIZER(deinit_random);
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 0);
|
||||
curstate = 1;
|
||||
#endif
|
||||
|
||||
return CTHR_ONCE_CB_SUCCESS;
|
||||
}
|
||||
|
||||
void generate_random_bytes_not_thread_safe(size_t n, void *result) {
|
||||
@@ -144,6 +150,9 @@ void generate_random_bytes_not_thread_safe(size_t n, void *result) {
|
||||
* leaving this function does not leak the previous squeezed values.
|
||||
*/
|
||||
|
||||
const int r = CTHR_ONCE_CALL(&init_random_once, init_random);
|
||||
(void) r; assert(r);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 2;
|
||||
@@ -171,6 +180,14 @@ void generate_random_bytes_not_thread_safe(size_t n, void *result) {
|
||||
|
||||
void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes)
|
||||
{
|
||||
const int r = CTHR_ONCE_CALL(&init_random_once, init_random);
|
||||
(void) r; assert(r);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 2;
|
||||
#endif
|
||||
|
||||
size_t i;
|
||||
|
||||
while (bytes > 0)
|
||||
@@ -182,4 +199,24 @@ void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes)
|
||||
ptr = cpadd(ptr, round_bytes);
|
||||
hash_permutation(&state);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 2);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static CTHR_ONCE_DECLARE_CB(init_sip)
|
||||
{
|
||||
generate_system_random_bytes(sizeof(crypto_siphash_key), crypto_siphash_key);
|
||||
REGISTER_FINALIZER(deinit_sip);
|
||||
return CTHR_ONCE_CB_SUCCESS;
|
||||
}
|
||||
|
||||
const unsigned char *get_static_siphash_key(void)
|
||||
{
|
||||
static CTHR_ONCE_FLAG once = CTHR_ONCE_INIT;
|
||||
const int r = CTHR_ONCE_CALL(&once, init_sip);
|
||||
(void) r; assert(r);
|
||||
return crypto_siphash_key;
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2024, The Monero Project
|
||||
// Copyright (c) 2014-2026, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -39,7 +39,8 @@ extern "C" {
|
||||
void generate_random_bytes_not_thread_safe(size_t n, void *result);
|
||||
void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes);
|
||||
|
||||
extern unsigned char crypto_siphash_key[16];
|
||||
//! @brief Return pointer to random, constant 16-byte key, thread-safe and static-init-safe
|
||||
const unsigned char *get_static_siphash_key(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "crypto-tests.h"
|
||||
|
||||
void setup_random(void) {
|
||||
generate_random_bytes_not_thread_safe(0, NULL);
|
||||
memset(&state, 42, sizeof(union hash_state));
|
||||
hash_permutation(&state);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user