bcrypt: Split the key structure into generic and backend-specific parts.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-09-29 15:27:32 +02:00
parent f0e1384777
commit 209b968efc
3 changed files with 58 additions and 103 deletions

View File

@ -21,14 +21,6 @@
#define __BCRYPT_INTERNAL_H #define __BCRYPT_INTERNAL_H
#include <stdarg.h> #include <stdarg.h>
#ifdef HAVE_GNUTLS_CIPHER_INIT
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <gnutls/abstract.h>
#elif HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
#include <AvailabilityMacros.h>
#include <CommonCrypto/CommonCryptor.h>
#endif
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
@ -162,12 +154,10 @@ struct algorithm
ULONG flags; ULONG flags;
}; };
#if defined(HAVE_GNUTLS_CIPHER_INIT)
struct key_symmetric struct key_symmetric
{ {
enum mode_id mode; enum mode_id mode;
ULONG block_size; ULONG block_size;
gnutls_cipher_hd_t handle;
UCHAR *vector; UCHAR *vector;
ULONG vector_len; ULONG vector_len;
UCHAR *secret; UCHAR *secret;
@ -176,7 +166,6 @@ struct key_symmetric
struct key_asymmetric struct key_asymmetric
{ {
gnutls_privkey_t handle;
ULONG bitlen; /* ignored for ECC keys */ ULONG bitlen; /* ignored for ECC keys */
UCHAR *pubkey; UCHAR *pubkey;
ULONG pubkey_len; ULONG pubkey_len;
@ -187,71 +176,13 @@ struct key
{ {
struct object hdr; struct object hdr;
enum alg_id alg_id; enum alg_id alg_id;
void *private[2]; /* private data for backend */
union union
{ {
struct key_symmetric s; struct key_symmetric s;
struct key_asymmetric a; struct key_asymmetric a;
} u; } u;
}; };
#elif defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
struct key_symmetric
{
enum mode_id mode;
ULONG block_size;
CCCryptorRef ref_encrypt;
CCCryptorRef ref_decrypt;
UCHAR *vector;
ULONG vector_len;
UCHAR *secret;
ULONG secret_len;
};
struct key_asymmetric
{
ULONG bitlen;
UCHAR *pubkey;
ULONG pubkey_len;
};
struct key
{
struct object hdr;
enum alg_id alg_id;
union
{
struct key_symmetric s;
struct key_asymmetric a;
} u;
};
#else
struct key_symmetric
{
enum mode_id mode;
ULONG block_size;
UCHAR *vector;
ULONG vector_len;
UCHAR *secret;
ULONG secret_len;
};
struct key_asymmetric
{
ULONG bitlen; /* ignored for ECC keys */
UCHAR *pubkey;
ULONG pubkey_len;
};
struct key
{
struct object hdr;
enum alg_id alg_id;
union
{
struct key_symmetric s;
struct key_asymmetric a;
} u;
};
#endif
struct secret struct secret
{ {

View File

@ -64,6 +64,18 @@ typedef enum
} gnutls_ecc_curve_t; } gnutls_ecc_curve_t;
#endif #endif
union key_data
{
gnutls_cipher_hd_t cipher;
gnutls_privkey_t privkey;
};
C_ASSERT( sizeof(union key_data) <= sizeof(((struct key *)0)->private) );
static union key_data *key_data( struct key *key )
{
return (union key_data *)key->private;
}
/* Not present in gnutls version < 3.0 */ /* Not present in gnutls version < 3.0 */
static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t, void *, size_t); static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t, void *, size_t);
static int (*pgnutls_cipher_add_auth)(gnutls_cipher_hd_t, const void *, size_t); static int (*pgnutls_cipher_add_auth)(gnutls_cipher_hd_t, const void *, size_t);
@ -502,10 +514,10 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
void key_symmetric_vector_reset( struct key *key ) void key_symmetric_vector_reset( struct key *key )
{ {
if (!key->u.s.handle) return; if (!key_data(key)->cipher) return;
TRACE( "invalidating cipher handle\n" ); TRACE( "invalidating cipher handle\n" );
pgnutls_cipher_deinit( key->u.s.handle ); pgnutls_cipher_deinit( key_data(key)->cipher );
key->u.s.handle = NULL; key_data(key)->cipher = NULL;
} }
static NTSTATUS init_cipher_handle( struct key *key ) static NTSTATUS init_cipher_handle( struct key *key )
@ -514,7 +526,7 @@ static NTSTATUS init_cipher_handle( struct key *key )
gnutls_datum_t secret, vector; gnutls_datum_t secret, vector;
int ret; int ret;
if (key->u.s.handle) return STATUS_SUCCESS; if (key_data(key)->cipher) return STATUS_SUCCESS;
if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) return STATUS_NOT_SUPPORTED; if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) return STATUS_NOT_SUPPORTED;
secret.data = key->u.s.secret; secret.data = key->u.s.secret;
@ -523,7 +535,7 @@ static NTSTATUS init_cipher_handle( struct key *key )
vector.data = key->u.s.vector; vector.data = key->u.s.vector;
vector.size = key->u.s.vector_len; vector.size = key->u.s.vector_len;
if ((ret = pgnutls_cipher_init( &key->u.s.handle, cipher, &secret, key->u.s.vector ? &vector : NULL ))) if ((ret = pgnutls_cipher_init( &key_data(key)->cipher, cipher, &secret, key->u.s.vector ? &vector : NULL )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -540,7 +552,7 @@ NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG l
if (!auth_data) return STATUS_SUCCESS; if (!auth_data) return STATUS_SUCCESS;
if ((status = init_cipher_handle( key ))) return status; if ((status = init_cipher_handle( key ))) return status;
if ((ret = pgnutls_cipher_add_auth( key->u.s.handle, auth_data, len ))) if ((ret = pgnutls_cipher_add_auth( key_data(key)->cipher, auth_data, len )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -555,7 +567,7 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
if ((status = init_cipher_handle( key ))) return status; if ((status = init_cipher_handle( key ))) return status;
if ((ret = pgnutls_cipher_encrypt2( key->u.s.handle, input, input_len, output, output_len ))) if ((ret = pgnutls_cipher_encrypt2( key_data(key)->cipher, input, input_len, output, output_len )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -570,7 +582,7 @@ NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input
if ((status = init_cipher_handle( key ))) return status; if ((status = init_cipher_handle( key ))) return status;
if ((ret = pgnutls_cipher_decrypt2( key->u.s.handle, input, input_len, output, output_len ))) if ((ret = pgnutls_cipher_decrypt2( key_data(key)->cipher, input, input_len, output, output_len )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -585,7 +597,7 @@ NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
if ((status = init_cipher_handle( key ))) return status; if ((status = init_cipher_handle( key ))) return status;
if ((ret = pgnutls_cipher_tag( key->u.s.handle, tag, len ))) if ((ret = pgnutls_cipher_tag( key_data(key)->cipher, tag, len )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -595,7 +607,7 @@ NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
void key_symmetric_destroy( struct key *key ) void key_symmetric_destroy( struct key *key )
{ {
if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle ); if (key_data(key)->cipher) pgnutls_cipher_deinit( key_data(key)->cipher );
} }
static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len ) static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
@ -861,7 +873,7 @@ NTSTATUS key_asymmetric_generate( struct key *key )
return status; return status;
} }
key->u.a.handle = handle; key_data(key)->privkey = handle;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -890,7 +902,7 @@ NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
if ((ret = pgnutls_privkey_export_ecc_raw( key->u.a.handle, &curve, &x, &y, &d ))) if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->privkey, &curve, &x, &y, &d )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -978,7 +990,7 @@ NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
return status; return status;
} }
key->u.a.handle = handle; key_data(key)->privkey = handle;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -990,7 +1002,7 @@ NTSTATUS key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret
UCHAR *src, *dst; UCHAR *src, *dst;
int ret, size; int ret, size;
if ((ret = pgnutls_privkey_export_dsa_raw( key->u.a.handle, &p, &q, &g, &y, &x ))) if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, &x )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -1087,7 +1099,7 @@ NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
memcpy( &key->u.a.dss_seed, x.data + x.size, sizeof(key->u.a.dss_seed) ); memcpy( &key->u.a.dss_seed, x.data + x.size, sizeof(key->u.a.dss_seed) );
key->u.a.handle = handle; key_data(key)->privkey = handle;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1528,7 +1540,7 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
*ret_len = key->u.a.bitlen / 8; *ret_len = key->u.a.bitlen / 8;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
if (!key->u.a.handle) return STATUS_INVALID_PARAMETER; if (!key_data(key)->privkey) return STATUS_INVALID_PARAMETER;
hash.data = input; hash.data = input;
hash.size = input_len; hash.size = input_len;
@ -1536,7 +1548,7 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
signature.data = NULL; signature.data = NULL;
signature.size = 0; signature.size = 0;
if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, hash_alg, 0, &hash, &signature ))) if ((ret = pgnutls_privkey_sign_hash( key_data(key)->privkey, hash_alg, 0, &hash, &signature )))
{ {
pgnutls_perror( ret ); pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -1550,6 +1562,6 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
void key_asymmetric_destroy( struct key *key ) void key_asymmetric_destroy( struct key *key )
{ {
if (key->u.a.handle) pgnutls_privkey_deinit( key->u.a.handle ); if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
} }
#endif #endif

View File

@ -43,6 +43,18 @@
#if defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 && !defined(HAVE_GNUTLS_CIPHER_INIT) #if defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 && !defined(HAVE_GNUTLS_CIPHER_INIT)
WINE_DEFAULT_DEBUG_CHANNEL(bcrypt); WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
struct key_data
{
CCCryptorRef ref_encrypt;
CCCryptorRef ref_decrypt;
};
C_ASSERT( sizeof(struct key_data) <= sizeof(((struct key *)0)->private) );
static struct key_data *key_data( struct key *key )
{
return (struct key_data *)key->private;
}
NTSTATUS key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) NTSTATUS key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
{ {
if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
@ -104,14 +116,14 @@ static CCMode get_cryptor_mode( struct key *key )
void key_symmetric_vector_reset( struct key *key ) void key_symmetric_vector_reset( struct key *key )
{ {
if (!key->u.s.ref_encrypt) return; if (!key_data(key)->ref_encrypt) return;
TRACE( "invalidating cryptor handles\n" ); TRACE( "invalidating cryptor handles\n" );
CCCryptorRelease( key->u.s.ref_encrypt ); CCCryptorRelease( key_data(key)->ref_encrypt );
key->u.s.ref_encrypt = NULL; key_data(key)->ref_encrypt = NULL;
CCCryptorRelease( key->u.s.ref_decrypt ); CCCryptorRelease( key_data(key)->ref_decrypt );
key->u.s.ref_decrypt = NULL; key_data(key)->ref_decrypt = NULL;
} }
static NTSTATUS init_cryptor_handles( struct key *key ) static NTSTATUS init_cryptor_handles( struct key *key )
@ -119,23 +131,23 @@ static NTSTATUS init_cryptor_handles( struct key *key )
CCCryptorStatus status; CCCryptorStatus status;
CCMode mode; CCMode mode;
if (key->u.s.ref_encrypt) return STATUS_SUCCESS; if (key_data(key)->ref_encrypt) return STATUS_SUCCESS;
if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED; if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED;
if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector, if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0, key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
&key->u.s.ref_encrypt )) != kCCSuccess) &key_data(key)->ref_encrypt )) != kCCSuccess)
{ {
WARN( "CCCryptorCreateWithMode failed %d\n", status ); WARN( "CCCryptorCreateWithMode failed %d\n", status );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
} }
if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector, if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0, key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
&key->u.s.ref_decrypt )) != kCCSuccess) &key_data(key)->ref_decrypt )) != kCCSuccess)
{ {
WARN( "CCCryptorCreateWithMode failed %d\n", status ); WARN( "CCCryptorCreateWithMode failed %d\n", status );
CCCryptorRelease( key->u.s.ref_encrypt ); CCCryptorRelease( key_data(key)->ref_encrypt );
key->u.s.ref_encrypt = NULL; key_data(key)->ref_encrypt = NULL;
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
} }
@ -155,7 +167,7 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
if ((ret = init_cryptor_handles( key ))) return ret; if ((ret = init_cryptor_handles( key ))) return ret;
if ((status = CCCryptorUpdate( key->u.s.ref_encrypt, input, input_len, output, output_len, NULL )) != kCCSuccess) if ((status = CCCryptorUpdate( key_data(key)->ref_encrypt, input, input_len, output, output_len, NULL )) != kCCSuccess)
{ {
WARN( "CCCryptorUpdate failed %d\n", status ); WARN( "CCCryptorUpdate failed %d\n", status );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -170,7 +182,7 @@ NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input
if ((ret = init_cryptor_handles( key ))) return ret; if ((ret = init_cryptor_handles( key ))) return ret;
if ((status = CCCryptorUpdate( key->u.s.ref_decrypt, input, input_len, output, output_len, NULL )) != kCCSuccess) if ((status = CCCryptorUpdate( key_data(key)->ref_decrypt, input, input_len, output, output_len, NULL )) != kCCSuccess)
{ {
WARN( "CCCryptorUpdate failed %d\n", status ); WARN( "CCCryptorUpdate failed %d\n", status );
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
@ -186,8 +198,8 @@ NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
void key_symmetric_destroy( struct key *key ) void key_symmetric_destroy( struct key *key )
{ {
if (key->u.s.ref_encrypt) CCCryptorRelease( key->u.s.ref_encrypt ); if (key_data(key)->ref_encrypt) CCCryptorRelease( key_data(key)->ref_encrypt );
if (key->u.s.ref_decrypt) CCCryptorRelease( key->u.s.ref_decrypt ); if (key_data(key)->ref_decrypt) CCCryptorRelease( key_data(key)->ref_decrypt );
} }
NTSTATUS key_asymmetric_init( struct key *key ) NTSTATUS key_asymmetric_init( struct key *key )