From 194669052e1bce63659f1fbb0880da3dcb03058e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 3 Oct 2020 18:48:06 +1000 Subject: [PATCH] Updated bcrypt-ECDHSecretAgreement patchset --- ...t-Allow-multiple-backends-to-coexist.patch | 339 ++++++++++++++++ ...BCryptSecretAgreement-with-libgcryp.patch} | 363 ++++++++++-------- ...03-bcrypt-Implement-BCRYPT_KDF_HASH.patch} | 32 +- patches/bcrypt-ECDHSecretAgreement/definition | 2 +- patches/patchinstall.sh | 20 + 5 files changed, 586 insertions(+), 170 deletions(-) create mode 100644 patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Allow-multiple-backends-to-coexist.patch rename patches/bcrypt-ECDHSecretAgreement/{0001-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch => 0002-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch} (63%) rename patches/bcrypt-ECDHSecretAgreement/{0002-bcrypt-Implement-BCRYPT_KDF_HASH.patch => 0003-bcrypt-Implement-BCRYPT_KDF_HASH.patch} (82%) diff --git a/patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Allow-multiple-backends-to-coexist.patch b/patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Allow-multiple-backends-to-coexist.patch new file mode 100644 index 00000000..cafbd7bc --- /dev/null +++ b/patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Allow-multiple-backends-to-coexist.patch @@ -0,0 +1,339 @@ +From 104e3d8f36af9bc2179f7878b4f99b7417f59376 Mon Sep 17 00:00:00 2001 +From: Derek Lesho +Date: Fri, 2 Oct 2020 11:29:24 -0500 +Subject: [PATCH] bcrypt: Allow multiple backends to coexist. + +Signed-off-by: Derek Lesho +--- + dlls/bcrypt/Makefile.in | 3 +- + dlls/bcrypt/bcrypt_internal.h | 3 + + dlls/bcrypt/gnutls.c | 34 +++++-- + dlls/bcrypt/macos.c | 20 +++- + dlls/bcrypt/unixlib.c | 186 ++++++++++++++++++++++++++++++++++ + 5 files changed, 229 insertions(+), 17 deletions(-) + create mode 100644 dlls/bcrypt/unixlib.c + +diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in +index 24803fb2d7c..46a20d473dd 100644 +--- a/dlls/bcrypt/Makefile.in ++++ b/dlls/bcrypt/Makefile.in +@@ -11,6 +11,7 @@ C_SRCS = \ + macos.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 5edc9e6c9c6..29db7210b59 100644 +--- a/dlls/bcrypt/bcrypt_internal.h ++++ b/dlls/bcrypt/bcrypt_internal.h +@@ -210,4 +210,7 @@ struct key_funcs + NTSTATUS (CDECL *key_import_ecc)( 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 21520bb4a84..b761c732acf 100644 +--- a/dlls/bcrypt/gnutls.c ++++ b/dlls/bcrypt/gnutls.c +@@ -332,9 +332,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 +@@ -1568,7 +1571,7 @@ static void CDECL key_asymmetric_destroy( struct key *key ) + if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey ); + } + +-static const struct key_funcs key_funcs = ++static struct key_funcs key_funcs = + { + key_set_property, + key_symmetric_init, +@@ -1589,19 +1592,28 @@ static const struct key_funcs key_funcs = + key_import_ecc + }; + +-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: + 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/macos.c b/dlls/bcrypt/macos.c +index 37615e97689..5868b445625 100644 +--- a/dlls/bcrypt/macos.c ++++ b/dlls/bcrypt/macos.c +@@ -259,7 +259,7 @@ static void CDECL key_asymmetric_destroy( struct key *key ) + { + } + +-static const struct key_funcs key_funcs = ++static struct key_funcs key_funcs = + { + key_set_property, + key_symmetric_init, +@@ -280,11 +280,21 @@ static const struct key_funcs key_funcs = + key_import_ecc + }; + +-NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) ++struct key_funcs * macos_lib_init( DWORD reason ) + { +- if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; +- *(const struct key_funcs **)ptr_out = &key_funcs; +- return STATUS_SUCCESS; ++ if (reason != DLL_PROCESS_ATTACH) return NULL; ++ return &key_funcs; + } + ++#else ++#include "ntstatus.h" ++#define WIN32_NO_STATUS ++#include "windef.h" ++#include "winbase.h" ++#include "winternl.h" ++ ++struct key_funcs * macos_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..791b5d54188 +--- /dev/null ++++ b/dlls/bcrypt/unixlib.c +@@ -0,0 +1,186 @@ ++#if 0 ++#pragma makedep unix ++#endif ++ ++#include "config.h" ++#include "wine/port.h" ++ ++#include ++ ++#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 void CDECL key_asymmetric_destroy( struct key *key ) ++{ ++ FIXME( "not implemented\n" ); ++} ++ ++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_sign, ++ key_asymmetric_verify, ++ key_asymmetric_destroy, ++ key_export_dsa_capi, ++ key_export_ecc, ++ key_import_dsa_capi, ++ key_import_ecc ++}; ++ ++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); ++ struct key_funcs *macos_funcs = macos_lib_init(reason); ++ ++ if (reason == DLL_PROCESS_ATTACH) ++ { ++#define RESOLVE_FUNC(name) \ ++ if (macos_funcs && macos_funcs->key_##name) \ ++ key_funcs.key_##name = macos_funcs->key_##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_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) ++ ++#undef RESOLVE_FUNC ++ ++ *(struct key_funcs **)ptr_out = &key_funcs; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++#endif +-- +2.28.0 + diff --git a/patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch b/patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch similarity index 63% rename from patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch rename to patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch index b5516951..038d60a9 100644 --- a/patches/bcrypt-ECDHSecretAgreement/0001-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch +++ b/patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch @@ -1,26 +1,27 @@ -From 7fcdf1faa257c90d6452f26ad3a68daca1dd96d1 Mon Sep 17 00:00:00 2001 +From d98bbb02ed35d835cf24f6bd470a10bb499feb2f Mon Sep 17 00:00:00 2001 From: Derek Lesho -Date: Tue, 7 Jan 2020 14:22:49 -0600 +Date: Fri, 2 Oct 2020 12:11:49 -0500 Subject: [PATCH] bcrypt: Implement BCryptSecretAgreement with libgcrypt. Signed-off-by: Derek Lesho --- configure.ac | 14 ++ dlls/bcrypt/Makefile.in | 1 + - dlls/bcrypt/bcrypt_internal.h | 6 + - dlls/bcrypt/bcrypt_main.c | 54 ++++++- - dlls/bcrypt/gcrypt.c | 263 ++++++++++++++++++++++++++++++++++ - dlls/bcrypt/gnutls.c | 9 ++ - dlls/bcrypt/macos.c | 6 + + dlls/bcrypt/bcrypt_internal.h | 4 + + dlls/bcrypt/bcrypt_main.c | 55 ++++++- + dlls/bcrypt/gcrypt.c | 288 ++++++++++++++++++++++++++++++++++ + dlls/bcrypt/gnutls.c | 3 +- + dlls/bcrypt/macos.c | 3 +- dlls/bcrypt/tests/bcrypt.c | 2 +- - 8 files changed, 349 insertions(+), 6 deletions(-) + dlls/bcrypt/unixlib.c | 15 +- + 9 files changed, 375 insertions(+), 10 deletions(-) create mode 100644 dlls/bcrypt/gcrypt.c diff --git a/configure.ac b/configure.ac -index 006087e05ec..b50737a766e 100644 +index 865aa924d07..35233aa5d08 100644 --- a/configure.ac +++ b/configure.ac -@@ -47,6 +47,7 @@ AC_ARG_WITH(faudio, AS_HELP_STRING([--without-faudio],[do not use FAudio (XAu +@@ -45,6 +45,7 @@ AC_ARG_WITH(faudio, AS_HELP_STRING([--without-faudio],[do not use FAudio (XAu AC_ARG_WITH(float-abi, AS_HELP_STRING([--with-float-abi=abi],[specify the ABI (soft|softfp|hard) for ARM platforms])) AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig])) AC_ARG_WITH(freetype, AS_HELP_STRING([--without-freetype],[do not use the FreeType library])) @@ -28,7 +29,7 @@ index 006087e05ec..b50737a766e 100644 AC_ARG_WITH(gettext, AS_HELP_STRING([--without-gettext],[do not use gettext])) AC_ARG_WITH(gettextpo, AS_HELP_STRING([--with-gettextpo],[use the GetTextPO library to rebuild po files]), [if test "x$withval" = "xno"; then ac_cv_header_gettext_po_h=no; fi]) -@@ -2044,6 +2045,19 @@ WINE_NOTICE_WITH(vkd3d,[test "x$ac_cv_lib_soname_vkd3d" = "x"], +@@ -2000,6 +2001,19 @@ WINE_NOTICE_WITH(vkd3d,[test "x$ac_cv_lib_soname_vkd3d" = "x"], [vkd3d ${notice_platform}development files not found (or too old), Direct3D 12 won't be supported.]) test "x$ac_cv_lib_soname_vkd3d" != "x" || enable_d3d12=${enable_d3d12:-no} @@ -49,10 +50,10 @@ index 006087e05ec..b50737a766e 100644 AC_SUBST(EXTRACFLAGS,"") diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in -index dd6d4a76640..ea3486a4002 100644 +index 46a20d473dd..4a3016784af 100644 --- a/dlls/bcrypt/Makefile.in +++ b/dlls/bcrypt/Makefile.in -@@ -5,6 +5,7 @@ EXTRAINCL = $(GNUTLS_CFLAGS) +@@ -7,6 +7,7 @@ EXTRADLLFLAGS = -mno-cygwin C_SRCS = \ bcrypt_main.c \ @@ -61,20 +62,10 @@ index dd6d4a76640..ea3486a4002 100644 macos.c \ md2.c \ diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h -index 43be170d77f..6c93ed78389 100644 +index 29db7210b59..2fab462d40e 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h -@@ -25,6 +25,9 @@ - #include - #include - #include -+#ifdef SONAME_LIBGCRYPT -+#include -+#endif - #elif HAVE_COMMONCRYPTO_COMMONCRYPTOR_H - #include - #include -@@ -243,6 +246,8 @@ struct key +@@ -187,6 +187,8 @@ struct key struct secret { struct object hdr; @@ -82,35 +73,29 @@ index 43be170d77f..6c93ed78389 100644 + ULONG len; }; - NTSTATUS get_alg_property( const struct algorithm *, const WCHAR *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN; -@@ -264,6 +269,7 @@ NTSTATUS key_export_dsa_capi( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_H - NTSTATUS key_export_ecc( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN; - NTSTATUS key_import_dsa_capi( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN; - NTSTATUS key_import_ecc( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN; -+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret) DECLSPEC_HIDDEN; + struct key_funcs +@@ -208,9 +210,11 @@ struct key_funcs + NTSTATUS (CDECL *key_export_ecc)( struct key *, UCHAR *, ULONG, ULONG * ); + NTSTATUS (CDECL *key_import_dsa_capi)( struct key *, UCHAR *, ULONG ); + NTSTATUS (CDECL *key_import_ecc)( struct key *, UCHAR *, ULONG ); ++ NTSTATUS (CDECL *key_compute_secret_ecc)( unsigned char *privkey_in, struct key *pubkey_in, struct secret *secret ); + }; - BOOL is_zero_vector( const UCHAR *, ULONG ) DECLSPEC_HIDDEN; - BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDDEN; + struct key_funcs *gnutls_lib_init(DWORD reason); + struct key_funcs *macos_lib_init(DWORD reason); ++struct key_funcs *gcrypt_lib_init(DWORD reason); + + #endif /* __BCRYPT_INTERNAL_H */ diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index cd3b746e295..7b2a3393902 100644 +index 16c68ed6911..8dae41a2e2e 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -1425,6 +1425,12 @@ NTSTATUS key_import_ecc( struct key *key, UCHAR *input, ULONG len ) - ERR( "support for keys not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; - } -+ -+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret) -+{ -+ ERR( "support for secrets not available at build time\n" ); -+ return STATUS_NOT_IMPLEMENTED; -+} - #endif - - NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, -@@ -1842,8 +1848,9 @@ NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_H +@@ -1776,9 +1776,12 @@ NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_H + { struct key *privkey = privatekey; struct key *pubkey = publickey; ++ UCHAR *privkey_blob = NULL; ++ ULONG privkey_len; struct secret *secret; + NTSTATUS status; @@ -119,25 +104,36 @@ index cd3b746e295..7b2a3393902 100644 if (!privkey || privkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; if (!pubkey || pubkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; -@@ -1852,7 +1859,16 @@ NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_H +@@ -1787,18 +1790,39 @@ NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_H if (!(secret = heap_alloc_zero( sizeof(*secret) ))) return STATUS_NO_MEMORY; secret->hdr.magic = MAGIC_SECRET; -- *handle = secret; -+ if ((status = compute_secret_ecc( privkey, pubkey, secret ))) ++ if ((status = key_funcs->key_export_ecc( privkey, NULL, 0, &privkey_len))) ++ goto done; ++ ++ privkey_blob = heap_alloc(privkey_len); ++ if ((status = key_funcs->key_export_ecc( privkey, privkey_blob, privkey_len, &privkey_len))) ++ goto done; ++ ++ if ((status = key_funcs->key_compute_secret_ecc( privkey_blob, pubkey, secret ))) ++ goto done; ++ ++done: ++ if (privkey_blob) ++ heap_free(privkey_blob); ++ ++ if (status) + { -+ heap_free( secret ); -+ *handle = NULL; -+ } -+ else -+ { -+ *handle = secret; ++ heap_free(secret); ++ secret = NULL; + } + - return STATUS_SUCCESS; + *handle = secret; +- return STATUS_SUCCESS; ++ return status; } -@@ -1860,10 +1876,11 @@ NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle) + NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle) { struct secret *secret = handle; @@ -150,7 +146,7 @@ index cd3b746e295..7b2a3393902 100644 heap_free( secret ); return STATUS_SUCCESS; } -@@ -1873,12 +1890,33 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt +@@ -1808,12 +1832,33 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt { struct secret *secret = handle; @@ -161,7 +157,7 @@ index cd3b746e295..7b2a3393902 100644 if (!kdf) return STATUS_INVALID_PARAMETER; - return STATUS_INTERNAL_ERROR; -+ if (!(strcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) ++ if (!(lstrcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) + { + ULONG n; + ULONG secret_length = secret->len; @@ -186,49 +182,29 @@ index cd3b746e295..7b2a3393902 100644 } BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) -@@ -1890,6 +1928,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) - DisableThreadLibraryCalls( hinst ); - #ifdef HAVE_GNUTLS_CIPHER_INIT - gnutls_initialize(); -+#ifdef SONAME_LIBGCRYPT -+ gcrypt_initialize(); -+#endif - #endif - break; - -@@ -1897,6 +1938,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) - if (reserved) break; - #ifdef HAVE_GNUTLS_CIPHER_INIT - gnutls_uninitialize(); -+#ifdef SONAME_LIBGCRYPT -+ gcrypt_uninitialize(); -+#endif - #endif - break; - } diff --git a/dlls/bcrypt/gcrypt.c b/dlls/bcrypt/gcrypt.c new file mode 100644 -index 00000000000..4e0386a3dda +index 00000000000..d0049b6cf69 --- /dev/null +++ b/dlls/bcrypt/gcrypt.c -@@ -0,0 +1,263 @@ +@@ -0,0 +1,288 @@ ++#if 0 ++#pragma makedep unix ++#endif ++ +#include "config.h" +#include "wine/port.h" + ++#ifdef HAVE_GCRYPT_H ++ +#include -+#ifdef HAVE_GNUTLS_CIPHER_INIT -+#include -+#include -+#include -+#ifdef HAVE_LIBGCRYPT -+#include -+#endif -+#endif ++#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" ++#include "winternl.h" +#include "bcrypt.h" + +#include "bcrypt_internal.h" @@ -237,7 +213,6 @@ index 00000000000..4e0386a3dda +#include "wine/heap.h" +#include "wine/unicode.h" + -+#if defined(HAVE_GNUTLS_CIPHER_INIT) && defined(SONAME_LIBGCRYPT) +WINE_DEFAULT_DEBUG_CHANNEL(bcrypt); +WINE_DECLARE_DEBUG_CHANNEL(winediag); + @@ -293,13 +268,16 @@ index 00000000000..4e0386a3dda +} + + -+void gcrypt_uninitialize(void) ++static void gcrypt_uninitialize(void) +{ -+ dlclose( libgcrypt_handle); -+ libgcrypt_handle = NULL; ++ if (libgcrypt_handle) ++ { ++ dlclose( libgcrypt_handle); ++ libgcrypt_handle = NULL; ++ } +} + -+NTSTATUS extract_result_into_secret(gcry_sexp_t result, struct secret *secret) ++static NTSTATUS extract_result_into_secret(gcry_sexp_t result, struct secret *secret) +{ + NTSTATUS status = STATUS_SUCCESS; + gcry_mpi_t fullcoords = NULL; @@ -329,7 +307,7 @@ index 00000000000..4e0386a3dda + goto done; + } + -+ tmp_buffer = heap_alloc(size); ++ tmp_buffer = malloc(size); + if ((err = pgcry_mpi_print(GCRYMPI_FMT_STD, tmp_buffer, size, NULL, fullcoords))) + { + ERR("Error = %s/%s.\n", pgcry_strsource(err), pgcry_strerror(err)); @@ -337,12 +315,12 @@ index 00000000000..4e0386a3dda + goto done; + } + -+ secret->data = heap_alloc(size / 2); ++ secret->data = RtlAllocateHeap(GetProcessHeap(), 0, size / 2); + memcpy(secret->data, tmp_buffer + size % 2, size / 2); + secret->len = size / 2; + +done: -+ heap_free(tmp_buffer); ++ free(tmp_buffer); + + pgcry_mpi_release(fullcoords); + pgcry_sexp_release(fragment); @@ -352,7 +330,7 @@ index 00000000000..4e0386a3dda + +/* this is necessary since GNUTLS doesn't support ECDH public key encryption, maybe we can replace this when it does: + https://github.com/gnutls/gnutls/blob/cdc4fc288d87f91f974aa23b6e8595a53970ce00/lib/nettle/pk.c#L495 */ -+NTSTATUS compute_secret_ecc (struct key *privkey_in, struct key *pubkey_in, struct secret *secret) ++static NTSTATUS CDECL key_compute_secret_ecc(unsigned char *privkey_in, struct key *pubkey_in, struct secret *secret) +{ + const char *pubkey_format; + DWORD key_size; @@ -382,7 +360,7 @@ index 00000000000..4e0386a3dda + /* import public key - + copy public key into temporary buffer so we can prepend 0x04 (to indicate it is uncompressed) */ + { -+ UCHAR *public_key_raw = heap_alloc((key_size * 2) + 1); ++ UCHAR *public_key_raw = malloc((key_size * 2) + 1); + public_key_raw[0] = 0x04; + memcpy(public_key_raw + 1, pubkey_in->u.a.pubkey + sizeof(BCRYPT_ECCKEY_BLOB), key_size * 2); + @@ -392,7 +370,7 @@ index 00000000000..4e0386a3dda + (key_size * 2) + 1, + public_key_raw); + -+ heap_free(public_key_raw); ++ free(public_key_raw); + } + + if (err) @@ -403,34 +381,10 @@ index 00000000000..4e0386a3dda + + /* import private key */ + /* extract private key from blob structure */ -+ { -+ UCHAR *private_key_raw = heap_alloc(key_size); -+ UCHAR *key_blob; -+ ULONG blob_size; -+ -+ status = key_export_ecc( privkey_in, NULL, 0, &blob_size ); -+ if (status) -+ goto done; -+ -+ key_blob = heap_alloc(blob_size); -+ status = key_export_ecc( privkey_in, key_blob, blob_size, &blob_size); -+ if (status) -+ { -+ heap_free(private_key_raw); -+ heap_free(key_blob); -+ goto done; -+ } -+ -+ memcpy(private_key_raw, key_blob + sizeof(BCRYPT_ECCKEY_BLOB) + key_size * 2, key_size); -+ heap_free(key_blob); -+ -+ err = pgcry_sexp_build(&privkey, NULL, -+ "(data(flags raw)(value %b))", -+ key_size, -+ private_key_raw); -+ -+ heap_free(private_key_raw); -+ } ++ err = pgcry_sexp_build(&privkey, NULL, ++ "(data(flags raw)(value %b))", ++ key_size, ++ privkey_in + sizeof(BCRYPT_ECCKEY_BLOB) + key_size * 2); + + if (err) + { @@ -474,40 +428,82 @@ index 00000000000..4e0386a3dda + } + return STATUS_SUCCESS; +} ++ ++static struct key_funcs key_funcs = ++{ ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ key_compute_secret_ecc ++}; ++ ++struct key_funcs * gcrypt_lib_init( DWORD reason ) ++{ ++ switch (reason) ++ { ++ case DLL_PROCESS_ATTACH: ++ if (!gcrypt_initialize()) return NULL; ++ return &key_funcs; ++ case DLL_PROCESS_DETACH: ++ gcrypt_uninitialize(); ++ } ++ return NULL; ++} ++ ++#else ++#include "ntstatus.h" ++#define WIN32_NO_STATUS ++#include "windef.h" ++#include "winbase.h" ++#include "winternl.h" ++ ++struct key_funcs * gcrypt_lib_init( DWORD reason ) ++{ ++ return NULL; ++} +#endif diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c -index 7acf8198626..8e5481aecc3 100644 +index b761c732acf..6ddcfce14d7 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c -@@ -1606,4 +1606,13 @@ NTSTATUS key_destroy( struct key *key ) - heap_free( key ); - return STATUS_SUCCESS; - } -+ -+#ifndef SONAME_LIBGCRYPT -+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret) -+{ -+ ERR("support for secrets not available without gcrypt\n"); -+ return STATUS_NOT_IMPLEMENTED; -+} -+#endif -+ - #endif +@@ -1589,7 +1589,8 @@ static struct key_funcs key_funcs = + key_export_dsa_capi, + key_export_ecc, + key_import_dsa_capi, +- key_import_ecc ++ key_import_ecc, ++ NULL + }; + + struct key_funcs * gnutls_lib_init( DWORD reason ) diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c -index 7f902535b8f..6c2a41a0725 100644 +index 5868b445625..a631d42b3f1 100644 --- a/dlls/bcrypt/macos.c +++ b/dlls/bcrypt/macos.c -@@ -279,4 +279,10 @@ NTSTATUS key_destroy( struct key *key ) - heap_free( key ); - return STATUS_SUCCESS; - } -+ -+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret) -+{ -+ ERR( "support for secrets not available at build time\n" ); -+ return STATUS_NOT_IMPLEMENTED; -+} - #endif +@@ -277,7 +277,8 @@ static struct key_funcs key_funcs = + key_export_dsa_capi, + key_export_ecc, + key_import_dsa_capi, +- key_import_ecc ++ key_import_ecc, ++ NULL + }; + + struct key_funcs * macos_lib_init( DWORD reason ) diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 7fdc0ac7fb2..5701a0a30ce 100644 --- a/dlls/bcrypt/tests/bcrypt.c @@ -521,6 +517,59 @@ index 7fdc0ac7fb2..5701a0a30ce 100644 if (status != STATUS_SUCCESS) { +diff --git a/dlls/bcrypt/unixlib.c b/dlls/bcrypt/unixlib.c +index 791b5d54188..a691d82afe2 100644 +--- a/dlls/bcrypt/unixlib.c ++++ b/dlls/bcrypt/unixlib.c +@@ -123,6 +123,12 @@ static void CDECL key_asymmetric_destroy( struct key *key ) + FIXME( "not implemented\n" ); + } + ++static NTSTATUS CDECL key_compute_secret_ecc (unsigned char *privkey_in, struct key *pubkey_in, struct secret *secret) ++{ ++ FIXME( "not implemented\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static struct key_funcs key_funcs = + { + key_set_property, +@@ -141,13 +147,15 @@ static struct key_funcs key_funcs = + key_export_dsa_capi, + key_export_ecc, + key_import_dsa_capi, +- key_import_ecc ++ key_import_ecc, ++ key_compute_secret_ecc + }; + + 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); + struct key_funcs *macos_funcs = macos_lib_init(reason); ++ struct key_funcs *gcrypt_funcs = gcrypt_lib_init(reason); + + if (reason == DLL_PROCESS_ATTACH) + { +@@ -155,7 +163,9 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p + if (macos_funcs && macos_funcs->key_##name) \ + key_funcs.key_##name = macos_funcs->key_##name; \ + if (gnutls_funcs && gnutls_funcs->key_##name) \ +- key_funcs.key_##name = gnutls_funcs->key_##name; ++ key_funcs.key_##name = gnutls_funcs->key_##name; \ ++ if (gcrypt_funcs && gcrypt_funcs->key_##name) \ ++ key_funcs.key_##name = gcrypt_funcs->key_##name; + + RESOLVE_FUNC(set_property) + RESOLVE_FUNC(symmetric_init) +@@ -174,6 +184,7 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p + RESOLVE_FUNC(export_ecc) + RESOLVE_FUNC(import_dsa_capi) + RESOLVE_FUNC(import_ecc) ++ RESOLVE_FUNC(compute_secret_ecc) + + #undef RESOLVE_FUNC + -- 2.28.0 diff --git a/patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCRYPT_KDF_HASH.patch b/patches/bcrypt-ECDHSecretAgreement/0003-bcrypt-Implement-BCRYPT_KDF_HASH.patch similarity index 82% rename from patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCRYPT_KDF_HASH.patch rename to patches/bcrypt-ECDHSecretAgreement/0003-bcrypt-Implement-BCRYPT_KDF_HASH.patch index 874066ec..15261183 100644 --- a/patches/bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCRYPT_KDF_HASH.patch +++ b/patches/bcrypt-ECDHSecretAgreement/0003-bcrypt-Implement-BCRYPT_KDF_HASH.patch @@ -1,4 +1,4 @@ -From d232882c571a14f4da8a134071a2125805ebd41f Mon Sep 17 00:00:00 2001 +From 01530fae68970b0c0af8811c5f6c5ea85c14372c Mon Sep 17 00:00:00 2001 From: Derek Lesho Date: Tue, 7 Jan 2020 14:22:49 -0600 Subject: [PATCH] bcrypt: Implement BCRYPT_KDF_HASH. @@ -7,21 +7,21 @@ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47699 Signed-off-by: Derek Lesho --- dlls/bcrypt/bcrypt_main.c | 108 ++++++++++++++++++++++++++++++++++++- - dlls/bcrypt/tests/bcrypt.c | 2 +- - 2 files changed, 108 insertions(+), 2 deletions(-) + dlls/bcrypt/tests/bcrypt.c | 3 +- + 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 65c28ca63e2..6e7b52e93b0 100644 +index 8dae41a2e2e..67be417aa61 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -1891,7 +1891,113 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt +@@ -1837,7 +1837,113 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt if (!secret || secret->hdr.magic != MAGIC_SECRET) return STATUS_INVALID_HANDLE; if (!kdf) return STATUS_INVALID_PARAMETER; -- if (!(strcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) +- if (!(lstrcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) + if (flags) FIXME("flags ignored: %08x\n", flags); + -+ if (!(strcmpW( kdf, BCRYPT_KDF_HASH ))) ++ if (!(lstrcmpW( kdf, BCRYPT_KDF_HASH ))) + { + unsigned int i; + BCryptBuffer *hash_algorithm = NULL; @@ -67,7 +67,7 @@ index 65c28ca63e2..6e7b52e93b0 100644 + { + for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++) + { -+ if (!strcmpW( hash_algorithm->pvBuffer, builtin_algorithms[i].name)) ++ if (!lstrcmpW( hash_algorithm->pvBuffer, builtin_algorithms[i].name)) + { + hash_alg_id = i; + break; @@ -125,15 +125,15 @@ index 65c28ca63e2..6e7b52e93b0 100644 + + return STATUS_SUCCESS; + } -+ else if (!(strcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) ++ else if (!(lstrcmpW( kdf, BCRYPT_KDF_RAW_SECRET ))) { ULONG n; ULONG secret_length = secret->len; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index a351aacf1f5..5333b879817 100644 +index 5701a0a30ce..d4ffb3fe69c 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -2085,7 +2085,7 @@ static void test_ECDH(void) +@@ -2132,7 +2132,7 @@ static void test_ECDH(void) raw_secret_end: status = pBCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); @@ -142,6 +142,14 @@ index a351aacf1f5..5333b879817 100644 if (status != STATUS_SUCCESS) { +@@ -2666,7 +2666,6 @@ static void test_SecretAgreement(void) + ok(status == STATUS_INVALID_PARAMETER, "got %08x\n", status); + + status = pBCryptDeriveKey(secret, L"HASH", NULL, NULL, 0, &size, 0); +- todo_wine + ok(status == STATUS_SUCCESS, "got %08x\n", status); + + status = pBCryptDestroyHash(secret); -- -2.27.0 +2.28.0 diff --git a/patches/bcrypt-ECDHSecretAgreement/definition b/patches/bcrypt-ECDHSecretAgreement/definition index 25c47b4f..19976b4e 100644 --- a/patches/bcrypt-ECDHSecretAgreement/definition +++ b/patches/bcrypt-ECDHSecretAgreement/definition @@ -2,4 +2,4 @@ Fixes: [47699] Multiple games fail to connect to online services (missing BCrypt # Needs to be moved to the unix lib, but that's a nontrivial amount of work, and # using gcrypt is the wrong way forward (we should expose the missing APIs from # gnutls instead). -Disabled: true +#Disabled: true diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 6f27c55c..0473ffd3 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -88,6 +88,7 @@ patch_enable_all () enable_advapi32_LsaLookupPrivilegeName="$1" enable_api_ms_win_Stub_DLLs="$1" enable_atl_AtlAxDialogBox="$1" + enable_bcrypt_ECDHSecretAgreement="$1" enable_cmd_launch_association="$1" enable_color_sRGB_profile="$1" enable_comctl32_Listview_DrawItem="$1" @@ -353,6 +354,9 @@ patch_enable () atl-AtlAxDialogBox) enable_atl_AtlAxDialogBox="$2" ;; + bcrypt-ECDHSecretAgreement) + enable_bcrypt_ECDHSecretAgreement="$2" + ;; cmd-launch-association) enable_cmd_launch_association="$2" ;; @@ -1785,6 +1789,22 @@ if test "$enable_atl_AtlAxDialogBox" -eq 1; then patch_apply atl-AtlAxDialogBox/0001-atl-Implement-AtlAxDialogBox-A-W.patch fi +# Patchset bcrypt-ECDHSecretAgreement +# | +# | This patchset fixes the following Wine bugs: +# | * [#47699] Multiple games fail to connect to online services (missing BCryptSecretAgreement / BCryptDeriveKey +# | implementation) +# | +# | Modified files: +# | * configure.ac, dlls/bcrypt/Makefile.in, dlls/bcrypt/bcrypt_internal.h, dlls/bcrypt/bcrypt_main.c, dlls/bcrypt/gcrypt.c, +# | dlls/bcrypt/gnutls.c, dlls/bcrypt/macos.c, dlls/bcrypt/tests/bcrypt.c, dlls/bcrypt/unixlib.c +# | +if test "$enable_bcrypt_ECDHSecretAgreement" -eq 1; then + patch_apply bcrypt-ECDHSecretAgreement/0001-bcrypt-Allow-multiple-backends-to-coexist.patch + patch_apply bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch + patch_apply bcrypt-ECDHSecretAgreement/0003-bcrypt-Implement-BCRYPT_KDF_HASH.patch +fi + # Patchset cmd-launch-association # | # | This patchset fixes the following Wine bugs: