crypt32: Split the import_cert_store function to move memory allocations to the PE side.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
677107378e
commit
f18ccfef7b
|
@ -460,11 +460,17 @@ void init_empty_store(void) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Unix interface */
|
/* Unix interface */
|
||||||
|
|
||||||
|
struct cert_store_data;
|
||||||
|
|
||||||
struct unix_funcs
|
struct unix_funcs
|
||||||
{
|
{
|
||||||
BOOL (WINAPI *enum_root_certs)( void *buffer, SIZE_T size, SIZE_T *needed );
|
BOOL (WINAPI *enum_root_certs)( void *buffer, SIZE_T size, SIZE_T *needed );
|
||||||
BOOL (WINAPI *import_cert_store)( CRYPT_DATA_BLOB *pfx, const WCHAR *password, DWORD flags,
|
BOOL (WINAPI *open_cert_store)( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
|
||||||
void **key_ret, void ***chain_ret, DWORD *count_ret );
|
struct cert_store_data **data_ret );
|
||||||
|
NTSTATUS (WINAPI *import_store_key)( struct cert_store_data *data, void *buf, DWORD *buf_size );
|
||||||
|
NTSTATUS (WINAPI *import_store_cert)( struct cert_store_data *data, unsigned int index,
|
||||||
|
void *buf, DWORD *buf_size );
|
||||||
|
void (WINAPI *close_cert_store)( struct cert_store_data *data );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
|
extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "wincrypt.h"
|
#include "wincrypt.h"
|
||||||
|
@ -29,13 +32,15 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||||
|
|
||||||
static HCRYPTPROV import_key( void *key, DWORD flags )
|
static HCRYPTPROV import_key( struct cert_store_data *data, DWORD flags )
|
||||||
{
|
{
|
||||||
HCRYPTPROV prov = 0;
|
HCRYPTPROV prov = 0;
|
||||||
HCRYPTKEY cryptkey;
|
HCRYPTKEY cryptkey;
|
||||||
DWORD size, acquire_flags;
|
DWORD size, acquire_flags;
|
||||||
|
void *key;
|
||||||
|
|
||||||
|
if (unix_funcs->import_store_key( data, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) return 0;
|
||||||
|
|
||||||
size = HeapSize( GetProcessHeap(), 0, key );
|
|
||||||
acquire_flags = (flags & CRYPT_MACHINE_KEYSET) | CRYPT_NEWKEYSET;
|
acquire_flags = (flags & CRYPT_MACHINE_KEYSET) | CRYPT_NEWKEYSET;
|
||||||
if (!CryptAcquireContextW( &prov, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL, acquire_flags ))
|
if (!CryptAcquireContextW( &prov, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL, acquire_flags ))
|
||||||
{
|
{
|
||||||
|
@ -49,13 +54,17 @@ static HCRYPTPROV import_key( void *key, DWORD flags )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CryptImportKey( prov, key, size, 0, flags & CRYPT_EXPORTABLE, &cryptkey ))
|
key = malloc( size );
|
||||||
|
if (unix_funcs->import_store_key( data, key, &size ) ||
|
||||||
|
!CryptImportKey( prov, key, size, 0, flags & CRYPT_EXPORTABLE, &cryptkey ))
|
||||||
{
|
{
|
||||||
WARN( "CryptImportKey failed %08x\n", GetLastError() );
|
WARN( "CryptImportKey failed %08x\n", GetLastError() );
|
||||||
CryptReleaseContext( prov, 0 );
|
CryptReleaseContext( prov, 0 );
|
||||||
|
free( key );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
CryptDestroyKey( cryptkey );
|
CryptDestroyKey( cryptkey );
|
||||||
|
free( key );
|
||||||
return prov;
|
return prov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,10 +141,10 @@ static BOOL set_key_prov_info( const void *ctx, HCRYPTPROV prov )
|
||||||
|
|
||||||
HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *password, DWORD flags )
|
HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *password, DWORD flags )
|
||||||
{
|
{
|
||||||
void *key, **chain;
|
DWORD i = 0, size;
|
||||||
DWORD i, chain_len = 0;
|
|
||||||
HCERTSTORE store = NULL;
|
HCERTSTORE store = NULL;
|
||||||
HCRYPTPROV prov = 0;
|
HCRYPTPROV prov = 0;
|
||||||
|
struct cert_store_data *data = NULL;
|
||||||
|
|
||||||
if (!pfx)
|
if (!pfx)
|
||||||
{
|
{
|
||||||
|
@ -147,15 +156,14 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
|
||||||
FIXME( "flags %08x not supported\n", flags );
|
FIXME( "flags %08x not supported\n", flags );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!unix_funcs->import_cert_store)
|
if (!unix_funcs->open_cert_store)
|
||||||
{
|
{
|
||||||
FIXME( "(%p, %p, %08x)\n", pfx, password, flags );
|
FIXME( "(%p, %p, %08x)\n", pfx, password, flags );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!unix_funcs->import_cert_store( pfx, password, flags, &key, &chain, &chain_len )) return NULL;
|
if (!unix_funcs->open_cert_store( pfx, password, &data )) return NULL;
|
||||||
|
|
||||||
prov = import_key( key, flags );
|
prov = import_key( data, flags );
|
||||||
heap_free( key );
|
|
||||||
if (!prov) goto error;
|
if (!prov) goto error;
|
||||||
|
|
||||||
if (!(store = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, 0, 0, NULL )))
|
if (!(store = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, 0, 0, NULL )))
|
||||||
|
@ -164,14 +172,17 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chain_len > 1) FIXME( "handle certificate chain\n" );
|
for (;;)
|
||||||
for (i = 0; i < chain_len; i++)
|
|
||||||
{
|
{
|
||||||
const void *ctx;
|
const void *ctx = NULL;
|
||||||
size_t size = HeapSize( GetProcessHeap(), 0, chain[i] );
|
void *cert;
|
||||||
|
|
||||||
if (!(ctx = CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT, X509_ASN_ENCODING,
|
if (unix_funcs->import_store_cert( data, i, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) break;
|
||||||
chain[i], size, 0, NULL )))
|
cert = malloc( size );
|
||||||
|
if (!unix_funcs->import_store_cert( data, i++, cert, &size ))
|
||||||
|
ctx = CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT, X509_ASN_ENCODING, cert, size, 0, NULL );
|
||||||
|
free( cert );
|
||||||
|
if (!ctx)
|
||||||
{
|
{
|
||||||
WARN( "CertCreateContext failed %08x\n", GetLastError() );
|
WARN( "CertCreateContext failed %08x\n", GetLastError() );
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -199,15 +210,13 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
|
||||||
}
|
}
|
||||||
CertFreeCertificateContext( ctx );
|
CertFreeCertificateContext( ctx );
|
||||||
}
|
}
|
||||||
while (chain_len) heap_free( chain[--chain_len] );
|
unix_funcs->close_cert_store( data );
|
||||||
heap_free( chain );
|
|
||||||
return store;
|
return store;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
CryptReleaseContext( prov, 0 );
|
CryptReleaseContext( prov, 0 );
|
||||||
CertCloseStore( store, 0 );
|
CertCloseStore( store, 0 );
|
||||||
while (chain_len) heap_free( chain[--chain_len] );
|
if (data) unix_funcs->close_cert_store( data );
|
||||||
heap_free( chain );
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,38 +155,37 @@ static void gnutls_uninitialize(void)
|
||||||
#define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
|
#define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
|
||||||
#define RSA_PUBEXP 65537
|
#define RSA_PUBEXP 65537
|
||||||
|
|
||||||
static DWORD import_key( gnutls_x509_privkey_t key, DWORD flags, void **data_ret )
|
struct cert_store_data
|
||||||
|
{
|
||||||
|
gnutls_pkcs12_t p12;
|
||||||
|
gnutls_x509_privkey_t key;
|
||||||
|
gnutls_x509_crt_t *chain;
|
||||||
|
unsigned int key_bitlen;
|
||||||
|
unsigned int chain_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf, DWORD *buf_size )
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
unsigned int bitlen;
|
unsigned int bitlen = data->key_bitlen;
|
||||||
gnutls_datum_t m, e, d, p, q, u, e1, e2;
|
gnutls_datum_t m, e, d, p, q, u, e1, e2;
|
||||||
BLOBHEADER *hdr;
|
BLOBHEADER *hdr;
|
||||||
RSAPUBKEY *rsakey;
|
RSAPUBKEY *rsakey;
|
||||||
BYTE *buf, *src, *dst;
|
BYTE *src, *dst;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
|
||||||
*data_ret = NULL;
|
|
||||||
|
|
||||||
if ((ret = pgnutls_x509_privkey_get_pk_algorithm2( key, &bitlen )) < 0)
|
|
||||||
{
|
|
||||||
pgnutls_perror( ret );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != GNUTLS_PK_RSA)
|
|
||||||
{
|
|
||||||
FIXME( "key algorithm %u not supported\n", ret );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = pgnutls_x509_privkey_export_rsa_raw2( key, &m, &e, &d, &p, &q, &u, &e1, &e2 )) < 0)
|
|
||||||
{
|
|
||||||
pgnutls_perror( ret );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = sizeof(*hdr) + sizeof(*rsakey) + (bitlen * 9 / 16);
|
size = sizeof(*hdr) + sizeof(*rsakey) + (bitlen * 9 / 16);
|
||||||
if (!(buf = RtlAllocateHeap( GetProcessHeap(), 0, size ))) goto done;
|
if (!buf || *buf_size < size)
|
||||||
|
{
|
||||||
|
*buf_size = size;
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = pgnutls_x509_privkey_export_rsa_raw2( data->key, &m, &e, &d, &p, &q, &u, &e1, &e2 )) < 0)
|
||||||
|
{
|
||||||
|
pgnutls_perror( ret );
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
hdr = (BLOBHEADER *)buf;
|
hdr = (BLOBHEADER *)buf;
|
||||||
hdr->bType = PRIVATEKEYBLOB;
|
hdr->bType = PRIVATEKEYBLOB;
|
||||||
|
@ -235,8 +234,6 @@ static DWORD import_key( gnutls_x509_privkey_t key, DWORD flags, void **data_ret
|
||||||
else src = d.data;
|
else src = d.data;
|
||||||
for (i = bitlen / 8 - 1; i >= 0; i--) *dst++ = src[i];
|
for (i = bitlen / 8 - 1; i >= 0; i--) *dst++ = src[i];
|
||||||
|
|
||||||
*data_ret = buf;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free( m.data );
|
free( m.data );
|
||||||
free( e.data );
|
free( e.data );
|
||||||
|
@ -246,8 +243,7 @@ done:
|
||||||
free( u.data );
|
free( u.data );
|
||||||
free( e1.data );
|
free( e1.data );
|
||||||
free( e2.data );
|
free( e2.data );
|
||||||
if (!*data_ret) RtlFreeHeap( GetProcessHeap(), 0, buf );
|
return STATUS_SUCCESS;
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *password_to_ascii( const WCHAR *str )
|
static char *password_to_ascii( const WCHAR *str )
|
||||||
|
@ -265,16 +261,18 @@ static char *password_to_ascii( const WCHAR *str )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI import_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password, DWORD flags,
|
static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password,
|
||||||
void **key_ret, void ***chain_ret, DWORD *count_ret )
|
struct cert_store_data **data_ret )
|
||||||
{
|
{
|
||||||
gnutls_pkcs12_t p12;
|
gnutls_pkcs12_t p12;
|
||||||
gnutls_datum_t pfx_data;
|
gnutls_datum_t pfx_data;
|
||||||
gnutls_x509_privkey_t key;
|
gnutls_x509_privkey_t key;
|
||||||
gnutls_x509_crt_t *chain;
|
gnutls_x509_crt_t *chain;
|
||||||
unsigned int chain_len, i;
|
unsigned int chain_len;
|
||||||
|
unsigned int bitlen;
|
||||||
char *pwd = NULL;
|
char *pwd = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct cert_store_data *store_data;
|
||||||
|
|
||||||
if (password && !(pwd = password_to_ascii( password ))) return FALSE;
|
if (password && !(pwd = password_to_ascii( password ))) return FALSE;
|
||||||
|
|
||||||
|
@ -287,27 +285,25 @@ static BOOL WINAPI import_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
|
||||||
if ((ret = pgnutls_pkcs12_simple_parse( p12, pwd ? pwd : "", &key, &chain, &chain_len, NULL, NULL, NULL, 0 )) < 0)
|
if ((ret = pgnutls_pkcs12_simple_parse( p12, pwd ? pwd : "", &key, &chain, &chain_len, NULL, NULL, NULL, 0 )) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!import_key( key, flags, key_ret )) goto error;
|
if ((ret = pgnutls_x509_privkey_get_pk_algorithm2( key, &bitlen )) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
*chain_ret = RtlAllocateHeap( GetProcessHeap(), 0, chain_len * sizeof(*chain_ret) );
|
free( pwd );
|
||||||
*count_ret = chain_len;
|
|
||||||
for (i = 0; i < chain_len; i++)
|
if (ret != GNUTLS_PK_RSA)
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
FIXME( "key algorithm %u not supported\n", ret );
|
||||||
|
pgnutls_pkcs12_deinit( p12 );
|
||||||
if ((ret = pgnutls_x509_crt_export( chain[i], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER)
|
return FALSE;
|
||||||
goto error;
|
|
||||||
|
|
||||||
(*chain_ret)[i] = RtlAllocateHeap( GetProcessHeap(), 0, size );
|
|
||||||
if ((ret = pgnutls_x509_crt_export( chain[i], GNUTLS_X509_FMT_DER, (*chain_ret)[i], &size )) < 0)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
while (i) RtlFreeHeap( GetProcessHeap(), 0, (*chain_ret)[--i] );
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, *chain_ret );
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pgnutls_pkcs12_deinit( p12 );
|
|
||||||
|
store_data = malloc( sizeof(*store_data) );
|
||||||
|
store_data->p12 = p12;
|
||||||
|
store_data->key = key;
|
||||||
|
store_data->chain = chain;
|
||||||
|
store_data->key_bitlen = bitlen;
|
||||||
|
store_data->chain_len = chain_len;
|
||||||
|
*data_ret = store_data;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -317,6 +313,34 @@ error:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS WINAPI import_store_cert( struct cert_store_data *data, unsigned int index,
|
||||||
|
void *buf, DWORD *buf_size )
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (index >= data->chain_len) return STATUS_NO_MORE_ENTRIES;
|
||||||
|
|
||||||
|
if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (!buf || *buf_size < size)
|
||||||
|
{
|
||||||
|
*buf_size = size;
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, buf, &size )) < 0)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI close_cert_store( struct cert_store_data *data )
|
||||||
|
{
|
||||||
|
pgnutls_pkcs12_deinit( data->p12 );
|
||||||
|
free( data );
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* SONAME_LIBGNUTLS */
|
#endif /* SONAME_LIBGNUTLS */
|
||||||
|
|
||||||
struct root_cert
|
struct root_cert
|
||||||
|
@ -649,7 +673,13 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
#ifdef SONAME_LIBGNUTLS
|
#ifdef SONAME_LIBGNUTLS
|
||||||
if (gnutls_initialize()) funcs.import_cert_store = import_cert_store;
|
if (gnutls_initialize())
|
||||||
|
{
|
||||||
|
funcs.open_cert_store = open_cert_store;
|
||||||
|
funcs.import_store_key = import_store_key;
|
||||||
|
funcs.import_store_cert = import_store_cert;
|
||||||
|
funcs.close_cert_store = close_cert_store;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
*(const struct unix_funcs **)ptr_out = &funcs;
|
*(const struct unix_funcs **)ptr_out = &funcs;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue