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 )