Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/bcrypt/bcrypt_internal.h | 1 + dlls/bcrypt/bcrypt_main.c | 97 +++++++++++++++++++---------------- dlls/bcrypt/gnutls.c | 94 +++++++++++++++++++++++++++++++++ dlls/bcrypt/macos.c | 7 +++ 4 files changed, 155 insertions(+), 44 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 13d6ba8d6c6..463672db470 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -205,6 +205,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_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 * ); diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index a91f31e9f09..b0ea7fce191 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1011,36 +1011,6 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U return STATUS_NOT_IMPLEMENTED; }
-static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) -{ - UCHAR *buffer; - - memset( key_copy, 0, sizeof(*key_copy) ); - key_copy->hdr = key_orig->hdr; - key_copy->alg_id = key_orig->alg_id; - - if (key_is_symmetric( key_orig )) - { - if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY; - memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len ); - - key_copy->u.s.mode = key_orig->u.s.mode; - key_copy->u.s.block_size = key_orig->u.s.block_size; - key_copy->u.s.secret = buffer; - key_copy->u.s.secret_len = key_orig->u.s.secret_len; - } - else - { - 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 ); - - key_copy->u.a.pubkey = buffer; - key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len; - } - - return STATUS_SUCCESS; -} - static NTSTATUS key_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 ) { @@ -1482,6 +1452,56 @@ NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE return key_export( key, type, output, output_len, size ); }
+static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) +{ + UCHAR *buffer; + NTSTATUS status; + + memset( key_copy, 0, sizeof(*key_copy) ); + key_copy->hdr = key_orig->hdr; + key_copy->alg_id = key_orig->alg_id; + + if (key_is_symmetric( key_orig )) + { + if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY; + memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len ); + + key_copy->u.s.mode = key_orig->u.s.mode; + key_copy->u.s.block_size = key_orig->u.s.block_size; + key_copy->u.s.secret = buffer; + key_copy->u.s.secret_len = key_orig->u.s.secret_len; + } + else + { + 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 ); + + key_copy->u.a.pubkey = buffer; + key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len; + + if ((status = key_funcs->key_asymmetric_duplicate( key_orig, key_copy ))) return status; + } + + return STATUS_SUCCESS; +} + +static void key_destroy( struct key *key ) +{ + if (key_is_symmetric( key )) + { + key_funcs->key_symmetric_destroy( key ); + heap_free( key->u.s.vector ); + heap_free( key->u.s.secret ); + } + else + { + key_funcs->key_asymmetric_destroy( key ); + heap_free( key->u.a.pubkey ); + } + key->hdr.magic = 0; + heap_free( key ); +} + NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy, UCHAR *object, ULONG object_len, ULONG flags ) { @@ -1498,7 +1518,7 @@ NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE
if ((status = key_duplicate( key_orig, key_copy ))) { - heap_free( key_copy ); + key_destroy( key_copy ); return status; }
@@ -1564,19 +1584,8 @@ NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle ) TRACE( "%p\n", handle );
if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; - if (key_is_symmetric( key )) - { - key_funcs->key_symmetric_destroy( key ); - heap_free( key->u.s.vector ); - heap_free( key->u.s.secret ); - } - else - { - key_funcs->key_asymmetric_destroy( key ); - heap_free( key->u.a.pubkey ); - } - key->hdr.magic = 0; - heap_free( key ); + + key_destroy( key ); return STATUS_SUCCESS; }
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 94e375cc8cf..5ed51e8704c 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -106,6 +106,9 @@ static int (*pgnutls_privkey_export_rsa_raw)(gnutls_privkey_t, gnutls_datum_t *, static int (*pgnutls_privkey_export_dsa_raw)(gnutls_privkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *); static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t, unsigned int, unsigned int); +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 *);
/* Not present in gnutls version < 3.6.0 */ static int (*pgnutls_decode_rs_value)(const gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *); @@ -205,6 +208,13 @@ static int compat_gnutls_decode_rs_value(const gnutls_datum_t * sig_value, gnutl return GNUTLS_E_INTERNAL_ERROR; }
+static int compat_gnutls_privkey_import_rsa_raw(gnutls_privkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e, + const gnutls_datum_t *d, const gnutls_datum_t *p, const gnutls_datum_t *q, + const gnutls_datum_t *u, const gnutls_datum_t *e1, const gnutls_datum_t *e2) +{ + return GNUTLS_E_UNKNOWN_PK_ALGORITHM; +} + static void gnutls_log( int level, const char *msg ) { TRACE( "<%d> %s", level, msg ); @@ -315,6 +325,11 @@ static BOOL gnutls_initialize(void) WARN("gnutls_decode_rs_value not found\n"); pgnutls_decode_rs_value = compat_gnutls_decode_rs_value; } + if (!(pgnutls_privkey_import_rsa_raw = dlsym( libgnutls_handle, "gnutls_privkey_import_rsa_raw" ))) + { + WARN("gnutls_privkey_import_rsa_raw not found\n"); + pgnutls_privkey_import_rsa_raw = compat_gnutls_privkey_import_rsa_raw; + }
if (TRACE_ON( bcrypt )) { @@ -1733,6 +1748,84 @@ static void CDECL key_asymmetric_destroy( struct key *key ) if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey ); }
+static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key *key_copy ) +{ + int ret; + + if (!key_data(key_orig)->privkey) return STATUS_SUCCESS; + + if ((ret = pgnutls_privkey_init( &key_data(key_copy)->privkey ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + + switch (key_orig->alg_id) + { + case ALG_ID_RSA: + case ALG_ID_RSA_SIGN: + { + gnutls_datum_t m, e, d, p, q, u, e1, e2; + if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key_orig)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + ret = pgnutls_privkey_import_rsa_raw( key_data(key_copy)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 ); + free( m.data ); free( e.data ); free( d.data ); free( p.data ); free( q.data ); free( u.data ); + free( e1.data ); free( e2.data ); + if (ret) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + break; + } + case ALG_ID_DSA: + { + gnutls_datum_t p, q, g, y, x; + if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key_orig)->privkey, &p, &q, &g, &y, &x ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + ret = pgnutls_privkey_import_dsa_raw( key_data(key_copy)->privkey, &p, &q, &g, &y, &x ); + free( p.data ); free( q.data ); free( g.data ); free( y.data ); free( x.data ); + if (ret) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + break; + } + case ALG_ID_ECDH_P256: + case ALG_ID_ECDSA_P256: + case ALG_ID_ECDSA_P384: + { + gnutls_ecc_curve_t curve; + gnutls_datum_t x, y, k; + if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key_orig)->privkey, &curve, &x, &y, &k ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + ret = pgnutls_privkey_import_ecc_raw( key_data(key_copy)->privkey, curve, &x, &y, &k ); + free( x.data ); free( y.data ); free( k.data ); + if (ret) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + break; + } + default: + ERR( "unhandled algorithm %u\n", key_orig->alg_id ); + return STATUS_INTERNAL_ERROR; + } + + return STATUS_SUCCESS; +} + static const struct key_funcs key_funcs = { key_set_property, @@ -1745,6 +1838,7 @@ static const struct key_funcs key_funcs = key_symmetric_destroy, key_asymmetric_init, key_asymmetric_generate, + key_asymmetric_duplicate, key_asymmetric_sign, key_asymmetric_verify, key_asymmetric_destroy, diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c index 37615e97689..d8bba46ad5c 100644 --- a/dlls/bcrypt/macos.c +++ b/dlls/bcrypt/macos.c @@ -259,6 +259,12 @@ static void CDECL key_asymmetric_destroy( struct key *key ) { }
+static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key *key_copy ) +{ + FIXME( "not implemented on Mac\n" ); + return STATUS_NOT_IMPLEMENTED; +} + static const struct key_funcs key_funcs = { key_set_property, @@ -271,6 +277,7 @@ static const struct key_funcs key_funcs = key_symmetric_destroy, key_asymmetric_init, key_asymmetric_generate, + key_asymmetric_duplicate, key_asymmetric_sign, key_asymmetric_verify, key_asymmetric_destroy,