summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2024-07-04 13:20:49 +0200
committerChristian Brabandt <cb@256bit.org>2024-07-04 13:20:49 +0200
commit9987fe8ca05e5d367fc54eb94a5a583138d2e1f8 (patch)
treefc04e22d216dff11fca50d4e352e65c54d7eeca8
parent898b3740c7f9fa544c82c9ae6927617aad9a6463 (diff)
patch 9.1.0518: initialize the random buffer can be improvedv9.1.0518
Problem: initialize the random buffer can be improved Solution: refactor init_srand() function, move machine-specific parts to os_mswin and os_unix, implement a fallback for Windows 10 and later (LemonBoy) closes: #15125 Signed-off-by: LemonBoy <thatlemon@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/evalfunc.c72
-rw-r--r--src/os_mswin.c34
-rw-r--r--src/os_unix.c28
-rw-r--r--src/proto/os_mswin.pro1
-rw-r--r--src/proto/os_unix.pro1
-rw-r--r--src/version.c2
6 files changed, 91 insertions, 47 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 4fffa50d31..d18d50a284 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -9267,69 +9267,47 @@ f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED)
static void
init_srand(UINT32_T *x)
{
-#ifndef MSWIN
- static int dev_urandom_state = NOTDONE; // FAIL or OK once tried
-#endif
+ struct {
+ union {
+ UINT32_T number;
+ char_u bytes[sizeof(UINT32_T)];
+ } contents;
+ } buf;
if (srand_seed_for_testing_is_used)
{
*x = srand_seed_for_testing;
return;
}
-#ifndef MSWIN
- if (dev_urandom_state != FAIL)
- {
- int fd = open("/dev/urandom", O_RDONLY);
- struct {
- union {
- UINT32_T number;
- char bytes[sizeof(UINT32_T)];
- } contents;
- } buf;
- // Attempt reading /dev/urandom.
- if (fd == -1)
- dev_urandom_state = FAIL;
- else
- {
- buf.contents.number = 0;
- if (read(fd, buf.contents.bytes, sizeof(UINT32_T))
- != sizeof(UINT32_T))
- dev_urandom_state = FAIL;
- else
- {
- dev_urandom_state = OK;
- *x = buf.contents.number;
- }
- close(fd);
- }
- }
- if (dev_urandom_state != OK)
-#endif
+ if (mch_get_random(buf.contents.bytes, sizeof(buf.contents.bytes)) == OK)
{
- // Reading /dev/urandom doesn't work, fall back to:
- // - randombytes_random()
- // - reltime() or time()
- // - XOR with process ID
+ *x = buf.contents.number;
+ return;
+ }
+
+ // The system's random number generator doesn't work, fall back to:
+ // - randombytes_random()
+ // - reltime() or time()
+ // - XOR with process ID
#if defined(FEAT_SODIUM)
- if (crypt_sodium_init() >= 0)
- *x = crypt_sodium_randombytes_random();
- else
+ if (crypt_sodium_init() >= 0)
+ *x = crypt_sodium_randombytes_random();
+ else
#endif
- {
+ {
#if defined(FEAT_RELTIME)
- proftime_T res;
- profile_start(&res);
+ proftime_T res;
+ profile_start(&res);
# if defined(MSWIN)
- *x = (UINT32_T)res.LowPart;
+ *x = (UINT32_T)res.LowPart;
# else
- *x = (UINT32_T)res.tv_fsec;
+ *x = (UINT32_T)res.tv_fsec;
# endif
#else
- *x = vim_time();
+ *x = vim_time();
#endif
- *x ^= mch_get_pid();
- }
+ *x ^= mch_get_pid();
}
}
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 9d0e1a08a4..df760fd5ec 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -830,6 +830,40 @@ mch_icon_load(HANDLE *iconp)
0, mch_icon_load_cb, iconp);
}
+/*
+ * Fill the buffer 'buf' with 'len' random bytes.
+ * Returns FAIL if the OS PRNG is not available or something went wrong.
+ */
+ int
+mch_get_random(char_u *buf, int len)
+{
+ static int initialized = NOTDONE;
+ static HINSTANCE hInstLib;
+ static BOOL (WINAPI *pProcessPrng)(PUCHAR, ULONG);
+
+ if (initialized == NOTDONE)
+ {
+ hInstLib = vimLoadLib("bcryptprimitives.dll");
+ if (hInstLib != NULL)
+ pProcessPrng = (void *)GetProcAddress(hInstLib, "ProcessPrng");
+ if (hInstLib == NULL || pProcessPrng == NULL)
+ {
+ FreeLibrary(hInstLib);
+ initialized = FAIL;
+ }
+ else
+ initialized = OK;
+ }
+
+ if (initialized == FAIL)
+ return FAIL;
+
+ // According to the documentation this call cannot fail.
+ pProcessPrng(buf, len);
+
+ return OK;
+}
+
int
mch_libcall(
char_u *libname,
diff --git a/src/os_unix.c b/src/os_unix.c
index d15514268f..b7da55205d 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -7722,6 +7722,34 @@ sig_sysmouse SIGDEFARG(sigarg)
}
#endif // FEAT_SYSMOUSE
+/*
+ * Fill the buffer 'buf' with 'len' random bytes.
+ * Returns FAIL if the OS PRNG is not available or something went wrong.
+ */
+ int
+mch_get_random(char_u *buf, int len)
+{
+ static int dev_urandom_state = NOTDONE;
+
+ if (dev_urandom_state == FAIL)
+ return FAIL;
+
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ // Attempt reading /dev/urandom.
+ if (fd == -1)
+ dev_urandom_state = FAIL;
+ else if (read(fd, buf, len) == len)
+ dev_urandom_state = OK;
+ else
+ {
+ dev_urandom_state = FAIL;
+ close(fd);
+ }
+
+ return dev_urandom_state;
+}
+
#if defined(FEAT_LIBCALL) || defined(PROTO)
typedef char_u * (*STRPROCSTR)(char_u *);
typedef char_u * (*INTPROCSTR)(int);
diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro
index 383dcbad1e..cde9ceaeed 100644
--- a/src/proto/os_mswin.pro
+++ b/src/proto/os_mswin.pro
@@ -23,6 +23,7 @@ int mch_has_wildcard(char_u *p);
int mch_chdir(char *path);
int mch_icon_load(HANDLE *iconp);
int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result);
+int mch_get_random(char_u *buf, int len);
void DumpPutS(const char *psz);
int mch_get_winpos(int *x, int *y);
void mch_set_winpos(int x, int y);
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
index 6e13de6caa..d9dc8d9d54 100644
--- a/src/proto/os_unix.pro
+++ b/src/proto/os_unix.pro
@@ -76,6 +76,7 @@ int mch_rename(const char *src, const char *dest);
int gpm_available(void);
int gpm_enabled(void);
int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result);
+int mch_get_random(char_u *buf, int len);
void setup_term_clip(void);
void start_xterm_trace(int button);
void stop_xterm_trace(void);
diff --git a/src/version.c b/src/version.c
index c33303ab43..2391e5ba9e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 518,
+/**/
517,
/**/
516,