Rebase against 1e4db62e0ba0b8595748c94b032dfb0064207de1.

This commit is contained in:
Zebediah Figura 2023-11-30 17:52:18 -06:00
parent 6702ce8bcc
commit 66c86503bd
5 changed files with 1 additions and 1033 deletions

View File

@ -1,312 +0,0 @@
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

View File

@ -1,559 +0,0 @@
From 528d7188ba7d6e68622d1b4f95608e68f26e1852 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 2 Oct 2020 12:11:49 -0500
Subject: [PATCH] bcrypt: Implement BCryptSecretAgreement with libgcrypt.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
configure.ac | 14 ++
dlls/bcrypt/Makefile.in | 1 +
dlls/bcrypt/bcrypt_internal.h | 4 +
dlls/bcrypt/bcrypt_main.c | 55 ++++++-
dlls/bcrypt/gcrypt.c | 292 ++++++++++++++++++++++++++++++++++
dlls/bcrypt/gnutls.c | 3 +-
dlls/bcrypt/tests/bcrypt.c | 2 +-
dlls/bcrypt/unixlib.c | 13 +-
8 files changed, 376 insertions(+), 8 deletions(-)
create mode 100644 dlls/bcrypt/gcrypt.c
diff --git a/configure.ac b/configure.ac
index f2401734035..b47f8d016e0 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
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]))
+AC_ARG_WITH(gcrypt, AS_HELP_STRING([--without-gcrypt],[do not use libgcrypt]))
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])
@@ -1954,6 +1955,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}
+dnl **** Check for gcrypt ****
+if test "x$with_gcrypt" != "xno"
+then
+ WINE_PACKAGE_FLAGS(GCRYPT,[libgcrypt],,,,
+ [AC_CHECK_HEADERS([gcrypt.h])
+ if test "$ac_cv_header_gcrypt_h" = "yes"
+ then
+ WINE_CHECK_SONAME(gcrypt,gcry_sexp_build,,,[$GCRYPT_LIBS])
+ fi])
+fi
+WINE_NOTICE_WITH(gcrypt,[test "x$ac_cv_lib_soname_gcrypt" = "x"],
+ [libgcrypt ${notice_platform}development files not found, GCRYPT won't be supported.])
+
dnl **** Check for gcc specific options ****
AC_SUBST(EXTRACFLAGS,"")
diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in
index 6dd3066d4a5..5336c8fc66b 100644
--- a/dlls/bcrypt/Makefile.in
+++ b/dlls/bcrypt/Makefile.in
@@ -5,6 +5,7 @@ EXTRAINCL = $(GNUTLS_CFLAGS)
C_SRCS = \
bcrypt_main.c \
+ gcrypt.c \
gnutls.c \
md2.c \
sha256.c \
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index d0697ed807e..66898c58cd2 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -193,6 +193,8 @@ struct key
struct secret
{
struct object hdr;
+ UCHAR *data;
+ ULONG len;
};
struct key_funcs
@@ -217,9 +219,11 @@ struct key_funcs
NTSTATUS (CDECL *key_import_dsa_capi)( struct key *, UCHAR *, ULONG );
NTSTATUS (CDECL *key_import_ecc)( struct key *, UCHAR *, ULONG );
NTSTATUS (CDECL *key_import_rsa)( struct key *, UCHAR *, ULONG );
+ NTSTATUS (CDECL *key_compute_secret_ecc)( unsigned char *privkey_in, struct key *pubkey_in, struct secret *secret );
};
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 5eb50cd616b..570f452d78e 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1925,9 +1925,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;
- FIXME( "%p, %p, %p, %08x\n", privatekey, publickey, handle, flags );
+ TRACE( "%p, %p, %p, %08x\n", privatekey, publickey, handle, flags );
if (!privkey || privkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
if (!pubkey || pubkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
@@ -1936,18 +1939,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;
+ 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);
+ secret = NULL;
+ }
+
*handle = secret;
- return STATUS_SUCCESS;
+ return status;
}
NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle)
{
struct secret *secret = handle;
- FIXME( "%p\n", handle );
+ TRACE( "%p\n", handle );
if (!secret || secret->hdr.magic != MAGIC_SECRET) return STATUS_INVALID_HANDLE;
secret->hdr.magic = 0;
+ heap_free( secret->data );
heap_free( secret );
return STATUS_SUCCESS;
}
@@ -1957,12 +1981,33 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt
{
struct secret *secret = handle;
- FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
+ TRACE( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
if (!secret || secret->hdr.magic != MAGIC_SECRET) return STATUS_INVALID_HANDLE;
if (!kdf) return STATUS_INVALID_PARAMETER;
- return STATUS_INTERNAL_ERROR;
+ if (!(lstrcmpW( kdf, BCRYPT_KDF_RAW_SECRET )))
+ {
+ ULONG n;
+ ULONG secret_length = secret->len;
+
+ if (!derived)
+ {
+ *result = secret_length;
+ return STATUS_SUCCESS;
+ }
+
+ /* outputs in little endian for some reason */
+ for (n = 0; n < secret_length && n < derived_size; n++)
+ {
+ derived[n] = secret->data[secret_length - n - 1];
+ }
+
+ *result = n;
+ return STATUS_SUCCESS;
+ }
+ FIXME( "Derivation function %s not supported.\n", debugstr_w(kdf) );
+ return STATUS_NOT_IMPLEMENTED;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
diff --git a/dlls/bcrypt/gcrypt.c b/dlls/bcrypt/gcrypt.c
new file mode 100644
index 00000000000..e72c27feb51
--- /dev/null
+++ b/dlls/bcrypt/gcrypt.c
@@ -0,0 +1,292 @@
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#ifdef HAVE_GCRYPT_H
+
+#include <gcrypt.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "bcrypt.h"
+
+#include "bcrypt_internal.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+static void *libgcrypt_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(gcry_check_version);
+MAKE_FUNCPTR(gcry_sexp_build);
+MAKE_FUNCPTR(gcry_pk_encrypt);
+MAKE_FUNCPTR(gcry_mpi_new);
+MAKE_FUNCPTR(gcry_mpi_print);
+MAKE_FUNCPTR(gcry_sexp_release);
+MAKE_FUNCPTR(gcry_mpi_release);
+MAKE_FUNCPTR(gcry_strsource);
+MAKE_FUNCPTR(gcry_strerror);
+MAKE_FUNCPTR(gcry_sexp_find_token);
+MAKE_FUNCPTR(gcry_sexp_nth_mpi);
+#undef MAKE_FUNCPTR
+
+BOOL gcrypt_initialize(void)
+{
+ if (!(libgcrypt_handle = dlopen( SONAME_LIBGCRYPT, RTLD_NOW)))
+ {
+ ERR_(winediag)( "failed to load libgcrypt, no support for diffie hellman key exchange\n" );
+ return FALSE;
+ }
+
+#define LOAD_FUNCPTR(f) \
+ if (!(p##f = dlsym( libgcrypt_handle, #f))) \
+ { \
+ ERR( "failed to load %s\n", #f ); \
+ goto fail; \
+ }
+
+ LOAD_FUNCPTR(gcry_check_version);
+ LOAD_FUNCPTR(gcry_sexp_build);
+ LOAD_FUNCPTR(gcry_pk_encrypt);
+ LOAD_FUNCPTR(gcry_mpi_new);
+ LOAD_FUNCPTR(gcry_mpi_print);
+ LOAD_FUNCPTR(gcry_sexp_release);
+ LOAD_FUNCPTR(gcry_mpi_release);
+ LOAD_FUNCPTR(gcry_strsource);
+ LOAD_FUNCPTR(gcry_strerror);
+ LOAD_FUNCPTR(gcry_sexp_find_token);
+ LOAD_FUNCPTR(gcry_sexp_nth_mpi);
+#undef LOAD_FUNCPTR
+
+ return TRUE;
+
+fail:
+ dlclose( libgcrypt_handle);
+ libgcrypt_handle = NULL;
+ return FALSE;
+}
+
+
+static void gcrypt_uninitialize(void)
+{
+ if (libgcrypt_handle)
+ {
+ dlclose( libgcrypt_handle);
+ libgcrypt_handle = NULL;
+ }
+}
+
+static NTSTATUS extract_result_into_secret(gcry_sexp_t result, struct secret *secret)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ gcry_mpi_t fullcoords = NULL;
+ gcry_sexp_t fragment = NULL;
+ UCHAR *tmp_buffer = NULL;
+ gcry_error_t err;
+ size_t size;
+
+ fragment = pgcry_sexp_find_token(result, "s", 0);
+ if (!fragment)
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ fullcoords = pgcry_sexp_nth_mpi(fragment, 1, GCRYMPI_FMT_USG);
+ if (!fullcoords)
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if ((err = pgcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &size, fullcoords)))
+ {
+ ERR("Error = %s/%s.\n", pgcry_strsource(err), pgcry_strerror(err));
+ status = STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ 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));
+ status = STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ secret->data = RtlAllocateHeap(GetProcessHeap(), 0, size / 2);
+ memcpy(secret->data, tmp_buffer + size % 2, size / 2);
+ secret->len = size / 2;
+
+done:
+ free(tmp_buffer);
+
+ pgcry_mpi_release(fullcoords);
+ pgcry_sexp_release(fragment);
+
+ return status;
+}
+
+/* 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 */
+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;
+ gcry_sexp_t pubkey = NULL;
+ gcry_sexp_t privkey = NULL;
+ gcry_sexp_t xchg_result = NULL;
+ gcry_error_t err;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (!libgcrypt_handle)
+ {
+ ERR("Secrets not supported without gcrypt\n");
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ switch (pubkey_in->alg_id)
+ {
+ case ALG_ID_ECDH_P256:
+ pubkey_format = "NIST P-256";
+ key_size = 32;
+ break;
+ default:
+ FIXME("Unsupported algorithm id: %u\n", pubkey_in->alg_id);
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ /* import public key -
+ copy public key into temporary buffer so we can prepend 0x04 (to indicate it is uncompressed) */
+ {
+ 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);
+
+ err = pgcry_sexp_build(&pubkey, NULL,
+ "(key-data(public-key(ecdh(curve %s)(q %b))))",
+ pubkey_format,
+ (key_size * 2) + 1,
+ public_key_raw);
+
+ free(public_key_raw);
+ }
+
+ if (err)
+ {
+ ERR("Failed to build gcrypt public key\n");
+ goto done;
+ }
+
+ /* import private key */
+ /* extract private key from blob structure */
+ err = pgcry_sexp_build(&privkey, NULL,
+ "(data(flags raw)(value %b))",
+ key_size,
+ privkey_in + sizeof(BCRYPT_ECCKEY_BLOB) + key_size * 2);
+
+ if (err)
+ {
+ ERR("Failed to build gcrypt private key data\n");
+ goto done;
+ }
+
+ if ((err = pgcry_pk_encrypt(&xchg_result, privkey, pubkey)))
+ {
+ ERR("Failed to perform key exchange\n");
+ goto done;
+ }
+
+ status = extract_result_into_secret(xchg_result, secret);
+ if (status)
+ {
+ ERR("Failed to extract secret key\n");
+ goto done;
+ }
+
+ if (secret->len != key_size)
+ {
+ ERR("got secret size %u, expected %u\n", secret->len, key_size);
+ status = STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ done:
+ pgcry_sexp_release(pubkey);
+ pgcry_sexp_release(privkey);
+ pgcry_sexp_release(xchg_result);
+
+ if (status)
+ {
+ return status;
+ }
+ if (err)
+ {
+ ERR("Error = %s/%s\n", pgcry_strsource (err), pgcry_strerror (err));
+ return STATUS_INTERNAL_ERROR;
+ }
+ 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,
+ 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 66845ffc8cf..64825f5b99b 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1894,7 +1894,8 @@ static const struct key_funcs key_funcs =
key_export_ecc,
key_import_dsa_capi,
key_import_ecc,
- key_import_rsa
+ key_import_rsa,
+ NULL
};
struct key_funcs * gnutls_lib_init( DWORD reason )
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index fb5ac03b039..894473d5346 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2248,7 +2248,7 @@ static void test_ECDH(void)
goto raw_secret_end;
}
- todo_wine ok(status == STATUS_SUCCESS, "got %08x\n", status);
+ ok(status == STATUS_SUCCESS, "got %08x\n", status);
if (status != STATUS_SUCCESS)
{
diff --git a/dlls/bcrypt/unixlib.c b/dlls/bcrypt/unixlib.c
index 1937a8172a4..e684a608eb5 100644
--- a/dlls/bcrypt/unixlib.c
+++ b/dlls/bcrypt/unixlib.c
@@ -142,6 +142,12 @@ static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *input, ULONG input
return STATUS_NOT_IMPLEMENTED;
}
+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,
@@ -164,17 +170,21 @@ static struct key_funcs key_funcs =
key_import_dsa_capi,
key_import_ecc,
key_import_rsa,
+ 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 *gcrypt_funcs = gcrypt_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;
+ 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)
@@ -196,6 +206,7 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
RESOLVE_FUNC(import_dsa_capi)
RESOLVE_FUNC(import_ecc)
RESOLVE_FUNC(import_rsa)
+ RESOLVE_FUNC(compute_secret_ecc)
#undef RESOLVE_FUNC
--
2.33.0

View File

@ -1,155 +0,0 @@
From 305131e59c071ca84e4447ab053b04bf4023fee8 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Tue, 7 Jan 2020 14:22:49 -0600
Subject: [PATCH] bcrypt: Implement BCRYPT_KDF_HASH.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47699
Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
dlls/bcrypt/bcrypt_main.c | 108 ++++++++++++++++++++++++++++++++++++-
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 0655c5dcfe81..70e914bd41f1 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1993,7 +1993,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 (!(lstrcmpW( kdf, BCRYPT_KDF_RAW_SECRET )))
+ if (flags) FIXME("flags ignored: %08x\n", flags);
+
+ if (!(lstrcmpW( kdf, BCRYPT_KDF_HASH )))
+ {
+ unsigned int i;
+ BCryptBuffer *hash_algorithm = NULL;
+ BCryptBuffer *secret_prepend = NULL;
+ BCryptBuffer *secret_append = NULL;
+ enum alg_id hash_alg_id;
+ ULONG hash_length;
+ struct hash_impl hash;
+ NTSTATUS status;
+
+ if (parameter)
+ {
+ for (i = 0; i < parameter->cBuffers; i++)
+ {
+ BCryptBuffer *cur_buffer = &parameter->pBuffers[i];
+ switch(cur_buffer->BufferType)
+ {
+ case KDF_HASH_ALGORITHM:
+ if (hash_algorithm)
+ FIXME("Duplicate KDF_HASH_ALGORITHM, untested\n");
+ hash_algorithm = cur_buffer;
+ break;
+ case KDF_SECRET_PREPEND:
+ if (secret_prepend)
+ FIXME("Multiple prefixes unsupported\n");
+ secret_prepend = cur_buffer;
+ break;
+ case KDF_SECRET_APPEND:
+ if (secret_append)
+ FIXME("Multiple suffixes unsupported\n");
+ secret_append = cur_buffer;
+ break;
+ default:
+ FIXME("Unsupported BCRYPT_KDF_HASH parameter type %x\n", cur_buffer->BufferType);
+ break;
+ }
+ }
+ }
+
+ if (!(hash_algorithm))
+ hash_alg_id = ALG_ID_SHA1;
+ else
+ {
+ for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
+ {
+ if (!lstrcmpW( hash_algorithm->pvBuffer, builtin_algorithms[i].name))
+ {
+ hash_alg_id = i;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(builtin_algorithms))
+ {
+ WARN("Algorithm %s not found\n", debugstr_w(hash_algorithm->pvBuffer));
+ return STATUS_NOT_SUPPORTED;
+ }
+ if (builtin_algorithms[hash_alg_id].class != BCRYPT_HASH_INTERFACE)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ hash_length = builtin_algorithms[hash_alg_id].hash_length;
+
+ if (!derived)
+ {
+ *result = hash_length;
+ return STATUS_SUCCESS;
+ }
+
+ if ((status = hash_init(&hash, hash_alg_id)))
+ {
+ return status;
+ }
+
+ if (secret_prepend)
+ {
+ hash_update(&hash, hash_alg_id, secret_prepend->pvBuffer, secret_prepend->cbBuffer);
+ }
+
+ hash_update(&hash, hash_alg_id, secret->data, secret->len);
+
+ if (secret_append)
+ {
+ hash_update(&hash, hash_alg_id, secret_append->pvBuffer, secret_append->cbBuffer);
+ }
+
+ if (derived_size >= hash_length)
+ {
+ hash_finish(&hash, hash_alg_id, derived, derived_size);
+ *result = hash_length;
+ }
+ else
+ {
+ UCHAR *output = heap_alloc(hash_length);
+ hash_finish(&hash, hash_alg_id, output, hash_length);
+ memcpy(derived, output, derived_size);
+ heap_free(output);
+ *result = derived_size;
+ }
+
+ return STATUS_SUCCESS;
+ }
+ 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 6be406dee21f..b13432523d15 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2180,7 +2180,7 @@ static void test_ECDH(void)
raw_secret_end:
status = pBCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0);
- todo_wine ok (status == STATUS_SUCCESS, "got %08x\n", status);
+ ok (status == STATUS_SUCCESS, "got %08x\n", status);
if (status != STATUS_SUCCESS)
{
@@ -2716,7 +2716,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.29.2

View File

@ -1,6 +0,0 @@
Fixes: [47699] Multiple games fail to connect to online services (missing BCryptSecretAgreement / BCryptDeriveKey implementation)
# 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).
# Temporarily disabled pending a rebase from author.
Disabled: true

View File

@ -1 +1 @@
fcddf19498fca9b51baea705f5748b998f4560b9
1e4db62e0ba0b8595748c94b032dfb0064207de1