From: Benoît Legat <benoit.legat@gmail.com> --- dlls/crypt32/pfx.c | 31 +++++++++++++++++++++++++++++-- dlls/crypt32/unixlib.c | 31 +++++++++++-------------------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/dlls/crypt32/pfx.c b/dlls/crypt32/pfx.c index 3d0caaf8cdd..0b92761a802 100644 --- a/dlls/crypt32/pfx.c +++ b/dlls/crypt32/pfx.c @@ -440,8 +440,35 @@ BOOL WINAPI PFXExportCertStoreEx( HCERTSTORE store, CRYPT_DATA_BLOB *pfx, const } } - params.cert_data = cert ? cert->pbCertEncoded : NULL; - params.cert_size = cert ? cert->cbCertEncoded : 0; + if (!cert && !key_blob) + { + /* Empty store: return a minimal valid PKCS#12 (version 3, empty content). */ + static const BYTE empty_pfx[] = { + 0x30, 0x15, /* SEQUENCE */ + 0x02, 0x01, 0x03, /* INTEGER 3 (version) */ + 0x30, 0x10, /* SEQUENCE (authSafe) */ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, /* OID 1.2.840.113549.1.7.1 */ + 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x03, 0x04, 0x01, 0x00, /* [0] OCTET STRING (empty) */ + }; + if (!pfx->pbData) + { + pfx->cbData = sizeof(empty_pfx); + return TRUE; + } + if (pfx->cbData < sizeof(empty_pfx)) + { + SetLastError( ERROR_MORE_DATA ); + pfx->cbData = sizeof(empty_pfx); + return FALSE; + } + memcpy( pfx->pbData, empty_pfx, sizeof(empty_pfx) ); + pfx->cbData = sizeof(empty_pfx); + return TRUE; + } + + params.cert_data = cert->pbCertEncoded; + params.cert_size = cert->cbCertEncoded; params.key_blob = key_blob; params.key_blob_size = key_blob ? key_blob_size : 0; params.password = password; diff --git a/dlls/crypt32/unixlib.c b/dlls/crypt32/unixlib.c index ad78996eeee..fe7b48750c5 100644 --- a/dlls/crypt32/unixlib.c +++ b/dlls/crypt32/unixlib.c @@ -551,20 +551,17 @@ static NTSTATUS export_cert_store( void *args ) if (params->password && !(pwd = password_to_ascii( params->password ))) return STATUS_NO_MEMORY; - /* Import the certificate if provided. */ - if (params->cert_data && params->cert_size) + /* Import the certificate. */ + if ((ret = pgnutls_x509_crt_init( &crt )) < 0) goto error; { - if ((ret = pgnutls_x509_crt_init( &crt )) < 0) goto error; - { - gnutls_datum_t cert_datum = { (unsigned char *)params->cert_data, params->cert_size }; - if ((ret = pgnutls_x509_crt_import( crt, &cert_datum, GNUTLS_X509_FMT_DER )) < 0) goto error; - } - - /* Create cert bag. */ - if ((ret = pgnutls_pkcs12_bag_init( &cert_bag )) < 0) goto error; - if ((ret = pgnutls_pkcs12_bag_set_crt( cert_bag, crt )) < 0) goto error; + gnutls_datum_t cert_datum = { (unsigned char *)params->cert_data, params->cert_size }; + if ((ret = pgnutls_x509_crt_import( crt, &cert_datum, GNUTLS_X509_FMT_DER )) < 0) goto error; } + /* Create cert bag. */ + if ((ret = pgnutls_pkcs12_bag_init( &cert_bag )) < 0) goto error; + if ((ret = pgnutls_pkcs12_bag_set_crt( cert_bag, crt )) < 0) goto error; + /* Import private key from BCRYPT_RSAKEY_BLOB if provided. */ if (params->key_blob && params->key_blob_size) { @@ -610,20 +607,14 @@ static NTSTATUS export_cert_store( void *args ) /* Build PKCS#12. */ if ((ret = pgnutls_pkcs12_init( &p12 )) < 0) goto error; - if (cert_bag) - { - if ((ret = pgnutls_pkcs12_set_bag( p12, cert_bag )) < 0) goto error; - } + if ((ret = pgnutls_pkcs12_set_bag( p12, cert_bag )) < 0) goto error; if (key_bag) { if ((ret = pgnutls_pkcs12_set_bag( p12, key_bag )) < 0) goto error; } - /* Generate MAC (only if there are bags, GnuTLS fails on empty PKCS#12). */ - if (cert_bag || key_bag) - { - if ((ret = pgnutls_pkcs12_generate_mac2( p12, GNUTLS_MAC_SHA256, pwd ? pwd : "" )) < 0) goto error; - } + /* Generate MAC. */ + if ((ret = pgnutls_pkcs12_generate_mac2( p12, GNUTLS_MAC_SHA256, pwd ? pwd : "" )) < 0) goto error; /* Export. */ if ((ret = pgnutls_pkcs12_export2( p12, GNUTLS_X509_FMT_DER, &out )) < 0) goto error; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10532