bcrypt: Add support for BCRYPT_RNG_ALGORITHM.

Hans Leidekker hans at codeweavers.com
Mon Apr 4 04:07:05 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/bcrypt/bcrypt_main.c  | 86 +++++++++++++++++++++++++++-------------------
 dlls/bcrypt/tests/bcrypt.c | 29 ++++++++++++++++
 include/bcrypt.h           |  1 +
 3 files changed, 80 insertions(+), 36 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 43d4688..6023c94 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -136,42 +136,6 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULONG count, ULONG 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;
-}
-
 #define MAGIC_ALG  (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
 struct object
@@ -182,6 +146,7 @@ struct object
 enum alg_id
 {
     ALG_ID_MD5,
+    ALG_ID_RNG,
     ALG_ID_SHA1,
     ALG_ID_SHA256,
     ALG_ID_SHA384,
@@ -193,6 +158,7 @@ static const struct {
     const WCHAR *alg_name;
 } alg_props[] = {
     /* ALG_ID_MD5    */ { 16, BCRYPT_MD5_ALGORITHM },
+    /* ALG_ID_RNG    */ {  0, BCRYPT_RNG_ALGORITHM },
     /* ALG_ID_SHA1   */ { 20, BCRYPT_SHA1_ALGORITHM },
     /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
     /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
@@ -206,6 +172,47 @@ struct algorithm
     BOOL hmac;
 };
 
+NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
+{
+    const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
+    struct algorithm *algorithm = handle;
+
+    TRACE("%p, %p, %u, %08x - semi-stub\n", handle, 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;
+    }
+    else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_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 (algorithm || (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;
+}
+
 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
 {
     struct algorithm *alg;
@@ -224,6 +231,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
 
     if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
     else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
+    else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG;
     else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
     else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
     else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
@@ -628,6 +636,12 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf,
         }
         FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
         return STATUS_NOT_IMPLEMENTED;
+
+    case ALG_ID_RNG:
+        if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED;
+        FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) );
+        return STATUS_NOT_IMPLEMENTED;
+
     case ALG_ID_SHA1:
         if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
         {
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index e2318c4..9bd2cea 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -694,6 +694,34 @@ static void test_BcryptHash(void)
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
 }
 
+static void test_rng(void)
+{
+    BCRYPT_ALG_HANDLE alg;
+    ULONG size, len;
+    UCHAR buf[16];
+    NTSTATUS ret;
+
+    alg = NULL;
+    ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+    ok(alg != NULL, "alg not set\n");
+
+    len = size = 0xdeadbeef;
+    ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
+    ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
+
+    test_alg_name(alg, "RNG");
+
+    memset(buf, 0, 16);
+    ret = BCryptGenRandom(alg, buf, 8, 0);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+    ok(memcmp(buf, buf + 8, 8), "got zeroes\n");
+
+    ret = BCryptCloseAlgorithmProvider(alg, 0);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+}
+
+
 START_TEST(bcrypt)
 {
     HMODULE module;
@@ -707,6 +735,7 @@ START_TEST(bcrypt)
     test_sha384();
     test_sha512();
     test_md5();
+    test_rng();
 
     pBCryptHash = (void *)GetProcAddress( module, "BCryptHash" );
 
diff --git a/include/bcrypt.h b/include/bcrypt.h
index 93f4326..c521bcc 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -64,6 +64,7 @@ typedef LONG NTSTATUS;
     {'M','i','c','r','o','s','o','f','t',' ','P','l','a','t','f','o','r','m',' ','C','r','y','p','t','o',' ','P','r','o','v','i','d','e','r',0}
 
 #define BCRYPT_MD5_ALGORITHM        (const WCHAR []){'M','D','5',0}
+#define BCRYPT_RNG_ALGORITHM        (const WCHAR []){'R','N','G',0}
 #define BCRYPT_SHA1_ALGORITHM       (const WCHAR []){'S','H','A','1',0}
 #define BCRYPT_SHA256_ALGORITHM     (const WCHAR []){'S','H','A','2','5','6',0}
 #define BCRYPT_SHA384_ALGORITHM     (const WCHAR []){'S','H','A','3','8','4',0}
-- 
2.1.4




More information about the wine-patches mailing list