[PATCH 2/2] advapi32: Reimplement SystemFunction036 using system interrupt information.
Hans Leidekker
hans at codeweavers.com
Mon Sep 7 07:10:13 CDT 2020
Here's another proposal based on the discussion. If we implement system interrupt
information with random values taken from the urandom source (patch 1/2), we can
reimplement SystemFunction036 on top of that and get the same level of randomness.
Adding a cache makes this as fast as Windows on my machine, in the getrandom() case.
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/advapi32/crypt.c | 62 +++++++++++++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 14 deletions(-)
diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c
index 7199795b475..ab06c14393b 100644
--- a/dlls/advapi32/crypt.c
+++ b/dlls/advapi32/crypt.c
@@ -2422,6 +2422,36 @@ BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
return TRUE;
}
+static CRITICAL_SECTION random_cs;
+static CRITICAL_SECTION_DEBUG random_debug =
+{
+ 0, 0, &random_cs,
+ { &random_debug.ProcessLocksList, &random_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": random_cs") }
+};
+static CRITICAL_SECTION random_cs = { &random_debug, -1, 0, 0, 0, 0 };
+
+#define MAX_CPUS 128
+static char random_buf[sizeof(SYSTEM_INTERRUPT_INFORMATION) * MAX_CPUS];
+static ULONG random_len;
+static ULONG random_pos;
+
+/* FIXME: assumes interrupt information provides sufficient randomness */
+static BOOL fill_random_buffer(void)
+{
+ ULONG len = sizeof(SYSTEM_INTERRUPT_INFORMATION) * min( NtCurrentTeb()->Peb->NumberOfProcessors, MAX_CPUS );
+ NTSTATUS status;
+
+ if ((status = NtQuerySystemInformation( SystemInterruptInformation, random_buf, len, NULL )))
+ {
+ WARN( "failed to get random bytes %08x\n", status );
+ return FALSE;
+ }
+ random_len = len;
+ random_pos = 0;
+ return TRUE;
+}
+
/******************************************************************************
* SystemFunction036 (ADVAPI32.@)
*
@@ -2436,26 +2466,30 @@ BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
* Failure: FALSE
*/
-BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
+BOOLEAN WINAPI SystemFunction036( void *buffer, ULONG len )
{
- int dev_random;
+ char *ptr = buffer;
- dev_random = open("/dev/urandom", O_RDONLY);
- if (dev_random != -1)
+ EnterCriticalSection( &random_cs );
+ while (len)
{
- if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
+ ULONG size;
+ if (random_pos >= random_len && !fill_random_buffer())
{
- close(dev_random);
- return TRUE;
+ SetLastError( NTE_FAIL );
+ LeaveCriticalSection( &random_cs );
+ return FALSE;
}
- close(dev_random);
+ size = min( len, random_len - random_pos );
+ memcpy( ptr, random_buf + random_pos, size );
+ random_pos += size;
+ ptr += size;
+ len -= size;
}
- else
- FIXME("couldn't open /dev/urandom\n");
- SetLastError(NTE_FAIL);
- return FALSE;
-}
-
+ LeaveCriticalSection( &random_cs );
+ return TRUE;
+}
+
/*
These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
in crypt32.dll.
--
2.20.1
More information about the wine-devel
mailing list