@@ -20219,19 +20219,45 @@ int wolfSSL_RAND_poll(void)
2021920219 int wolfSSL_RAND_status(void)
2022020220 {
2022120221 int ret = WOLFSSL_SUCCESS;
20222+ int useGlobalRng = 1;
2022220223 #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
2022320224 if (wolfSSL_RAND_InitMutex() == 0 &&
2022420225 wc_LockMutex(&gRandMethodMutex) == 0) {
20225- if (gRandMethods && gRandMethods->status)
20226+ if (gRandMethods && gRandMethods->status) {
2022620227 ret = gRandMethods->status();
20228+ useGlobalRng = 0;
20229+ }
2022720230 wc_UnLockMutex(&gRandMethodMutex);
2022820231 }
2022920232 else {
2023020233 ret = WOLFSSL_FAILURE;
20234+ useGlobalRng = 0;
20235+ }
20236+ #endif
20237+
20238+ /* Drive the global RNG so init / DRBG state failures (mutex
20239+ * acquisition, reseed required, corrupted state) surface to the
20240+ * caller. DRBG output is deterministic between reseeds, so this
20241+ * does not directly probe the entropy source. */
20242+ #ifdef HAVE_GLOBAL_RNG
20243+ if (useGlobalRng) {
20244+ if (wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
20245+ ret = WOLFSSL_FAILURE;
20246+ }
20247+ else if (wc_LockMutex(&globalRNGMutex) != 0) {
20248+ ret = WOLFSSL_FAILURE;
20249+ }
20250+ else {
20251+ byte b = 0;
20252+ int genRet = wc_RNG_GenerateBlock(&globalRNG, &b, 1);
20253+ wc_UnLockMutex(&globalRNGMutex);
20254+ ForceZero(&b, 1);
20255+ if (genRet != 0)
20256+ ret = WOLFSSL_FAILURE;
20257+ }
2023120258 }
20232- #else
20233- /* wolfCrypt provides enough seed internally, so return success */
2023420259 #endif
20260+ (void)useGlobalRng;
2023520261 return ret;
2023620262 }
2023720263
@@ -20263,14 +20289,106 @@ void wolfSSL_RAND_screen(void)
2026320289}
2026420290#endif
2026520291
20292+ #ifndef WOLFSSL_RAND_LOAD_FILE_BUF_SZ
20293+ #define WOLFSSL_RAND_LOAD_FILE_BUF_SZ 256
20294+ #endif
20295+ #ifndef WOLFSSL_RAND_LOAD_FILE_MAX_BYTES
20296+ #define WOLFSSL_RAND_LOAD_FILE_MAX_BYTES (1L << 20)
20297+ #endif
20298+
2026620299int wolfSSL_RAND_load_file(const char* fname, long len)
2026720300{
20301+ #if !defined(NO_FILESYSTEM) && defined(HAVE_HASHDRBG)
20302+ XFILE f;
20303+ long maxBytes;
20304+ long readSoFar = 0;
20305+ int ret = 0;
20306+ #ifndef WOLFSSL_SMALL_STACK
20307+ unsigned char buf[WOLFSSL_RAND_LOAD_FILE_BUF_SZ];
20308+ #else
20309+ unsigned char* buf;
20310+ #endif
20311+
20312+ WOLFSSL_ENTER("wolfSSL_RAND_load_file");
20313+
20314+ if (fname == NULL)
20315+ return WOLFSSL_FATAL_ERROR;
20316+
20317+ /* OpenSSL semantics: RAND_load_file(file, -1) reads up to an
20318+ * implementation-defined maximum. WOLFSSL_RAND_LOAD_FILE_MAX_BYTES
20319+ * caps the read so callers passing -1 to ingest a seed file aren't
20320+ * silently truncated at a small default. */
20321+ maxBytes = (len < 0) ? WOLFSSL_RAND_LOAD_FILE_MAX_BYTES : len;
20322+ if (maxBytes == 0)
20323+ return 0;
20324+
20325+ f = XFOPEN(fname, "rb");
20326+ if (f == XBADFILE) {
20327+ WOLFSSL_MSG("RAND_load_file: cannot open file");
20328+ return WOLFSSL_FATAL_ERROR;
20329+ }
20330+
20331+ #ifdef WOLFSSL_SMALL_STACK
20332+ buf = (unsigned char*)XMALLOC(WOLFSSL_RAND_LOAD_FILE_BUF_SZ, NULL,
20333+ DYNAMIC_TYPE_TMP_BUFFER);
20334+ if (buf == NULL) {
20335+ XFCLOSE(f);
20336+ return WOLFSSL_FATAL_ERROR;
20337+ }
20338+ #endif
20339+ #ifdef WOLFSSL_CHECK_MEM_ZERO
20340+ wc_MemZero_Add("wolfSSL_RAND_load_file buf", buf,
20341+ WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20342+ #endif
20343+
20344+ if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
20345+ WOLFSSL_MSG("RAND_load_file: global RNG not available");
20346+ ret = WOLFSSL_FATAL_ERROR;
20347+ goto cleanup;
20348+ }
20349+
20350+ while (readSoFar < maxBytes) {
20351+ size_t toRead = (size_t)((maxBytes - readSoFar) <
20352+ WOLFSSL_RAND_LOAD_FILE_BUF_SZ
20353+ ? (maxBytes - readSoFar) : WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20354+ size_t n = XFREAD(buf, 1, toRead, f);
20355+ if (n == 0)
20356+ break;
20357+ if (wc_LockMutex(&globalRNGMutex) != 0) {
20358+ ret = WOLFSSL_FATAL_ERROR;
20359+ break;
20360+ }
20361+ if (wc_RNG_DRBG_Reseed(&globalRNG, buf, (word32)n) != 0) {
20362+ wc_UnLockMutex(&globalRNGMutex);
20363+ WOLFSSL_MSG("RAND_load_file: DRBG reseed failed");
20364+ ret = WOLFSSL_FATAL_ERROR;
20365+ break;
20366+ }
20367+ wc_UnLockMutex(&globalRNGMutex);
20368+ readSoFar += (long)n;
20369+ }
20370+
20371+ cleanup:
20372+ XFCLOSE(f);
20373+ ForceZero(buf, WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20374+ #ifdef WOLFSSL_SMALL_STACK
20375+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
20376+ #elif defined(WOLFSSL_CHECK_MEM_ZERO)
20377+ wc_MemZero_Check(buf, WOLFSSL_RAND_LOAD_FILE_BUF_SZ);
20378+ #endif
20379+
20380+ if (ret < 0)
20381+ return WOLFSSL_FATAL_ERROR;
20382+ return (int)readSoFar;
20383+ #else
20384+ /* Without HAVE_HASHDRBG / filesystem support there is no way to feed
20385+ * external entropy to the wolfCrypt RNG; return success so callers
20386+ * in those configurations are not broken. */
2026820387 (void)fname;
20269- /* wolfCrypt provides enough entropy internally or will report error */
2027020388 if (len == -1)
2027120389 return 1024;
20272- else
20273- return (int)len;
20390+ return (int)len;
20391+ #endif
2027420392}
2027520393
2027620394#endif /* OPENSSL_EXTRA */
0 commit comments