Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/bcrypt/bcrypt_internal.h | 1 + dlls/bcrypt/bcrypt_main.c | 22 ++++++++++++++++-- dlls/bcrypt/gnutls.c | 43 +++++++++++++++++++++++++++++++++++ dlls/bcrypt/macos.c | 8 +++++++ 4 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index e1777ed130b..eb136111509 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -206,6 +206,7 @@ struct key_funcs void (CDECL *key_symmetric_destroy)( struct key * ); NTSTATUS (CDECL *key_asymmetric_init)( struct key * ); NTSTATUS (CDECL *key_asymmetric_generate)( struct key * ); + NTSTATUS (CDECL *key_asymmetric_decrypt)( struct key *, UCHAR *, ULONG, UCHAR *, 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 ); diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 591c01c710c..a1423dcd836 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1160,8 +1160,8 @@ static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, vo return status; }
-static NTSTATUS key_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 ) +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 ) { ULONG bytes_left = input_len; UCHAR *buf, *src, *dst; @@ -1240,6 +1240,24 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi return status; }
+static NTSTATUS key_asymmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len, UCHAR *output, + ULONG output_len, ULONG *ret_len ) +{ + NTSTATUS status; + + if (!(status = key_funcs->key_asymmetric_decrypt( key, input, input_len, output, &output_len ))) + *ret_len = output_len; + + return status; +} + +static NTSTATUS key_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 ) +{ + return key_is_symmetric( key ) ? key_symmetric_decrypt( key, input, input_len, padding, iv, iv_len, + output, output_len, ret_len, flags ) : key_asymmetric_decrypt( key, input, input_len, output, output_len, ret_len ); +} + static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len ) { diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 162ac9ea732..c065ac31fba 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -109,6 +109,7 @@ static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t, static int (*pgnutls_privkey_import_rsa_raw)(gnutls_privkey_t, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *); +static int (*pgnutls_privkey_decrypt_data)(gnutls_privkey_t, unsigned int flags, const gnutls_datum_t *, gnutls_datum_t *);
/* Not present in gnutls version < 3.6.0 */ static int (*pgnutls_decode_rs_value)(const gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *); @@ -124,6 +125,7 @@ MAKE_FUNCPTR(gnutls_global_init); MAKE_FUNCPTR(gnutls_global_set_log_function); MAKE_FUNCPTR(gnutls_global_set_log_level); MAKE_FUNCPTR(gnutls_perror); +MAKE_FUNCPTR(gnutls_privkey_decrypt_data); MAKE_FUNCPTR(gnutls_privkey_deinit); MAKE_FUNCPTR(gnutls_privkey_import_dsa_raw); MAKE_FUNCPTR(gnutls_privkey_init); @@ -215,6 +217,12 @@ static int compat_gnutls_privkey_import_rsa_raw(gnutls_privkey_t key, const gnut return GNUTLS_E_UNKNOWN_PK_ALGORITHM; }
+static int compat_gnutls_privkey_decrypt_data(gnutls_privkey_t key, unsigned int flags, const gnutls_datum_t *cipher_text, + gnutls_datum_t *plain_text) +{ + return GNUTLS_E_UNKNOWN_PK_ALGORITHM; +} + static void gnutls_log( int level, const char *msg ) { TRACE( "<%d> %s", level, msg ); @@ -341,6 +349,11 @@ static BOOL gnutls_initialize(void) WARN("gnutls_privkey_import_rsa_raw not found\n"); pgnutls_privkey_import_rsa_raw = compat_gnutls_privkey_import_rsa_raw; } + if (!(pgnutls_privkey_decrypt_data = dlsym( libgnutls_handle, "gnutls_privkey_decrypt_data" ))) + { + WARN("gnutls_privkey_decrypt_data not found\n"); + pgnutls_privkey_decrypt_data = compat_gnutls_privkey_decrypt_data; + }
if (TRACE_ON( bcrypt )) { @@ -1883,6 +1896,35 @@ 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 ) +{ + gnutls_datum_t e, d = { 0 }; + NTSTATUS status = STATUS_SUCCESS; + int ret; + + e.data = (unsigned char *)input; + e.size = input_len; + + if ((ret = pgnutls_privkey_decrypt_data( key_data(key)->privkey, 0, &e, &d ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + + if (*output_len >= d.size) + { + *output_len = d.size; + memcpy( output, d.data, *output_len ); + } + else + status = STATUS_BUFFER_TOO_SMALL; + + free( d.data ); + + return status; +} + static const struct key_funcs key_funcs = { key_set_property, @@ -1895,6 +1937,7 @@ static const struct key_funcs key_funcs = key_symmetric_destroy, key_asymmetric_init, key_asymmetric_generate, + key_asymmetric_decrypt, key_asymmetric_duplicate, key_asymmetric_sign, key_asymmetric_verify, diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c index 57edc3e262b..44906519cef 100644 --- a/dlls/bcrypt/macos.c +++ b/dlls/bcrypt/macos.c @@ -271,6 +271,13 @@ static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key return STATUS_NOT_IMPLEMENTED; }
+static NTSTATUS CDECL key_asymmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len, + UCHAR *output, ULONG *output_len ) +{ + FIXME( "not implemented on Mac\n" ); + return STATUS_NOT_IMPLEMENTED; +} + static const struct key_funcs key_funcs = { key_set_property, @@ -283,6 +290,7 @@ static const struct key_funcs key_funcs = key_symmetric_destroy, key_asymmetric_init, key_asymmetric_generate, + key_asymmetric_decrypt, key_asymmetric_duplicate, key_asymmetric_sign, key_asymmetric_verify,