mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 23:14:09 +00:00
bcrypt: Add support for duplicating asymmetric keys.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
af33515989
commit
6decf17305
|
@ -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 * );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue