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"
2020-12-29 17:15:51 +00:00
static rustsecp256k1_v0_4_0_rfc6979_hmac_sha256 rustsecp256k1_v0_4_0_test_rng ;
static uint32_t rustsecp256k1_v0_4_0_test_rng_precomputed [ 8 ] ;
static int rustsecp256k1_v0_4_0_test_rng_precomputed_used = 8 ;
static uint64_t rustsecp256k1_v0_4_0_test_rng_integer ;
static int rustsecp256k1_v0_4_0_test_rng_integer_bits_left = 0 ;
2015-10-26 14:54:21 +00:00
2020-12-29 17:15:51 +00:00
SECP256K1_INLINE static void rustsecp256k1_v0_4_0_testrand_seed ( const unsigned char * seed16 ) {
rustsecp256k1_v0_4_0_rfc6979_hmac_sha256_initialize ( & rustsecp256k1_v0_4_0_test_rng , seed16 , 16 ) ;
2015-10-26 14:54:21 +00:00
}
2020-12-29 17:15:51 +00:00
SECP256K1_INLINE static uint32_t rustsecp256k1_v0_4_0_testrand32 ( void ) {
if ( rustsecp256k1_v0_4_0_test_rng_precomputed_used = = 8 ) {
rustsecp256k1_v0_4_0_rfc6979_hmac_sha256_generate ( & rustsecp256k1_v0_4_0_test_rng , ( unsigned char * ) ( & rustsecp256k1_v0_4_0_test_rng_precomputed [ 0 ] ) , sizeof ( rustsecp256k1_v0_4_0_test_rng_precomputed ) ) ;
rustsecp256k1_v0_4_0_test_rng_precomputed_used = 0 ;
2015-10-26 14:54:21 +00:00
}
2020-12-29 17:15:51 +00:00
return rustsecp256k1_v0_4_0_test_rng_precomputed [ rustsecp256k1_v0_4_0_test_rng_precomputed_used + + ] ;
2015-10-26 14:54:21 +00:00
}
2020-12-29 17:15:51 +00:00
static uint32_t rustsecp256k1_v0_4_0_testrand_bits ( int bits ) {
2015-10-26 14:54:21 +00:00
uint32_t ret ;
2020-12-29 17:15:51 +00:00
if ( rustsecp256k1_v0_4_0_test_rng_integer_bits_left < bits ) {
rustsecp256k1_v0_4_0_test_rng_integer | = ( ( ( uint64_t ) rustsecp256k1_v0_4_0_testrand32 ( ) ) < < rustsecp256k1_v0_4_0_test_rng_integer_bits_left ) ;
rustsecp256k1_v0_4_0_test_rng_integer_bits_left + = 32 ;
2015-10-26 14:54:21 +00:00
}
2020-12-29 17:15:51 +00:00
ret = rustsecp256k1_v0_4_0_test_rng_integer ;
rustsecp256k1_v0_4_0_test_rng_integer > > = bits ;
rustsecp256k1_v0_4_0_test_rng_integer_bits_left - = bits ;
2015-10-26 14:54:21 +00:00
ret & = ( ( ~ ( ( uint32_t ) 0 ) ) > > ( 32 - bits ) ) ;
return ret ;
}
2020-12-29 17:15:51 +00:00
static uint32_t rustsecp256k1_v0_4_0_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 ) {
2020-12-29 17:15:51 +00:00
uint32_t x = rustsecp256k1_v0_4_0_testrand_bits ( bits ) ;
2015-10-26 14:54:21 +00:00
if ( x < trange ) {
return ( mult = = 1 ) ? x : ( x % range ) ;
}
}
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_testrand256 ( unsigned char * b32 ) {
rustsecp256k1_v0_4_0_rfc6979_hmac_sha256_generate ( & rustsecp256k1_v0_4_0_test_rng , b32 , 32 ) ;
2015-10-26 14:54:21 +00:00
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_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 ;
2020-12-29 17:15:51 +00:00
now = 1 + ( rustsecp256k1_v0_4_0_testrand_bits ( 6 ) * rustsecp256k1_v0_4_0_testrand_bits ( 5 ) + 16 ) / 31 ;
val = rustsecp256k1_v0_4_0_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 + + ;
}
}
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_testrand256_test ( unsigned char * b32 ) {
rustsecp256k1_v0_4_0_testrand_bytes_test ( b32 , 32 ) ;
2020-09-15 01:39:26 +00:00
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_testrand_flip ( unsigned char * b , size_t len ) {
b [ rustsecp256k1_v0_4_0_testrand_int ( len ) ] ^ = ( 1 < < rustsecp256k1_v0_4_0_testrand_int ( 8 ) ) ;
2020-09-15 01:39:26 +00:00
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_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 {
FILE * frand = fopen ( " /dev/urandom " , " r " ) ;
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 ] ) ;
2020-12-29 17:15:51 +00:00
rustsecp256k1_v0_4_0_testrand_seed ( seed16 ) ;
2020-09-15 01:39:26 +00:00
}
2020-12-29 17:15:51 +00:00
static void rustsecp256k1_v0_4_0_testrand_finish ( void ) {
2020-09-15 01:39:26 +00:00
unsigned char run32 [ 32 ] ;
2020-12-29 17:15:51 +00:00
rustsecp256k1_v0_4_0_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 */