bcrypt: Add semi-stub implementation of BCryptGenRandom (try 2)

Bruno Jesus 00cpxxx at gmail.com
Sun Feb 9 19:36:36 CST 2014


try 2:
Better error handling, more tests, comments.

If advapi is not a good approach please point me another as it was the
only way I found to generate random numbers, thanks =)
-------------- next part --------------
diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in
index f9aacec..6f39a49 100644
--- a/dlls/bcrypt/Makefile.in
+++ b/dlls/bcrypt/Makefile.in
@@ -1,4 +1,5 @@
 MODULE    = bcrypt.dll
+IMPORTLIB = advapi32
 
 C_SRCS = \
 	bcrypt_main.c
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 02d0a7d..22da0dd 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -25,6 +25,7 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
+#include "ntsecapi.h"
 #include "bcrypt.h"
 #include "wine/debug.h"
 
@@ -57,7 +58,36 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
 
 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULONG count, ULONG flags)
 {
-    FIXME("%p, %p, %u, %08x - stub\n", algorithm, buffer, count, flags);
+    const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
+    TRACE("%p, %p, %u, %08x - semi-stub\n", algorithm, buffer, count, flags);
 
+    if (!algorithm)
+    {
+        /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
+         * is set. In this case the preferred system RNG is used.
+         */
+        if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
+            return STATUS_INVALID_HANDLE;
+    }
+    if (!buffer)
+        return STATUS_INVALID_PARAMETER;
+
+    if (flags & ~supported_flags)
+        FIXME("unsupported flags %08x\n", flags & ~supported_flags);
+
+    if (algorithm)
+        FIXME("ignoring selected algorithm\n");
+
+    /* When zero bytes are requested the function returns success too. */
+    if (!count)
+        return STATUS_SUCCESS;
+
+    if (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)
+    {
+        if (RtlGenRandom(buffer, count))
+            return STATUS_SUCCESS;
+    }
+
+    FIXME("called with unsupported parameters, returning error\n");
     return STATUS_NOT_IMPLEMENTED;
 }
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 1d18634..41208ed 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -46,6 +46,7 @@ static void test_BCryptGenRandom(void)
 {
     NTSTATUS ret;
     UCHAR buffer[256];
+    DWORD *rnd = (DWORD*) buffer;
 
     if (!pBCryptGenRandom)
     {
@@ -53,7 +54,6 @@ static void test_BCryptGenRandom(void)
         return;
     }
 
-    todo_wine {
     ret = pBCryptGenRandom(NULL, NULL, 0, 0);
     ok(ret == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got 0x%x\n", ret);
     ret = pBCryptGenRandom(NULL, buffer, 0, 0);
@@ -62,9 +62,23 @@ static void test_BCryptGenRandom(void)
     ok(ret == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got 0x%x\n", ret);
     ret = pBCryptGenRandom(NULL, buffer, sizeof(buffer), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
     ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
+    ret = pBCryptGenRandom(NULL, buffer, sizeof(buffer),
+          BCRYPT_USE_SYSTEM_PREFERRED_RNG|BCRYPT_RNG_USE_ENTROPY_IN_BUFFER);
+    ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
     ret = pBCryptGenRandom(NULL, NULL, sizeof(buffer), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
     ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got 0x%x\n", ret);
-    }
+
+    /* Zero sized buffer should work too */
+    ret = pBCryptGenRandom(NULL, buffer, 0, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+    ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
+
+    /* Test random number generation - It's impossible for a sane RNG to return 8 zeros */
+    rnd[0] = 0;
+    rnd[1] = 0;
+    ret = pBCryptGenRandom(NULL, buffer, sizeof(DWORD) * 2, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+    ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
+    ok(rnd[0] || rnd[1], "Expected a random number, got 0\n");
+    trace("BCryptGenRandom : %08X%08X\n", rnd[0], rnd[1]);
 }
 
 START_TEST(bcrypt)


More information about the wine-patches mailing list