Nikolay Sivov : bcrypt: Add initial support for asymmetric keys in BCryptDecrypt().

Alexandre Julliard julliard at winehq.org
Fri Dec 4 14:36:03 CST 2020


Module: wine
Branch: master
Commit: 38d9020f29dad8d6d76916826da7a59ac308d92e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=38d9020f29dad8d6d76916826da7a59ac308d92e

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Dec  4 16:40:06 2020 +0300

bcrypt: Add initial support for asymmetric keys in BCryptDecrypt().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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,




More information about the wine-cvs mailing list