bcrypt: Move public key allocation to the PE side.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-10-07 11:18:55 +02:00
parent 52ca433e78
commit 696255907c
2 changed files with 47 additions and 42 deletions

View file

@ -974,17 +974,15 @@ static NTSTATUS key_asymmetric_create( struct key **ret_key, struct algorithm *a
key->hdr.magic = MAGIC_KEY;
key->alg_id = alg->id;
key->u.a.bitlen = bitlen;
key->u.a.pubkey_len = pubkey_len;
if (pubkey_len)
if (!(key->u.a.pubkey = heap_alloc( pubkey_len )))
{
if (!(key->u.a.pubkey = heap_alloc( pubkey_len )))
{
heap_free( key );
return STATUS_NO_MEMORY;
}
memcpy( key->u.a.pubkey, pubkey, pubkey_len );
key->u.a.pubkey_len = pubkey_len;
heap_free( key );
return STATUS_NO_MEMORY;
}
if (pubkey) memcpy( key->u.a.pubkey, pubkey, pubkey_len );
*ret_key = key;
return STATUS_SUCCESS;
}
@ -1268,11 +1266,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
{
struct key *key;
NTSTATUS status;
ULONG size;
if (!wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ))
{
BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
DWORD key_size, magic, size;
DWORD key_size, magic;
if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
@ -1332,7 +1331,8 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3)
return STATUS_INVALID_PARAMETER;
if ((status = key_asymmetric_create( &key, alg, key_size * 8, NULL, 0 ))) return status;
size = sizeof(*ecc_blob) + key_size * 2;
if ((status = key_asymmetric_create( &key, alg, key_size * 8, NULL, size ))) return status;
if ((status = key_funcs->key_import_ecc( key, input, input_len )))
{
BCryptDestroyKey( key );
@ -1345,7 +1345,6 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
else if (!wcscmp( type, BCRYPT_RSAPUBLIC_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 && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC)
@ -1357,7 +1356,6 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
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)
@ -1378,7 +1376,6 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ))
{
BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
ULONG size;
if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER;
if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
@ -1412,7 +1409,8 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED))
return STATUS_INVALID_PARAMETER;
if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, NULL, 0 ))) return status;
size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED);
if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, NULL, size ))) return status;
if ((status = key_funcs->key_import_dsa_capi( key, input, input_len )))
{
BCryptDestroyKey( key );
@ -1426,7 +1424,6 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
{
BLOBHEADER *hdr = (BLOBHEADER *)input;
DSSPUBKEY *pubkey;
ULONG size;
if (alg->id != ALG_ID_DSA) return STATUS_NOT_SUPPORTED;
if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
@ -1508,6 +1505,7 @@ NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_H
struct algorithm *alg = algorithm;
struct key *key;
NTSTATUS status;
ULONG size;
TRACE( "%p, %p, %u, %08x\n", algorithm, handle, key_len, flags );
@ -1518,18 +1516,25 @@ NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_H
{
case ALG_ID_ECDH_P256:
case ALG_ID_ECDSA_P256:
size = sizeof(BCRYPT_ECCKEY_BLOB) + 2 * 256 / 8;
break;
case ALG_ID_ECDSA_P384:
size = sizeof(BCRYPT_ECCKEY_BLOB) + 2 * 384 / 8;
break;
case ALG_ID_RSA:
case ALG_ID_RSA_SIGN:
size = sizeof(BCRYPT_RSAKEY_BLOB) + 2 * key_len / 8;
break;
case ALG_ID_DSA:
if (!(status = key_asymmetric_create( &key, alg, key_len, NULL, 0 ))) *handle = key;
return status;
size = sizeof(BCRYPT_DSA_KEY_BLOB) + 3 * key_len / 8;
break;
default:
FIXME( "algorithm %u not supported\n", alg->id );
return STATUS_NOT_SUPPORTED;
}
if (!(status = key_asymmetric_create( &key, alg, key_len, NULL, size ))) *handle = key;
return status;
}
NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )

View file

@ -594,9 +594,9 @@ static void export_gnutls_datum( UCHAR *buffer, ULONG length, gnutls_datum_t *d,
memcpy( buffer + offset, src, size );
}
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, void *pubkey, ULONG *pubkey_len )
{
BCRYPT_RSAKEY_BLOB *rsa_blob;
BCRYPT_RSAKEY_BLOB *rsa_blob = pubkey;
gnutls_datum_t m, e;
UCHAR *dst;
int ret;
@ -607,11 +607,12 @@ static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bit
return STATUS_INTERNAL_ERROR;
}
if (!(rsa_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*rsa_blob) + e.size + m.size )))
if (*pubkey_len < sizeof(*rsa_blob) + e.size + m.size)
{
FIXME( "wrong pubkey len %u / %u\n", *pubkey_len, (ULONG)sizeof(*rsa_blob) + e.size + m.size );
pgnutls_perror( ret );
free( e.data ); free( m.data );
return STATUS_NO_MEMORY;
return STATUS_BUFFER_TOO_SMALL;
}
dst = (UCHAR *)(rsa_blob + 1);
@ -625,17 +626,16 @@ static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bit
rsa_blob->cbPrime1 = 0;
rsa_blob->cbPrime2 = 0;
*pubkey = (UCHAR *)rsa_blob;
*pubkey_len = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
free( e.data ); free( m.data );
return STATUS_SUCCESS;
}
static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_id alg_id, UCHAR **pubkey,
static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_id alg_id, void *pubkey,
ULONG *pubkey_len )
{
BCRYPT_ECCKEY_BLOB *ecc_blob;
BCRYPT_ECCKEY_BLOB *ecc_blob = pubkey;
gnutls_ecc_curve_t curve;
gnutls_datum_t x, y;
DWORD magic, size;
@ -670,11 +670,12 @@ static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_
return STATUS_NOT_IMPLEMENTED;
}
if (!(ecc_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ecc_blob) + size * 2 )))
if (*pubkey_len < sizeof(*ecc_blob) + size * 2)
{
FIXME( "wrong pubkey len %u / %u\n", *pubkey_len, (ULONG)sizeof(*ecc_blob) + size * 2 );
pgnutls_perror( ret );
free( x.data ); free( y.data );
return STATUS_NO_MEMORY;
return STATUS_BUFFER_TOO_SMALL;
}
ecc_blob->dwMagic = magic;
@ -686,16 +687,15 @@ static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_
dst += size;
export_gnutls_datum( dst, size, &y, NULL );
*pubkey = (UCHAR *)ecc_blob;
*pubkey_len = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
free( x.data ); free( y.data );
return STATUS_SUCCESS;
}
static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bitlen, void *pubkey, ULONG *pubkey_len )
{
BCRYPT_DSA_KEY_BLOB *dsa_blob;
BCRYPT_DSA_KEY_BLOB *dsa_blob = pubkey;
gnutls_datum_t p, q, g, y;
UCHAR *dst;
int ret;
@ -712,8 +712,9 @@ static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bit
return STATUS_NOT_IMPLEMENTED;
}
if (!(dsa_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*dsa_blob) + bitlen / 8 * 3 )))
if (*pubkey_len < sizeof(*dsa_blob) + bitlen / 8 * 3)
{
FIXME( "wrong pubkey len %u / %u\n", *pubkey_len, (ULONG)sizeof(*dsa_blob) + bitlen / 8 * 3 );
pgnutls_perror( ret );
free( p.data ); free( q.data ); free( g.data ); free( y.data );
return STATUS_NO_MEMORY;
@ -736,7 +737,6 @@ static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bit
memset( dsa_blob->Count, 0, sizeof(dsa_blob->Count) ); /* FIXME */
memset( dsa_blob->Seed, 0, sizeof(dsa_blob->Seed) ); /* FIXME */
*pubkey = (UCHAR *)dsa_blob;
*pubkey_len = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
free( p.data ); free( q.data ); free( g.data ); free( y.data );
@ -758,9 +758,9 @@ static void reverse_bytes( UCHAR *buf, ULONG len )
#define Q_SIZE 20
static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, const DSSSEED *seed, ULONG bitlen,
UCHAR **pubkey, ULONG *pubkey_len )
void *pubkey, ULONG *pubkey_len )
{
BLOBHEADER *hdr;
BLOBHEADER *hdr = pubkey;
DSSPUBKEY *dsskey;
gnutls_datum_t p, q, g, y;
UCHAR *dst;
@ -778,8 +778,9 @@ static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, cons
return STATUS_INTERNAL_ERROR;
}
if (!(hdr = RtlAllocateHeap( GetProcessHeap(), 0, size + bitlen / 8 * 3 + Q_SIZE )))
if (*pubkey_len < size + bitlen / 8 * 3 + Q_SIZE)
{
FIXME( "wrong pubkey len %u / %u\n", *pubkey_len, size + bitlen / 8 * 3 + Q_SIZE );
pgnutls_perror( ret );
free( p.data ); free( q.data ); free( g.data ); free( y.data );
return STATUS_NO_MEMORY;
@ -813,7 +814,6 @@ static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, cons
memcpy( dst, seed, sizeof(*seed) );
*pubkey = (UCHAR *)hdr;
*pubkey_len = size + bitlen / 8 * 3 + Q_SIZE;
free( p.data ); free( q.data ); free( g.data ); free( y.data );
@ -870,15 +870,15 @@ static NTSTATUS CDECL key_asymmetric_generate( struct key *key )
switch (pk_alg)
{
case GNUTLS_PK_RSA:
status = export_gnutls_pubkey_rsa( handle, key->u.a.bitlen, &key->u.a.pubkey, &key->u.a.pubkey_len );
status = export_gnutls_pubkey_rsa( handle, key->u.a.bitlen, key->u.a.pubkey, &key->u.a.pubkey_len );
break;
case GNUTLS_PK_ECC:
status = export_gnutls_pubkey_ecc( handle, key->alg_id, &key->u.a.pubkey, &key->u.a.pubkey_len );
status = export_gnutls_pubkey_ecc( handle, key->alg_id, key->u.a.pubkey, &key->u.a.pubkey_len );
break;
case GNUTLS_PK_DSA:
status = export_gnutls_pubkey_dsa( handle, key->u.a.bitlen, &key->u.a.pubkey, &key->u.a.pubkey_len );
status = export_gnutls_pubkey_dsa( handle, key->u.a.bitlen, key->u.a.pubkey, &key->u.a.pubkey_len );
break;
default:
@ -997,7 +997,7 @@ static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
return STATUS_INTERNAL_ERROR;
}
if ((status = export_gnutls_pubkey_ecc( handle, key->alg_id, &key->u.a.pubkey, &key->u.a.pubkey_len )))
if ((status = export_gnutls_pubkey_ecc( handle, key->alg_id, key->u.a.pubkey, &key->u.a.pubkey_len )))
{
pgnutls_privkey_deinit( handle );
return status;
@ -1158,8 +1158,8 @@ static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG le
return STATUS_INTERNAL_ERROR;
}
if ((status = export_gnutls_pubkey_dsa_capi( handle, &key->u.a.dss_seed, key->u.a.bitlen, &key->u.a.pubkey,
&key->u.a.pubkey_len )))
if ((status = export_gnutls_pubkey_dsa_capi( handle, &key->u.a.dss_seed, key->u.a.bitlen,
key->u.a.pubkey, &key->u.a.pubkey_len )))
{
pgnutls_privkey_deinit( handle );
return status;