2020-12-29 17:15:51 +00:00
/***********************************************************************
* Copyright ( c ) 2013 - 2015 Pieter Wuille *
* Distributed under the MIT software license , see the accompanying *
* file COPYING or https : //www.opensource.org/licenses/mit-license.php.*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-10-26 14:54:21 +00:00
2018-07-09 11:17:44 +00:00
# ifndef SECP256K1_TESTRAND_IMPL_H
# define SECP256K1_TESTRAND_IMPL_H
2015-10-26 14:54:21 +00:00
# include <stdint.h>
2020-09-15 01:39:26 +00:00
# include <stdio.h>
2015-10-26 14:54:21 +00:00
# include <string.h>
# include "testrand.h"
# include "hash.h"
2023-09-27 18:37:09 +00:00
# include "util.h"
2015-10-26 14:54:21 +00:00
2024-01-02 16:22:20 +00:00
static uint64_t rustsecp256k1_v0_9_2_test_state [ 4 ] ;
2022-03-08 19:45:41 +00:00
2024-01-02 16:22:20 +00:00
SECP256K1_INLINE static void rustsecp256k1_v0_9_2_testrand_seed ( const unsigned char * seed16 ) {
2022-03-08 19:45:41 +00:00
static const unsigned char PREFIX [ 19 ] = " secp256k1 test init " ;
unsigned char out32 [ 32 ] ;
2024-01-02 16:22:20 +00:00
rustsecp256k1_v0_9_2_sha256 hash ;
2022-03-08 19:45:41 +00:00
int i ;
/* Use SHA256(PREFIX || seed16) as initial state. */
2024-01-02 16:22:20 +00:00
rustsecp256k1_v0_9_2_sha256_initialize ( & hash ) ;
rustsecp256k1_v0_9_2_sha256_write ( & hash , PREFIX , sizeof ( PREFIX ) ) ;
rustsecp256k1_v0_9_2_sha256_write ( & hash , seed16 , 16 ) ;
rustsecp256k1_v0_9_2_sha256_finalize ( & hash , out32 ) ;
2022-03-08 19:45:41 +00:00
for ( i = 0 ; i < 4 ; + + i ) {
uint64_t s = 0 ;
int j ;
for ( j = 0 ; j < 8 ; + + j ) s = ( s < < 8 ) | out32 [ 8 * i + j ] ;
2024-01-02 16:22:20 +00:00
rustsecp256k1_v0_9_2_test_state [ i ] = s ;
2022-03-08 19:45:41 +00:00
}
2015-10-26 14:54:21 +00:00
}
2022-03-08 19:45:41 +00:00
SECP256K1_INLINE static uint64_t rotl ( const uint64_t x , int k ) {
return ( x < < k ) | ( x > > ( 64 - k ) ) ;
}
2024-01-02 16:22:20 +00:00
SECP256K1_INLINE static uint64_t rustsecp256k1_v0_9_2_testrand64 ( void ) {
2022-03-08 19:45:41 +00:00
/* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */
2024-01-02 16:22:20 +00:00
const uint64_t result = rotl ( rustsecp256k1_v0_9_2_test_state [ 0 ] + rustsecp256k1_v0_9_2_test_state [ 3 ] , 23 ) + rustsecp256k1_v0_9_2_test_state [ 0 ] ;
const uint64_t t = rustsecp256k1_v0_9_2_test_state [ 1 ] < < 17 ;
rustsecp256k1_v0_9_2_test_state [ 2 ] ^ = rustsecp256k1_v0_9_2_test_state [ 0 ] ;
rustsecp256k1_v0_9_2_test_state [ 3 ] ^ = rustsecp256k1_v0_9_2_test_state [ 1 ] ;
rustsecp256k1_v0_9_2_test_state [ 1 ] ^ = rustsecp256k1_v0_9_2_test_state [ 2 ] ;
rustsecp256k1_v0_9_2_test_state [ 0 ] ^ = rustsecp256k1_v0_9_2_test_state [ 3 ] ;
rustsecp256k1_v0_9_2_test_state [ 2 ] ^ = t ;
rustsecp256k1_v0_9_2_test_state [ 3 ] = rotl ( rustsecp256k1_v0_9_2_test_state [ 3 ] , 45 ) ;
2022-03-08 19:45:41 +00:00
return result ;
2015-10-26 14:54:21 +00:00
}
2024-01-02 16:22:20 +00:00
SECP256K1_INLINE static uint64_t rustsecp256k1_v0_9_2_testrand_bits ( int bits ) {
2023-09-27 18:37:09 +00:00
if ( bits = = 0 ) return 0 ;
2024-01-02 16:22:20 +00:00
return rustsecp256k1_v0_9_2_testrand64 ( ) > > ( 64 - bits ) ;
2015-10-26 14:54:21 +00:00
}
2024-01-02 16:22:20 +00:00
SECP256K1_INLINE static uint32_t rustsecp256k1_v0_9_2_testrand32 ( void ) {
return rustsecp256k1_v0_9_2_testrand64 ( ) > > 32 ;
2022-03-08 19:45:41 +00:00
}
2024-01-02 16:22:20 +00:00
static uint32_t rustsecp256k1_v0_9_2_testrand_int ( uint32_t range ) {
2023-09-27 18:37:09 +00:00
uint32_t mask = 0 ;
uint32_t range_copy ;
/* Reduce range by 1, changing its meaning to "maximum value". */
VERIFY_CHECK ( range ! = 0 ) ;
range - = 1 ;
/* Count the number of bits in range. */
range_copy = range ;
while ( range_copy ) {
mask = ( mask < < 1 ) | 1U ;
range_copy > > = 1 ;
2015-10-26 14:54:21 +00:00
}
2023-09-27 18:37:09 +00:00
/* Generation loop. */
while ( 1 ) {
2024-01-02 16:22:20 +00:00
uint32_t val = rustsecp256k1_v0_9_2_testrand64 ( ) & mask ;
2023-09-27 18:37:09 +00:00
if ( val < = range ) return val ;
2015-10-26 14:54:21 +00:00
}
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand256 ( unsigned char * b32 ) {
2022-03-08 19:45:41 +00:00
int i ;
for ( i = 0 ; i < 4 ; + + i ) {
2024-01-02 16:22:20 +00:00
uint64_t val = rustsecp256k1_v0_9_2_testrand64 ( ) ;
2022-03-08 19:45:41 +00:00
b32 [ 0 ] = val ;
b32 [ 1 ] = val > > 8 ;
b32 [ 2 ] = val > > 16 ;
b32 [ 3 ] = val > > 24 ;
b32 [ 4 ] = val > > 32 ;
b32 [ 5 ] = val > > 40 ;
b32 [ 6 ] = val > > 48 ;
b32 [ 7 ] = val > > 56 ;
b32 + = 8 ;
}
2015-10-26 14:54:21 +00:00
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand_bytes_test ( unsigned char * bytes , size_t len ) {
2015-10-26 14:54:21 +00:00
size_t bits = 0 ;
memset ( bytes , 0 , len ) ;
while ( bits < len * 8 ) {
int now ;
uint32_t val ;
2024-01-02 16:22:20 +00:00
now = 1 + ( rustsecp256k1_v0_9_2_testrand_bits ( 6 ) * rustsecp256k1_v0_9_2_testrand_bits ( 5 ) + 16 ) / 31 ;
val = rustsecp256k1_v0_9_2_testrand_bits ( 1 ) ;
2015-10-26 14:54:21 +00:00
while ( now > 0 & & bits < len * 8 ) {
bytes [ bits / 8 ] | = val < < ( bits % 8 ) ;
now - - ;
bits + + ;
}
}
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand256_test ( unsigned char * b32 ) {
rustsecp256k1_v0_9_2_testrand_bytes_test ( b32 , 32 ) ;
2020-09-15 01:39:26 +00:00
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand_flip ( unsigned char * b , size_t len ) {
b [ rustsecp256k1_v0_9_2_testrand_int ( len ) ] ^ = ( 1 < < rustsecp256k1_v0_9_2_testrand_bits ( 3 ) ) ;
2020-09-15 01:39:26 +00:00
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand_init ( const char * hexseed ) {
2020-09-15 01:39:26 +00:00
unsigned char seed16 [ 16 ] = { 0 } ;
if ( hexseed & & strlen ( hexseed ) ! = 0 ) {
int pos = 0 ;
while ( pos < 16 & & hexseed [ 0 ] ! = 0 & & hexseed [ 1 ] ! = 0 ) {
unsigned short sh ;
if ( ( sscanf ( hexseed , " %2hx " , & sh ) ) = = 1 ) {
seed16 [ pos ] = sh ;
} else {
break ;
}
hexseed + = 2 ;
pos + + ;
}
} else {
2021-06-14 14:55:38 +00:00
FILE * frand = fopen ( " /dev/urandom " , " rb " ) ;
2020-09-15 01:39:26 +00:00
if ( ( frand = = NULL ) | | fread ( & seed16 , 1 , sizeof ( seed16 ) , frand ) ! = sizeof ( seed16 ) ) {
uint64_t t = time ( NULL ) * ( uint64_t ) 1337 ;
fprintf ( stderr , " WARNING: could not read 16 bytes from /dev/urandom; falling back to insecure PRNG \n " ) ;
seed16 [ 0 ] ^ = t ;
seed16 [ 1 ] ^ = t > > 8 ;
seed16 [ 2 ] ^ = t > > 16 ;
seed16 [ 3 ] ^ = t > > 24 ;
seed16 [ 4 ] ^ = t > > 32 ;
seed16 [ 5 ] ^ = t > > 40 ;
seed16 [ 6 ] ^ = t > > 48 ;
seed16 [ 7 ] ^ = t > > 56 ;
}
if ( frand ) {
fclose ( frand ) ;
}
}
printf ( " random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x \n " , seed16 [ 0 ] , seed16 [ 1 ] , seed16 [ 2 ] , seed16 [ 3 ] , seed16 [ 4 ] , seed16 [ 5 ] , seed16 [ 6 ] , seed16 [ 7 ] , seed16 [ 8 ] , seed16 [ 9 ] , seed16 [ 10 ] , seed16 [ 11 ] , seed16 [ 12 ] , seed16 [ 13 ] , seed16 [ 14 ] , seed16 [ 15 ] ) ;
2024-01-02 16:22:20 +00:00
rustsecp256k1_v0_9_2_testrand_seed ( seed16 ) ;
2020-09-15 01:39:26 +00:00
}
2024-01-02 16:22:20 +00:00
static void rustsecp256k1_v0_9_2_testrand_finish ( void ) {
2020-09-15 01:39:26 +00:00
unsigned char run32 [ 32 ] ;
2024-01-02 16:22:20 +00:00
rustsecp256k1_v0_9_2_testrand256 ( run32 ) ;
2020-09-15 01:39:26 +00:00
printf ( " random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x \n " , run32 [ 0 ] , run32 [ 1 ] , run32 [ 2 ] , run32 [ 3 ] , run32 [ 4 ] , run32 [ 5 ] , run32 [ 6 ] , run32 [ 7 ] , run32 [ 8 ] , run32 [ 9 ] , run32 [ 10 ] , run32 [ 11 ] , run32 [ 12 ] , run32 [ 13 ] , run32 [ 14 ] , run32 [ 15 ] ) ;
2015-10-26 14:54:21 +00:00
}
2018-07-09 11:17:44 +00:00
# endif /* SECP256K1_TESTRAND_IMPL_H */