2020-07-20 17:55:28 -07:00
|
|
|
From 2674bbd626b4a9e46e5ab729cb47c81950efefea Mon Sep 17 00:00:00 2001
|
2020-02-26 00:17:43 -08:00
|
|
|
From: Derek Lesho <dlesho@codeweavers.com>
|
|
|
|
Date: Tue, 7 Jan 2020 14:22:49 -0600
|
|
|
|
Subject: [PATCH] bcrypt: Implement BCryptSecretAgreement with libgcrypt.
|
|
|
|
|
|
|
|
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
|
|
|
---
|
|
|
|
configure.ac | 14 ++
|
|
|
|
dlls/bcrypt/Makefile.in | 1 +
|
2020-07-20 17:55:28 -07:00
|
|
|
dlls/bcrypt/bcrypt_internal.h | 6 +
|
|
|
|
dlls/bcrypt/bcrypt_main.c | 54 ++++++-
|
2020-02-26 00:17:43 -08:00
|
|
|
dlls/bcrypt/gcrypt.c | 264 ++++++++++++++++++++++++++++++++++
|
|
|
|
dlls/bcrypt/gnutls.c | 9 ++
|
2020-02-27 13:19:41 -08:00
|
|
|
dlls/bcrypt/macos.c | 6 +
|
2020-02-26 00:17:43 -08:00
|
|
|
dlls/bcrypt/tests/bcrypt.c | 2 +-
|
2020-07-20 17:55:28 -07:00
|
|
|
8 files changed, 350 insertions(+), 6 deletions(-)
|
2020-02-26 00:17:43 -08:00
|
|
|
create mode 100644 dlls/bcrypt/gcrypt.c
|
|
|
|
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
2020-07-20 17:55:28 -07:00
|
|
|
index 928f8ebd1b1..f9db147e7d5 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- a/configure.ac
|
|
|
|
+++ b/configure.ac
|
2020-06-03 22:08:14 -07:00
|
|
|
@@ -47,6 +47,7 @@ AC_ARG_WITH(faudio, AS_HELP_STRING([--without-faudio],[do not use FAudio (XAu
|
2020-02-26 00:17:43 -08:00
|
|
|
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])
|
2020-06-03 22:08:14 -07:00
|
|
|
@@ -2033,6 +2034,19 @@ WINE_NOTICE_WITH(vkd3d,[test "x$ac_cv_lib_soname_vkd3d" = "x"],
|
2020-02-26 00:17:43 -08:00
|
|
|
[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
|
2020-02-27 13:19:41 -08:00
|
|
|
index dd6d4a76640..ea3486a4002 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- 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 \
|
|
|
|
macos.c \
|
|
|
|
md2.c \
|
|
|
|
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
|
2020-07-20 17:55:28 -07:00
|
|
|
index 43be170d77f..6c93ed78389 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- a/dlls/bcrypt/bcrypt_internal.h
|
|
|
|
+++ b/dlls/bcrypt/bcrypt_internal.h
|
|
|
|
@@ -25,6 +25,9 @@
|
|
|
|
#include <gnutls/gnutls.h>
|
|
|
|
#include <gnutls/crypto.h>
|
|
|
|
#include <gnutls/abstract.h>
|
|
|
|
+#ifdef SONAME_LIBGCRYPT
|
|
|
|
+#include <gcrypt.h>
|
|
|
|
+#endif
|
|
|
|
#elif HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
|
|
|
|
#include <AvailabilityMacros.h>
|
|
|
|
#include <CommonCrypto/CommonCryptor.h>
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -243,6 +246,8 @@ struct key
|
|
|
|
struct secret
|
|
|
|
{
|
|
|
|
struct object hdr;
|
2020-02-26 00:17:43 -08:00
|
|
|
+ UCHAR *data;
|
|
|
|
+ ULONG len;
|
2020-07-20 17:55:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2020-02-26 00:17:43 -08:00
|
|
|
NTSTATUS key_export_ecc( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN;
|
2020-06-03 22:08:14 -07:00
|
|
|
NTSTATUS key_import_dsa_capi( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
2020-02-26 00:17:43 -08:00
|
|
|
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;
|
|
|
|
|
|
|
|
BOOL is_zero_vector( const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
|
|
|
BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
|
|
|
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
|
2020-07-20 17:55:28 -07:00
|
|
|
index bea2001a677..65c28ca63e2 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- a/dlls/bcrypt/bcrypt_main.c
|
|
|
|
+++ b/dlls/bcrypt/bcrypt_main.c
|
2020-06-03 22:08:14 -07:00
|
|
|
@@ -1421,6 +1421,12 @@ NTSTATUS key_import_ecc( struct key *key, UCHAR *input, ULONG len )
|
2020-02-26 00:17:43 -08:00
|
|
|
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,
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1838,8 +1844,9 @@ NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_H
|
|
|
|
struct key *privkey = privatekey;
|
|
|
|
struct key *pubkey = publickey;
|
|
|
|
struct secret *secret;
|
2020-02-26 00:17:43 -08:00
|
|
|
+ NTSTATUS status;
|
|
|
|
|
2020-07-20 17:55:28 -07:00
|
|
|
- FIXME( "%p, %p, %p, %08x\n", privatekey, publickey, handle, flags );
|
|
|
|
+ TRACE( "%p, %p, %p, %08x\n", privatekey, publickey, handle, flags );
|
2020-02-26 00:17:43 -08:00
|
|
|
|
2020-07-20 17:55:28 -07:00
|
|
|
if (!privkey || privkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
|
|
|
|
if (!pubkey || pubkey->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
|
|
|
|
@@ -1848,7 +1855,16 @@ 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 )))
|
2020-02-26 00:17:43 -08:00
|
|
|
+ {
|
2020-07-20 17:55:28 -07:00
|
|
|
+ heap_free( secret );
|
|
|
|
+ *handle = NULL;
|
2020-02-26 00:17:43 -08:00
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
2020-07-20 17:55:28 -07:00
|
|
|
+ *handle = secret;
|
2020-02-26 00:17:43 -08:00
|
|
|
+ }
|
|
|
|
+
|
2020-07-20 17:55:28 -07:00
|
|
|
return STATUS_SUCCESS;
|
2020-02-26 00:17:43 -08:00
|
|
|
}
|
|
|
|
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1856,10 +1872,11 @@ NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle)
|
2020-02-26 00:17:43 -08:00
|
|
|
{
|
2020-07-20 17:55:28 -07:00
|
|
|
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 );
|
2020-02-26 00:17:43 -08:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1869,12 +1886,33 @@ NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle, LPCWSTR kdf, BCrypt
|
2020-02-26 00:17:43 -08:00
|
|
|
{
|
2020-07-20 17:55:28 -07:00
|
|
|
struct secret *secret = handle;
|
|
|
|
|
2020-02-26 00:17:43 -08:00
|
|
|
- FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
|
2020-07-20 17:55:28 -07:00
|
|
|
+ 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;
|
|
|
|
|
2020-02-26 00:17:43 -08:00
|
|
|
- return STATUS_INTERNAL_ERROR;
|
2020-07-20 17:55:28 -07:00
|
|
|
+ if (!(strcmpW( kdf, BCRYPT_KDF_RAW_SECRET )))
|
2020-02-26 00:17:43 -08:00
|
|
|
+ {
|
|
|
|
+ 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;
|
|
|
|
+ }
|
2020-07-20 17:55:28 -07:00
|
|
|
+ FIXME( "Derivation function %s not supported.\n", debugstr_w(kdf) );
|
2020-02-26 00:17:43 -08:00
|
|
|
+ return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1886,6 +1924,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
|
2020-02-26 00:17:43 -08:00
|
|
|
DisableThreadLibraryCalls( hinst );
|
|
|
|
#ifdef HAVE_GNUTLS_CIPHER_INIT
|
|
|
|
gnutls_initialize();
|
|
|
|
+#ifdef SONAME_LIBGCRYPT
|
|
|
|
+ gcrypt_initialize();
|
|
|
|
+#endif
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1893,6 +1934,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
|
2020-02-26 00:17:43 -08:00
|
|
|
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
|
2020-06-03 22:08:14 -07:00
|
|
|
index 00000000000..f882d61def8
|
2020-02-26 00:17:43 -08:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/dlls/bcrypt/gcrypt.c
|
|
|
|
@@ -0,0 +1,264 @@
|
|
|
|
+#include "config.h"
|
|
|
|
+#include "wine/port.h"
|
|
|
|
+
|
|
|
|
+#include <stdarg.h>
|
|
|
|
+#ifdef HAVE_GNUTLS_CIPHER_INIT
|
|
|
|
+#include <gnutls/gnutls.h>
|
|
|
|
+#include <gnutls/crypto.h>
|
|
|
|
+#include <gnutls/abstract.h>
|
|
|
|
+#ifdef HAVE_LIBGCRYPT
|
|
|
|
+#include <libgcrypt/libgcrypt.h>
|
|
|
|
+#endif
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#include "ntstatus.h"
|
|
|
|
+#define WIN32_NO_STATUS
|
|
|
|
+#include "windef.h"
|
|
|
|
+#include "winbase.h"
|
|
|
|
+#include "bcrypt.h"
|
|
|
|
+
|
|
|
|
+#include "bcrypt_internal.h"
|
|
|
|
+
|
|
|
|
+#include "wine/debug.h"
|
|
|
|
+#include "wine/heap.h"
|
|
|
|
+#include "wine/library.h"
|
|
|
|
+#include "wine/unicode.h"
|
|
|
|
+
|
|
|
|
+#if defined(HAVE_GNUTLS_CIPHER_INIT) && defined(SONAME_LIBGCRYPT)
|
|
|
|
+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)
|
|
|
|
+{
|
2020-04-07 16:15:39 -07:00
|
|
|
+ if (!(libgcrypt_handle = dlopen( SONAME_LIBGCRYPT, RTLD_NOW)))
|
2020-02-26 00:17:43 -08:00
|
|
|
+ {
|
|
|
|
+ ERR_(winediag)( "failed to load libgcrypt, no support for diffie hellman key exchange\n" );
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#define LOAD_FUNCPTR(f) \
|
2020-04-07 16:15:39 -07:00
|
|
|
+ if (!(p##f = dlsym( libgcrypt_handle, #f))) \
|
2020-02-26 00:17:43 -08:00
|
|
|
+ { \
|
|
|
|
+ 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:
|
2020-04-07 16:15:39 -07:00
|
|
|
+ dlclose( libgcrypt_handle);
|
2020-02-26 00:17:43 -08:00
|
|
|
+ libgcrypt_handle = NULL;
|
|
|
|
+ return FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void gcrypt_uninitialize(void)
|
|
|
|
+{
|
2020-04-07 16:15:39 -07:00
|
|
|
+ dlclose( libgcrypt_handle);
|
2020-02-26 00:17:43 -08:00
|
|
|
+ libgcrypt_handle = NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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 = heap_alloc(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 = heap_alloc(size / 2);
|
|
|
|
+ memcpy(secret->data, tmp_buffer + size % 2, size / 2);
|
|
|
|
+ secret->len = size / 2;
|
|
|
|
+
|
|
|
|
+done:
|
|
|
|
+ heap_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 */
|
|
|
|
+NTSTATUS compute_secret_ecc (struct key *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 = heap_alloc((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);
|
|
|
|
+
|
|
|
|
+ heap_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 */
|
|
|
|
+ {
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
|
2020-07-20 17:55:28 -07:00
|
|
|
index 19a00e2ee25..1e075fe9994 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- a/dlls/bcrypt/gnutls.c
|
|
|
|
+++ b/dlls/bcrypt/gnutls.c
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -1585,4 +1585,13 @@ NTSTATUS key_destroy( struct key *key )
|
2020-02-26 00:17:43 -08:00
|
|
|
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
|
2020-02-27 13:19:41 -08:00
|
|
|
diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c
|
2020-07-20 17:55:28 -07:00
|
|
|
index 7f902535b8f..6c2a41a0725 100644
|
2020-02-27 13:19:41 -08:00
|
|
|
--- a/dlls/bcrypt/macos.c
|
|
|
|
+++ b/dlls/bcrypt/macos.c
|
2020-07-20 17:55:28 -07:00
|
|
|
@@ -279,4 +279,10 @@ NTSTATUS key_destroy( struct key *key )
|
2020-02-27 13:19:41 -08:00
|
|
|
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
|
2020-02-26 00:17:43 -08:00
|
|
|
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
|
2020-07-20 17:55:28 -07:00
|
|
|
index eb7a72e0ff4..a351aacf1f5 100644
|
2020-02-26 00:17:43 -08:00
|
|
|
--- a/dlls/bcrypt/tests/bcrypt.c
|
|
|
|
+++ b/dlls/bcrypt/tests/bcrypt.c
|
2020-06-03 22:08:14 -07:00
|
|
|
@@ -2068,7 +2068,7 @@ static void test_ECDH(void)
|
2020-02-26 00:17:43 -08:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
--
|
2020-07-20 17:55:28 -07:00
|
|
|
2.27.0
|
2020-02-26 00:17:43 -08:00
|
|
|
|