[RFC PATCH] advapi32: Use Windows APIs to read /dev/urandom.
Hans Leidekker
hans at codeweavers.com
Fri Sep 4 06:15:46 CDT 2020
This will cause a performance regression. SystemFunction036 (RtlGenRandom)
is already an order of magnitude slower than native because it opens and closes
/dev/urandom on every call. Going through wineserver makes it 2 orders of
magnitude slower:
int buf[4], i;
for (i = 0; i < 100000; i++) RtlGenRandom(buf, sizeof(buf));
Windows: 16 ticks
Wine/open(): 209 ticks
Wine/NtCreateFile(): 3612 ticks
Wine/NtCreateFile()/cached: 96 ticks
We could cache the file handle to mitigate that, but then there's the risk that
an application accidentally closes the handle.
Ideally we'd implement this with getrandom() on Linux. We probably don't want
to split advapi32 just for this, so maybe a private ntdll export is justified
here?
---
dlls/advapi32/crypt.c | 40 +++++++++++++++++++++++++---------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c
index 7199795b475..53e911820b0 100644
--- a/dlls/advapi32/crypt.c
+++ b/dlls/advapi32/crypt.c
@@ -2436,26 +2436,36 @@ BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
* Failure: FALSE
*/
-BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
+BOOLEAN WINAPI SystemFunction036(void *buffer, ULONG len)
{
- int dev_random;
-
- dev_random = open("/dev/urandom", O_RDONLY);
- if (dev_random != -1)
+ static const WCHAR urandomW[] =
+ {'\\','?','?','\\','u','n','i','x','\\','/','d','e','v','/','u','r','a','n','d','o','m',0};
+ UNICODE_STRING filename;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ HANDLE handle;
+
+ RtlInitUnicodeString(&filename, urandomW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = 0;
+ attr.ObjectName = &filename;
+ attr.SecurityDescriptor = NULL;
+ if (NtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ, FILE_OPEN, 0, NULL, 0))
{
- if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
- {
- close(dev_random);
- return TRUE;
- }
- close(dev_random);
- }
- else
FIXME("couldn't open /dev/urandom\n");
+ SetLastError(NTE_FAIL);
+ return FALSE;
+ }
+
+ if (!NtReadFile(handle, 0, NULL, NULL, &io, buffer, len, NULL, NULL) && io.Information == len)
+ return TRUE;
+
SetLastError(NTE_FAIL);
return FALSE;
-}
-
+}
+
/*
These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
in crypt32.dll.
--
2.20.1
More information about the wine-devel
mailing list