@@ -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,42 @@ 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. Reads use a
5991+ * scratch cursor so a partial read leaves output untouched. */
5992+ devOut = output ;
5993+ devSz = sz ;
5994+ devFd = wc_open_cloexec (WC_RNG_SEED_DEVICE , O_RDONLY );
5995+ if (devFd != XBADFD ) {
5996+ while (devSz > 0 ) {
5997+ errno = 0 ;
5998+ devLen = (int )read (devFd , devOut , devSz );
5999+ if (devLen < 0 ) {
6000+ if (errno == EINTR )
6001+ continue ; /* interrupted, read again */
6002+ break ;
6003+ }
6004+ if (devLen == 0 )
6005+ break ; /* at EOF, will never fill the request */
6006+
6007+ devSz -= (word32 )devLen ;
6008+ devOut += devLen ;
6009+ }
6010+ close (devFd );
6011+ }
6012+ #if defined(DEBUG_WOLFSSL )
6013+ if (devSz == 0 )
6014+ WOLFSSL_MSG ("seeded from WC_RNG_SEED_DEVICE." );
6015+ else
6016+ WOLFSSL_MSG ("WC_RNG_SEED_DEVICE unusable, using default." );
6017+ #endif /* DEBUG_WOLFSSL */
6018+ if (devSz == 0 ) {
6019+ /* success, we're done */
6020+ return 0 ;
6021+ }
6022+ #endif /* WC_RNG_SEED_DEVICE */
6023+
59746024 #if defined(HAVE_INTEL_RDSEED ) || defined(HAVE_AMD_RDSEED )
59756025 if (IS_INTEL_RDSEED (intel_flags )) {
59766026 ret = wc_GenerateSeed_IntelRD (NULL , output , sz );
@@ -6038,44 +6088,50 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
60386088 #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
60396089 if (!os -> seedFdOpen )
60406090 {
6091+ os -> fd = XBADFD ;
60416092 #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
6042- os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
6093+ if (os -> fd == XBADFD ) {
6094+ os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
60436095 #if defined(DEBUG_WOLFSSL )
6044- WOLFSSL_MSG ("opened /dev/urandom." );
6096+ if (os -> fd != XBADFD )
6097+ WOLFSSL_MSG ("opened /dev/urandom." );
60456098 #endif /* DEBUG_WOLFSSL */
6046- if ( os -> fd == XBADFD )
6099+ }
60476100 #endif /* NO_DEV_URANDOM */
6048- {
6101+ if ( os -> fd == XBADFD ) {
60496102 /* may still have /dev/random */
60506103 os -> fd = wc_open_cloexec ("/dev/random" , O_RDONLY );
60516104 #if defined(DEBUG_WOLFSSL )
6052- WOLFSSL_MSG ("opened /dev/random." );
6105+ if (os -> fd != XBADFD )
6106+ WOLFSSL_MSG ("opened /dev/random." );
60536107 #endif /* DEBUG_WOLFSSL */
60546108 if (os -> fd == XBADFD )
60556109 return OPEN_RAN_E ;
6056- else {
6057- os -> keepSeedFdOpen = 0 ;
6058- os -> seedFdOpen = 1 ;
6059- }
6110+ os -> keepSeedFdOpen = 0 ;
6111+ os -> seedFdOpen = 1 ;
60606112 }
60616113 else {
60626114 os -> keepSeedFdOpen = 1 ;
60636115 os -> seedFdOpen = 1 ;
60646116 }
60656117 }
60666118 #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 );
6119+ os -> fd = XBADFD ;
6120+ #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
6121+ if (os -> fd == XBADFD ) {
6122+ os -> fd = wc_open_cloexec ("/dev/urandom" , O_RDONLY );
60696123 #if defined(DEBUG_WOLFSSL )
6070- WOLFSSL_MSG ("opened /dev/urandom." );
6124+ if (os -> fd != XBADFD )
6125+ WOLFSSL_MSG ("opened /dev/urandom." );
60716126 #endif /* DEBUG_WOLFSSL */
6072- if ( os -> fd == XBADFD )
6073- #endif /* !NO_DEV_URANDOM */
6074- {
6127+ }
6128+ #endif /* !NO_DEV_URANDOM */
6129+ if ( os -> fd == XBADFD ) {
60756130 /* may still have /dev/random */
60766131 os -> fd = wc_open_cloexec ("/dev/random" , O_RDONLY );
60776132 #if defined(DEBUG_WOLFSSL )
6078- WOLFSSL_MSG ("opened /dev/random." );
6133+ if (os -> fd != XBADFD )
6134+ WOLFSSL_MSG ("opened /dev/random." );
60796135 #endif /* DEBUG_WOLFSSL */
60806136 if (os -> fd == XBADFD )
60816137 return OPEN_RAN_E ;
@@ -6086,7 +6142,8 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
60866142 #endif /* DEBUG_WOLFSSL */
60876143 while (sz ) {
60886144 int len = (int )read (os -> fd , output , sz );
6089- if (len == -1 ) {
6145+ /* EOF never fills the request, don't retry forever */
6146+ if (len <= 0 ) {
60906147 ret = READ_RAN_E ;
60916148 break ;
60926149 }
0 commit comments