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-03-17 05:22:01 +00:00
static uint64_t rustsecp256k1_v0_8_1_test_state [ 4 ] ;
static uint64_t rustsecp256k1_v0_8_1_test_rng_integer ;
static int rustsecp256k1_v0_8_1_test_rng_integer_bits_left = 0 ;
2022-03-08 19:45:41 +00:00
2023-03-17 05:22:01 +00:00
SECP256K1_INLINE static void rustsecp256k1_v0_8_1_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 ] ;
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_sha256 hash ;
2022-03-08 19:45:41 +00:00
int i ;
/* Use SHA256(PREFIX || seed16) as initial state. */
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_sha256_initialize ( & hash ) ;
rustsecp256k1_v0_8_1_sha256_write ( & hash , PREFIX , sizeof ( PREFIX ) ) ;
rustsecp256k1_v0_8_1_sha256_write ( & hash , seed16 , 16 ) ;
rustsecp256k1_v0_8_1_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 ] ;
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_test_state [ i ] = s ;
2022-03-08 19:45:41 +00:00
}
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_test_rng_integer_bits_left = 0 ;
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 ) ) ;
}
2023-03-17 05:22:01 +00:00
SECP256K1_INLINE static uint64_t rustsecp256k1_v0_8_1_testrand64 ( void ) {
2022-03-08 19:45:41 +00:00
/* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */
2023-03-17 05:22:01 +00:00
const uint64_t result = rotl ( rustsecp256k1_v0_8_1_test_state [ 0 ] + rustsecp256k1_v0_8_1_test_state [ 3 ] , 23 ) + rustsecp256k1_v0_8_1_test_state [ 0 ] ;
const uint64_t t = rustsecp256k1_v0_8_1_test_state [ 1 ] < < 17 ;
rustsecp256k1_v0_8_1_test_state [ 2 ] ^ = rustsecp256k1_v0_8_1_test_state [ 0 ] ;
rustsecp256k1_v0_8_1_test_state [ 3 ] ^ = rustsecp256k1_v0_8_1_test_state [ 1 ] ;
rustsecp256k1_v0_8_1_test_state [ 1 ] ^ = rustsecp256k1_v0_8_1_test_state [ 2 ] ;
rustsecp256k1_v0_8_1_test_state [ 0 ] ^ = rustsecp256k1_v0_8_1_test_state [ 3 ] ;
rustsecp256k1_v0_8_1_test_state [ 2 ] ^ = t ;
rustsecp256k1_v0_8_1_test_state [ 3 ] = rotl ( rustsecp256k1_v0_8_1_test_state [ 3 ] , 45 ) ;
2022-03-08 19:45:41 +00:00
return result ;
2015-10-26 14:54:21 +00:00
}
2023-03-17 05:22:01 +00:00
SECP256K1_INLINE static uint64_t rustsecp256k1_v0_8_1_testrand_bits ( int bits ) {
2022-03-08 19:45:41 +00:00
uint64_t ret ;
2023-03-17 05:22:01 +00:00
if ( rustsecp256k1_v0_8_1_test_rng_integer_bits_left < bits ) {
rustsecp256k1_v0_8_1_test_rng_integer = rustsecp256k1_v0_8_1_testrand64 ( ) ;
rustsecp256k1_v0_8_1_test_rng_integer_bits_left = 64 ;
2015-10-26 14:54:21 +00:00
}
2023-03-17 05:22:01 +00:00
ret = rustsecp256k1_v0_8_1_test_rng_integer ;
rustsecp256k1_v0_8_1_test_rng_integer > > = bits ;
rustsecp256k1_v0_8_1_test_rng_integer_bits_left - = bits ;
2022-03-08 19:45:41 +00:00
ret & = ( ( ~ ( ( uint64_t ) 0 ) ) > > ( 64 - bits ) ) ;
2015-10-26 14:54:21 +00:00
return ret ;
}
2023-03-17 05:22:01 +00:00
SECP256K1_INLINE static uint32_t rustsecp256k1_v0_8_1_testrand32 ( void ) {
return rustsecp256k1_v0_8_1_testrand_bits ( 32 ) ;
2022-03-08 19:45:41 +00:00
}
2023-03-17 05:22:01 +00:00
static uint32_t rustsecp256k1_v0_8_1_testrand_int ( uint32_t range ) {
2015-10-26 14:54:21 +00:00
/* We want a uniform integer between 0 and range-1, inclusive.
* B is the smallest number such that range < = 2 * * B .
* two mechanisms implemented here :
* - generate B bits numbers until one below range is found , and return it
* - find the largest multiple M of range that is < = 2 * * ( B + A ) , generate B + A
* bits numbers until one below M is found , and return it modulo range
* The second mechanism consumes A more bits of entropy in every iteration ,
* but may need fewer iterations due to M being closer to 2 * * ( B + A ) then
* range is to 2 * * B . The array below ( indexed by B ) contains a 0 when the
* first mechanism is to be used , and the number A otherwise .
*/
static const int addbits [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 2 , 1 , 0 } ;
uint32_t trange , mult ;
int bits = 0 ;
if ( range < = 1 ) {
return 0 ;
}
trange = range - 1 ;
while ( trange > 0 ) {
trange > > = 1 ;
bits + + ;
}
if ( addbits [ bits ] ) {
bits = bits + addbits [ bits ] ;
mult = ( ( ~ ( ( uint32_t ) 0 ) ) > > ( 32 - bits ) ) / range ;
trange = range * mult ;
} else {
trange = range ;
mult = 1 ;
}
while ( 1 ) {
2023-03-17 05:22:01 +00:00
uint32_t x = rustsecp256k1_v0_8_1_testrand_bits ( bits ) ;
2015-10-26 14:54:21 +00:00
if ( x < trange ) {
return ( mult = = 1 ) ? x : ( x % range ) ;
}
}
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_testrand256 ( unsigned char * b32 ) {
2022-03-08 19:45:41 +00:00
int i ;
for ( i = 0 ; i < 4 ; + + i ) {
2023-03-17 05:22:01 +00:00
uint64_t val = rustsecp256k1_v0_8_1_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
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_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 ;
2023-03-17 05:22:01 +00:00
now = 1 + ( rustsecp256k1_v0_8_1_testrand_bits ( 6 ) * rustsecp256k1_v0_8_1_testrand_bits ( 5 ) + 16 ) / 31 ;
val = rustsecp256k1_v0_8_1_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 + + ;
}
}
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_testrand256_test ( unsigned char * b32 ) {
rustsecp256k1_v0_8_1_testrand_bytes_test ( b32 , 32 ) ;
2020-09-15 01:39:26 +00:00
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_testrand_flip ( unsigned char * b , size_t len ) {
b [ rustsecp256k1_v0_8_1_testrand_int ( len ) ] ^ = ( 1 < < rustsecp256k1_v0_8_1_testrand_bits ( 3 ) ) ;
2020-09-15 01:39:26 +00:00
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_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 ] ) ;
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_testrand_seed ( seed16 ) ;
2020-09-15 01:39:26 +00:00
}
2023-03-17 05:22:01 +00:00
static void rustsecp256k1_v0_8_1_testrand_finish ( void ) {
2020-09-15 01:39:26 +00:00
unsigned char run32 [ 32 ] ;
2023-03-17 05:22:01 +00:00
rustsecp256k1_v0_8_1_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 */