Nikolay Sivov : bcrypt: Implement RSA key pair importing.

Alexandre Julliard julliard at winehq.org
Thu Dec 3 15:35:58 CST 2020


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Dec  3 09:02:35 2020 +0300

bcrypt: Implement RSA key pair importing.

Requires libgnutls 3.7.0, that contains fixes for optional arguments handling
in gnutls_privkey_import_rsa_raw() to support BCRYPT_RSAPRIVATE_BLOB.

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     | 21 +++++++++++++++++++++
 dlls/bcrypt/gnutls.c          | 36 +++++++++++++++++++++++++++++++++++-
 dlls/bcrypt/macos.c           |  9 ++++++++-
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index d5a54aad92b..e1777ed130b 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -214,6 +214,7 @@ struct key_funcs
     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 );
 };
 
 #endif /* __BCRYPT_INTERNAL_H */
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 1b7881d4910..591c01c710c 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1331,6 +1331,27 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
         size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
         return key_asymmetric_create( (struct key **)ret_key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size );
     }
+    else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ))
+    {
+        BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
+        ULONG size;
+
+        if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
+        if (alg->id != ALG_ID_RSA || rsa_blob->Magic != BCRYPT_RSAPRIVATE_MAGIC)
+            return STATUS_NOT_SUPPORTED;
+
+        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 )))
+        {
+            BCryptDestroyKey( key );
+            return status;
+        }
+
+        *ret_key = key;
+        return STATUS_SUCCESS;
+    }
     else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ))
     {
         BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 41df88ca8f6..162ac9ea732 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1119,6 +1119,39 @@ 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 )
+{
+    BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
+    gnutls_datum_t m, e, p, q;
+    gnutls_privkey_t handle;
+    int ret;
+
+    if ((ret = pgnutls_privkey_init( &handle )))
+    {
+        pgnutls_perror( ret );
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    e.data = (unsigned char *)(rsa_blob + 1);
+    e.size = rsa_blob->cbPublicExp;
+    m.data = e.data + e.size;
+    m.size = rsa_blob->cbModulus;
+    p.data = m.data + m.size;
+    p.size = rsa_blob->cbPrime1;
+    q.data = p.data + p.size;
+    q.size = rsa_blob->cbPrime2;
+
+    if ((ret = pgnutls_privkey_import_rsa_raw( handle, &m, &e, NULL, &p, &q, NULL, NULL, NULL )))
+    {
+        pgnutls_perror( ret );
+        pgnutls_privkey_deinit( handle );
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    key_data(key)->privkey = handle;
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
 {
     BLOBHEADER *hdr;
@@ -1869,7 +1902,8 @@ static const struct key_funcs key_funcs =
     key_export_dsa_capi,
     key_export_ecc,
     key_import_dsa_capi,
-    key_import_ecc
+    key_import_ecc,
+    key_import_rsa
 };
 
 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c
index d8bba46ad5c..57edc3e262b 100644
--- a/dlls/bcrypt/macos.c
+++ b/dlls/bcrypt/macos.c
@@ -249,6 +249,12 @@ static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *input, ULONG len )
     return STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *input, ULONG len )
+{
+    FIXME( "not implemented on Mac\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS CDECL key_asymmetric_generate( struct key *key )
 {
     FIXME( "not implemented on Mac\n" );
@@ -284,7 +290,8 @@ static const struct key_funcs key_funcs =
     key_export_dsa_capi,
     key_export_ecc,
     key_import_dsa_capi,
-    key_import_ecc
+    key_import_ecc,
+    key_import_rsa
 };
 
 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )




More information about the wine-cvs mailing list