From 1768ecfc4a7181600df254069f02655fe4e5fa0b Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 2 Oct 2020 11:29:24 -0500
Subject: [PATCH] bcrypt: Allow multiple backends to coexist.

Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
 dlls/bcrypt/Makefile.in       |   3 +-
 dlls/bcrypt/bcrypt_internal.h |   3 +
 dlls/bcrypt/gnutls.c          |  32 ++++--
 dlls/bcrypt/unixlib.c         | 208 ++++++++++++++++++++++++++++++++++
 4 files changed, 235 insertions(+), 11 deletions(-)
 create mode 100644 dlls/bcrypt/unixlib.c

diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in
index 63a731fa9d9..6dd3066d4a5 100644
--- a/dlls/bcrypt/Makefile.in
+++ b/dlls/bcrypt/Makefile.in
@@ -8,6 +8,7 @@ C_SRCS = \
 	gnutls.c \
 	md2.c \
 	sha256.c \
-	sha512.c
+	sha512.c \
+	unixlib.c
 
 RC_SRCS = version.rc
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index 61c367cae9d..d0697ed807e 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -219,4 +219,7 @@ struct key_funcs
     NTSTATUS (CDECL *key_import_rsa)( struct key *, UCHAR *, ULONG );
 };
 
+struct key_funcs *gnutls_lib_init(DWORD reason);
+struct key_funcs *macos_lib_init(DWORD reason);
+
 #endif /* __BCRYPT_INTERNAL_H */
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 7b1bceda889..66845ffc8cf 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -373,9 +373,12 @@ fail:
 
 static void gnutls_uninitialize(void)
 {
-    pgnutls_global_deinit();
-    dlclose( libgnutls_handle );
-    libgnutls_handle = NULL;
+    if (libgnutls_handle)
+    {
+        pgnutls_global_deinit();
+        dlclose( libgnutls_handle );
+        libgnutls_handle = NULL;
+    }
 }
 
 struct buffer
@@ -1894,19 +1897,28 @@ static const struct key_funcs key_funcs =
     key_import_rsa
 };
 
-NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+struct key_funcs * gnutls_lib_init( DWORD reason )
 {
     switch (reason)
     {
     case DLL_PROCESS_ATTACH:
-        if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND;
-        *(const struct key_funcs **)ptr_out = &key_funcs;
-        break;
+        if (!gnutls_initialize()) return NULL;
+        return &key_funcs;
     case DLL_PROCESS_DETACH:
         if (libgnutls_handle) gnutls_uninitialize();
-        break;
     }
-    return STATUS_SUCCESS;
+    return NULL;
 }
 
-#endif /* HAVE_GNUTLS_CIPHER_INIT */
+#else /* HAVE_GNUTLS_CIPHER_INIT */
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+
+struct key_funcs * gnutls_lib_init( DWORD reason )
+{
+    return NULL;
+}
+#endif
diff --git a/dlls/bcrypt/unixlib.c b/dlls/bcrypt/unixlib.c
new file mode 100644
index 00000000000..1937a8172a4
--- /dev/null
+++ b/dlls/bcrypt/unixlib.c
@@ -0,0 +1,208 @@
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "ntsecapi.h"
+#include "bcrypt.h"
+
+#include "bcrypt_internal.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#if defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 || defined(HAVE_GNUTLS_CIPHER_INIT)
+WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
+
+static NTSTATUS CDECL key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_symmetric_init( struct key *key )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static void CDECL key_symmetric_vector_reset( struct key *key )
+{
+    FIXME( "not implemented\n" );
+}
+
+static NTSTATUS CDECL key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len  )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static void CDECL key_symmetric_destroy( struct key *key )
+{
+    FIXME( "not implemented\n" );
+}
+
+static NTSTATUS CDECL key_asymmetric_init( struct key *key )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
+                                           ULONG output_len, ULONG *ret_len, ULONG flags )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len,
+                                             UCHAR *signature, ULONG signature_len, DWORD flags )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_export_ecc( struct key *key, UCHAR *output, ULONG len, ULONG *ret_len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *input, ULONG len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_asymmetric_generate( struct key *key )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key *key_copy )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static void CDECL key_asymmetric_destroy( struct key *key )
+{
+    FIXME( "not implemented\n" );
+}
+
+static NTSTATUS CDECL key_asymmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len,
+        UCHAR *output, ULONG output_len, ULONG *ret)
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *input, ULONG input_len )
+{
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static struct key_funcs key_funcs =
+{
+    key_set_property,
+    key_symmetric_init,
+    key_symmetric_vector_reset,
+    key_symmetric_set_auth_data,
+    key_symmetric_encrypt,
+    key_symmetric_decrypt,
+    key_symmetric_get_tag,
+    key_symmetric_destroy,
+    key_asymmetric_init,
+    key_asymmetric_generate,
+    key_asymmetric_decrypt,
+    key_asymmetric_duplicate,
+    key_asymmetric_sign,
+    key_asymmetric_verify,
+    key_asymmetric_destroy,
+    key_export_dsa_capi,
+    key_export_ecc,
+    key_import_dsa_capi,
+    key_import_ecc,
+    key_import_rsa,
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+    struct key_funcs *gnutls_funcs = gnutls_lib_init(reason);
+
+    if (reason == DLL_PROCESS_ATTACH)
+    {
+#define RESOLVE_FUNC(name) \
+        if (gnutls_funcs && gnutls_funcs->key_##name) \
+            key_funcs.key_##name = gnutls_funcs->key_##name;
+
+        RESOLVE_FUNC(set_property)
+        RESOLVE_FUNC(symmetric_init)
+        RESOLVE_FUNC(symmetric_vector_reset)
+        RESOLVE_FUNC(symmetric_set_auth_data)
+        RESOLVE_FUNC(symmetric_encrypt)
+        RESOLVE_FUNC(symmetric_decrypt)
+        RESOLVE_FUNC(symmetric_get_tag)
+        RESOLVE_FUNC(symmetric_destroy)
+        RESOLVE_FUNC(asymmetric_init)
+        RESOLVE_FUNC(asymmetric_generate)
+        RESOLVE_FUNC(asymmetric_decrypt)
+        RESOLVE_FUNC(asymmetric_duplicate)
+        RESOLVE_FUNC(asymmetric_sign)
+        RESOLVE_FUNC(asymmetric_verify)
+        RESOLVE_FUNC(asymmetric_destroy)
+        RESOLVE_FUNC(export_dsa_capi)
+        RESOLVE_FUNC(export_ecc)
+        RESOLVE_FUNC(import_dsa_capi)
+        RESOLVE_FUNC(import_ecc)
+        RESOLVE_FUNC(import_rsa)
+
+#undef RESOLVE_FUNC
+
+        *(struct key_funcs **)ptr_out = &key_funcs;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+#endif
-- 
2.33.0