@@ -20130,17 +20130,40 @@ int wolfSSL_RAND_poll(void)
2013020130 {
2013120131 int ret = WOLFSSL_SUCCESS;
2013220132 #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
20133+ int customMethodChecked = 0;
2013320134 if (wolfSSL_RAND_InitMutex() == 0 &&
2013420135 wc_LockMutex(&gRandMethodMutex) == 0) {
20135- if (gRandMethods && gRandMethods->status)
20136+ if (gRandMethods && gRandMethods->status) {
2013620137 ret = gRandMethods->status();
20138+ customMethodChecked = 1;
20139+ }
2013720140 wc_UnLockMutex(&gRandMethodMutex);
2013820141 }
2013920142 else {
20140- ret = WOLFSSL_FAILURE;
20143+ return WOLFSSL_FAILURE;
20144+ }
20145+ if (customMethodChecked)
20146+ return ret;
20147+ #endif
20148+
20149+ /* Drive the global RNG so init / DRBG state failures (mutex
20150+ * acquisition, reseed required, corrupted state) surface to the
20151+ * caller. DRBG output is deterministic between reseeds, so this
20152+ * does not directly probe the entropy source. */
20153+ #ifdef HAVE_GLOBAL_RNG
20154+ if (wolfSSL_RAND_Init() != WOLFSSL_SUCCESS)
20155+ return WOLFSSL_FAILURE;
20156+ {
20157+ byte b = 0;
20158+ int genRet;
20159+ if (wc_LockMutex(&globalRNGMutex) != 0)
20160+ return WOLFSSL_FAILURE;
20161+ genRet = wc_RNG_GenerateBlock(&globalRNG, &b, 1);
20162+ wc_UnLockMutex(&globalRNGMutex);
20163+ ForceZero(&b, 1);
20164+ if (genRet != 0)
20165+ return WOLFSSL_FAILURE;
2014120166 }
20142- #else
20143- /* wolfCrypt provides enough seed internally, so return success */
2014420167 #endif
2014520168 return ret;
2014620169 }
@@ -20175,12 +20198,96 @@ void wolfSSL_RAND_screen(void)
2017520198
2017620199int wolfSSL_RAND_load_file(const char* fname, long len)
2017720200{
20201+ #if !defined(NO_FILESYSTEM) && defined(HAVE_HASHDRBG)
20202+ XFILE f;
20203+ long maxBytes;
20204+ long readSoFar = 0;
20205+ int ret = 0;
20206+ #ifndef WOLFSSL_SMALL_STACK
20207+ unsigned char buf[256];
20208+ #else
20209+ unsigned char* buf;
20210+ #endif
20211+
20212+ WOLFSSL_ENTER("wolfSSL_RAND_load_file");
20213+
20214+ if (fname == NULL)
20215+ return WOLFSSL_FATAL_ERROR;
20216+
20217+ /* OpenSSL semantics: RAND_load_file(file, -1) reads up to an
20218+ * implementation-defined maximum. Match OpenSSL's RAND_LOAD_BUF_SIZE
20219+ * (1 MB) so callers passing -1 to ingest a multi-KB seed file aren't
20220+ * silently truncated. */
20221+ maxBytes = (len < 0) ? (1L << 20) : len;
20222+ if (maxBytes == 0)
20223+ return 0;
20224+
20225+ f = XFOPEN(fname, "rb");
20226+ if (f == XBADFILE) {
20227+ WOLFSSL_MSG("RAND_load_file: cannot open file");
20228+ return WOLFSSL_FATAL_ERROR;
20229+ }
20230+
20231+ #ifdef WOLFSSL_SMALL_STACK
20232+ buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
20233+ if (buf == NULL) {
20234+ XFCLOSE(f);
20235+ return WOLFSSL_FATAL_ERROR;
20236+ }
20237+ #endif
20238+ #ifdef WOLFSSL_CHECK_MEM_ZERO
20239+ wc_MemZero_Add("wolfSSL_RAND_load_file buf", buf, 256);
20240+ #endif
20241+
20242+ if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
20243+ WOLFSSL_MSG("RAND_load_file: global RNG not available");
20244+ ret = WOLFSSL_FATAL_ERROR;
20245+ goto cleanup;
20246+ }
20247+
20248+ while (readSoFar < maxBytes) {
20249+ size_t toRead = (size_t)((maxBytes - readSoFar) < 256
20250+ ? (maxBytes - readSoFar) : 256);
20251+ size_t n = XFREAD(buf, 1, toRead, f);
20252+ if (n == 0)
20253+ break;
20254+ if (wc_LockMutex(&globalRNGMutex) != 0) {
20255+ ret = WOLFSSL_FATAL_ERROR;
20256+ break;
20257+ }
20258+ if (wc_RNG_DRBG_Reseed(&globalRNG, buf, (word32)n) != 0) {
20259+ wc_UnLockMutex(&globalRNGMutex);
20260+ WOLFSSL_MSG("RAND_load_file: DRBG reseed failed");
20261+ ret = WOLFSSL_FATAL_ERROR;
20262+ break;
20263+ }
20264+ wc_UnLockMutex(&globalRNGMutex);
20265+ readSoFar += (long)n;
20266+ }
20267+
20268+ cleanup:
20269+ XFCLOSE(f);
20270+ ForceZero(buf, 256);
20271+ #ifdef WOLFSSL_CHECK_MEM_ZERO
20272+ /* Balance the wc_MemZero_Add above for both stack/heap paths. */
20273+ wc_MemZero_Check(buf, 256);
20274+ #endif
20275+ #ifdef WOLFSSL_SMALL_STACK
20276+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
20277+ #endif
20278+
20279+ if (ret < 0)
20280+ return WOLFSSL_FATAL_ERROR;
20281+ return (int)readSoFar;
20282+ #else
20283+ /* Without HAVE_HASHDRBG / filesystem support there is no way to feed
20284+ * external entropy to the wolfCrypt RNG; return success so callers
20285+ * in those configurations are not broken. */
2017820286 (void)fname;
20179- /* wolfCrypt provides enough entropy internally or will report error */
2018020287 if (len == -1)
2018120288 return 1024;
20182- else
20183- return (int)len;
20289+ return (int)len;
20290+ #endif
2018420291}
2018520292
2018620293#endif /* OPENSSL_EXTRA */
0 commit comments