@@ -20129,19 +20129,45 @@ int wolfSSL_RAND_poll(void)
2012920129 int wolfSSL_RAND_status(void)
2013020130 {
2013120131 int ret = WOLFSSL_SUCCESS;
20132+ int useGlobalRng = 1;
2013220133 #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
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+ useGlobalRng = 0;
20139+ }
2013720140 wc_UnLockMutex(&gRandMethodMutex);
2013820141 }
2013920142 else {
2014020143 ret = WOLFSSL_FAILURE;
20144+ useGlobalRng = 0;
20145+ }
20146+ #endif
20147+
20148+ /* Drive the global RNG so init / DRBG state failures (mutex
20149+ * acquisition, reseed required, corrupted state) surface to the
20150+ * caller. DRBG output is deterministic between reseeds, so this
20151+ * does not directly probe the entropy source. */
20152+ #ifdef HAVE_GLOBAL_RNG
20153+ if (useGlobalRng) {
20154+ if (wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
20155+ ret = WOLFSSL_FAILURE;
20156+ }
20157+ else if (wc_LockMutex(&globalRNGMutex) != 0) {
20158+ ret = WOLFSSL_FAILURE;
20159+ }
20160+ else {
20161+ byte b = 0;
20162+ int genRet = wc_RNG_GenerateBlock(&globalRNG, &b, 1);
20163+ wc_UnLockMutex(&globalRNGMutex);
20164+ ForceZero(&b, 1);
20165+ if (genRet != 0)
20166+ ret = WOLFSSL_FAILURE;
20167+ }
2014120168 }
20142- #else
20143- /* wolfCrypt provides enough seed internally, so return success */
2014420169 #endif
20170+ (void)useGlobalRng;
2014520171 return ret;
2014620172 }
2014720173
@@ -20173,14 +20199,106 @@ void wolfSSL_RAND_screen(void)
2017320199}
2017420200#endif
2017520201
20202+ #ifndef WOLFSSL_RAND_LOAD_FILE_BUF_SZ
20203+ #define WOLFSSL_RAND_LOAD_FILE_BUF_SZ 256
20204+ #endif
20205+ #ifndef WOLFSSL_RAND_LOAD_FILE_MAX_BYTES
20206+ #define WOLFSSL_RAND_LOAD_FILE_MAX_BYTES (1L << 20)
20207+ #endif
20208+
2017620209int wolfSSL_RAND_load_file(const char* fname, long len)
2017720210{
20211+ #if !defined(NO_FILESYSTEM) && defined(HAVE_HASHDRBG)
20212+ XFILE f;
20213+ long maxBytes;
20214+ long readSoFar = 0;
20215+ int ret = 0;
20216+ #ifndef WOLFSSL_SMALL_STACK
20217+ unsigned char buf[WOLFSSL_RAND_LOAD_FILE_BUF_SZ];
20218+ #else
20219+ unsigned char* buf;
20220+ #endif
20221+
20222+ WOLFSSL_ENTER("wolfSSL_RAND_load_file");
20223+
20224+ if (fname == NULL)
20225+ return WOLFSSL_FATAL_ERROR;
20226+
20227+ /* OpenSSL semantics: RAND_load_file(file, -1) reads up to an
20228+ * implementation-defined maximum. WOLFSSL_RAND_LOAD_FILE_MAX_BYTES
20229+ * caps the read so callers passing -1 to ingest a seed file aren't
20230+ * silently truncated at a small default. */
20231+ maxBytes = (len < 0) ? WOLFSSL_RAND_LOAD_FILE_MAX_BYTES : len;
20232+ if (maxBytes == 0)
20233+ return 0;
20234+
20235+ f = XFOPEN(fname, "rb");
20236+ if (f == XBADFILE) {
20237+ WOLFSSL_MSG("RAND_load_file: cannot open file");
20238+ return WOLFSSL_FATAL_ERROR;
20239+ }
20240+
20241+ #ifdef WOLFSSL_SMALL_STACK
20242+ buf = (unsigned char*)XMALLOC(WOLFSSL_RAND_LOAD_FILE_BUF_SZ, NULL,
20243+ DYNAMIC_TYPE_TMP_BUFFER);
20244+ if (buf == NULL) {
20245+ XFCLOSE(f);
20246+ return WOLFSSL_FATAL_ERROR;
20247+ }
20248+ #endif
20249+ #ifdef WOLFSSL_CHECK_MEM_ZERO
20250+ wc_MemZero_Add("wolfSSL_RAND_load_file buf", buf,
20251+ WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20252+ #endif
20253+
20254+ if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
20255+ WOLFSSL_MSG("RAND_load_file: global RNG not available");
20256+ ret = WOLFSSL_FATAL_ERROR;
20257+ goto cleanup;
20258+ }
20259+
20260+ while (readSoFar < maxBytes) {
20261+ size_t toRead = (size_t)((maxBytes - readSoFar) <
20262+ WOLFSSL_RAND_LOAD_FILE_BUF_SZ
20263+ ? (maxBytes - readSoFar) : WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20264+ size_t n = XFREAD(buf, 1, toRead, f);
20265+ if (n == 0)
20266+ break;
20267+ if (wc_LockMutex(&globalRNGMutex) != 0) {
20268+ ret = WOLFSSL_FATAL_ERROR;
20269+ break;
20270+ }
20271+ if (wc_RNG_DRBG_Reseed(&globalRNG, buf, (word32)n) != 0) {
20272+ wc_UnLockMutex(&globalRNGMutex);
20273+ WOLFSSL_MSG("RAND_load_file: DRBG reseed failed");
20274+ ret = WOLFSSL_FATAL_ERROR;
20275+ break;
20276+ }
20277+ wc_UnLockMutex(&globalRNGMutex);
20278+ readSoFar += (long)n;
20279+ }
20280+
20281+ cleanup:
20282+ XFCLOSE(f);
20283+ ForceZero(buf, WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20284+ #ifdef WOLFSSL_SMALL_STACK
20285+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
20286+ #elif defined(WOLFSSL_CHECK_MEM_ZERO)
20287+ wc_MemZero_Check(buf, WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20288+ #endif
20289+
20290+ if (ret < 0)
20291+ return WOLFSSL_FATAL_ERROR;
20292+ return (int)readSoFar;
20293+ #else
20294+ /* Without HAVE_HASHDRBG / filesystem support there is no way to feed
20295+ * external entropy to the wolfCrypt RNG; return success so callers
20296+ * in those configurations are not broken. */
2017820297 (void)fname;
20179- /* wolfCrypt provides enough entropy internally or will report error */
2018020298 if (len == -1)
2018120299 return 1024;
20182- else
20183- return (int)len;
20300+ return (int)len;
20301+ #endif
2018420302}
2018520303
2018620304#endif /* OPENSSL_EXTRA */
0 commit comments