From dc3a240a2dc89e5280f37c3b50df86e09705dc70 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 7 Oct 2021 11:19:27 +0200 Subject: [PATCH] bcrypt: Convert the Unix library to the __wine_unix_call() interface. Signed-off-by: Alexandre Julliard --- dlls/bcrypt/Makefile.in | 1 + dlls/bcrypt/bcrypt_internal.h | 126 ++++++++++++++++++--- dlls/bcrypt/bcrypt_main.c | 177 +++++++++++++++++++++-------- dlls/bcrypt/gnutls.c | 203 +++++++++++++++++++--------------- 4 files changed, 355 insertions(+), 152 deletions(-) diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in index 63a731fa9d9..9f3510361c4 100644 --- a/dlls/bcrypt/Makefile.in +++ b/dlls/bcrypt/Makefile.in @@ -1,6 +1,7 @@ MODULE = bcrypt.dll IMPORTS = advapi32 IMPORTLIB = bcrypt +UNIXLIB = bcrypt.so EXTRAINCL = $(GNUTLS_CFLAGS) C_SRCS = \ diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 590e0a666c9..0a600a2ebb5 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -24,8 +24,10 @@ #include "windef.h" #include "winbase.h" +#include "winternl.h" #include "wincrypt.h" #include "bcrypt.h" +#include "wine/unixlib.h" #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24)) #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24)) @@ -195,25 +197,113 @@ struct secret struct object hdr; }; -struct key_funcs +struct key_symmetric_set_auth_data_params { - void (CDECL *key_symmetric_vector_reset)( struct key * ); - NTSTATUS (CDECL *key_symmetric_set_auth_data)( struct key *, UCHAR *, ULONG ); - NTSTATUS (CDECL *key_symmetric_encrypt)( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ); - NTSTATUS (CDECL *key_symmetric_decrypt)( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ); - NTSTATUS (CDECL *key_symmetric_get_tag)( struct key *, UCHAR *, ULONG ); - void (CDECL *key_symmetric_destroy)( struct key * ); - NTSTATUS (CDECL *key_asymmetric_generate)( struct key * ); - NTSTATUS (CDECL *key_asymmetric_decrypt)( struct key *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG * ); - NTSTATUS (CDECL *key_asymmetric_duplicate)( struct key *, struct key * ); - NTSTATUS (CDECL *key_asymmetric_sign)( struct key *, void *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG *, ULONG ); - NTSTATUS (CDECL *key_asymmetric_verify)( struct key *, void *, UCHAR *, ULONG, UCHAR *, ULONG, DWORD ); - void (CDECL *key_asymmetric_destroy)( struct key * ); - NTSTATUS (CDECL *key_export_dsa_capi)( struct key *, UCHAR *, ULONG, ULONG * ); - NTSTATUS (CDECL *key_export_ecc)( struct key *, UCHAR *, ULONG, ULONG * ); - NTSTATUS (CDECL *key_import_dsa_capi)( struct key *, UCHAR *, ULONG ); - NTSTATUS (CDECL *key_import_ecc)( struct key *, UCHAR *, ULONG ); - NTSTATUS (CDECL *key_import_rsa)( struct key *, UCHAR *, ULONG ); + struct key *key; + UCHAR *auth_data; + ULONG len; +}; + +struct key_symmetric_encrypt_params +{ + struct key *key; + const UCHAR *input; + ULONG input_len; + UCHAR *output; + ULONG output_len; +}; + +struct key_symmetric_decrypt_params +{ + struct key *key; + const UCHAR *input; + ULONG input_len; + UCHAR *output; + ULONG output_len; +}; + +struct key_symmetric_get_tag_params +{ + struct key *key; + UCHAR *tag; + ULONG len; +}; + +struct key_asymmetric_decrypt_params +{ + struct key *key; + UCHAR *input; + ULONG input_len; + UCHAR *output; + ULONG output_len; + ULONG *ret_len; +}; + +struct key_asymmetric_duplicate_params +{ + struct key *key_orig; + struct key *key_copy; +}; + +struct key_asymmetric_sign_params +{ + struct key *key; + void *padding; + UCHAR *input; + ULONG input_len; + UCHAR *output; + ULONG output_len; + ULONG *ret_len; + ULONG flags; +}; + +struct key_asymmetric_verify_params +{ + struct key *key; + void *padding; + UCHAR *hash; + ULONG hash_len; + UCHAR *signature; + ULONG signature_len; + ULONG flags; +}; + +struct key_export_params +{ + struct key *key; + UCHAR *buf; + ULONG len; + ULONG *ret_len; +}; + +struct key_import_params +{ + struct key *key; + UCHAR *buf; + ULONG len; +}; + +enum key_funcs +{ + unix_process_attach, + unix_process_detach, + unix_key_symmetric_vector_reset, + unix_key_symmetric_set_auth_data, + unix_key_symmetric_encrypt, + unix_key_symmetric_decrypt, + unix_key_symmetric_get_tag, + unix_key_symmetric_destroy, + unix_key_asymmetric_generate, + unix_key_asymmetric_decrypt, + unix_key_asymmetric_duplicate, + unix_key_asymmetric_sign, + unix_key_asymmetric_verify, + unix_key_asymmetric_destroy, + unix_key_export_dsa_capi, + unix_key_export_ecc, + unix_key_import_dsa_capi, + unix_key_import_ecc, + unix_key_import_rsa, }; #endif /* __BCRYPT_INTERNAL_H */ diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 680dc84768c..9e0d06e9cc7 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -35,9 +35,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(bcrypt); -static HINSTANCE instance; +static unixlib_handle_t bcrypt_handle; + +#define UNIX_CALL( func, params ) __wine_unix_call( bcrypt_handle, unix_ ## func, params ) -static const struct key_funcs *key_funcs; NTSTATUS WINAPI BCryptAddContextFunction(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, ULONG pos) { @@ -964,7 +965,7 @@ static NTSTATUS key_asymmetric_create( struct key **ret_key, struct algorithm *a { struct key *key; - if (!key_funcs) + if (!bcrypt_handle) { ERR( "no encryption support\n" ); return STATUS_NOT_IMPLEMENTED; @@ -1021,7 +1022,7 @@ static NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG memcpy( key->u.s.vector, vector, vector_len ); key->u.s.vector_len = vector_len; } - if (needs_reset) key_funcs->key_symmetric_vector_reset( key ); + if (needs_reset) UNIX_CALL( key_symmetric_vector_reset, key ); return STATUS_SUCCESS; } @@ -1061,6 +1062,8 @@ 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; + if (!wcscmp( type, BCRYPT_KEY_DATA_BLOB )) { BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)output; @@ -1100,11 +1103,19 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U } else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB )) { - return key_funcs->key_export_ecc( key, output, output_len, size ); + params.key = key; + params.buf = output; + params.len = output_len; + params.ret_len = size; + return UNIX_CALL( key_export_ecc, ¶ms ); } else if (!wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB )) { - return key_funcs->key_export_dsa_capi( key, output, output_len, size ); + params.key = key; + params.buf = output; + params.len = output_len; + params.ret_len = size; + return UNIX_CALL( key_export_dsa_capi, ¶ms ); } FIXME( "unsupported key type %s\n", debugstr_w(type) ); @@ -1114,8 +1125,11 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U static NTSTATUS key_symmetric_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags ) { + struct key_symmetric_set_auth_data_params auth_params; + struct key_symmetric_encrypt_params encrypt_params; + struct key_symmetric_get_tag_params tag_params; ULONG bytes_left = input_len; - UCHAR *buf, *src, *dst; + UCHAR *buf; NTSTATUS status; if (key->u.s.mode == MODE_ID_GCM) @@ -1137,11 +1151,22 @@ static NTSTATUS key_symmetric_encrypt( struct key *key, UCHAR *input, ULONG inp if (input && !output) return STATUS_SUCCESS; if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; - if ((status = key_funcs->key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData ))) - return status; - if ((status = key_funcs->key_symmetric_encrypt( key, input, input_len, output, output_len ))) return status; + auth_params.key = key; + auth_params.auth_data = auth_info->pbAuthData; + auth_params.len = auth_info->cbAuthData; + if ((status = UNIX_CALL( key_symmetric_set_auth_data, &auth_params ))) return status; - return key_funcs->key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag ); + encrypt_params.key = key; + encrypt_params.input = input; + encrypt_params.input_len = input_len; + encrypt_params.output = output; + encrypt_params.output_len = output_len; + if ((status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params ))) return status; + + tag_params.key = key; + tag_params.tag = auth_info->pbTag; + tag_params.len = auth_info->cbTag; + return UNIX_CALL( key_symmetric_get_tag, &tag_params ); } *ret_len = input_len; @@ -1156,25 +1181,29 @@ static NTSTATUS key_symmetric_encrypt( struct key *key, UCHAR *input, ULONG inp if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER; if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status; - src = input; - dst = output; + encrypt_params.key = key; + encrypt_params.input = input; + encrypt_params.input_len = key->u.s.block_size; + encrypt_params.output = output; + encrypt_params.output_len = key->u.s.block_size; while (bytes_left >= key->u.s.block_size) { - if ((status = key_funcs->key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size ))) + if ((status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params ))) return status; if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status; bytes_left -= key->u.s.block_size; - src += key->u.s.block_size; - dst += key->u.s.block_size; + encrypt_params.input += key->u.s.block_size; + encrypt_params.output += key->u.s.block_size; } if (flags & BCRYPT_BLOCK_PADDING) { if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY; - memcpy( buf, src, bytes_left ); + memcpy( buf, encrypt_params.input, bytes_left ); memset( buf + bytes_left, key->u.s.block_size - bytes_left, key->u.s.block_size - bytes_left ); - status = key_funcs->key_symmetric_encrypt( key, buf, key->u.s.block_size, dst, key->u.s.block_size ); + encrypt_params.input = buf; + status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params ); heap_free( buf ); } @@ -1184,8 +1213,10 @@ static NTSTATUS key_symmetric_encrypt( struct key *key, UCHAR *input, ULONG inp static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags ) { + struct key_symmetric_set_auth_data_params auth_params; + struct key_symmetric_decrypt_params decrypt_params; + struct key_symmetric_get_tag_params tag_params; ULONG bytes_left = input_len; - UCHAR *buf, *src, *dst; NTSTATUS status; if (key->u.s.mode == MODE_ID_GCM) @@ -1206,11 +1237,22 @@ static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG inpu if (!output) return STATUS_SUCCESS; if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; - if ((status = key_funcs->key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData ))) - return status; - if ((status = key_funcs->key_symmetric_decrypt( key, input, input_len, output, output_len ))) return status; + auth_params.key = key; + auth_params.auth_data = auth_info->pbAuthData; + auth_params.len = auth_info->cbAuthData; + if ((status = UNIX_CALL( key_symmetric_set_auth_data, &auth_params ))) return status; - if ((status = key_funcs->key_symmetric_get_tag( key, tag, sizeof(tag) ))) return status; + decrypt_params.key = key; + decrypt_params.input = input; + decrypt_params.input_len = input_len; + decrypt_params.output = output; + decrypt_params.output_len = output_len; + if ((status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params ))) return status; + + tag_params.key = key; + tag_params.tag = tag; + tag_params.len = sizeof(tag); + if ((status = UNIX_CALL( key_symmetric_get_tag, &tag_params ))) return status; if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) return STATUS_AUTH_TAG_MISMATCH; return STATUS_SUCCESS; @@ -1231,23 +1273,27 @@ static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG inpu if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER; if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status; - src = input; - dst = output; + decrypt_params.key = key; + decrypt_params.input = input; + decrypt_params.input_len = key->u.s.block_size; + decrypt_params.output = output; + decrypt_params.output_len = key->u.s.block_size; while (bytes_left >= key->u.s.block_size) { - if ((status = key_funcs->key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size ))) - return status; + if ((status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params ))) return status; if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status; bytes_left -= key->u.s.block_size; - src += key->u.s.block_size; - dst += key->u.s.block_size; + decrypt_params.input += key->u.s.block_size; + decrypt_params.output += key->u.s.block_size; } if (flags & BCRYPT_BLOCK_PADDING) { + UCHAR *buf, *dst = decrypt_params.output; if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY; - status = key_funcs->key_symmetric_decrypt( key, src, key->u.s.block_size, buf, key->u.s.block_size ); + decrypt_params.output = buf; + status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params ); if (!status && buf[ key->u.s.block_size - 1 ] <= key->u.s.block_size) { *ret_len -= buf[ key->u.s.block_size - 1 ]; @@ -1264,6 +1310,7 @@ static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG inpu 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 *key; NTSTATUS status; ULONG size; @@ -1333,7 +1380,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, key_size * 8, NULL, size ))) return status; - if ((status = key_funcs->key_import_ecc( key, input, input_len ))) + + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_ecc, ¶ms ))) { BCryptDestroyKey( key ); return status; @@ -1364,7 +1415,10 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus; if ((status = key_asymmetric_create( &key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) return status; - if ((status = key_funcs->key_import_rsa( key, input, input_len ))) + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_rsa, ¶ms ))) { BCryptDestroyKey( key ); return status; @@ -1411,7 +1465,11 @@ 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, pubkey->bitlen, NULL, size ))) return status; - if ((status = key_funcs->key_import_dsa_capi( key, input, input_len ))) + + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_dsa_capi, ¶ms ))) { BCryptDestroyKey( key ); return status; @@ -1472,7 +1530,7 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; if (object) FIXME( "ignoring object buffer\n" ); - if (!key_funcs) + if (!bcrypt_handle) { ERR( "no encryption support\n" ); return STATUS_NOT_IMPLEMENTED; @@ -1544,7 +1602,7 @@ NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags ) TRACE( "%p, %08x\n", key, flags ); if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; - return key_funcs->key_asymmetric_generate( key ); + return UNIX_CALL( key_asymmetric_generate, key ); } NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type, @@ -1609,6 +1667,8 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) } else { + struct key_asymmetric_duplicate_params params; + if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY; memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len ); @@ -1618,7 +1678,9 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len; key_copy->u.a.dss_seed = key_orig->u.a.dss_seed; - if ((status = key_funcs->key_asymmetric_duplicate( key_orig, key_copy ))) return status; + params.key_orig = key_orig; + params.key_copy = key_copy; + if ((status = UNIX_CALL( key_asymmetric_duplicate, ¶ms ))) return status; } return STATUS_SUCCESS; @@ -1628,14 +1690,14 @@ static void key_destroy( struct key *key ) { if (key_is_symmetric( key )) { - key_funcs->key_symmetric_destroy( key ); + UNIX_CALL( key_symmetric_destroy, key ); heap_free( key->u.s.vector ); heap_free( key->u.s.secret ); DeleteCriticalSection( &key->u.s.cs ); } else { - key_funcs->key_asymmetric_destroy( key ); + UNIX_CALL( key_asymmetric_destroy, key ); heap_free( key->u.a.pubkey ); } key->hdr.magic = 0; @@ -1688,6 +1750,7 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags ) { + struct key_asymmetric_sign_params params; struct key *key = handle; TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle, padding, input, input_len, output, output_len, @@ -1700,12 +1763,21 @@ NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR * return STATUS_NOT_IMPLEMENTED; } - return key_funcs->key_asymmetric_sign( key, padding, input, input_len, output, output_len, ret_len, flags ); + params.key = key; + params.padding = padding; + params.input = input; + params.input_len = input_len; + params.output = output; + params.output_len = output_len; + params.ret_len = ret_len; + params.flags = flags; + return UNIX_CALL( key_asymmetric_sign, ¶ms ); } NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature, ULONG signature_len, ULONG flags ) { + struct key_asymmetric_verify_params params; struct key *key = handle; TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle, padding, hash, hash_len, signature, signature_len, flags ); @@ -1714,7 +1786,14 @@ NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, if (!hash || !hash_len || !signature || !signature_len) return STATUS_INVALID_PARAMETER; if (key_is_symmetric( key )) return STATUS_NOT_SUPPORTED; - return key_funcs->key_asymmetric_verify( key, padding, hash, hash_len, signature, signature_len, flags ); + params.key = key; + params.padding = padding; + params.hash = hash; + params.hash_len = hash_len; + params.signature = signature; + params.signature_len = signature_len; + params.flags = flags; + return UNIX_CALL( key_asymmetric_verify, ¶ms ); } NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle ) @@ -1759,6 +1838,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags ) { + struct key_asymmetric_decrypt_params params; struct key *key = handle; TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output, @@ -1780,7 +1860,13 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp return ret; } - return key_funcs->key_asymmetric_decrypt( key, input, input_len, output, output_len, ret_len ); + params.key = key; + params.input = input; + params.input_len = input_len; + params.output = output; + params.output_len = output_len; + params.ret_len = ret_len; + return UNIX_CALL( key_asymmetric_decrypt, ¶ms ); } NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) @@ -2004,13 +2090,16 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) switch (reason) { case DLL_PROCESS_ATTACH: - instance = hinst; DisableThreadLibraryCalls( hinst ); - __wine_init_unix_lib( hinst, reason, NULL, &key_funcs ); + if (!NtQueryVirtualMemory( GetCurrentProcess(), hinst, MemoryWineUnixFuncs, + &bcrypt_handle, sizeof(bcrypt_handle), NULL )) + { + if (UNIX_CALL( process_attach, NULL)) bcrypt_handle = 0; + } break; case DLL_PROCESS_DETACH: if (reserved) break; - __wine_init_unix_lib( hinst, reason, NULL, NULL ); + if (bcrypt_handle) UNIX_CALL( process_detach, NULL ); break; } return TRUE; diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 2aeecfedf3d..a015d85f85d 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -229,7 +229,7 @@ static void gnutls_log( int level, const char *msg ) TRACE( "<%d> %s", level, msg ); } -static BOOL gnutls_initialize(void) +static NTSTATUS gnutls_process_attach( void *args ) { const char *env_str; int ret; @@ -247,7 +247,7 @@ static BOOL gnutls_initialize(void) if (!(libgnutls_handle = dlopen( SONAME_LIBGNUTLS, RTLD_NOW ))) { ERR_(winediag)( "failed to load libgnutls, no support for encryption\n" ); - return FALSE; + return STATUS_DLL_NOT_FOUND; } #define LOAD_FUNCPTR(f) \ @@ -310,19 +310,23 @@ static BOOL gnutls_initialize(void) pgnutls_global_set_log_function( gnutls_log ); } - return TRUE; + return STATUS_SUCCESS; fail: dlclose( libgnutls_handle ); libgnutls_handle = NULL; - return FALSE; + return STATUS_DLL_NOT_FOUND; } -static void gnutls_uninitialize(void) +static NTSTATUS gnutls_process_detach( void *args ) { - pgnutls_global_deinit(); - dlclose( libgnutls_handle ); - libgnutls_handle = NULL; + if (libgnutls_handle) + { + pgnutls_global_deinit(); + dlclose( libgnutls_handle ); + libgnutls_handle = NULL; + } + return STATUS_SUCCESS; } struct buffer @@ -470,12 +474,15 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) } } -static void CDECL key_symmetric_vector_reset( struct key *key ) +static NTSTATUS key_symmetric_vector_reset( void *args ) { - if (!key_data(key)->cipher) return; + struct key *key = args; + + if (!key_data(key)->cipher) return STATUS_SUCCESS; TRACE( "invalidating cipher handle\n" ); pgnutls_cipher_deinit( key_data(key)->cipher ); key_data(key)->cipher = NULL; + return STATUS_SUCCESS; } static NTSTATUS init_cipher_handle( struct key *key ) @@ -502,15 +509,16 @@ static NTSTATUS init_cipher_handle( struct key *key ) return STATUS_SUCCESS; } -static NTSTATUS CDECL key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len ) +static NTSTATUS key_symmetric_set_auth_data( void *args ) { + struct key_symmetric_set_auth_data_params *params = args; NTSTATUS status; int ret; - if (!auth_data) return STATUS_SUCCESS; - if ((status = init_cipher_handle( key ))) return status; + if (!params->auth_data) return STATUS_SUCCESS; + if ((status = init_cipher_handle( params->key ))) return status; - if ((ret = pgnutls_cipher_add_auth( key_data(key)->cipher, auth_data, len ))) + if ((ret = pgnutls_cipher_add_auth( key_data(params->key)->cipher, params->auth_data, params->len ))) { pgnutls_perror( ret ); return STATUS_INTERNAL_ERROR; @@ -518,14 +526,16 @@ static NTSTATUS CDECL key_symmetric_set_auth_data( struct key *key, UCHAR *auth_ return STATUS_SUCCESS; } -static NTSTATUS CDECL key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len ) +static NTSTATUS key_symmetric_encrypt( void *args ) { + struct key_symmetric_encrypt_params *params = args; NTSTATUS status; int ret; - if ((status = init_cipher_handle( key ))) return status; + if ((status = init_cipher_handle( params->key ))) return status; - if ((ret = pgnutls_cipher_encrypt2( key_data(key)->cipher, input, input_len, output, output_len ))) + if ((ret = pgnutls_cipher_encrypt2( key_data(params->key)->cipher, params->input, params->input_len, + params->output, params->output_len ))) { pgnutls_perror( ret ); return STATUS_INTERNAL_ERROR; @@ -533,14 +543,16 @@ static NTSTATUS CDECL key_symmetric_encrypt( struct key *key, const UCHAR *input return STATUS_SUCCESS; } -static NTSTATUS CDECL key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len ) +static NTSTATUS key_symmetric_decrypt( void *args ) { + struct key_symmetric_decrypt_params *params = args; NTSTATUS status; int ret; - if ((status = init_cipher_handle( key ))) return status; + if ((status = init_cipher_handle( params->key ))) return status; - if ((ret = pgnutls_cipher_decrypt2( key_data(key)->cipher, input, input_len, output, output_len ))) + if ((ret = pgnutls_cipher_decrypt2( key_data(params->key)->cipher, params->input, params->input_len, + params->output, params->output_len ))) { pgnutls_perror( ret ); return STATUS_INTERNAL_ERROR; @@ -548,14 +560,15 @@ static NTSTATUS CDECL key_symmetric_decrypt( struct key *key, const UCHAR *input return STATUS_SUCCESS; } -static NTSTATUS CDECL key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len ) +static NTSTATUS key_symmetric_get_tag( void *args ) { + struct key_symmetric_get_tag_params *params = args; NTSTATUS status; int ret; - if ((status = init_cipher_handle( key ))) return status; + if ((status = init_cipher_handle( params->key ))) return status; - if ((ret = pgnutls_cipher_tag( key_data(key)->cipher, tag, len ))) + if ((ret = pgnutls_cipher_tag( key_data(params->key)->cipher, params->tag, params->len ))) { pgnutls_perror( ret ); return STATUS_INTERNAL_ERROR; @@ -563,9 +576,12 @@ static NTSTATUS CDECL key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG return STATUS_SUCCESS; } -static void CDECL key_symmetric_destroy( struct key *key ) +static NTSTATUS key_symmetric_destroy( void *args ) { + struct key *key = args; + if (key_data(key)->cipher) pgnutls_cipher_deinit( key_data(key)->cipher ); + return STATUS_SUCCESS; } static void export_gnutls_datum( UCHAR *buffer, ULONG length, gnutls_datum_t *d, ULONG *actual_length ) @@ -820,8 +836,9 @@ static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, cons return STATUS_SUCCESS; } -static NTSTATUS CDECL key_asymmetric_generate( struct key *key ) +static NTSTATUS key_asymmetric_generate( void *args ) { + struct key *key = args; gnutls_pk_algorithm_t pk_alg; gnutls_privkey_t handle; unsigned int bitlen; @@ -896,8 +913,10 @@ static NTSTATUS CDECL key_asymmetric_generate( struct key *key ) return STATUS_SUCCESS; } -static NTSTATUS CDECL key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len ) +static NTSTATUS key_export_ecc( void *args ) { + 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; @@ -934,10 +953,10 @@ static NTSTATUS CDECL key_export_ecc( struct key *key, UCHAR *buf, ULONG len, UL return STATUS_NOT_IMPLEMENTED; } - *ret_len = sizeof(*ecc_blob) + size * 3; - if (len >= *ret_len && buf) + *params->ret_len = sizeof(*ecc_blob) + size * 3; + if (params->len >= *params->ret_len && params->buf) { - ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf; + ecc_blob = (BCRYPT_ECCKEY_BLOB *)params->buf; ecc_blob->dwMagic = magic; ecc_blob->cbKey = size; @@ -955,8 +974,10 @@ static NTSTATUS CDECL key_export_ecc( struct key *key, UCHAR *buf, ULONG len, UL return STATUS_SUCCESS; } -static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) +static NTSTATUS key_import_ecc( void *args ) { + 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; @@ -982,7 +1003,7 @@ static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) return STATUS_INTERNAL_ERROR; } - ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf; + ecc_blob = (BCRYPT_ECCKEY_BLOB *)params->buf; x.data = (unsigned char *)(ecc_blob + 1); x.size = ecc_blob->cbKey; y.data = x.data + ecc_blob->cbKey; @@ -1007,9 +1028,10 @@ static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) return STATUS_SUCCESS; } -static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *buf, ULONG len ) +static NTSTATUS key_import_rsa( void *args ) { - BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf; + struct key_import_params *params = args; + BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)params->buf; gnutls_datum_t m, e, p, q; gnutls_privkey_t handle; int ret; @@ -1036,12 +1058,14 @@ static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *buf, ULONG len ) return STATUS_INTERNAL_ERROR; } - key_data(key)->privkey = handle; + key_data(params->key)->privkey = handle; return STATUS_SUCCESS; } -static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len ) +static NTSTATUS key_export_dsa_capi( void *args ) { + struct key_export_params *params = args; + struct key *key = params->key; BLOBHEADER *hdr; DSSPUBKEY *pubkey; gnutls_datum_t p, q, g, y, x; @@ -1062,10 +1086,10 @@ static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG le } size = key->u.a.bitlen / 8; - *ret_len = sizeof(*hdr) + sizeof(*pubkey) + size * 2 + 40 + sizeof(key->u.a.dss_seed); - if (len >= *ret_len && buf) + *params->ret_len = sizeof(*hdr) + sizeof(*pubkey) + size * 2 + 40 + sizeof(key->u.a.dss_seed); + if (params->len >= *params->ret_len && params->buf) { - hdr = (BLOBHEADER *)buf; + hdr = (BLOBHEADER *)params->buf; hdr->bType = PRIVATEKEYBLOB; hdr->bVersion = 2; hdr->reserved = 0; @@ -1099,9 +1123,11 @@ static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG le return STATUS_SUCCESS; } -static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len ) +static NTSTATUS key_import_dsa_capi( void *args ) { - BLOBHEADER *hdr = (BLOBHEADER *)buf; + struct key_import_params *params = args; + struct key *key = params->key; + BLOBHEADER *hdr = (BLOBHEADER *)params->buf; DSSPUBKEY *pubkey; gnutls_privkey_t handle; gnutls_datum_t p, q, g, y, x; @@ -1116,7 +1142,6 @@ static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG le return STATUS_INTERNAL_ERROR; } - hdr = (BLOBHEADER *)buf; pubkey = (DSSPUBKEY *)(hdr + 1); if ((size = pubkey->bitlen / 8) > sizeof(p_data)) { @@ -1405,9 +1430,11 @@ static gnutls_digest_algorithm_t get_digest_from_id( const WCHAR *alg_id ) return -1; } -static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, - UCHAR *signature, ULONG signature_len, DWORD flags ) +static NTSTATUS key_asymmetric_verify( void *args ) { + struct key_asymmetric_verify_params *params = args; + struct key *key = params->key; + ULONG flags = params->flags; gnutls_digest_algorithm_t hash_alg; gnutls_sign_algorithm_t sign_alg; gnutls_datum_t gnutls_hash, gnutls_signature; @@ -1424,14 +1451,14 @@ static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCH if (flags) FIXME( "flags %08x not supported\n", flags ); /* only the hash size must match, not the actual hash function */ - switch (hash_len) + switch (params->hash_len) { case 20: hash_alg = GNUTLS_DIG_SHA1; break; case 32: hash_alg = GNUTLS_DIG_SHA256; break; case 48: hash_alg = GNUTLS_DIG_SHA384; break; default: - FIXME( "hash size %u not yet supported\n", hash_len ); + FIXME( "hash size %u not yet supported\n", params->hash_len ); return STATUS_INVALID_SIGNATURE; } pk_alg = GNUTLS_PK_ECC; @@ -1440,7 +1467,7 @@ static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCH case ALG_ID_RSA: case ALG_ID_RSA_SIGN: { - BCRYPT_PKCS1_PADDING_INFO *info = (BCRYPT_PKCS1_PADDING_INFO *)padding; + BCRYPT_PKCS1_PADDING_INFO *info = params->padding; if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER; if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE; @@ -1456,9 +1483,9 @@ static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCH case ALG_ID_DSA: { if (flags) FIXME( "flags %08x not supported\n", flags ); - if (hash_len != 20) + if (params->hash_len != 20) { - FIXME( "hash size %u not supported\n", hash_len ); + FIXME( "hash size %u not supported\n", params->hash_len ); return STATUS_INVALID_PARAMETER; } hash_alg = GNUTLS_DIG_SHA1; @@ -1472,22 +1499,22 @@ static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCH if ((sign_alg = pgnutls_pk_to_sign( pk_alg, hash_alg )) == GNUTLS_SIGN_UNKNOWN) { - FIXME("GnuTLS does not support algorithm %u with hash len %u\n", key->alg_id, hash_len ); + FIXME("GnuTLS does not support algorithm %u with hash len %u\n", key->alg_id, params->hash_len ); return STATUS_NOT_IMPLEMENTED; } if ((status = import_gnutls_pubkey( key, &gnutls_key ))) return status; - if ((status = prepare_gnutls_signature( key, signature, signature_len, &gnutls_signature ))) + if ((status = prepare_gnutls_signature( key, params->signature, params->signature_len, &gnutls_signature ))) { pgnutls_pubkey_deinit( gnutls_key ); return status; } - gnutls_hash.data = hash; - gnutls_hash.size = hash_len; + 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 ); - if (gnutls_signature.data != signature) free( gnutls_signature.data ); + if (gnutls_signature.data != params->signature) free( gnutls_signature.data ); pgnutls_pubkey_deinit( gnutls_key ); return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS; } @@ -1555,10 +1582,12 @@ static NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signat } } -static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output, - ULONG output_len, ULONG *ret_len, ULONG flags ) +static NTSTATUS key_asymmetric_sign( void *args ) { - BCRYPT_PKCS1_PADDING_INFO *pad = padding; + struct key_asymmetric_sign_params *params = args; + struct key *key = params->key; + ULONG flags = params->flags; + BCRYPT_PKCS1_PADDING_INFO *pad = params->padding; gnutls_datum_t hash, signature; gnutls_digest_algorithm_t hash_alg; NTSTATUS status; @@ -1567,7 +1596,7 @@ static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384) { /* With ECDSA, we find the digest algorithm from the hash length, and verify it */ - switch (input_len) + switch (params->input_len) { case 20: hash_alg = GNUTLS_DIG_SHA1; break; case 32: hash_alg = GNUTLS_DIG_SHA256; break; @@ -1575,7 +1604,7 @@ static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR case 64: hash_alg = GNUTLS_DIG_SHA512; break; default: - FIXME( "hash size %u not yet supported\n", input_len ); + FIXME( "hash size %u not yet supported\n", params->input_len ); return STATUS_INVALID_PARAMETER; } @@ -1588,9 +1617,9 @@ static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR else if (key->alg_id == ALG_ID_DSA) { if (flags) FIXME( "flags %08x not supported\n", flags ); - if (input_len != 20) + if (params->input_len != 20) { - FIXME( "hash size %u not supported\n", input_len ); + FIXME( "hash size %u not supported\n", params->input_len ); return STATUS_INVALID_PARAMETER; } hash_alg = GNUTLS_DIG_SHA1; @@ -1620,15 +1649,15 @@ static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR return STATUS_NOT_IMPLEMENTED; } - if (!input) + if (!params->input) { - *ret_len = key->u.a.bitlen / 8; + *params->ret_len = key->u.a.bitlen / 8; return STATUS_SUCCESS; } if (!key_data(key)->privkey) return STATUS_INVALID_PARAMETER; - hash.data = input; - hash.size = input_len; + hash.data = params->input; + hash.size = params->input_len; signature.data = NULL; signature.size = 0; @@ -1639,19 +1668,26 @@ static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR return STATUS_INTERNAL_ERROR; } - status = format_gnutls_signature( key->alg_id, signature, output, output_len, ret_len ); + status = format_gnutls_signature( key->alg_id, signature, params->output, + params->output_len, params->ret_len ); free( signature.data ); return status; } -static void CDECL key_asymmetric_destroy( struct key *key ) +static NTSTATUS key_asymmetric_destroy( void *args ) { + struct key *key = args; + if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey ); + return STATUS_SUCCESS; } -static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key *key_copy ) +static NTSTATUS key_asymmetric_duplicate( void *args ) { + struct key_asymmetric_duplicate_params *params = args; + struct key *key_orig = params->key_orig; + struct key *key_copy = params->key_copy; int ret; if (!key_data(key_orig)->privkey) return STATUS_SUCCESS; @@ -1728,31 +1764,33 @@ static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key return STATUS_SUCCESS; } -static NTSTATUS CDECL key_asymmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len, UCHAR *output, - ULONG output_len, ULONG *ret_len ) +static NTSTATUS key_asymmetric_decrypt( void *args ) { + struct key_asymmetric_decrypt_params *params = args; gnutls_datum_t e, d = { 0 }; NTSTATUS status = STATUS_SUCCESS; int ret; - e.data = input; - e.size = input_len; - if ((ret = pgnutls_privkey_decrypt_data( key_data(key)->privkey, 0, &e, &d ))) + e.data = params->input; + e.size = params->input_len; + if ((ret = pgnutls_privkey_decrypt_data( key_data(params->key)->privkey, 0, &e, &d ))) { pgnutls_perror( ret ); return STATUS_INTERNAL_ERROR; } - *ret_len = d.size; - if (output_len >= d.size) memcpy( output, d.data, *ret_len ); + *params->ret_len = d.size; + if (params->output_len >= d.size) memcpy( params->output, d.data, *params->ret_len ); else status = STATUS_BUFFER_TOO_SMALL; free( d.data ); return status; } -static const struct key_funcs key_funcs = +unixlib_entry_t __wine_unix_call_funcs[] = { + gnutls_process_attach, + gnutls_process_detach, key_symmetric_vector_reset, key_symmetric_set_auth_data, key_symmetric_encrypt, @@ -1772,19 +1810,4 @@ static const struct key_funcs key_funcs = key_import_rsa }; -NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND; - *(const struct key_funcs **)ptr_out = &key_funcs; - break; - case DLL_PROCESS_DETACH: - if (libgnutls_handle) gnutls_uninitialize(); - break; - } - return STATUS_SUCCESS; -} - #endif /* HAVE_GNUTLS_CIPHER_INIT */