@@ -58,6 +58,9 @@ This library contains implementation for the random number generator.
5858 * FORCE_FAILURE_GETRANDOM: Force getrandom failure (testing) default: off
5959 * NO_DEV_RANDOM: Don't use /dev/random for seeding default: off
6060 * NO_DEV_URANDOM: Don't use /dev/urandom for seeding default: off
61+ * WC_RNG_SEED_DEVICE: Device tried before the usual seed default: off
62+ * sources. Must be a quoted string,
63+ * e.g. -DWC_RNG_SEED_DEVICE='"/dev/hwrng"'
6164 * HAVE_INTEL_RDRAND: Use Intel RDRAND instruction default: off
6265 * HAVE_INTEL_RDSEED: Use Intel RDSEED instruction default: off
6366 * HAVE_AMD_RDSEED: Use AMD RDSEED instruction default: off
@@ -352,6 +355,11 @@ enum {
352355 #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
353356#endif
354357
358+ /* the seed device is read through the filesystem API */
359+ #if defined(WC_RNG_SEED_DEVICE ) && defined(NO_FILESYSTEM )
360+ #error WC_RNG_SEED_DEVICE requires filesystem support
361+ #endif
362+
355363enum {
356364 drbgInitC = 0 ,
357365 drbgReseed = 1 ,
@@ -5933,6 +5941,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
59335941 int wc_GenerateSeed (OS_Seed * os , byte * output , word32 sz )
59345942 {
59355943 int ret = 0 ;
5944+ #ifdef WC_RNG_SEED_DEVICE
5945+ byte * devOut ;
5946+ word32 devSz ;
5947+ int devFd ;
5948+ int devLen ;
5949+ #endif
59365950
59375951 /* Validate output before any entropy backend dereferences it: some
59385952 * (e.g. glibc's vDSO getrandom()) fault on a NULL buffer rather than
@@ -5971,6 +5985,43 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
59715985
59725986 #if !defined(HAVE_ENTROPY_MEMUSE ) || !defined(ENTROPY_MEMUSE_FORCE_FAILURE )
59735987
5988+ #ifdef WC_RNG_SEED_DEVICE
5989+ /* Nominated entropy source, usually a hardware RNG. Best effort: on
5990+ * any failure fall through to the default sources below. Those refill
5991+ * the whole request from the start, so bytes a partial read left in
5992+ * output are overwritten rather than mixed in. */
5993+ devOut = output ;
5994+ devSz = sz ;
5995+ devFd = wc_open_cloexec (WC_RNG_SEED_DEVICE , O_RDONLY );
5996+ if (devFd != XBADFD ) {
5997+ while (devSz > 0 ) {
5998+ errno = 0 ;
5999+ devLen = (int )read (devFd , devOut , devSz );
6000+ if (devLen < 0 ) {
6001+ if (errno == EINTR )
6002+ continue ; /* interrupted, read again */
6003+ break ;
6004+ }
6005+ if (devLen == 0 )
6006+ break ; /* at EOF, will never fill the request */
6007+
6008+ devSz -= (word32 )devLen ;
6009+ devOut += devLen ;
6010+ }
6011+ close (devFd );
6012+ }
6013+ #if defined(DEBUG_WOLFSSL )
6014+ if (devSz == 0 )
6015+ WOLFSSL_MSG ("seeded from WC_RNG_SEED_DEVICE." );
6016+ else
6017+ WOLFSSL_MSG ("WC_RNG_SEED_DEVICE unusable, using default." );
6018+ #endif /* DEBUG_WOLFSSL */
6019+ if (devSz == 0 ) {
6020+ /* success, we're done */
6021+ return 0 ;
6022+ }
6023+ #endif /* WC_RNG_SEED_DEVICE */
6024+
59746025 #if defined(HAVE_INTEL_RDSEED ) || defined(HAVE_AMD_RDSEED )
59756026 if (IS_INTEL_RDSEED (intel_flags )) {
59766027 ret = wc_GenerateSeed_IntelRD (NULL , output , sz );
@@ -6038,44 +6089,50 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
60386089 #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
60396090 if (!os -> seedFdOpen )
60406091 {
6092+ os -> fd = XBADFD ;
60416093 #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
6042- os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
6094+ if (os -> fd == XBADFD ) {
6095+ os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
60436096 #if defined(DEBUG_WOLFSSL )
6044- WOLFSSL_MSG ("opened /dev/urandom." );
6097+ if (os -> fd != XBADFD )
6098+ WOLFSSL_MSG ("opened /dev/urandom." );
60456099 #endif /* DEBUG_WOLFSSL */
6046- if ( os -> fd == XBADFD )
6100+ }
60476101 #endif /* NO_DEV_URANDOM */
6048- {
6102+ if ( os -> fd == XBADFD ) {
60496103 /* may still have /dev/random */
60506104 os -> fd = wc_open_cloexec ("/dev/random" , O_RDONLY );
60516105 #if defined(DEBUG_WOLFSSL )
6052- WOLFSSL_MSG ("opened /dev/random." );
6106+ if (os -> fd != XBADFD )
6107+ WOLFSSL_MSG ("opened /dev/random." );
60536108 #endif /* DEBUG_WOLFSSL */
60546109 if (os -> fd == XBADFD )
60556110 return OPEN_RAN_E ;
6056- else {
6057- os -> keepSeedFdOpen = 0 ;
6058- os -> seedFdOpen = 1 ;
6059- }
6111+ os -> keepSeedFdOpen = 0 ;
6112+ os -> seedFdOpen = 1 ;
60606113 }
60616114 else {
60626115 os -> keepSeedFdOpen = 1 ;
60636116 os -> seedFdOpen = 1 ;
60646117 }
60656118 }
60666119 #else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
6067- #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
6068- os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
6120+ os -> fd = XBADFD ;
6121+ #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
6122+ if (os -> fd == XBADFD ) {
6123+ os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
60696124 #if defined(DEBUG_WOLFSSL )
6070- WOLFSSL_MSG ("opened /dev/urandom." );
6125+ if (os -> fd != XBADFD )
6126+ WOLFSSL_MSG ("opened /dev/urandom." );
60716127 #endif /* DEBUG_WOLFSSL */
6072- if ( os -> fd == XBADFD )
6073- #endif /* !NO_DEV_URANDOM */
6074- {
6128+ }
6129+ #endif /* !NO_DEV_URANDOM */
6130+ if ( os -> fd == XBADFD ) {
60756131 /* may still have /dev/random */
60766132 os -> fd = wc_open_cloexec ("/dev/random" , O_RDONLY );
60776133 #if defined(DEBUG_WOLFSSL )
6078- WOLFSSL_MSG ("opened /dev/random." );
6134+ if (os -> fd != XBADFD )
6135+ WOLFSSL_MSG ("opened /dev/random." );
60796136 #endif /* DEBUG_WOLFSSL */
60806137 if (os -> fd == XBADFD )
60816138 return OPEN_RAN_E ;
@@ -6086,7 +6143,8 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
60866143 #endif /* DEBUG_WOLFSSL */
60876144 while (sz ) {
60886145 int len = (int )read (os -> fd , output , sz );
6089- if (len == -1 ) {
6146+ /* EOF never fills the request, don't retry forever */
6147+ if (len <= 0 ) {
60906148 ret = READ_RAN_E ;
60916149 break ;
60926150 }
0 commit comments