Wine-Devel
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 4 participants
- 84517 discussions
March 21, 2022
In order for a debugger to properly resolve loaded modules and detect
loading of them, it's necessary that the correct DT_DEBUG entry is visible
to the debugger. We had two problems with this before:
1. Since the preloader is the main executable, its ELF metadata is used
instead of the executable that we are trying to load.
2. The ELF header was actually getting overwritten by the reserved region,
since we only adjusted the placement for the .text section.
While 1. cannot be solved unless we run the preloader in another way, e.g.
as an interpreter, we can use some dirty hacks to solve 2.
This patch simply creates a stub PT_DYNAMIC section in the preloader,
then during execution patch that to point to the main executable's
respective section.
This allows GDB to have full shared library support when attaching.
There are numerous limitation due to the nature of the hack: It relies on the
BFD linker to create a PT_DYNAMIC entry, it doesn't work when the executable
was launched within the debugger, and it doesn't work with LLDB.
GDB doesn't seem to resolve the symbols of the main executable,
but that should not be much of an issue since the loader itself is very
short.
Some alternative ways to fix this are also possible:
1. Run the preloader as an ELF interpreter. This would get rid of the need
of messing with the auxiliary vector and various ELF metadata, but the
interpreter can be only specified by absolute path, which is a packaging
nuisance.
2. Get rid of the preloader entirely, make the loader static and let it perform
the reservation. This should work on glibc, but it's in general not a
very well supported use case and feels like a compatibility disaster.
---
configure | 17 ++++++----
configure.ac | 17 ++++++----
loader/Makefile.in | 5 +--
loader/preloader.c | 68 ++++++++++++++++++++++++++++++++------
loader/preloader_dynamic.s | 11 ++++++
5 files changed, 93 insertions(+), 25 deletions(-)
create mode 100644 loader/preloader_dynamic.s
diff --git a/configure b/configure
index 6a3a43a9e97..098c67f250a 100755
--- a/configure
+++ b/configure
@@ -10372,7 +10372,7 @@ if test "x$ac_cv_cflags__Wl___export_dynamic" = xyes
then :
WINELOADER_LDFLAGS="-Wl,--export-dynamic"
fi
- WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000"
+ WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs"
case $host_cpu in
*i[3456789]86* | x86_64 | *aarch64* | arm*)
@@ -10402,10 +10402,13 @@ fi
printf "%s\n" "$ac_cv_cflags__Wl__Ttext_segment_0x7bc00000" >&6; }
if test "x$ac_cv_cflags__Wl__Ttext_segment_0x7bc00000" = xyes
then :
- case $host_os in
- freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x60000000" ;;
- *) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d000000" ;;
- esac
+
+ case $host_os in
+ freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x60000000" ;;
+ *) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d000000" ;;
+ esac
+ WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d400000"
+
else $as_nop
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,--section-start,.interp=0x7d000400" >&5
printf %s "checking whether the compiler supports -Wl,--section-start,.interp=0x7d000400... " >&6; }
@@ -10433,11 +10436,13 @@ fi
printf "%s\n" "$ac_cv_cflags__Wl___section_start__interp_0x7d000400" >&6; }
if test "x$ac_cv_cflags__Wl___section_start__interp_0x7d000400" = xyes
then :
- case $host_os in
+
+ case $host_os in
freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,--section-start,.interp=0x60000400" ;;
*) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,--section-start,.interp=0x7d000400" ;;
esac
fi
+ WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,-Ttext=0x7d400000"
# Extract the first word of "prelink", so it can be a program name with args.
set dummy prelink; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
diff --git a/configure.ac b/configure.ac
index 5a85fce12a4..9b0e167448f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -826,20 +826,25 @@ case $host_os in
WINE_TRY_CFLAGS([-Wl,-z,defs],[UNIXLDFLAGS="$UNIXLDFLAGS -Wl,-z,defs"])
WINE_TRY_CFLAGS([-Wl,--export-dynamic],[WINELOADER_LDFLAGS="-Wl,--export-dynamic"])
- WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000"
+ WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs"
case $host_cpu in
*i[[3456789]]86* | x86_64 | *aarch64* | arm*)
WINE_TRY_CFLAGS([-Wl,-Ttext-segment=0x7bc00000],
- [case $host_os in
- freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x60000000" ;;
- *) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d000000" ;;
- esac],
+ [
+ case $host_os in
+ freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x60000000" ;;
+ *) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d000000" ;;
+ esac
+ WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,-Ttext-segment=0x7d400000"
+ ],
[WINE_TRY_CFLAGS([-Wl,--section-start,.interp=0x7d000400],
- [case $host_os in
+ [
+ case $host_os in
freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,--section-start,.interp=0x60000400" ;;
*) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,--section-start,.interp=0x7d000400" ;;
esac])
+ WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,-Ttext=0x7d400000"
AC_PATH_PROG(PRELINK, prelink, false, [/sbin /usr/sbin $PATH])
if test "x$PRELINK" = xfalse
then
diff --git a/loader/Makefile.in b/loader/Makefile.in
index 7302c231915..b5bdf6e1439 100644
--- a/loader/Makefile.in
+++ b/loader/Makefile.in
@@ -2,6 +2,7 @@ SOURCES = \
main.c \
preloader.c \
preloader_mac.c \
+ preloader_dynamic.s \
wine.de.UTF-8.man.in \
wine.desktop \
wine.fr.UTF-8.man.in \
@@ -25,10 +26,10 @@ wine64_OBJS = main.o
wine64_DEPS = $(WINELOADER_DEPENDS)
wine64_LDFLAGS = $(WINELOADER_LDFLAGS) $(LDEXECFLAGS) $(PTHREAD_LIBS)
-wine_preloader_OBJS = preloader.o preloader_mac.o
+wine_preloader_OBJS = preloader.o preloader_mac.o preloader_dynamic.o
wine_preloader_DEPS = $(WINELOADER_DEPENDS)
wine_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS)
-wine64_preloader_OBJS = preloader.o preloader_mac.o
+wine64_preloader_OBJS = preloader.o preloader_mac.o preloader_dynamic.o
wine64_preloader_DEPS = $(WINELOADER_DEPENDS)
wine64_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS)
diff --git a/loader/preloader.c b/loader/preloader.c
index 585be50624f..6af37cfca12 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -868,7 +868,7 @@ static void set_auxiliary_values( struct wld_auxv *av, const struct wld_auxv *ne
*
* Get a field of the auxiliary structure
*/
-static int get_auxiliary( struct wld_auxv *av, int type, int def_val )
+static unsigned long get_auxiliary(struct wld_auxv *av, unsigned long type, unsigned long def_val)
{
for ( ; av->a_type != AT_NULL; av++)
if( av->a_type == type ) return av->a_un.a_val;
@@ -1148,13 +1148,30 @@ static unsigned int gnu_hash( const char *name )
return h;
}
+static void *find_segment(const struct wld_link_map *map, int type, ElfW(Half) * size)
+{
+ void *ret = NULL;
+ const ElfW(Phdr) *ph;
+ /* parse the (already loaded) ELF executable's header */
+ for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
+ {
+ if (type == ph->p_type)
+ {
+ ret = (void *)(ph->p_vaddr + map->l_addr);
+ if (size)
+ *size = ph->p_memsz;
+ break;
+ }
+ }
+ return ret;
+}
+
/*
* Find a symbol in the symbol table of the executable loaded
*/
static void *find_symbol( const struct wld_link_map *map, const char *var, int type )
{
const ElfW(Dyn) *dyn = NULL;
- const ElfW(Phdr) *ph;
const ElfW(Sym) *symtab = NULL;
const Elf32_Word *hashtab = NULL;
const Elf32_Word *gnu_hashtab = NULL;
@@ -1165,15 +1182,7 @@ static void *find_symbol( const struct wld_link_map *map, const char *var, int t
#ifdef DUMP_SYMS
wld_printf("%p %x\n", map->l_phdr, map->l_phnum );
#endif
- /* parse the (already loaded) ELF executable's header */
- for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
- {
- if( PT_DYNAMIC == ph->p_type )
- {
- dyn = (void *)(ph->p_vaddr + map->l_addr);
- break;
- }
- }
+ dyn = find_segment( map, PT_DYNAMIC, NULL );
if( !dyn ) return NULL;
while( dyn->d_tag )
@@ -1375,6 +1384,12 @@ void* wld_start( void **stack )
struct wld_auxv new_av[8], delete_av[3], *av;
struct wld_link_map main_binary_map, ld_so_map;
struct wine_preload_info **wine_main_preload_info;
+ void *main_binary_dynamic = NULL;
+ ElfW(Half) main_binary_dynamic_size = 0;
+ ElfW(Phdr) *self_phdr;
+ unsigned long phdr_offset = 0;
+ ElfW(Half) self_phnum;
+ ElfW(Phdr) *ph;
pargc = *stack;
argv = (char **)pargc + 1;
@@ -1394,6 +1409,8 @@ void* wld_start( void **stack )
av = (struct wld_auxv *)(p+1);
page_size = get_auxiliary( av, AT_PAGESZ, 4096 );
page_mask = page_size - 1;
+ self_phdr = (void *)get_auxiliary(av, AT_PHDR, (unsigned long)NULL);
+ self_phnum = get_auxiliary(av, AT_PHNUM, 0);
preloader_start = (char *)_start - ((unsigned long)_start & page_mask);
preloader_end = (char *)((unsigned long)(_end + page_mask) & ~page_mask);
@@ -1442,6 +1459,35 @@ void* wld_start( void **stack )
interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
map_so_lib( interp, &ld_so_map );
+ main_binary_dynamic = find_segment(&main_binary_map, PT_DYNAMIC, &main_binary_dynamic_size);
+ for (ph = self_phdr; ph < &self_phdr[self_phnum]; ++ph)
+ {
+ if (is_addr_reserved(ph))
+ {
+ wld_printf("preloader: Warning: preloader PHDR is in reserved range, symbols in gdb "
+ "will be broken! (Make sure the linker used to build Wine supports "
+ "-Ttext-segment)\n");
+ break;
+ }
+
+ if (PT_PHDR == ph->p_type)
+ {
+ /* Best effort PIE support */
+ phdr_offset = (unsigned long)self_phdr - (unsigned long)ph->p_vaddr;
+ }
+ else if (PT_DYNAMIC == ph->p_type)
+ {
+ /*
+ * Monkey patch our PT_DYNAMIC entry to point it to the real executable's PT_DYNAMIC section.
+ * This is required by debuggers to resolve loaded shared libraries and more.
+ */
+ wld_mprotect((void *)((unsigned long)ph & ~page_mask), page_size, PROT_READ | PROT_WRITE);
+ ph->p_vaddr = (unsigned long)main_binary_dynamic - phdr_offset;
+ ph->p_memsz = main_binary_dynamic_size;
+ break;
+ }
+ }
+
/* store pointer to the preload info into the appropriate main binary variable */
wine_main_preload_info = find_symbol( &main_binary_map, "wine_main_preload_info", STT_OBJECT );
if (wine_main_preload_info) *wine_main_preload_info = preload_info;
diff --git a/loader/preloader_dynamic.s b/loader/preloader_dynamic.s
new file mode 100644
index 00000000000..cd658c758d8
--- /dev/null
+++ b/loader/preloader_dynamic.s
@@ -0,0 +1,11 @@
+DT_NULL=0
+# This section is a stub PT_DYNAMIC entry that will be patched over to the real exectuable's
+# respective section.
+# This only works with ld.bfd. gold and lld (with --image-base) will create their own
+# PT_DYNAMIC entry unless instructed otherwise with a linker script.
+.section ".dynamic"
+ _DYNAMIC: .globl _DYNAMIC
+ # Don't put any "real" entries here: GDB will look at the on-disk image first, and we
+ # need to make sure that the stub entries doesn't get preferred over the real entries
+ # that we forward to.
+ .long DT_NULL,0
--
2.35.1
1
0
[PATCH 1/2] riched20: Add back-reference to outer ME_Run from struct re_object.
by Jinoh Kang March 21, 2022
by Jinoh Kang March 21, 2022
March 21, 2022
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/caret.c | 5 +++--
dlls/riched20/editstr.h | 2 ++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 6d32776e3d2..c8658098e18 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -442,7 +442,7 @@ BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars)
nChars, FALSE);
}
-static struct re_object* create_re_object(const REOBJECT *reo)
+static struct re_object* create_re_object(const REOBJECT *reo, ME_Run *run)
{
struct re_object *reobj = heap_alloc(sizeof(*reobj));
@@ -452,6 +452,7 @@ static struct re_object* create_re_object(const REOBJECT *reo)
return NULL;
}
ME_CopyReObject(&reobj->obj, reo, REO_GETOBJ_ALL_INTERFACES);
+ reobj->run = run;
return reobj;
}
@@ -477,7 +478,7 @@ void editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
run = run_insert( editor, cursor, style, &space, 1, MERF_GRAPHICS );
- run->reobj = create_re_object( reo );
+ run->reobj = create_re_object( reo, run );
prev = run;
while ((prev = run_prev_all_paras( prev )))
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 889795de189..3b166234f23 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -147,11 +147,13 @@ typedef enum {
/******************************** structures *************************/
struct tagME_DisplayItem;
+struct tagME_Run;
struct re_object
{
struct list entry;
REOBJECT obj;
+ struct tagME_Run *run; /* ptr to the reobj's run */
};
typedef struct tagME_Run
--
2.34.1
2
3
March 21, 2022
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/tests/driver_hid.c | 27 ++++++++----
dlls/dinput/tests/driver_hid.h | 75 ++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput/tests/driver_hid.c b/dlls/dinput/tests/driver_hid.c
index 99aa9bd688c..e4101853833 100644
--- a/dlls/dinput/tests/driver_hid.c
+++ b/dlls/dinput/tests/driver_hid.c
@@ -411,11 +411,12 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp )
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
HID_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_device *impl = ext->MiniDeviceExtension;
+ ULONG code = stack->MinorFunction;
KIRQL irql;
- if (winetest_debug > 1) trace( "pnp %#x\n", stack->MinorFunction );
+ if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_pnp(code) );
- switch (stack->MinorFunction)
+ switch (code)
{
case IRP_MN_START_DEVICE:
++got_start_device;
@@ -502,7 +503,7 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
KIRQL irql;
LONG index;
- if (winetest_debug > 1) trace( "ioctl %#lx\n", code );
+ if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
ok( got_start_device, "expected IRP_MN_START_DEVICE before any ioctls\n" );
@@ -725,6 +726,8 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp )
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
KIRQL irql;
+ if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
+
switch (code)
{
case IOCTL_WINETEST_HID_SET_EXPECT:
@@ -752,27 +755,32 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp )
return hidclass_driver_ioctl( device, irp );
}
-static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *fdo )
+static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *device )
{
- HID_DEVICE_EXTENSION *ext = fdo->DeviceExtension;
+ HID_DEVICE_EXTENSION *ext = device->DeviceExtension;
NTSTATUS ret;
+ if (winetest_debug > 1) trace( "%s: driver %p, device %p\n", __func__, driver, device );
+
/* We should be given the FDO, not the PDO. */
ok( !!ext->PhysicalDeviceObject, "expected non-NULL pdo\n" );
ok( ext->NextDeviceObject == ext->PhysicalDeviceObject, "got pdo %p, next %p\n",
ext->PhysicalDeviceObject, ext->NextDeviceObject );
todo_wine
- ok( ext->NextDeviceObject->AttachedDevice == fdo, "wrong attached device\n" );
+ ok( ext->NextDeviceObject->AttachedDevice == device, "wrong attached device\n" );
ret = IoRegisterDeviceInterface( ext->PhysicalDeviceObject, &control_class, NULL, &control_symlink );
ok( !ret, "got %#lx\n", ret );
- fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+ if (winetest_debug > 1) trace( "Created HID FDO %p for Bus PDO %p\n", device, ext->PhysicalDeviceObject );
+
+ device->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
static NTSTATUS WINAPI driver_create( DEVICE_OBJECT *device, IRP *irp )
{
+ if (winetest_debug > 1) trace( "%s: device %p\n", __func__, device );
ok( 0, "unexpected call\n" );
irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( irp, IO_NO_INCREMENT );
@@ -781,6 +789,7 @@ static NTSTATUS WINAPI driver_create( DEVICE_OBJECT *device, IRP *irp )
static NTSTATUS WINAPI driver_close( DEVICE_OBJECT *device, IRP *irp )
{
+ if (winetest_debug > 1) trace( "%s: device %p\n", __func__, device );
ok( 0, "unexpected call\n" );
irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( irp, IO_NO_INCREMENT );
@@ -789,6 +798,7 @@ static NTSTATUS WINAPI driver_close( DEVICE_OBJECT *device, IRP *irp )
static void WINAPI driver_unload( DRIVER_OBJECT *driver )
{
+ if (winetest_debug > 1) trace( "%s: driver %p\n", __func__, driver );
input_queue_cleanup( &input_queue );
expect_queue_cleanup( &expect_queue );
winetest_cleanup();
@@ -812,6 +822,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry )
DWORD size;
if ((ret = winetest_init())) return ret;
+ if (winetest_debug > 1) trace( "%s: driver %p\n", __func__, driver );
InitializeObjectAttributes( &attr, registry, 0, NULL, NULL );
ret = ZwOpenKey( &hkey, KEY_ALL_ACCESS, &attr );
@@ -833,6 +844,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry )
ok( !ret, "ZwQueryValueKey returned %#lx\n", ret );
memcpy( &polled, buffer + info_size, size - info_size );
params.DevicesArePolled = polled;
+ /* polled mode calls this in a state where printing anything locks the system up */
+ if (polled) winetest_debug = 0;
RtlInitUnicodeString( &name_str, L"Descriptor" );
size = info_size + sizeof(report_descriptor_buf);
diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h
index 089d12b70fc..80073a6ae3f 100644
--- a/dlls/dinput/tests/driver_hid.h
+++ b/dlls/dinput/tests/driver_hid.h
@@ -31,9 +31,11 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "winioctl.h"
#include "winternl.h"
#include "ddk/wdm.h"
+#include "ddk/hidclass.h"
DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3,0x62,0xc0);
@@ -65,6 +67,79 @@ struct winetest_shared_data
LONG todo_failures;
};
+static inline const char *debugstr_pnp( ULONG code )
+{
+ switch (code)
+ {
+ case IRP_MN_START_DEVICE: return "IRP_MN_START_DEVICE";
+ case IRP_MN_QUERY_REMOVE_DEVICE: return "IRP_MN_QUERY_REMOVE_DEVICE";
+ case IRP_MN_REMOVE_DEVICE: return "IRP_MN_REMOVE_DEVICE";
+ case IRP_MN_CANCEL_REMOVE_DEVICE: return "IRP_MN_CANCEL_REMOVE_DEVICE";
+ case IRP_MN_STOP_DEVICE: return "IRP_MN_STOP_DEVICE";
+ case IRP_MN_QUERY_STOP_DEVICE: return "IRP_MN_QUERY_STOP_DEVICE";
+ case IRP_MN_CANCEL_STOP_DEVICE: return "IRP_MN_CANCEL_STOP_DEVICE";
+ case IRP_MN_QUERY_DEVICE_RELATIONS: return "IRP_MN_QUERY_DEVICE_RELATIONS";
+ case IRP_MN_QUERY_INTERFACE: return "IRP_MN_QUERY_INTERFACE";
+ case IRP_MN_QUERY_CAPABILITIES: return "IRP_MN_QUERY_CAPABILITIES";
+ case IRP_MN_QUERY_RESOURCES: return "IRP_MN_QUERY_RESOURCES";
+ case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
+ case IRP_MN_QUERY_DEVICE_TEXT: return "IRP_MN_QUERY_DEVICE_TEXT";
+ case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
+ case IRP_MN_READ_CONFIG: return "IRP_MN_READ_CONFIG";
+ case IRP_MN_WRITE_CONFIG: return "IRP_MN_WRITE_CONFIG";
+ case IRP_MN_EJECT: return "IRP_MN_EJECT";
+ case IRP_MN_SET_LOCK: return "IRP_MN_SET_LOCK";
+ case IRP_MN_QUERY_ID: return "IRP_MN_QUERY_ID";
+ case IRP_MN_QUERY_PNP_DEVICE_STATE: return "IRP_MN_QUERY_PNP_DEVICE_STATE";
+ case IRP_MN_QUERY_BUS_INFORMATION: return "IRP_MN_QUERY_BUS_INFORMATION";
+ case IRP_MN_DEVICE_USAGE_NOTIFICATION: return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
+ case IRP_MN_SURPRISE_REMOVAL: return "IRP_MN_SURPRISE_REMOVAL";
+ case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION";
+ default: return "unknown";
+ }
+}
+
+static inline const char *debugstr_ioctl( ULONG code )
+{
+ switch (code)
+ {
+ case HID_CTL_CODE(0): return "IOCTL_HID_GET_DEVICE_DESCRIPTOR";
+ case HID_CTL_CODE(1): return "IOCTL_HID_GET_REPORT_DESCRIPTOR";
+ case HID_CTL_CODE(2): return "IOCTL_HID_READ_REPORT";
+ case HID_CTL_CODE(3): return "IOCTL_HID_WRITE_REPORT";
+ case HID_CTL_CODE(4): return "IOCTL_HID_GET_STRING";
+ case HID_CTL_CODE(7): return "IOCTL_HID_ACTIVATE_DEVICE";
+ case HID_CTL_CODE(8): return "IOCTL_HID_DEACTIVATE_DEVICE";
+ case HID_CTL_CODE(9): return "IOCTL_HID_GET_DEVICE_ATTRIBUTES";
+ case HID_CTL_CODE(10): return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST";
+ case HID_OUT_CTL_CODE(102): return "IOCTL_GET_PHYSICAL_DESCRIPTOR";
+ case HID_CTL_CODE(101): return "IOCTL_HID_FLUSH_QUEUE";
+ case HID_CTL_CODE(100): return "IOCTL_HID_GET_COLLECTION_DESCRIPTOR";
+ case HID_BUFFER_CTL_CODE(106): return "IOCTL_HID_GET_COLLECTION_INFORMATION";
+ case HID_OUT_CTL_CODE(100): return "IOCTL_HID_GET_FEATURE";
+ case HID_OUT_CTL_CODE(103): return "IOCTL_HID_GET_HARDWARE_ID";
+ case HID_OUT_CTL_CODE(120): return "IOCTL_HID_GET_INDEXED_STRING";
+ case HID_OUT_CTL_CODE(104): return "IOCTL_HID_GET_INPUT_REPORT";
+ case HID_OUT_CTL_CODE(110): return "IOCTL_HID_GET_MANUFACTURER_STRING";
+ case HID_BUFFER_CTL_CODE(104): return "IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS";
+ case HID_BUFFER_CTL_CODE(102): return "IOCTL_HID_GET_POLL_FREQUENCY_MSEC";
+ case HID_OUT_CTL_CODE(111): return "IOCTL_HID_GET_PRODUCT_STRING";
+ case HID_OUT_CTL_CODE(112): return "IOCTL_HID_GET_SERIALNUMBER_STRING";
+ case HID_IN_CTL_CODE(100): return "IOCTL_HID_SET_FEATURE";
+ case HID_BUFFER_CTL_CODE(105): return "IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS";
+ case HID_IN_CTL_CODE(101): return "IOCTL_HID_SET_OUTPUT_REPORT";
+ case HID_BUFFER_CTL_CODE(103): return "IOCTL_HID_SET_POLL_FREQUENCY_MSEC";
+ case HID_BUFFER_CTL_CODE(100): return "IOCTL_HID_GET_DRIVER_CONFIG";
+ case HID_BUFFER_CTL_CODE(101): return "IOCTL_HID_SET_DRIVER_CONFIG";
+ case HID_OUT_CTL_CODE(121): return "IOCTL_HID_GET_MS_GENRE_DESCRIPTOR";
+ case IOCTL_WINETEST_HID_SET_EXPECT: return "IOCTL_WINETEST_HID_SET_EXPECT";
+ case IOCTL_WINETEST_HID_WAIT_EXPECT: return "IOCTL_WINETEST_HID_WAIT_EXPECT";
+ case IOCTL_WINETEST_HID_SEND_INPUT: return "IOCTL_WINETEST_HID_SEND_INPUT";
+ case IOCTL_WINETEST_HID_SET_CONTEXT: return "IOCTL_WINETEST_HID_SET_CONTEXT";
+ default: return "unknown";
+ }
+}
+
#ifndef __WINE_WINE_TEST_H
#if !defined( __WINE_USE_MSVCRT ) || defined( __MINGW32__ )
--
2.35.1
2
8
March 21, 2022
Currently, apartment OXIDs are generated using the process ID
(and the thread ID for a single threaded-apartment). This means
that if an apartment is destroyed and re-created (using
`CoUninitialize` followed by `CoInitializeEx`), the newly created
apartment will end up with the same OXID as the old apartment.
However, testing shows that Windows will generate a *new* OXID
when an apartment is created in the above manner. Using
RtlGenRandom makes our behavior more consistent with Windows -
however, the actual OXIDs we generate will still differ
from those of Windows.
Additionally, this fixes an issue that caused the .NET 4.8
installer to become stuck during the downloading stage under Wine.
The installer appears to perform the following actions:
1. Call `IBackgroundCopyJob_SetNotify` interface on a BITS
job. This causes us to create a proxy (in the other process
hosting 'qmgr') for the `IBackgroundCopyCallback` pointer
passed as a parameter.
2. Trigger MTA apartment re-creation (in the process running the setup,
*not* the process with the `IBackgroundCopyCallback` proxy)
through `CoUninitialize` followed by `CoInitializeEx`.
3. Call `IBackgroundCopyJob_SetNotify` on a newly created job,
but with the same `IBackgroundCopyCallback` pointer parameter.
When we deserialize the pointer passed to
`IBackgroundCopyJob_SetNotify`, we will end up re-using the same
`proxy_manager` that we created for the previous `IBackgroundCopyCallback`.
This is due to the fact that the OIDs happen to match (due to the fact that
the .NET 4.8 setup appears to perform actions in the same order between
the old and new apartments), and the apartment OXIDs match as explained above.
above. As a result, we will use the old IPID when we send RPC packets
using this `proxy_manager`. However, the new and old IPIDs will *never* match,
since their generation process includes `RtlGenRandom`. This will cause a fault
packet to be generated on the listening side of the RPC connection.
By using RtlGenRandom when we generate the apartment OXID, we ensure that
the proxy side will never incorrectly re-use a stale `proxy_manager`
Signed-off-by: Aaron Hill <aa1ronham(a)gmail.com>
---
dlls/combase/apartment.c | 18 ++++++--------
dlls/ole32/tests/marshal.c | 49 ++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c
index c1b381879d3..d4d78264dea 100644
--- a/dlls/combase/apartment.c
+++ b/dlls/combase/apartment.c
@@ -32,6 +32,7 @@
#include "windef.h"
#include "winbase.h"
#include "servprov.h"
+#include "ntsecapi.h"
#include "combase_private.h"
@@ -382,17 +383,12 @@ static struct apartment *apartment_construct(DWORD model)
apt->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": apartment");
apt->multi_threaded = !(model & COINIT_APARTMENTTHREADED);
-
- if (apt->multi_threaded)
- {
- /* FIXME: should be randomly generated by in an RPC call to rpcss */
- apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
- }
- else
- {
- /* FIXME: should be randomly generated by in an RPC call to rpcss */
- apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
- }
+ /* FIXME: should be generated by in an RPC call to rpcss
+ * Re-creating an apartment (via `CoUninitialize` followed by `CoInitializeEx`)
+ * will result in a *different* oxid. This is consistent with the behavior of
+ * Windows, and ensures that proxies in a different process will create
+ * a new RPC connection, instead of attempting to re-use an old one. */
+ RtlGenRandom(&apt->oxid, sizeof(apt->oxid));
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index 6e21ed1889b..0f8a7a643de 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -1239,6 +1239,54 @@ static void test_marshal_proxy_apartment_shutdown(void)
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
}
+static OXID get_apartment_oxid(void)
+{
+ HRESULT hr;
+ OBJREF objref;
+ DWORD size, read;
+ IStream *pStream = NULL;
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+
+ hr = IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+
+ size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr);
+ hr = IStream_Read(pStream, &objref, size, &read);
+ ok_ole_success(hr, IStream_Read);
+
+ IStream_Release(pStream);
+
+ return objref.u_objref.u_standard.std.oxid;
+}
+
+/* tests that re-creating an apartment (via `CoUninitialize` followed by `CoInitializeEx`)
+ * results in an apartment with a different OXID than the previous apartment
+ */
+static void test_apartment_oxid(void)
+{
+
+ OXID first_oxid;
+ OXID second_oxid;
+
+ cLocks = 0;
+ external_connections = 0;
+
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ first_oxid = get_apartment_oxid();
+ CoUninitialize();
+
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ second_oxid = get_apartment_oxid();
+ CoUninitialize();
+
+ ok(first_oxid != second_oxid, "Re-created apartment has old OXID: %s\n", wine_dbgstr_longlong(first_oxid));
+}
+
/* tests that proxies are released when the containing mta apartment is destroyed */
static void test_marshal_proxy_mta_apartment_shutdown(void)
{
@@ -4511,6 +4559,7 @@ START_TEST(marshal)
test_cocreateinstance_proxy();
test_implicit_mta();
+ test_apartment_oxid();
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
--
2.35.1
2
1
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52623
Signed-off-by: Austin English <austinenglish(a)gmail.com>
---
dlls/winspool.drv/info.c | 9 +++++++++
dlls/winspool.drv/winspool.drv.spec | 1 +
2 files changed, 10 insertions(+)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 52edd362622..7e3b0476735 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -8076,3 +8076,12 @@ DWORD WINAPI PerfCollect(LPWSTR query, LPVOID *data, LPDWORD size, LPDWORD obj_c
*obj_count = 0;
return ERROR_SUCCESS;
}
+
+/*****************************************************************************
+ * GetSpoolFileHandle [WINSPOOL.@]
+ */
+HANDLE WINAPI GetSpoolFileHandle(HANDLE printer)
+{
+ FIXME("%p: stub\n", printer);
+ return INVALID_HANDLE_VALUE;
+}
diff --git a/dlls/winspool.drv/winspool.drv.spec b/dlls/winspool.drv/winspool.drv.spec
index 5d8a62d4695..d7bb49bd34b 100644
--- a/dlls/winspool.drv/winspool.drv.spec
+++ b/dlls/winspool.drv/winspool.drv.spec
@@ -144,6 +144,7 @@
@ stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr)
@ stdcall GetPrinterDriverW(long wstr long ptr long ptr)
@ stdcall GetPrinterW(long long ptr long ptr)
+@ stdcall GetSpoolFileHandle(ptr)
@ stdcall IsValidDevmodeA(ptr long)
@ stdcall IsValidDevmodeW(ptr long)
@ stdcall OpenPrinterA(str ptr ptr)
--
2.35.1
2
1
From: Austin English <austinenglish(a)gmail.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52623
Signed-off-by: Austin English <austinenglish(a)gmail.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winspool.drv/info.c | 9 +++++++++
dlls/winspool.drv/winspool.drv.spec | 1 +
include/winspool.h | 2 ++
3 files changed, 12 insertions(+)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 52edd362622..a89abd0ced9 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -8076,3 +8076,12 @@ DWORD WINAPI PerfCollect(LPWSTR query, LPVOID *data, LPDWORD size, LPDWORD obj_c
*obj_count = 0;
return ERROR_SUCCESS;
}
+
+/*****************************************************************************
+ * GetSpoolFileHandle [WINSPOOL.@]
+ */
+HANDLE WINAPI GetSpoolFileHandle( HANDLE printer )
+{
+ FIXME( "%p: stub\n", printer );
+ return INVALID_HANDLE_VALUE;
+}
diff --git a/dlls/winspool.drv/winspool.drv.spec b/dlls/winspool.drv/winspool.drv.spec
index 5d8a62d4695..d7bb49bd34b 100644
--- a/dlls/winspool.drv/winspool.drv.spec
+++ b/dlls/winspool.drv/winspool.drv.spec
@@ -144,6 +144,7 @@
@ stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr)
@ stdcall GetPrinterDriverW(long wstr long ptr long ptr)
@ stdcall GetPrinterW(long long ptr long ptr)
+@ stdcall GetSpoolFileHandle(ptr)
@ stdcall IsValidDevmodeA(ptr long)
@ stdcall IsValidDevmodeW(ptr long)
@ stdcall OpenPrinterA(str ptr ptr)
diff --git a/include/winspool.h b/include/winspool.h
index 68619741f38..db8773ec418 100644
--- a/include/winspool.h
+++ b/include/winspool.h
@@ -1768,6 +1768,8 @@ BOOL WINAPI XcvDataW(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData,
BOOL WINAPI IsValidDevmodeA(PDEVMODEA pDevMode, SIZE_T size);
BOOL WINAPI IsValidDevmodeW(PDEVMODEW pDevMode, SIZE_T size);
+HANDLE WINAPI GetSpoolFileHandle(HANDLE printer);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--
2.23.0
1
0
[PATCH 6/6] bcrypt: Stop passing a dummy public key to gnutls_privkey_import_dsa_raw().
by Hans Leidekker March 21, 2022
by Hans Leidekker March 21, 2022
March 21, 2022
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/gnutls.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 6a55c84efef..884f4b1d37e 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1145,8 +1145,7 @@ static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
BLOBHEADER *hdr = (BLOBHEADER *)buf;
DSSPUBKEY *pubkey;
gnutls_privkey_t handle;
- gnutls_datum_t p, q, g, y, x;
- unsigned char dummy[128];
+ gnutls_datum_t p, q, g, x;
unsigned char *data, p_data[128], q_data[20], g_data[128], x_data[20];
int i, ret, size;
@@ -1185,12 +1184,7 @@ static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
for (i = 0; i < x.size; i++) x.data[i] = data[x.size - i - 1];
data += x.size;
- WARN( "using dummy public key\n" );
- memset( dummy, 1, sizeof(dummy) );
- y.data = dummy;
- y.size = min( p.size, sizeof(dummy) );
-
- if ((ret = pgnutls_privkey_import_dsa_raw( handle, &p, &q, &g, &y, &x )))
+ if ((ret = pgnutls_privkey_import_dsa_raw( handle, &p, &q, &g, NULL, &x )))
{
pgnutls_perror( ret );
pgnutls_privkey_deinit( handle );
--
2.30.2
1
0
March 21, 2022
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/bcrypt_internal.h | 2 -
dlls/bcrypt/bcrypt_main.c | 68 +----
dlls/bcrypt/gnutls.c | 481 ++++++++--------------------------
3 files changed, 125 insertions(+), 426 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index 7342b66479a..d57819f2ec6 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -175,8 +175,6 @@ struct key_asymmetric
{
ULONG bitlen; /* ignored for ECC keys */
unsigned flags;
- UCHAR *pubkey;
- unsigned pubkey_len;
DSSSEED dss_seed;
};
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 23f30833235..2ffeff66d7b 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -968,8 +968,7 @@ NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG se
return status;
}
-static NTSTATUS key_asymmetric_create( struct key **ret_key, enum alg_id alg_id, ULONG bitlen,
- const UCHAR *pubkey, ULONG pubkey_len )
+static NTSTATUS key_asymmetric_create( enum alg_id alg_id, ULONG bitlen, struct key **ret_key )
{
struct key *key;
@@ -983,14 +982,6 @@ static NTSTATUS key_asymmetric_create( struct key **ret_key, enum alg_id alg_id,
key->hdr.magic = MAGIC_KEY;
key->alg_id = alg_id;
key->u.a.bitlen = bitlen;
- key->u.a.pubkey_len = pubkey_len;
-
- if (!(key->u.a.pubkey = malloc( pubkey_len )))
- {
- free( key );
- return STATUS_NO_MEMORY;
- }
- if (pubkey) memcpy( key->u.a.pubkey, pubkey, pubkey_len );
*ret_key = key;
return STATUS_SUCCESS;
@@ -1377,8 +1368,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2)
return STATUS_INVALID_PARAMETER;
- size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
- if ((status = key_asymmetric_create( &key, alg->id, key_size * 8, (BYTE *)ecc_blob, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, key_size * 8, &key ))) return status;
params.key = key;
params.flags = KEY_IMPORT_FLAG_PUBLIC;
params.buf = input;
@@ -1419,8 +1409,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3)
return STATUS_INVALID_PARAMETER;
- size = sizeof(*ecc_blob) + key_size * 2;
- if ((status = key_asymmetric_create( &key, alg->id, key_size * 8, NULL, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, key_size * 8, &key ))) return status;
params.key = key;
params.flags = 0;
params.buf = input;
@@ -1445,7 +1434,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
if (size != input_len) return NTE_BAD_DATA;
- if ((status = key_asymmetric_create( &key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, rsa_blob->BitLength, &key ))) return status;
params.key = key;
params.flags = KEY_IMPORT_FLAG_PUBLIC;
params.buf = input;
@@ -1467,8 +1456,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (alg->id != ALG_ID_RSA || (rsa_blob->Magic != BCRYPT_RSAPRIVATE_MAGIC &&
rsa_blob->Magic != BCRYPT_RSAFULLPRIVATE_MAGIC)) return STATUS_NOT_SUPPORTED;
- size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
- if ((status = key_asymmetric_create( &key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, rsa_blob->BitLength, &key ))) return status;
params.key = key;
params.flags = 0;
params.buf = input;
@@ -1490,8 +1478,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
return STATUS_NOT_SUPPORTED;
- size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
- if ((status = key_asymmetric_create( &key, alg->id, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, dsa_blob->cbKey * 8, &key ))) return status;
params.key = key;
params.flags = KEY_IMPORT_FLAG_PUBLIC;
params.buf = input;
@@ -1530,8 +1517,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED))
return STATUS_INVALID_PARAMETER;
- size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED);
- if ((status = key_asymmetric_create( &key, alg->id, pubkey->bitlen, NULL, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, pubkey->bitlen, &key ))) return status;
key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
params.key = key;
params.flags = 0;
@@ -1567,7 +1553,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED);
if (input_len < size) return STATUS_INVALID_PARAMETER;
- if ((status = key_asymmetric_create( &key, alg->id, pubkey->bitlen, (BYTE *)hdr, size ))) return status;
+ if ((status = key_asymmetric_create( alg->id, pubkey->bitlen, &key ))) return status;
key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
params.key = key;
params.flags = KEY_IMPORT_FLAG_PUBLIC;
@@ -1660,36 +1646,15 @@ NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_H
struct algorithm *alg = algorithm;
struct key *key;
NTSTATUS status;
- ULONG size;
TRACE( "%p, %p, %lu, %#lx\n", algorithm, handle, key_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (!handle) return STATUS_INVALID_PARAMETER;
- switch (alg->id)
- {
- case ALG_ID_ECDH_P256:
- case ALG_ID_ECDSA_P256:
- size = sizeof(BCRYPT_ECCKEY_BLOB) + 2 * 256 / 8;
- break;
- case ALG_ID_ECDSA_P384:
- size = sizeof(BCRYPT_ECCKEY_BLOB) + 2 * 384 / 8;
- break;
- case ALG_ID_RSA:
- case ALG_ID_RSA_SIGN:
- size = sizeof(BCRYPT_RSAKEY_BLOB) + 2 * key_len / 8;
- break;
- case ALG_ID_DSA:
- size = sizeof(BCRYPT_DSA_KEY_BLOB) + 3 * key_len / 8;
- break;
- default:
- FIXME( "algorithm %u not supported\n", alg->id );
- return STATUS_NOT_SUPPORTED;
- }
-
- if (!(status = key_asymmetric_create( &key, alg->id, key_len, NULL, size ))) *handle = key;
- return status;
+ if ((status = key_asymmetric_create( alg->id, key_len, &key ))) return status;
+ *handle = key;
+ return STATUS_SUCCESS;
}
NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )
@@ -1766,14 +1731,9 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
{
struct key_asymmetric_duplicate_params params;
- if (!(buffer = malloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY;
- memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len );
-
- key_copy->u.a.bitlen = key_orig->u.a.bitlen;
- key_copy->u.a.flags = key_orig->u.a.flags;
- key_copy->u.a.pubkey = buffer;
- key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len;
- key_copy->u.a.dss_seed = key_orig->u.a.dss_seed;
+ key_copy->u.a.bitlen = key_orig->u.a.bitlen;
+ key_copy->u.a.flags = key_orig->u.a.flags;
+ key_copy->u.a.dss_seed = key_orig->u.a.dss_seed;
params.key_orig = key_orig;
params.key_copy = key_copy;
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 28119fc9e78..6a55c84efef 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -72,7 +72,11 @@ typedef enum
union key_data
{
gnutls_cipher_hd_t cipher;
- gnutls_privkey_t privkey;
+ struct
+ {
+ gnutls_privkey_t privkey;
+ gnutls_pubkey_t pubkey;
+ } a;
};
C_ASSERT( sizeof(union key_data) <= sizeof(((struct key *)0)->private) );
@@ -98,6 +102,7 @@ static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_
/* Not present in gnutls version < 2.12.0 */
static int (*pgnutls_pubkey_import_dsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
const gnutls_datum_t *, const gnutls_datum_t *);
+static int (*pgnutls_pubkey_import_privkey)(gnutls_pubkey_t, gnutls_privkey_t, unsigned int, unsigned int);
/* Not present in gnutls version < 3.3.0 */
static int (*pgnutls_privkey_export_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_t *,
@@ -133,6 +138,7 @@ MAKE_FUNCPTR(gnutls_privkey_import_dsa_raw);
MAKE_FUNCPTR(gnutls_privkey_init);
MAKE_FUNCPTR(gnutls_privkey_sign_hash);
MAKE_FUNCPTR(gnutls_pubkey_deinit);
+MAKE_FUNCPTR(gnutls_pubkey_import_privkey);
MAKE_FUNCPTR(gnutls_pubkey_init);
#undef MAKE_FUNCPTR
@@ -272,6 +278,7 @@ static NTSTATUS gnutls_process_attach( void *args )
LOAD_FUNCPTR(gnutls_privkey_init);
LOAD_FUNCPTR(gnutls_privkey_sign_hash);
LOAD_FUNCPTR(gnutls_pubkey_deinit);
+ LOAD_FUNCPTR(gnutls_pubkey_import_privkey);
LOAD_FUNCPTR(gnutls_pubkey_init);
#undef LOAD_FUNCPTR
@@ -609,234 +616,6 @@ static ULONG export_gnutls_datum( UCHAR *buffer, ULONG buflen, gnutls_datum_t *d
return size;
}
-#define EXPORT_SIZE(d,f,p) export_gnutls_datum( NULL, bitlen / f, &d, p )
-static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bitlen, void *pubkey, unsigned *pubkey_len )
-{
- BCRYPT_RSAKEY_BLOB *rsa_blob = pubkey;
- gnutls_datum_t m, e;
- UCHAR *dst;
- int ret;
-
- if ((ret = pgnutls_privkey_export_rsa_raw( gnutls_key, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
- {
- pgnutls_perror( ret );
- return STATUS_INTERNAL_ERROR;
- }
-
- if (*pubkey_len < sizeof(*rsa_blob) + EXPORT_SIZE(e,8,0) + EXPORT_SIZE(m,8,1))
- {
- FIXME( "wrong pubkey len %u\n", *pubkey_len );
- pgnutls_perror( ret );
- free( e.data ); free( m.data );
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- dst = (UCHAR *)(rsa_blob + 1);
- rsa_blob->cbPublicExp = export_gnutls_datum( dst, bitlen / 8, &e, 0 );
-
- dst += rsa_blob->cbPublicExp;
- rsa_blob->cbModulus = export_gnutls_datum( dst, bitlen / 8, &m, 1 );
-
- rsa_blob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
- rsa_blob->BitLength = bitlen;
- rsa_blob->cbPrime1 = 0;
- rsa_blob->cbPrime2 = 0;
-
- *pubkey_len = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
-
- free( e.data ); free( m.data );
- return STATUS_SUCCESS;
-}
-#undef EXPORT_SIZE
-
-static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_id alg_id, void *pubkey,
- unsigned *pubkey_len )
-{
- BCRYPT_ECCKEY_BLOB *ecc_blob = pubkey;
- gnutls_ecc_curve_t curve;
- gnutls_datum_t x, y;
- DWORD magic, size;
- UCHAR *dst;
- int ret;
-
- switch (alg_id)
- {
- case ALG_ID_ECDH_P256:
- magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
- size = 32;
- break;
- case ALG_ID_ECDSA_P256:
- magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
- size = 32;
- break;
- default:
- FIXME( "algorithm %u not supported\n", alg_id );
- return STATUS_NOT_IMPLEMENTED;
- }
-
- if ((ret = pgnutls_privkey_export_ecc_raw( gnutls_key, &curve, &x, &y, NULL )))
- {
- pgnutls_perror( ret );
- return STATUS_INTERNAL_ERROR;
- }
-
- if (curve != GNUTLS_ECC_CURVE_SECP256R1)
- {
- FIXME( "curve %u not supported\n", curve );
- free( x.data ); free( y.data );
- return STATUS_NOT_IMPLEMENTED;
- }
-
- if (*pubkey_len < sizeof(*ecc_blob) + size * 2)
- {
- FIXME( "wrong pubkey len %u / %lu\n", *pubkey_len, sizeof(*ecc_blob) + size * 2 );
- pgnutls_perror( ret );
- free( x.data ); free( y.data );
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- ecc_blob->dwMagic = magic;
- ecc_blob->cbKey = size;
-
- dst = (UCHAR *)(ecc_blob + 1);
- export_gnutls_datum( dst, size, &x, 1 );
-
- dst += size;
- export_gnutls_datum( dst, size, &y, 1 );
-
- *pubkey_len = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
-
- free( x.data ); free( y.data );
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bitlen, void *pubkey, unsigned *pubkey_len )
-{
- BCRYPT_DSA_KEY_BLOB *dsa_blob = pubkey;
- gnutls_datum_t p, q, g, y;
- UCHAR *dst;
- int ret;
-
- if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
- {
- pgnutls_perror( ret );
- return STATUS_INTERNAL_ERROR;
- }
-
- if (bitlen > 1024)
- {
- FIXME( "bitlen > 1024 not supported\n" );
- return STATUS_NOT_IMPLEMENTED;
- }
-
- if (*pubkey_len < sizeof(*dsa_blob) + bitlen / 8 * 3)
- {
- FIXME( "wrong pubkey len %u / %lu\n", *pubkey_len, sizeof(*dsa_blob) + bitlen / 8 * 3 );
- pgnutls_perror( ret );
- free( p.data ); free( q.data ); free( g.data ); free( y.data );
- return STATUS_NO_MEMORY;
- }
-
- dst = (UCHAR *)(dsa_blob + 1);
- export_gnutls_datum( dst, bitlen / 8, &p, 1 );
-
- dst += bitlen / 8;
- export_gnutls_datum( dst, bitlen / 8, &g, 1 );
-
- dst += bitlen / 8;
- export_gnutls_datum( dst, bitlen / 8, &y, 1 );
-
- dst = dsa_blob->q;
- export_gnutls_datum( dst, sizeof(dsa_blob->q), &q, 1 );
-
- dsa_blob->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
- dsa_blob->cbKey = bitlen / 8;
- memset( dsa_blob->Count, 0, sizeof(dsa_blob->Count) ); /* FIXME */
- memset( dsa_blob->Seed, 0, sizeof(dsa_blob->Seed) ); /* FIXME */
-
- *pubkey_len = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
-
- free( p.data ); free( q.data ); free( g.data ); free( y.data );
- return STATUS_SUCCESS;
-}
-
-static void reverse_bytes( UCHAR *buf, ULONG len )
-{
- unsigned int i;
- UCHAR tmp;
-
- for (i = 0; i < len / 2; ++i)
- {
- tmp = buf[i];
- buf[i] = buf[len - i - 1];
- buf[len - i - 1] = tmp;
- }
-}
-
-#define Q_SIZE 20
-static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, const DSSSEED *seed, unsigned bitlen,
- void *pubkey, unsigned *pubkey_len )
-{
- BLOBHEADER *hdr = pubkey;
- DSSPUBKEY *dsskey;
- gnutls_datum_t p, q, g, y;
- UCHAR *dst;
- int ret, size = sizeof(*hdr) + sizeof(*dsskey) + sizeof(*seed);
-
- if (bitlen > 1024)
- {
- FIXME( "bitlen > 1024 not supported\n" );
- return STATUS_NOT_IMPLEMENTED;
- }
-
- if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
- {
- pgnutls_perror( ret );
- return STATUS_INTERNAL_ERROR;
- }
-
- if (*pubkey_len < size + bitlen / 8 * 3 + Q_SIZE)
- {
- FIXME( "wrong pubkey len %u / %u\n", *pubkey_len, size + bitlen / 8 * 3 + Q_SIZE );
- pgnutls_perror( ret );
- free( p.data ); free( q.data ); free( g.data ); free( y.data );
- return STATUS_NO_MEMORY;
- }
-
- hdr->bType = PUBLICKEYBLOB;
- hdr->bVersion = 2;
- hdr->reserved = 0;
- hdr->aiKeyAlg = CALG_DSS_SIGN;
-
- dsskey = (DSSPUBKEY *)(hdr + 1);
- dsskey->magic = MAGIC_DSS1;
- dsskey->bitlen = bitlen;
-
- dst = (UCHAR *)(dsskey + 1);
- export_gnutls_datum( dst, bitlen / 8, &p, 1 );
- reverse_bytes( dst, bitlen / 8 );
- dst += bitlen / 8;
-
- export_gnutls_datum( dst, Q_SIZE, &q, 1 );
- reverse_bytes( dst, Q_SIZE );
- dst += Q_SIZE;
-
- export_gnutls_datum( dst, bitlen / 8, &g, 1 );
- reverse_bytes( dst, bitlen / 8 );
- dst += bitlen / 8;
-
- export_gnutls_datum( dst, bitlen / 8, &y, 1 );
- reverse_bytes( dst, bitlen / 8 );
- dst += bitlen / 8;
-
- memcpy( dst, seed, sizeof(*seed) );
-
- *pubkey_len = size + bitlen / 8 * 3 + Q_SIZE;
-
- free( p.data ); free( q.data ); free( g.data ); free( y.data );
- return STATUS_SUCCESS;
-}
-
#define EXPORT_SIZE(d,f,p) export_gnutls_datum( NULL, key->u.a.bitlen / f, &d, p )
static NTSTATUS key_export_rsa_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
{
@@ -845,7 +624,7 @@ static NTSTATUS key_export_rsa_public( struct key *key, UCHAR *buf, ULONG len, U
UCHAR *dst;
int ret;
- if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key)->privkey, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
+ if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key)->a.privkey, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -894,7 +673,7 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U
return STATUS_NOT_IMPLEMENTED;
}
- if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->privkey, &curve, &x, &y, NULL )))
+ if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->a.privkey, &curve, &x, &y, NULL )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -931,7 +710,7 @@ static NTSTATUS key_export_dsa_public( struct key *key, UCHAR *buf, ULONG len, U
UCHAR *dst;
int ret;
- if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, NULL )))
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->a.privkey, &p, &q, &g, &y, NULL )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -968,6 +747,19 @@ static NTSTATUS key_export_dsa_public( struct key *key, UCHAR *buf, ULONG len, U
return STATUS_SUCCESS;
}
+static void reverse_bytes( UCHAR *buf, ULONG len )
+{
+ unsigned int i;
+ UCHAR tmp;
+
+ for (i = 0; i < len / 2; ++i)
+ {
+ tmp = buf[i];
+ buf[i] = buf[len - i - 1];
+ buf[len - i - 1] = tmp;
+ }
+}
+
#define Q_SIZE 20
static NTSTATUS key_export_dsa_capi_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
{
@@ -983,7 +775,7 @@ static NTSTATUS key_export_dsa_capi_public( struct key *key, UCHAR *buf, ULONG l
return STATUS_NOT_IMPLEMENTED;
}
- if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, NULL )))
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->a.privkey, &p, &q, &g, &y, NULL )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -1029,13 +821,13 @@ static NTSTATUS key_asymmetric_generate( void *args )
{
struct key *key = args;
gnutls_pk_algorithm_t pk_alg;
- gnutls_privkey_t handle;
+ gnutls_privkey_t privkey;
+ gnutls_pubkey_t pubkey;
unsigned int bitlen;
- NTSTATUS status;
int ret;
if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
- if (key_data(key)->privkey) return STATUS_INVALID_HANDLE;
+ if (key_data(key)->a.privkey) return STATUS_INVALID_HANDLE;
switch (key->alg_id)
{
@@ -1061,45 +853,35 @@ static NTSTATUS key_asymmetric_generate( void *args )
return STATUS_NOT_SUPPORTED;
}
- if ((ret = pgnutls_privkey_init( &handle )))
+ if ((ret = pgnutls_privkey_init( &privkey )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
-
- if ((ret = pgnutls_privkey_generate( handle, pk_alg, bitlen, 0 )))
+ if ((ret = pgnutls_pubkey_init( &pubkey )))
{
pgnutls_perror( ret );
- pgnutls_privkey_deinit( handle );
+ pgnutls_privkey_deinit( privkey );
return STATUS_INTERNAL_ERROR;
}
- switch (pk_alg)
+ if ((ret = pgnutls_privkey_generate( privkey, pk_alg, bitlen, 0 )))
{
- case GNUTLS_PK_RSA:
- status = export_gnutls_pubkey_rsa( handle, key->u.a.bitlen, key->u.a.pubkey, &key->u.a.pubkey_len );
- break;
-
- case GNUTLS_PK_ECC:
- status = export_gnutls_pubkey_ecc( handle, key->alg_id, key->u.a.pubkey, &key->u.a.pubkey_len );
- break;
-
- case GNUTLS_PK_DSA:
- status = export_gnutls_pubkey_dsa( handle, key->u.a.bitlen, key->u.a.pubkey, &key->u.a.pubkey_len );
- break;
-
- default:
- ERR( "unhandled algorithm %u\n", pk_alg );
+ pgnutls_perror( ret );
+ pgnutls_privkey_deinit( privkey );
+ pgnutls_pubkey_deinit( pubkey );
return STATUS_INTERNAL_ERROR;
}
-
- if (status)
+ if ((ret = pgnutls_pubkey_import_privkey( pubkey, privkey, 0, 0 )))
{
- pgnutls_privkey_deinit( handle );
- return status;
+ pgnutls_perror( ret );
+ pgnutls_privkey_deinit( privkey );
+ pgnutls_pubkey_deinit( pubkey );
+ return STATUS_INTERNAL_ERROR;
}
- key_data(key)->privkey = handle;
+ key_data(key)->a.privkey = privkey;
+ key_data(key)->a.pubkey = pubkey;
return STATUS_SUCCESS;
}
@@ -1128,7 +910,7 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r
return STATUS_NOT_IMPLEMENTED;
}
- if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->privkey, &curve, &x, &y, &d )))
+ if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->a.privkey, &curve, &x, &y, &d )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -1168,7 +950,6 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
gnutls_ecc_curve_t curve;
gnutls_privkey_t handle;
gnutls_datum_t x, y, k;
- NTSTATUS status;
int ret;
switch (key->alg_id)
@@ -1204,14 +985,8 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
return STATUS_INTERNAL_ERROR;
}
- if ((status = export_gnutls_pubkey_ecc( handle, key->alg_id, key->u.a.pubkey, &key->u.a.pubkey_len )))
- {
- pgnutls_privkey_deinit( handle );
- return status;
- }
-
- if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
- key_data(key)->privkey = handle;
+ if (key_data(key)->a.privkey) pgnutls_privkey_deinit( key_data(key)->a.privkey );
+ key_data(key)->a.privkey = handle;
return STATUS_SUCCESS;
}
@@ -1224,7 +999,7 @@ static NTSTATUS key_export_rsa( struct key *key, ULONG flags, UCHAR *buf, ULONG
UCHAR *dst;
int ret;
- if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 )))
+ if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key)->a.privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -1301,8 +1076,8 @@ static NTSTATUS key_import_rsa( struct key *key, UCHAR *buf, ULONG len )
return STATUS_INTERNAL_ERROR;
}
- if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
- key_data(key)->privkey = handle;
+ if (key_data(key)->a.privkey) pgnutls_privkey_deinit( key_data(key)->a.privkey );
+ key_data(key)->a.privkey = handle;
return STATUS_SUCCESS;
}
@@ -1314,7 +1089,7 @@ static NTSTATUS key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULO
UCHAR *dst;
int ret, size;
- if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, &x )))
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->a.privkey, &p, &q, &g, &y, &x )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -1374,7 +1149,6 @@ static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
unsigned char dummy[128];
unsigned char *data, p_data[128], q_data[20], g_data[128], x_data[20];
int i, ret, size;
- NTSTATUS status;
if ((ret = pgnutls_privkey_init( &handle )))
{
@@ -1423,29 +1197,24 @@ static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
return STATUS_INTERNAL_ERROR;
}
- if ((status = export_gnutls_pubkey_dsa_capi( handle, &key->u.a.dss_seed, key->u.a.bitlen,
- key->u.a.pubkey, &key->u.a.pubkey_len )))
- {
- pgnutls_privkey_deinit( handle );
- return status;
- }
-
memcpy( &key->u.a.dss_seed, data, sizeof(key->u.a.dss_seed) );
- if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
- key_data(key)->privkey = handle;
+ if (key_data(key)->a.privkey) pgnutls_privkey_deinit( key_data(key)->a.privkey );
+ key_data(key)->a.privkey = handle;
return STATUS_SUCCESS;
}
-static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnutls_key )
+static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len )
{
BCRYPT_ECCKEY_BLOB *ecc_blob;
gnutls_ecc_curve_t curve;
gnutls_datum_t x, y;
+ gnutls_pubkey_t handle;
int ret;
switch (key->alg_id)
{
+ case ALG_ID_ECDH_P256:
case ALG_ID_ECDSA_P256: curve = GNUTLS_ECC_CURVE_SECP256R1; break;
case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break;
@@ -1454,103 +1223,112 @@ static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnut
return STATUS_NOT_IMPLEMENTED;
}
- if ((ret = pgnutls_pubkey_init( gnutls_key )))
+ if ((ret = pgnutls_pubkey_init( &handle )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- ecc_blob = (BCRYPT_ECCKEY_BLOB *)key->u.a.pubkey;
- x.data = key->u.a.pubkey + sizeof(*ecc_blob);
+ ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
+ x.data = buf + sizeof(*ecc_blob);
x.size = ecc_blob->cbKey;
- y.data = key->u.a.pubkey + sizeof(*ecc_blob) + ecc_blob->cbKey;
+ y.data = buf + sizeof(*ecc_blob) + ecc_blob->cbKey;
y.size = ecc_blob->cbKey;
- if ((ret = pgnutls_pubkey_import_ecc_raw( *gnutls_key, curve, &x, &y )))
+ if ((ret = pgnutls_pubkey_import_ecc_raw( handle, curve, &x, &y )))
{
pgnutls_perror( ret );
- pgnutls_pubkey_deinit( *gnutls_key );
+ pgnutls_pubkey_deinit( handle );
return STATUS_INTERNAL_ERROR;
}
+ if (key_data(key)->a.pubkey) pgnutls_pubkey_deinit( key_data(key)->a.pubkey );
+ key_data(key)->a.pubkey = handle;
return STATUS_SUCCESS;
}
-static NTSTATUS import_gnutls_pubkey_rsa( struct key *key, gnutls_pubkey_t *gnutls_key )
+static NTSTATUS key_import_rsa_public( struct key *key, UCHAR *buf, ULONG len )
{
BCRYPT_RSAKEY_BLOB *rsa_blob;
+ gnutls_pubkey_t handle;
gnutls_datum_t m, e;
int ret;
- if ((ret = pgnutls_pubkey_init( gnutls_key )))
+ if ((ret = pgnutls_pubkey_init( &handle )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- rsa_blob = (BCRYPT_RSAKEY_BLOB *)key->u.a.pubkey;
- e.data = key->u.a.pubkey + sizeof(*rsa_blob);
+ rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
+ e.data = buf + sizeof(*rsa_blob);
e.size = rsa_blob->cbPublicExp;
- m.data = key->u.a.pubkey + sizeof(*rsa_blob) + rsa_blob->cbPublicExp;
+ m.data = buf + sizeof(*rsa_blob) + rsa_blob->cbPublicExp;
m.size = rsa_blob->cbModulus;
- if ((ret = pgnutls_pubkey_import_rsa_raw( *gnutls_key, &m, &e )))
+ if ((ret = pgnutls_pubkey_import_rsa_raw( handle, &m, &e )))
{
pgnutls_perror( ret );
- pgnutls_pubkey_deinit( *gnutls_key );
+ pgnutls_pubkey_deinit( handle );
return STATUS_INTERNAL_ERROR;
}
+ if (key_data(key)->a.pubkey) pgnutls_pubkey_deinit( key_data(key)->a.pubkey );
+ key_data(key)->a.pubkey = handle;
return STATUS_SUCCESS;
}
-static NTSTATUS import_gnutls_pubkey_dsa( struct key *key, gnutls_pubkey_t *gnutls_key )
+static NTSTATUS key_import_dsa_public( struct key *key, UCHAR *buf, ULONG len )
{
BCRYPT_DSA_KEY_BLOB *dsa_blob;
gnutls_datum_t p, q, g, y;
+ gnutls_pubkey_t handle;
int ret;
- if ((ret = pgnutls_pubkey_init( gnutls_key )))
+ if ((ret = pgnutls_pubkey_init( &handle )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- dsa_blob = (BCRYPT_DSA_KEY_BLOB *)key->u.a.pubkey;
- p.data = key->u.a.pubkey + sizeof(*dsa_blob);
+ dsa_blob = (BCRYPT_DSA_KEY_BLOB *)buf;
+ p.data = buf + sizeof(*dsa_blob);
p.size = dsa_blob->cbKey;
q.data = dsa_blob->q;
q.size = sizeof(dsa_blob->q);
- g.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey;
+ g.data = buf + sizeof(*dsa_blob) + dsa_blob->cbKey;
g.size = dsa_blob->cbKey;
- y.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey * 2;
+ y.data = buf + sizeof(*dsa_blob) + dsa_blob->cbKey * 2;
y.size = dsa_blob->cbKey;
- if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y )))
+ if ((ret = pgnutls_pubkey_import_dsa_raw( handle, &p, &q, &g, &y )))
{
pgnutls_perror( ret );
- pgnutls_pubkey_deinit( *gnutls_key );
+ pgnutls_pubkey_deinit( handle );
return STATUS_INTERNAL_ERROR;
}
+ if (key_data(key)->a.pubkey) pgnutls_pubkey_deinit( key_data(key)->a.pubkey );
+ key_data(key)->a.pubkey = handle;
return STATUS_SUCCESS;
}
-static NTSTATUS import_gnutls_pubkey_dsa_capi( struct key *key, gnutls_pubkey_t *gnutls_key )
+static NTSTATUS key_import_dsa_capi_public( struct key *key, UCHAR *buf, ULONG len )
{
BLOBHEADER *hdr;
DSSPUBKEY *pubkey;
gnutls_datum_t p, q, g, y;
+ gnutls_pubkey_t handle;
unsigned char *data, p_data[128], q_data[20], g_data[128], y_data[128];
int i, ret, size;
- if ((ret = pgnutls_pubkey_init( gnutls_key )))
+ if ((ret = pgnutls_pubkey_init( &handle )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- hdr = (BLOBHEADER *)key->u.a.pubkey;
+ hdr = (BLOBHEADER *)buf;
pubkey = (DSSPUBKEY *)(hdr + 1);
size = pubkey->bitlen / 8;
data = (unsigned char *)(pubkey + 1);
@@ -1574,40 +1352,18 @@ static NTSTATUS import_gnutls_pubkey_dsa_capi( struct key *key, gnutls_pubkey_t
y.size = sizeof(y_data);
for (i = 0; i < y.size; i++) y.data[i] = data[y.size - i - 1];
- if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y )))
+ if ((ret = pgnutls_pubkey_import_dsa_raw( handle, &p, &q, &g, &y )))
{
pgnutls_perror( ret );
- pgnutls_pubkey_deinit( *gnutls_key );
+ pgnutls_pubkey_deinit( handle );
return STATUS_INTERNAL_ERROR;
}
+ if (key_data(key)->a.pubkey) pgnutls_pubkey_deinit( key_data(key)->a.pubkey );
+ key_data(key)->a.pubkey = handle;
return STATUS_SUCCESS;
}
-static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_key )
-{
- switch (key->alg_id)
- {
- case ALG_ID_ECDSA_P256:
- case ALG_ID_ECDSA_P384:
- return import_gnutls_pubkey_ecc( key, gnutls_key );
-
- case ALG_ID_RSA:
- case ALG_ID_RSA_SIGN:
- return import_gnutls_pubkey_rsa( key, gnutls_key );
-
- case ALG_ID_DSA:
- if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
- return import_gnutls_pubkey_dsa_capi( key, gnutls_key );
- else
- return import_gnutls_pubkey_dsa( key, gnutls_key );
-
- default:
- FIXME("algorithm %u not yet supported\n", key->alg_id );
- return STATUS_NOT_IMPLEMENTED;
- }
-}
-
static NTSTATUS key_asymmetric_export( void *args )
{
const struct key_asymmetric_export_params *params = args;
@@ -1658,26 +1414,21 @@ static NTSTATUS key_asymmetric_import( void *args )
case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384:
if (flags & KEY_IMPORT_FLAG_PUBLIC)
- {
- FIXME("\n");
- return STATUS_SUCCESS;
- }
+ return key_import_ecc_public( key, params->buf, params->len );
return key_import_ecc( key, params->buf, params->len );
case ALG_ID_RSA:
case ALG_ID_RSA_SIGN:
if (flags & KEY_IMPORT_FLAG_PUBLIC)
- {
- FIXME("\n");
- return STATUS_SUCCESS;
- }
+ return key_import_rsa_public( key, params->buf, params->len );
return key_import_rsa( key, params->buf, params->len );
case ALG_ID_DSA:
if (flags & KEY_IMPORT_FLAG_PUBLIC)
{
- FIXME("\n");
- return STATUS_SUCCESS;
+ if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
+ return key_import_dsa_capi_public( key, params->buf, params->len );
+ return key_import_dsa_public( key, params->buf, params->len );
}
if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
return key_import_dsa_capi( key, params->buf, params->len );
@@ -1760,7 +1511,6 @@ static NTSTATUS key_asymmetric_verify( void *args )
gnutls_sign_algorithm_t sign_alg;
gnutls_datum_t gnutls_hash, gnutls_signature;
gnutls_pk_algorithm_t pk_alg;
- gnutls_pubkey_t gnutls_key;
NTSTATUS status;
int ret;
@@ -1824,19 +1574,14 @@ static NTSTATUS key_asymmetric_verify( void *args )
return STATUS_NOT_IMPLEMENTED;
}
- if ((status = import_gnutls_pubkey( key, &gnutls_key ))) return status;
if ((status = prepare_gnutls_signature( key, params->signature, params->signature_len, &gnutls_signature )))
- {
- pgnutls_pubkey_deinit( gnutls_key );
return status;
- }
gnutls_hash.data = params->hash;
gnutls_hash.size = params->hash_len;
- ret = pgnutls_pubkey_verify_hash2( gnutls_key, sign_alg, 0, &gnutls_hash, &gnutls_signature );
+ ret = pgnutls_pubkey_verify_hash2( key_data(key)->a.pubkey, sign_alg, 0, &gnutls_hash, &gnutls_signature );
if (gnutls_signature.data != params->signature) free( gnutls_signature.data );
- pgnutls_pubkey_deinit( gnutls_key );
return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
}
@@ -1975,7 +1720,7 @@ static NTSTATUS key_asymmetric_sign( void *args )
*params->ret_len = key->u.a.bitlen / 8;
return STATUS_SUCCESS;
}
- if (!key_data(key)->privkey) return STATUS_INVALID_PARAMETER;
+ if (!key_data(key)->a.privkey) return STATUS_INVALID_PARAMETER;
hash.data = params->input;
hash.size = params->input_len;
@@ -1983,15 +1728,13 @@ static NTSTATUS key_asymmetric_sign( void *args )
signature.data = NULL;
signature.size = 0;
- if ((ret = pgnutls_privkey_sign_hash( key_data(key)->privkey, hash_alg, 0, &hash, &signature )))
+ if ((ret = pgnutls_privkey_sign_hash( key_data(key)->a.privkey, hash_alg, 0, &hash, &signature )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- status = format_gnutls_signature( key->alg_id, signature, params->output,
- params->output_len, params->ret_len );
-
+ status = format_gnutls_signature( key->alg_id, signature, params->output, params->output_len, params->ret_len );
free( signature.data );
return status;
}
@@ -2000,7 +1743,8 @@ static NTSTATUS key_asymmetric_destroy( void *args )
{
struct key *key = args;
- if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
+ if (key_data(key)->a.privkey) pgnutls_privkey_deinit( key_data(key)->a.privkey );
+ if (key_data(key)->a.pubkey) pgnutls_pubkey_deinit( key_data(key)->a.pubkey );
return STATUS_SUCCESS;
}
@@ -2011,9 +1755,9 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
struct key *key_copy = params->key_copy;
int ret;
- if (!key_data(key_orig)->privkey) return STATUS_SUCCESS;
+ if (!key_data(key_orig)->a.privkey) return STATUS_SUCCESS;
- if ((ret = pgnutls_privkey_init( &key_data(key_copy)->privkey )))
+ if ((ret = pgnutls_privkey_init( &key_data(key_copy)->a.privkey )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -2025,12 +1769,12 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
case ALG_ID_RSA_SIGN:
{
gnutls_datum_t m, e, d, p, q, u, e1, e2;
- if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key_orig)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 )))
+ if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key_orig)->a.privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- ret = pgnutls_privkey_import_rsa_raw( key_data(key_copy)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 );
+ ret = pgnutls_privkey_import_rsa_raw( key_data(key_copy)->a.privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 );
free( m.data ); free( e.data ); free( d.data ); free( p.data ); free( q.data ); free( u.data );
free( e1.data ); free( e2.data );
if (ret)
@@ -2043,12 +1787,12 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
case ALG_ID_DSA:
{
gnutls_datum_t p, q, g, y, x;
- if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key_orig)->privkey, &p, &q, &g, &y, &x )))
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key_orig)->a.privkey, &p, &q, &g, &y, &x )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- ret = pgnutls_privkey_import_dsa_raw( key_data(key_copy)->privkey, &p, &q, &g, &y, &x );
+ ret = pgnutls_privkey_import_dsa_raw( key_data(key_copy)->a.privkey, &p, &q, &g, &y, &x );
free( p.data ); free( q.data ); free( g.data ); free( y.data ); free( x.data );
if (ret)
{
@@ -2063,12 +1807,12 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
{
gnutls_ecc_curve_t curve;
gnutls_datum_t x, y, k;
- if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key_orig)->privkey, &curve, &x, &y, &k )))
+ if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key_orig)->a.privkey, &curve, &x, &y, &k )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- ret = pgnutls_privkey_import_ecc_raw( key_data(key_copy)->privkey, curve, &x, &y, &k );
+ ret = pgnutls_privkey_import_ecc_raw( key_data(key_copy)->a.privkey, curve, &x, &y, &k );
free( x.data ); free( y.data ); free( k.data );
if (ret)
{
@@ -2094,7 +1838,7 @@ static NTSTATUS key_asymmetric_decrypt( void *args )
e.data = params->input;
e.size = params->input_len;
- if ((ret = pgnutls_privkey_decrypt_data( key_data(params->key)->privkey, 0, &e, &d )))
+ if ((ret = pgnutls_privkey_decrypt_data( key_data(params->key)->a.privkey, 0, &e, &d )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
@@ -2187,8 +1931,6 @@ static struct key *get_asymmetric_key( struct key32 *key32, struct key *key )
key->private[1] = key32->private[1];
key->u.a.bitlen = key32->u.a.bitlen;
key->u.a.flags = key32->u.a.flags;
- key->u.a.pubkey = ULongToPtr(key32->u.a.pubkey);
- key->u.a.pubkey_len = key32->u.a.pubkey_len;
key->u.a.dss_seed = key32->u.a.dss_seed;
return key;
}
@@ -2204,7 +1946,6 @@ static void put_asymmetric_key32( struct key *key, struct key32 *key32 )
key32->private[0] = key->private[0];
key32->private[1] = key->private[1];
key32->u.a.flags = key->u.a.flags;
- key32->u.a.pubkey_len = key->u.a.pubkey_len;
key32->u.a.dss_seed = key->u.a.dss_seed;
}
--
2.30.2
1
0
[PATCH 4/6] bcrypt: Merge the various key import Unix calls into one.
by Hans Leidekker March 21, 2022
by Hans Leidekker March 21, 2022
March 21, 2022
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/bcrypt_internal.h | 8 +--
dlls/bcrypt/bcrypt_main.c | 87 ++++++++++++++++------
dlls/bcrypt/gnutls.c | 132 ++++++++++++++++------------------
3 files changed, 132 insertions(+), 95 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index d299def6e11..7342b66479a 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -279,9 +279,11 @@ struct key_asymmetric_export_params
ULONG *ret_len;
};
-struct key_import_params
+#define KEY_IMPORT_FLAG_PUBLIC 0x00000001
+struct key_asymmetric_import_params
{
struct key *key;
+ ULONG flags;
UCHAR *buf;
ULONG len;
};
@@ -303,9 +305,7 @@ enum key_funcs
unix_key_asymmetric_verify,
unix_key_asymmetric_destroy,
unix_key_asymmetric_export,
- unix_key_import_dsa_capi,
- unix_key_import_ecc,
- unix_key_import_rsa,
+ unix_key_asymmetric_import,
};
#endif /* __BCRYPT_INTERNAL_H */
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 408c477b92f..23f30833235 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1339,7 +1339,7 @@ static void key_destroy( struct key *key )
static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
ULONG input_len )
{
- struct key_import_params params;
+ struct key_asymmetric_import_params params;
struct key *key;
NTSTATUS status;
ULONG size;
@@ -1378,7 +1378,19 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
return STATUS_INVALID_PARAMETER;
size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
- return key_asymmetric_create( (struct key **)ret_key, alg->id, key_size * 8, (BYTE *)ecc_blob, size );
+ if ((status = key_asymmetric_create( &key, alg->id, key_size * 8, (BYTE *)ecc_blob, size ))) return status;
+ params.key = key;
+ params.flags = KEY_IMPORT_FLAG_PUBLIC;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
+ {
+ key_destroy( key );
+ return status;
+ }
+
+ *ret_key = key;
+ return STATUS_SUCCESS;
}
else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB ))
{
@@ -1409,11 +1421,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
size = sizeof(*ecc_blob) + key_size * 2;
if ((status = key_asymmetric_create( &key, alg->id, key_size * 8, NULL, size ))) return status;
-
- params.key = key;
- params.buf = input;
- params.len = input_len;
- if ((status = UNIX_CALL( key_import_ecc, ¶ms )))
+ params.key = key;
+ params.flags = 0;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
{
key_destroy( key );
return status;
@@ -1432,7 +1444,20 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
if (size != input_len) return NTE_BAD_DATA;
- return key_asymmetric_create( (struct key **)ret_key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size );
+
+ if ((status = key_asymmetric_create( &key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) return status;
+ params.key = key;
+ params.flags = KEY_IMPORT_FLAG_PUBLIC;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
+ {
+ key_destroy( key );
+ return status;
+ }
+
+ *ret_key = key;
+ return STATUS_SUCCESS;
}
else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB ))
{
@@ -1443,12 +1468,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
rsa_blob->Magic != BCRYPT_RSAFULLPRIVATE_MAGIC)) return STATUS_NOT_SUPPORTED;
size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
- if ((status = key_asymmetric_create( &key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size )))
- return status;
- params.key = key;
- params.buf = input;
- params.len = input_len;
- if ((status = UNIX_CALL( key_import_rsa, ¶ms )))
+ if ((status = key_asymmetric_create( &key, alg->id, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) return status;
+ params.key = key;
+ params.flags = 0;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
{
key_destroy( key );
return status;
@@ -1466,7 +1491,19 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
return STATUS_NOT_SUPPORTED;
size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
- return key_asymmetric_create( (struct key **)ret_key, alg->id, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size );
+ if ((status = key_asymmetric_create( &key, alg->id, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size ))) return status;
+ params.key = key;
+ params.flags = KEY_IMPORT_FLAG_PUBLIC;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
+ {
+ key_destroy( key );
+ return status;
+ }
+
+ *ret_key = key;
+ return STATUS_SUCCESS;
}
else if (!wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB ))
{
@@ -1495,11 +1532,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED);
if ((status = key_asymmetric_create( &key, alg->id, pubkey->bitlen, NULL, size ))) return status;
-
- params.key = key;
- params.buf = input;
- params.len = input_len;
- if ((status = UNIX_CALL( key_import_dsa_capi, ¶ms )))
+ key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
+ params.key = key;
+ params.flags = 0;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
{
key_destroy( key );
return status;
@@ -1531,6 +1569,15 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if ((status = key_asymmetric_create( &key, alg->id, pubkey->bitlen, (BYTE *)hdr, size ))) return status;
key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
+ params.key = key;
+ params.flags = KEY_IMPORT_FLAG_PUBLIC;
+ params.buf = input;
+ params.len = input_len;
+ if ((status = UNIX_CALL( key_asymmetric_import, ¶ms )))
+ {
+ key_destroy( key );
+ return status;
+ }
*ret_key = key;
return STATUS_SUCCESS;
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 01e1fe72092..28119fc9e78 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1162,10 +1162,8 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r
return STATUS_SUCCESS;
}
-static NTSTATUS key_import_ecc( void *args )
+static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
{
- const struct key_import_params *params = args;
- struct key *key = params->key;
BCRYPT_ECCKEY_BLOB *ecc_blob;
gnutls_ecc_curve_t curve;
gnutls_privkey_t handle;
@@ -1191,7 +1189,7 @@ static NTSTATUS key_import_ecc( void *args )
return STATUS_INTERNAL_ERROR;
}
- ecc_blob = (BCRYPT_ECCKEY_BLOB *)params->buf;
+ ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
x.data = (unsigned char *)(ecc_blob + 1);
x.size = ecc_blob->cbKey;
y.data = x.data + ecc_blob->cbKey;
@@ -1212,6 +1210,7 @@ static NTSTATUS key_import_ecc( void *args )
return status;
}
+ if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
key_data(key)->privkey = handle;
return STATUS_SUCCESS;
}
@@ -1273,10 +1272,9 @@ static NTSTATUS key_export_rsa( struct key *key, ULONG flags, UCHAR *buf, ULONG
return STATUS_SUCCESS;
}
-static NTSTATUS key_import_rsa( void *args )
+static NTSTATUS key_import_rsa( struct key *key, UCHAR *buf, ULONG len )
{
- const struct key_import_params *params = args;
- BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)params->buf;
+ BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
gnutls_datum_t m, e, p, q;
gnutls_privkey_t handle;
int ret;
@@ -1303,7 +1301,8 @@ static NTSTATUS key_import_rsa( void *args )
return STATUS_INTERNAL_ERROR;
}
- key_data(params->key)->privkey = handle;
+ if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
+ key_data(key)->privkey = handle;
return STATUS_SUCCESS;
}
@@ -1366,11 +1365,9 @@ static NTSTATUS key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULO
return STATUS_SUCCESS;
}
-static NTSTATUS key_import_dsa_capi( void *args )
+static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
{
- const struct key_import_params *params = args;
- struct key *key = params->key;
- BLOBHEADER *hdr = (BLOBHEADER *)params->buf;
+ BLOBHEADER *hdr = (BLOBHEADER *)buf;
DSSPUBKEY *pubkey;
gnutls_privkey_t handle;
gnutls_datum_t p, q, g, y, x;
@@ -1435,9 +1432,8 @@ static NTSTATUS key_import_dsa_capi( void *args )
memcpy( &key->u.a.dss_seed, data, sizeof(key->u.a.dss_seed) );
- key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
+ if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
key_data(key)->privkey = handle;
-
return STATUS_SUCCESS;
}
@@ -1650,6 +1646,50 @@ static NTSTATUS key_asymmetric_export( void *args )
}
}
+static NTSTATUS key_asymmetric_import( void *args )
+{
+ const struct key_asymmetric_import_params *params = args;
+ struct key *key = params->key;
+ unsigned flags = params->flags;
+
+ switch (key->alg_id)
+ {
+ case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ if (flags & KEY_IMPORT_FLAG_PUBLIC)
+ {
+ FIXME("\n");
+ return STATUS_SUCCESS;
+ }
+ return key_import_ecc( key, params->buf, params->len );
+
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ if (flags & KEY_IMPORT_FLAG_PUBLIC)
+ {
+ FIXME("\n");
+ return STATUS_SUCCESS;
+ }
+ return key_import_rsa( key, params->buf, params->len );
+
+ case ALG_ID_DSA:
+ if (flags & KEY_IMPORT_FLAG_PUBLIC)
+ {
+ FIXME("\n");
+ return STATUS_SUCCESS;
+ }
+ if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
+ return key_import_dsa_capi( key, params->buf, params->len );
+ FIXME( "DSA private key not supported\n" );
+ return STATUS_NOT_IMPLEMENTED;
+
+ default:
+ FIXME( "algorithm %u not yet supported\n", key->alg_id );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
+
static NTSTATUS prepare_gnutls_signature_dsa( struct key *key, UCHAR *signature, ULONG signature_len,
gnutls_datum_t *gnutls_signature )
{
@@ -2085,9 +2125,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
key_asymmetric_verify,
key_asymmetric_destroy,
key_asymmetric_export,
- key_import_dsa_capi,
- key_import_ecc,
- key_import_rsa
+ key_asymmetric_import
};
#ifdef _WIN64
@@ -2477,59 +2515,12 @@ static NTSTATUS wow64_key_asymmetric_export( void *args )
return ret;
}
-static NTSTATUS wow64_key_import_dsa_capi( void *args )
-{
- struct
- {
- PTR32 key;
- PTR32 buf;
- ULONG len;
- } const *params32 = args;
-
- NTSTATUS ret;
- struct key key;
- struct key32 *key32 = ULongToPtr( params32->key );
- struct key_import_params params =
- {
- get_asymmetric_key( key32, &key ),
- ULongToPtr(params32->buf),
- params32->len
- };
-
- ret = key_import_dsa_capi( ¶ms );
- put_asymmetric_key32( &key, key32 );
- return ret;
-}
-
-static NTSTATUS wow64_key_import_ecc( void *args )
-{
- struct
- {
- PTR32 key;
- PTR32 buf;
- ULONG len;
- } const *params32 = args;
-
- NTSTATUS ret;
- struct key key;
- struct key32 *key32 = ULongToPtr( params32->key );
- struct key_import_params params =
- {
- get_asymmetric_key( key32, &key ),
- ULongToPtr(params32->buf),
- params32->len
- };
-
- ret = key_import_ecc( ¶ms );
- put_asymmetric_key32( &key, key32 );
- return ret;
-}
-
-static NTSTATUS wow64_key_import_rsa( void *args )
+static NTSTATUS wow64_key_asymmetric_import( void *args )
{
struct
{
PTR32 key;
+ ULONG flags;
PTR32 buf;
ULONG len;
} const *params32 = args;
@@ -2537,14 +2528,15 @@ static NTSTATUS wow64_key_import_rsa( void *args )
NTSTATUS ret;
struct key key;
struct key32 *key32 = ULongToPtr( params32->key );
- struct key_import_params params =
+ struct key_asymmetric_import_params params =
{
get_asymmetric_key( key32, &key ),
+ params32->flags,
ULongToPtr(params32->buf),
params32->len
};
- ret = key_import_rsa( ¶ms );
+ ret = key_asymmetric_import( ¶ms );
put_asymmetric_key32( &key, key32 );
return ret;
}
@@ -2566,9 +2558,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
wow64_key_asymmetric_verify,
wow64_key_asymmetric_destroy,
wow64_key_asymmetric_export,
- wow64_key_import_dsa_capi,
- wow64_key_import_ecc,
- wow64_key_import_rsa
+ wow64_key_asymmetric_import
};
#endif /* _WIN64 */
--
2.30.2
1
0
[PATCH 3/6] bcrypt: Merge the various key export Unix calls into one.
by Hans Leidekker March 21, 2022
by Hans Leidekker March 21, 2022
March 21, 2022
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/bcrypt_internal.h | 10 +-
dlls/bcrypt/bcrypt_main.c | 46 +++--
dlls/bcrypt/gnutls.c | 336 +++++++++++++++++++++++++---------
3 files changed, 277 insertions(+), 115 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index 6d115e10e54..d299def6e11 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -268,13 +268,15 @@ struct key_asymmetric_verify_params
unsigned flags;
};
-struct key_export_params
+#define KEY_EXPORT_FLAG_PUBLIC 0x00000001
+#define KEY_EXPORT_FLAG_RSA_FULL 0x00000002
+struct key_asymmetric_export_params
{
struct key *key;
+ ULONG flags;
UCHAR *buf;
ULONG len;
ULONG *ret_len;
- BOOL full;
};
struct key_import_params
@@ -300,9 +302,7 @@ enum key_funcs
unix_key_asymmetric_sign,
unix_key_asymmetric_verify,
unix_key_asymmetric_destroy,
- unix_key_export_dsa_capi,
- unix_key_export_ecc,
- unix_key_export_rsa,
+ unix_key_asymmetric_export,
unix_key_import_dsa_capi,
unix_key_import_ecc,
unix_key_import_rsa,
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index ab9cf67923d..408c477b92f 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1070,7 +1070,7 @@ static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRY
static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
{
- struct key_export_params params;
+ struct key_asymmetric_export_params params;
if (!wcscmp( type, BCRYPT_KEY_DATA_BLOB ))
{
@@ -1101,38 +1101,34 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
}
return STATUS_SUCCESS;
}
- else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ) ||
- !wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB ))
+ else if (!wcscmp( type, BCRYPT_DSA_PRIVATE_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB ) ||
+ !wcscmp( type, BCRYPT_ECCPRIVATE_BLOB ))
{
- *size = key->u.a.pubkey_len;
- if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
- if (output) memcpy( output, key->u.a.pubkey, key->u.a.pubkey_len );
- return STATUS_SUCCESS;
- }
- else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB ))
- {
- params.key = key;
- params.buf = output;
- params.len = output_len;
+ params.key = key;
+ params.flags = 0;
+ params.buf = output;
+ params.len = output_len;
params.ret_len = size;
- params.full = wcscmp( type, BCRYPT_RSAPRIVATE_BLOB );
- return UNIX_CALL( key_export_rsa, ¶ms );
+ return UNIX_CALL( key_asymmetric_export, ¶ms );
}
- else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB ))
+ else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB ))
{
- params.key = key;
- params.buf = output;
- params.len = output_len;
+ params.key = key;
+ params.flags = (wcscmp( type, BCRYPT_RSAPRIVATE_BLOB )) ? KEY_EXPORT_FLAG_RSA_FULL : 0;
+ params.buf = output;
+ params.len = output_len;
params.ret_len = size;
- return UNIX_CALL( key_export_ecc, ¶ms );
+ return UNIX_CALL( key_asymmetric_export, ¶ms );
}
- else if (!wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB ))
+ else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB ) ||
+ !wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ))
{
- params.key = key;
- params.buf = output;
- params.len = output_len;
+ params.key = key;
+ params.flags = KEY_EXPORT_FLAG_PUBLIC;
+ params.buf = output;
+ params.len = output_len;
params.ret_len = size;
- return UNIX_CALL( key_export_dsa_capi, ¶ms );
+ return UNIX_CALL( key_asymmetric_export, ¶ms );
}
FIXME( "unsupported key type %s\n", debugstr_w(type) );
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 6862c5cdcf2..01e1fe72092 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -647,6 +647,7 @@ static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bit
free( e.data ); free( m.data );
return STATUS_SUCCESS;
}
+#undef EXPORT_SIZE
static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_id alg_id, void *pubkey,
unsigned *pubkey_len )
@@ -836,6 +837,194 @@ static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, cons
return STATUS_SUCCESS;
}
+#define EXPORT_SIZE(d,f,p) export_gnutls_datum( NULL, key->u.a.bitlen / f, &d, p )
+static NTSTATUS key_export_rsa_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
+{
+ BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
+ gnutls_datum_t m, e;
+ UCHAR *dst;
+ int ret;
+
+ if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key)->privkey, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ *ret_len = sizeof(*rsa_blob) + EXPORT_SIZE(e,8,0) + EXPORT_SIZE(m,8,1);
+ if (len >= *ret_len && buf)
+ {
+ dst = (UCHAR *)(rsa_blob + 1);
+ rsa_blob->cbPublicExp = export_gnutls_datum( dst, key->u.a.bitlen / 8, &e, 0 );
+
+ dst += rsa_blob->cbPublicExp;
+ rsa_blob->cbModulus = export_gnutls_datum( dst, key->u.a.bitlen / 8, &m, 1 );
+
+ rsa_blob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
+ rsa_blob->BitLength = key->u.a.bitlen;
+ rsa_blob->cbPrime1 = 0;
+ rsa_blob->cbPrime2 = 0;
+ }
+
+ free( e.data ); free( m.data );
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
+{
+ BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
+ gnutls_ecc_curve_t curve;
+ gnutls_datum_t x, y;
+ DWORD magic, size;
+ UCHAR *dst;
+ int ret;
+
+ switch (key->alg_id)
+ {
+ case ALG_ID_ECDH_P256:
+ magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
+ size = 32;
+ break;
+ case ALG_ID_ECDSA_P256:
+ magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
+ size = 32;
+ break;
+ default:
+ FIXME( "algorithm %u not supported\n", key->alg_id );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->privkey, &curve, &x, &y, NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (curve != GNUTLS_ECC_CURVE_SECP256R1)
+ {
+ FIXME( "curve %u not supported\n", curve );
+ free( x.data ); free( y.data );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ *ret_len = sizeof(*ecc_blob) + size * 2;
+ if (len >= *ret_len && buf)
+ {
+ ecc_blob->dwMagic = magic;
+ ecc_blob->cbKey = size;
+
+ dst = (UCHAR *)(ecc_blob + 1);
+ export_gnutls_datum( dst, size, &x, 1 );
+
+ dst += size;
+ export_gnutls_datum( dst, size, &y, 1 );
+ }
+
+ free( x.data ); free( y.data );
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS key_export_dsa_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
+{
+ BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)buf;
+ gnutls_datum_t p, q, g, y;
+ UCHAR *dst;
+ int ret;
+
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (key->u.a.bitlen > 1024)
+ {
+ FIXME( "bitlen > 1024 not supported\n" );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ *ret_len = sizeof(*dsa_blob) + key->u.a.bitlen / 8 * 3;
+ if (len >= *ret_len && buf)
+ {
+ dst = (UCHAR *)(dsa_blob + 1);
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &p, 1 );
+
+ dst += key->u.a.bitlen / 8;
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &g, 1 );
+
+ dst += key->u.a.bitlen / 8;
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &y, 1 );
+
+ dst = dsa_blob->q;
+ export_gnutls_datum( dst, sizeof(dsa_blob->q), &q, 1 );
+
+ dsa_blob->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
+ dsa_blob->cbKey = key->u.a.bitlen / 8;
+ memset( dsa_blob->Count, 0, sizeof(dsa_blob->Count) ); /* FIXME */
+ memset( dsa_blob->Seed, 0, sizeof(dsa_blob->Seed) ); /* FIXME */
+ }
+
+ free( p.data ); free( q.data ); free( g.data ); free( y.data );
+ return STATUS_SUCCESS;
+}
+
+#define Q_SIZE 20
+static NTSTATUS key_export_dsa_capi_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
+{
+ BLOBHEADER *hdr = (BLOBHEADER *)buf;
+ DSSPUBKEY *dsskey;
+ gnutls_datum_t p, q, g, y;
+ UCHAR *dst;
+ int ret, size = sizeof(*hdr) + sizeof(*dsskey) + sizeof(key->u.a.dss_seed);
+
+ if (key->u.a.bitlen > 1024)
+ {
+ FIXME( "bitlen > 1024 not supported\n" );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ *ret_len = size + key->u.a.bitlen / 8 * 3 + Q_SIZE;
+ if (len >= *ret_len && buf)
+ {
+ hdr->bType = PUBLICKEYBLOB;
+ hdr->bVersion = 2;
+ hdr->reserved = 0;
+ hdr->aiKeyAlg = CALG_DSS_SIGN;
+
+ dsskey = (DSSPUBKEY *)(hdr + 1);
+ dsskey->magic = MAGIC_DSS1;
+ dsskey->bitlen = key->u.a.bitlen;
+
+ dst = (UCHAR *)(dsskey + 1);
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &p, 1 );
+ reverse_bytes( dst, key->u.a.bitlen / 8 );
+ dst += key->u.a.bitlen / 8;
+
+ export_gnutls_datum( dst, Q_SIZE, &q, 1 );
+ reverse_bytes( dst, Q_SIZE );
+ dst += Q_SIZE;
+
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &g, 1 );
+ reverse_bytes( dst, key->u.a.bitlen / 8 );
+ dst += key->u.a.bitlen / 8;
+
+ export_gnutls_datum( dst, key->u.a.bitlen / 8, &y, 1 );
+ reverse_bytes( dst, key->u.a.bitlen / 8 );
+ dst += key->u.a.bitlen / 8;
+
+ memcpy( dst, &key->u.a.dss_seed, sizeof(key->u.a.dss_seed) );
+ }
+
+ free( p.data ); free( q.data ); free( g.data ); free( y.data );
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS key_asymmetric_generate( void *args )
{
struct key *key = args;
@@ -914,10 +1103,8 @@ static NTSTATUS key_asymmetric_generate( void *args )
return STATUS_SUCCESS;
}
-static NTSTATUS key_export_ecc( void *args )
+static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
{
- const struct key_export_params *params = args;
- struct key *key = params->key;
BCRYPT_ECCKEY_BLOB *ecc_blob;
gnutls_ecc_curve_t curve;
gnutls_datum_t x, y, d;
@@ -954,10 +1141,10 @@ static NTSTATUS key_export_ecc( void *args )
return STATUS_NOT_IMPLEMENTED;
}
- *params->ret_len = sizeof(*ecc_blob) + size * 3;
- if (params->len >= *params->ret_len && params->buf)
+ *ret_len = sizeof(*ecc_blob) + size * 3;
+ if (len >= *ret_len && buf)
{
- ecc_blob = (BCRYPT_ECCKEY_BLOB *)params->buf;
+ ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
ecc_blob->dwMagic = magic;
ecc_blob->cbKey = size;
@@ -1029,13 +1216,12 @@ static NTSTATUS key_import_ecc( void *args )
return STATUS_SUCCESS;
}
-static NTSTATUS key_export_rsa( void *args )
+static NTSTATUS key_export_rsa( struct key *key, ULONG flags, UCHAR *buf, ULONG len, ULONG *ret_len )
{
- const struct key_export_params *params = args;
- struct key *key = params->key;
BCRYPT_RSAKEY_BLOB *rsa_blob;
gnutls_datum_t m, e, d, p, q, u, e1, e2;
ULONG bitlen = key->u.a.bitlen;
+ BOOL full = (flags & KEY_EXPORT_FLAG_RSA_FULL);
UCHAR *dst;
int ret;
@@ -1045,13 +1231,13 @@ static NTSTATUS key_export_rsa( void *args )
return STATUS_INTERNAL_ERROR;
}
- *params->ret_len = sizeof(*rsa_blob) + EXPORT_SIZE(e,8,0) + EXPORT_SIZE(m,8,1) + EXPORT_SIZE(p,16,1) + EXPORT_SIZE(q,16,1);
- if (params->full) *params->ret_len += EXPORT_SIZE(e1,16,1) + EXPORT_SIZE(e2,16,1) + EXPORT_SIZE(u,16,1) + EXPORT_SIZE(d,8,1);
+ *ret_len = sizeof(*rsa_blob) + EXPORT_SIZE(e,8,0) + EXPORT_SIZE(m,8,1) + EXPORT_SIZE(p,16,1) + EXPORT_SIZE(q,16,1);
+ if (full) *ret_len += EXPORT_SIZE(e1,16,1) + EXPORT_SIZE(e2,16,1) + EXPORT_SIZE(u,16,1) + EXPORT_SIZE(d,8,1);
- if (params->len >= *params->ret_len && params->buf)
+ if (len >= *ret_len && buf)
{
- rsa_blob = (BCRYPT_RSAKEY_BLOB *)params->buf;
- rsa_blob->Magic = params->full ? BCRYPT_RSAFULLPRIVATE_MAGIC : BCRYPT_RSAPRIVATE_MAGIC;
+ rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
+ rsa_blob->Magic = full ? BCRYPT_RSAFULLPRIVATE_MAGIC : BCRYPT_RSAPRIVATE_MAGIC;
rsa_blob->BitLength = bitlen;
dst = (UCHAR *)(rsa_blob + 1);
@@ -1066,7 +1252,7 @@ static NTSTATUS key_export_rsa( void *args )
dst += rsa_blob->cbPrime1;
rsa_blob->cbPrime2 = export_gnutls_datum( dst, bitlen / 16, &q, 1 );
- if (params->full)
+ if (full)
{
dst += rsa_blob->cbPrime2;
export_gnutls_datum( dst, bitlen / 16, &e1, 1 );
@@ -1121,10 +1307,8 @@ static NTSTATUS key_import_rsa( void *args )
return STATUS_SUCCESS;
}
-static NTSTATUS key_export_dsa_capi( void *args )
+static NTSTATUS key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
{
- const struct key_export_params *params = args;
- struct key *key = params->key;
BLOBHEADER *hdr;
DSSPUBKEY *pubkey;
gnutls_datum_t p, q, g, y, x;
@@ -1145,10 +1329,10 @@ static NTSTATUS key_export_dsa_capi( void *args )
}
size = key->u.a.bitlen / 8;
- *params->ret_len = sizeof(*hdr) + sizeof(*pubkey) + size * 2 + 40 + sizeof(key->u.a.dss_seed);
- if (params->len >= *params->ret_len && params->buf)
+ *ret_len = sizeof(*hdr) + sizeof(*pubkey) + size * 2 + 40 + sizeof(key->u.a.dss_seed);
+ if (len >= *ret_len && buf)
{
- hdr = (BLOBHEADER *)params->buf;
+ hdr = (BLOBHEADER *)buf;
hdr->bType = PRIVATEKEYBLOB;
hdr->bVersion = 2;
hdr->reserved = 0;
@@ -1428,6 +1612,44 @@ static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_k
}
}
+static NTSTATUS key_asymmetric_export( void *args )
+{
+ const struct key_asymmetric_export_params *params = args;
+ struct key *key = params->key;
+ unsigned flags = params->flags;
+
+ switch (key->alg_id)
+ {
+ case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ if (flags & KEY_EXPORT_FLAG_PUBLIC)
+ return key_export_ecc_public( key, params->buf, params->len, params->ret_len );
+ return key_export_ecc( key, params->buf, params->len, params->ret_len );
+
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ if (flags & KEY_EXPORT_FLAG_PUBLIC)
+ return key_export_rsa_public( key, params->buf, params->len, params->ret_len );
+ return key_export_rsa( key, flags, params->buf, params->len, params->ret_len );
+
+ case ALG_ID_DSA:
+ if (flags & KEY_EXPORT_FLAG_PUBLIC)
+ {
+ if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
+ return key_export_dsa_capi_public( key, params->buf, params->len, params->ret_len );
+ return key_export_dsa_public( key, params->buf, params->len, params->ret_len );
+ }
+ if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
+ return key_export_dsa_capi( key, params->buf, params->len, params->ret_len );
+ return STATUS_NOT_IMPLEMENTED;
+
+ default:
+ FIXME( "algorithm %u not yet supported\n", key->alg_id );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
+
static NTSTATUS prepare_gnutls_signature_dsa( struct key *key, UCHAR *signature, ULONG signature_len,
gnutls_datum_t *gnutls_signature )
{
@@ -1862,9 +2084,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
key_asymmetric_sign,
key_asymmetric_verify,
key_asymmetric_destroy,
- key_export_dsa_capi,
- key_export_ecc,
- key_export_rsa,
+ key_asymmetric_export,
key_import_dsa_capi,
key_import_ecc,
key_import_rsa
@@ -2229,37 +2449,12 @@ static NTSTATUS wow64_key_asymmetric_destroy( void *args )
return key_asymmetric_destroy( get_asymmetric_key( key32, &key ));
}
-static NTSTATUS wow64_key_export_dsa_capi( void *args )
-{
- struct
- {
- PTR32 key;
- PTR32 buf;
- ULONG len;
- PTR32 ret_len;
- } const *params32 = args;
-
- NTSTATUS ret;
- struct key key;
- struct key32 *key32 = ULongToPtr( params32->key );
- struct key_export_params params =
- {
- get_asymmetric_key( key32, &key ),
- ULongToPtr(params32->buf),
- params32->len,
- ULongToPtr(params32->ret_len)
- };
-
- ret = key_export_dsa_capi( ¶ms );
- put_asymmetric_key32( &key, key32 );
- return ret;
-}
-
-static NTSTATUS wow64_key_export_ecc( void *args )
+static NTSTATUS wow64_key_asymmetric_export( void *args )
{
struct
{
PTR32 key;
+ ULONG flags;
PTR32 buf;
ULONG len;
PTR32 ret_len;
@@ -2268,15 +2463,16 @@ static NTSTATUS wow64_key_export_ecc( void *args )
NTSTATUS ret;
struct key key;
struct key32 *key32 = ULongToPtr( params32->key );
- struct key_export_params params =
+ struct key_asymmetric_export_params params =
{
get_asymmetric_key( key32, &key ),
+ params32->flags,
ULongToPtr(params32->buf),
params32->len,
- ULongToPtr(params32->ret_len)
+ ULongToPtr(params32->ret_len),
};
- ret = key_export_ecc( ¶ms );
+ ret = key_asymmetric_export( ¶ms );
put_asymmetric_key32( &key, key32 );
return ret;
}
@@ -2329,34 +2525,6 @@ static NTSTATUS wow64_key_import_ecc( void *args )
return ret;
}
-static NTSTATUS wow64_key_export_rsa( void *args )
-{
- struct
- {
- PTR32 key;
- PTR32 buf;
- ULONG len;
- PTR32 ret_len;
- BOOL full;
- } const *params32 = args;
-
- NTSTATUS ret;
- struct key key;
- struct key32 *key32 = ULongToPtr( params32->key );
- struct key_export_params params =
- {
- get_asymmetric_key( key32, &key ),
- ULongToPtr(params32->buf),
- params32->len,
- ULongToPtr(params32->ret_len),
- params32->full
- };
-
- ret = key_export_rsa( ¶ms );
- put_asymmetric_key32( &key, key32 );
- return ret;
-}
-
static NTSTATUS wow64_key_import_rsa( void *args )
{
struct
@@ -2397,9 +2565,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
wow64_key_asymmetric_sign,
wow64_key_asymmetric_verify,
wow64_key_asymmetric_destroy,
- wow64_key_export_dsa_capi,
- wow64_key_export_ecc,
- wow64_key_export_rsa,
+ wow64_key_asymmetric_export,
wow64_key_import_dsa_capi,
wow64_key_import_ecc,
wow64_key_import_rsa
--
2.30.2
1
0