crypt32: Convert the Unix library to the __wine_unix_call interface.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-10-31 17:09:05 +01:00
parent f18ccfef7b
commit 41663e6ea5
6 changed files with 147 additions and 105 deletions

View file

@ -1,5 +1,6 @@
EXTRADEFS = -D_CRYPT32_
MODULE = crypt32.dll
UNIXLIB = crypt32.so
IMPORTLIB = crypt32
IMPORTS = user32 advapi32 bcrypt
DELAYIMPORTS = cryptnet

View file

@ -20,6 +20,7 @@
#define __CRYPT32_PRIVATE_H__
#include "wine/list.h"
#include "wine/unixlib.h"
BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key) DECLSPEC_HIDDEN;
@ -462,17 +463,53 @@ void init_empty_store(void) DECLSPEC_HIDDEN;
struct cert_store_data;
struct unix_funcs
struct open_cert_store_params
{
BOOL (WINAPI *enum_root_certs)( void *buffer, SIZE_T size, SIZE_T *needed );
BOOL (WINAPI *open_cert_store)( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
struct cert_store_data **data_ret );
NTSTATUS (WINAPI *import_store_key)( struct cert_store_data *data, void *buf, DWORD *buf_size );
NTSTATUS (WINAPI *import_store_cert)( struct cert_store_data *data, unsigned int index,
void *buf, DWORD *buf_size );
void (WINAPI *close_cert_store)( struct cert_store_data *data );
CRYPT_DATA_BLOB *pfx;
const WCHAR *password;
struct cert_store_data **data_ret;
};
extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
struct import_store_key_params
{
struct cert_store_data *data;
void *buf;
DWORD *buf_size;
};
struct import_store_cert_params
{
struct cert_store_data *data;
unsigned int index;
void *buf;
DWORD *buf_size;
};
struct close_cert_store_params
{
struct cert_store_data *data;
};
struct enum_root_certs_params
{
void *buffer;
DWORD size;
DWORD *needed;
};
enum unix_funcs
{
unix_process_attach,
unix_process_detach,
unix_open_cert_store,
unix_import_store_key,
unix_import_store_cert,
unix_close_cert_store,
unix_enum_root_certs,
};
extern unixlib_handle_t crypt32_handle;
#define CRYPT32_CALL( func, params ) __wine_unix_call( crypt32_handle, unix_ ## func, params )
#endif

View file

@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
static HCRYPTPROV hDefProv;
HINSTANCE hInstance;
const struct unix_funcs *unix_funcs = NULL;
unixlib_handle_t crypt32_handle = 0;
static CRITICAL_SECTION prov_param_cs;
static CRITICAL_SECTION_DEBUG prov_param_cs_debug =
@ -55,7 +55,10 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, PVOID pvReserved)
DisableThreadLibraryCalls(hInst);
init_empty_store();
crypt_oid_init();
__wine_init_unix_lib( hInst, reason, NULL, &unix_funcs );
if (NtQueryVirtualMemory( GetCurrentProcess(), hInst, MemoryWineUnixFuncs,
&crypt32_handle, sizeof(crypt32_handle), NULL ))
return FALSE;
CRYPT32_CALL( process_attach, NULL );
break;
case DLL_PROCESS_DETACH:
if (pvReserved) break;
@ -63,7 +66,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, PVOID pvReserved)
crypt_sip_free();
default_chain_engine_free();
if (hDefProv) CryptReleaseContext(hDefProv, 0);
__wine_init_unix_lib( hInst, reason, NULL, NULL );
CRYPT32_CALL( process_detach, NULL );
break;
}
return TRUE;

View file

@ -38,8 +38,9 @@ static HCRYPTPROV import_key( struct cert_store_data *data, DWORD flags )
HCRYPTKEY cryptkey;
DWORD size, acquire_flags;
void *key;
struct import_store_key_params params = { data, NULL, &size };
if (unix_funcs->import_store_key( data, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) return 0;
if (CRYPT32_CALL( import_store_key, &params ) != STATUS_BUFFER_TOO_SMALL) return 0;
acquire_flags = (flags & CRYPT_MACHINE_KEYSET) | CRYPT_NEWKEYSET;
if (!CryptAcquireContextW( &prov, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL, acquire_flags ))
@ -54,8 +55,8 @@ static HCRYPTPROV import_key( struct cert_store_data *data, DWORD flags )
}
}
key = malloc( size );
if (unix_funcs->import_store_key( data, key, &size ) ||
params.buf = key = malloc( size );
if (CRYPT32_CALL( import_store_key, &params ) ||
!CryptImportKey( prov, key, size, 0, flags & CRYPT_EXPORTABLE, &cryptkey ))
{
WARN( "CryptImportKey failed %08x\n", GetLastError() );
@ -145,6 +146,8 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
HCERTSTORE store = NULL;
HCRYPTPROV prov = 0;
struct cert_store_data *data = NULL;
struct open_cert_store_params open_params = { pfx, password, &data };
struct close_cert_store_params close_params;
if (!pfx)
{
@ -156,12 +159,7 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
FIXME( "flags %08x not supported\n", flags );
return NULL;
}
if (!unix_funcs->open_cert_store)
{
FIXME( "(%p, %p, %08x)\n", pfx, password, flags );
return NULL;
}
if (!unix_funcs->open_cert_store( pfx, password, &data )) return NULL;
if (CRYPT32_CALL( open_cert_store, &open_params )) return NULL;
prov = import_key( data, flags );
if (!prov) goto error;
@ -176,10 +174,11 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
{
const void *ctx = NULL;
void *cert;
struct import_store_cert_params import_params = { data, i, NULL, &size };
if (unix_funcs->import_store_cert( data, i, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) break;
cert = malloc( size );
if (!unix_funcs->import_store_cert( data, i++, cert, &size ))
if (CRYPT32_CALL( import_store_cert, &import_params ) != STATUS_BUFFER_TOO_SMALL) break;
import_params.buf = cert = malloc( size );
if (!CRYPT32_CALL( import_store_cert, &import_params ))
ctx = CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT, X509_ASN_ENCODING, cert, size, 0, NULL );
free( cert );
if (!ctx)
@ -209,14 +208,17 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
goto error;
}
CertFreeCertificateContext( ctx );
i++;
}
unix_funcs->close_cert_store( data );
close_params.data = data;
CRYPT32_CALL( close_cert_store, &close_params );
return store;
error:
CryptReleaseContext( prov, 0 );
CertCloseStore( store, 0 );
if (data) unix_funcs->close_cert_store( data );
close_params.data = data;
CRYPT32_CALL( close_cert_store, &close_params );
return NULL;
}

View file

@ -18,6 +18,8 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
@ -615,24 +617,24 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store)
{
HCERTSTORE from = CertOpenStore(CERT_STORE_PROV_MEMORY,
X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
SIZE_T needed, size = 2048;
void *buffer;
DWORD needed;
struct enum_root_certs_params params = { NULL, 2048, &needed };
if (from)
{
buffer = HeapAlloc( GetProcessHeap(), 0, size );
while (unix_funcs->enum_root_certs( buffer, size, &needed ))
params.buffer = malloc( params.size );
while (!CRYPT32_CALL( enum_root_certs, &params ))
{
if (needed > size)
if (needed > params.size)
{
HeapFree( GetProcessHeap(), 0, buffer );
buffer = HeapAlloc( GetProcessHeap(), 0, needed );
size = needed;
free( params.buffer );
params.buffer = malloc( needed );
params.size = needed;
}
else CertAddEncodedCertificateToStore( from, X509_ASN_ENCODING, buffer, needed,
else CertAddEncodedCertificateToStore( from, X509_ASN_ENCODING, params.buffer, needed,
CERT_STORE_ADD_NEW, NULL );
}
HeapFree( GetProcessHeap(), 0, buffer );
free( params.buffer );
check_and_store_certs(from, store);
}
CertCloseStore(from, 0);

View file

@ -21,15 +21,14 @@
#endif
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_SYS_STAT_H
#include <dlfcn.h>
#include <sys/stat.h>
#endif
#ifdef HAVE_SECURITY_SECURITY_H
#include <Security/Security.h>
#endif
@ -43,11 +42,8 @@
#include "winbase.h"
#include "winternl.h"
#include "wincrypt.h"
#include "snmp.h"
#include "crypt32_private.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@ -84,7 +80,7 @@ static void gnutls_log( int level, const char *msg )
TRACE( "<%d> %s", level, msg );
}
static BOOL gnutls_initialize(void)
static NTSTATUS process_attach( void *args )
{
const char *env_str;
int ret;
@ -102,7 +98,7 @@ static BOOL gnutls_initialize(void)
if (!(libgnutls_handle = dlopen( SONAME_LIBGNUTLS, RTLD_NOW )))
{
ERR_(winediag)( "failed to load libgnutls, no support for pfx import/export\n" );
return FALSE;
return STATUS_DLL_NOT_FOUND;
}
#define LOAD_FUNCPTR(f) \
@ -143,14 +139,15 @@ static BOOL gnutls_initialize(void)
fail:
dlclose( libgnutls_handle );
libgnutls_handle = NULL;
return FALSE;
return STATUS_DLL_INIT_FAILED;
}
static void gnutls_uninitialize(void)
static NTSTATUS process_detach( void *args )
{
pgnutls_global_deinit();
dlclose( libgnutls_handle );
libgnutls_handle = NULL;
return STATUS_SUCCESS;
}
#define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
#define RSA_PUBEXP 65537
@ -164,8 +161,10 @@ struct cert_store_data
unsigned int chain_len;
};
static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf, DWORD *buf_size )
static NTSTATUS import_store_key( void *args )
{
struct import_store_key_params *params = args;
struct cert_store_data *data = params->data;
int i, ret;
unsigned int bitlen = data->key_bitlen;
gnutls_datum_t m, e, d, p, q, u, e1, e2;
@ -175,9 +174,9 @@ static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf
DWORD size;
size = sizeof(*hdr) + sizeof(*rsakey) + (bitlen * 9 / 16);
if (!buf || *buf_size < size)
if (!params->buf || *params->buf_size < size)
{
*buf_size = size;
*params->buf_size = size;
return STATUS_BUFFER_TOO_SMALL;
}
@ -187,7 +186,7 @@ static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf
return STATUS_INVALID_PARAMETER;
}
hdr = (BLOBHEADER *)buf;
hdr = params->buf;
hdr->bType = PRIVATEKEYBLOB;
hdr->bVersion = CUR_BLOB_VERSION;
hdr->reserved = 0;
@ -261,9 +260,9 @@ static char *password_to_ascii( const WCHAR *str )
return ret;
}
static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
struct cert_store_data **data_ret )
static NTSTATUS open_cert_store( void *args )
{
struct open_cert_store_params *params = args;
gnutls_pkcs12_t p12;
gnutls_datum_t pfx_data;
gnutls_x509_privkey_t key;
@ -274,12 +273,13 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
int ret;
struct cert_store_data *store_data;
if (password && !(pwd = password_to_ascii( password ))) return FALSE;
if (!libgnutls_handle) return STATUS_DLL_NOT_FOUND;
if (params->password && !(pwd = password_to_ascii( params->password ))) return STATUS_NO_MEMORY;
if ((ret = pgnutls_pkcs12_init( &p12 )) < 0) goto error;
pfx_data.data = pfx->pbData;
pfx_data.size = pfx->cbData;
pfx_data.data = params->pfx->pbData;
pfx_data.size = params->pfx->cbData;
if ((ret = pgnutls_pkcs12_import( p12, &pfx_data, GNUTLS_X509_FMT_DER, 0 )) < 0) goto error;
if ((ret = pgnutls_pkcs12_simple_parse( p12, pwd ? pwd : "", &key, &chain, &chain_len, NULL, NULL, NULL, 0 )) < 0)
@ -294,7 +294,7 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
{
FIXME( "key algorithm %u not supported\n", ret );
pgnutls_pkcs12_deinit( p12 );
return FALSE;
return STATUS_INVALID_PARAMETER;
}
store_data = malloc( sizeof(*store_data) );
@ -303,44 +303,60 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
store_data->chain = chain;
store_data->key_bitlen = bitlen;
store_data->chain_len = chain_len;
*data_ret = store_data;
return TRUE;
*params->data_ret = store_data;
return STATUS_SUCCESS;
error:
pgnutls_perror( ret );
pgnutls_pkcs12_deinit( p12 );
free( pwd );
return FALSE;
return STATUS_INVALID_PARAMETER;
}
static NTSTATUS WINAPI import_store_cert( struct cert_store_data *data, unsigned int index,
void *buf, DWORD *buf_size )
static NTSTATUS import_store_cert( void *args )
{
struct import_store_cert_params *params = args;
struct cert_store_data *data = params->data;
size_t size = 0;
int ret;
if (index >= data->chain_len) return STATUS_NO_MORE_ENTRIES;
if (params->index >= data->chain_len) return STATUS_NO_MORE_ENTRIES;
if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER)
if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER)
return STATUS_INVALID_PARAMETER;
if (!buf || *buf_size < size)
if (!params->buf || *params->buf_size < size)
{
*buf_size = size;
*params->buf_size = size;
return STATUS_BUFFER_TOO_SMALL;
}
if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, buf, &size )) < 0)
if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, params->buf, &size )) < 0)
return STATUS_INVALID_PARAMETER;
return STATUS_SUCCESS;
}
static void WINAPI close_cert_store( struct cert_store_data *data )
static NTSTATUS close_cert_store( void *args )
{
pgnutls_pkcs12_deinit( data->p12 );
free( data );
struct close_cert_store_params *params = args;
if (params->data)
{
pgnutls_pkcs12_deinit( params->data->p12 );
free( params->data );
}
return STATUS_SUCCESS;
}
#else /* SONAME_LIBGNUTLS */
static NTSTATUS process_attach( void *args ) { return STATUS_SUCCESS; }
static NTSTATUS process_detach( void *args ) { return STATUS_SUCCESS; }
static NTSTATUS open_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; }
static NTSTATUS import_store_key( void *args ) { return STATUS_DLL_NOT_FOUND; }
static NTSTATUS import_store_cert( void *args ) { return STATUS_DLL_NOT_FOUND; }
static NTSTATUS close_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; }
#endif /* SONAME_LIBGNUTLS */
struct root_cert
@ -640,8 +656,9 @@ static void load_root_certs(void)
import_certs_from_path( CRYPT_knownLocations[i], TRUE );
}
static BOOL WINAPI enum_root_certs( void *buffer, SIZE_T size, SIZE_T *needed )
static NTSTATUS enum_root_certs( void *args )
{
struct enum_root_certs_params *params = args;
static BOOL loaded;
struct list *ptr;
struct root_cert *cert;
@ -649,45 +666,25 @@ static BOOL WINAPI enum_root_certs( void *buffer, SIZE_T size, SIZE_T *needed )
if (!loaded) load_root_certs();
loaded = TRUE;
if (!(ptr = list_head( &root_cert_list ))) return FALSE;
if (!(ptr = list_head( &root_cert_list ))) return STATUS_NO_MORE_ENTRIES;
cert = LIST_ENTRY( ptr, struct root_cert, entry );
*needed = cert->size;
if (cert->size <= size)
*params->needed = cert->size;
if (cert->size <= params->size)
{
memcpy( buffer, cert->data, cert->size );
memcpy( params->buffer, cert->data, cert->size );
list_remove( &cert->entry );
free( cert );
}
return TRUE;
}
static struct unix_funcs funcs =
{
enum_root_certs,
NULL
};
NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
#ifdef SONAME_LIBGNUTLS
if (gnutls_initialize())
{
funcs.open_cert_store = open_cert_store;
funcs.import_store_key = import_store_key;
funcs.import_store_cert = import_store_cert;
funcs.close_cert_store = close_cert_store;
}
#endif
*(const struct unix_funcs **)ptr_out = &funcs;
break;
case DLL_PROCESS_DETACH:
#ifdef SONAME_LIBGNUTLS
if (libgnutls_handle) gnutls_uninitialize();
#endif
break;
}
return STATUS_SUCCESS;
}
unixlib_entry_t __wine_unix_call_funcs[] =
{
process_attach,
process_detach,
open_cert_store,
import_store_key,
import_store_cert,
close_cert_store,
enum_root_certs,
};