libp11 PKCS#11 provider support

This commit is contained in:
olszomal 2025-03-28 12:49:43 +01:00 committed by Michał Trojnara
parent e8f19a6efe
commit 838aaaee8d
6 changed files with 363 additions and 314 deletions

View File

@ -27,8 +27,15 @@ set(PACKAGE_BUGREPORT "Michal.Trojnara@stunnel.org")
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
if(WIN32)
add_definitions(-DUSE_WIN32)
endif()
# load CMake library modules # load CMake library modules
include(FindOpenSSL) include(FindOpenSSL)
if(OPENSSL_VERSION VERSION_LESS "1.1.1")
message(FATAL_ERROR "OpenSSL version must be at least 1.1.1")
endif()
if(OPENSSL_VERSION VERSION_LESS "3.0.0") if(OPENSSL_VERSION VERSION_LESS "3.0.0")
include(FindCURL) include(FindCURL)
endif(OPENSSL_VERSION VERSION_LESS "3.0.0") endif(OPENSSL_VERSION VERSION_LESS "3.0.0")

View File

@ -6,6 +6,7 @@
- added the "-engineCtrl" option to control hardware and CNG engines - added the "-engineCtrl" option to control hardware and CNG engines
- improved unauthenticated blob support (thanks to Asger Hautop Drewsen) - improved unauthenticated blob support (thanks to Asger Hautop Drewsen)
- added the '-blobFile' option to specify a file containing the blob content - added the '-blobFile' option to specify a file containing the blob content
- added PKCS#11 provider support (requires OpenSSL 3.0)
### 2.9 (2024.06.29) ### 2.9 (2024.06.29)

View File

@ -131,17 +131,28 @@ To sign a CAB file containing java class files:
``` ```
Only the 'low' parameter is currently supported. Only the 'low' parameter is currently supported.
If you want to use PKCS11 token, you should indicate PKCS11 engine and module. If you want to use a PKCS#11 token, you should specify the PKCS#11 engine and module.
An example of using osslsigncode with SoftHSM: An example of using osslsigncode with SoftHSM:
``` ```
osslsigncode sign \ osslsigncode sign \
-pkcs11engine /usr/lib64/engines-1.1/pkcs11.so \ -engine /usr/lib64/engines-1.1/pkcs11.so \
-pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \ -pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \
-pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \ -pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \
-key 'pkcs11:token=softhsm-token;object=key' \ -key 'pkcs11:token=softhsm-token;object=key' \
-in yourapp.exe -out yourapp-signed.exe -in yourapp.exe -out yourapp-signed.exe
``` ```
Since OpenSSL 3.0, you can use a PKCS#11 token with the PKCS#11 provider.
An example of using osslsigncode with OpenSC:
```
osslsigncode sign \
-provider /usr/lib64/ossl-modules/pkcs11prov.so \
-pkcs11module /usr/lib64/opensc-pkcs11.so \
-pkcs11cert 'pkcs11:token=my-token;object=cert' \
-key 'pkcs11:token=my-token;object=key' \
-in yourapp.exe -out yourapp-signed.exe
```
You can use a certificate and key stored in the Windows Certificate Store with You can use a certificate and key stored in the Windows Certificate Store with
the CNG engine version 1.1 or later. For more information, refer to the CNG engine version 1.1 or later. For more information, refer to
@ -156,7 +167,7 @@ placed in the same directory as the `osslsigncode.exe` executable.
Below is an example of how to use osslsigncode with the CNG engine: Below is an example of how to use osslsigncode with the CNG engine:
``` ```
osslsigncode sign \ osslsigncode sign \
-pkcs11engine cng \ -engine cng \
-pkcs11cert osslsigncode_cert \ -pkcs11cert osslsigncode_cert \
-key osslsigncode_cert \ -key osslsigncode_cert \
-engineCtrl store_flags:0 \ -engineCtrl store_flags:0 \

View File

@ -165,73 +165,76 @@ int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx) PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
{ {
int i, signer = -1; int i, signer = -1;
PKCS7 *p7;
PKCS7_SIGNER_INFO *si = NULL; PKCS7_SIGNER_INFO *si = NULL;
STACK_OF(X509) *chain = NULL; STACK_OF(X509) *chain = NULL;
PKCS7 *p7 = PKCS7_new();
if (!p7)
return NULL;
p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_set_type(p7, NID_pkcs7_signed);
PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_content_new(p7, NID_pkcs7_data);
if (ctx->options->cert != NULL) {
/* /* find the signer's certificate located somewhere in the whole certificate chain */
* the private key and corresponding certificate are parsed from the PKCS12 for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
* structure or loaded from the security token, so we may omit to check X509 *signcert = sk_X509_value(ctx->options->certs, i);
* the consistency of a private key with the public key in an X509 certificate
*/ if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, ctx->options->cert, ctx->options->pkey, si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
ctx->options->md); signer = i;
if (si == NULL) if (signer > 0)
return NULL; /* FAILED */ printf("Warning: For optimal performance, consider placing the signer certificate at the beginning of the certificate chain.\n");
} else { break;
/* find the signer's certificate located somewhere in the whole certificate chain */
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
X509 *signcert = sk_X509_value(ctx->options->certs, i);
if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
signer = i;
break;
}
}
if (si == NULL) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
ctx->options->certfile);
return NULL; /* FAILED */
} }
} }
if (!si) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
ctx->options->certfile ? ctx->options->certfile : ctx->options->p11cert);
#else
ctx->options->certfile);
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
goto err;
}
if (!pkcs7_signer_info_add_signing_time(si, ctx)) { if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
if (!pkcs7_signer_info_add_purpose(si, ctx)) { if (!pkcs7_signer_info_add_purpose(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
if ((ctx->options->desc || ctx->options->url) && if ((ctx->options->desc || ctx->options->url) &&
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) { !pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
fprintf(stderr, "Couldn't allocate memory for opus info\n"); fprintf(stderr, "Couldn't allocate memory for opus info\n");
return NULL; /* FAILED */ goto err;
} }
if ((ctx->options->nested_number >= 0) && if ((ctx->options->nested_number >= 0) &&
!pkcs7_signer_info_add_sequence_number(si, ctx)) { !pkcs7_signer_info_add_sequence_number(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
/* create X509 chain sorted in ascending order by their DER encoding */ /* create X509 chain sorted in ascending order by their DER encoding */
chain = X509_chain_get_sorted(ctx, signer); chain = X509_chain_get_sorted(ctx, signer);
if (chain == NULL) { if (!chain) {
fprintf(stderr, "Failed to create a sorted certificate chain\n"); fprintf(stderr, "Failed to create a sorted certificate chain\n");
return NULL; /* FAILED */ goto err;
} }
/* add sorted certificate chain */ /* add sorted certificate chain */
for (i=0; i<sk_X509_num(chain); i++) { for (i=0; i<sk_X509_num(chain); i++) {
PKCS7_add_certificate(p7, sk_X509_value(chain, i)); (void)PKCS7_add_certificate(p7, sk_X509_value(chain, i));
} }
/* add crls */ /* add crls */
if (ctx->options->crls) { if (ctx->options->crls) {
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++) for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i)); (void)PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
} }
sk_X509_free(chain); sk_X509_free(chain);
return p7; /* OK */ return p7; /* OK */
err:
PKCS7_free(p7);
return NULL; /* FAILED */
} }
/* /*
@ -732,11 +735,6 @@ static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
int i; int i;
STACK_OF(X509) *chain = sk_X509_new(X509_compare); STACK_OF(X509) *chain = sk_X509_new(X509_compare);
/* add the signer's certificate */
if (ctx->options->cert != NULL && !sk_X509_push(chain, ctx->options->cert)) {
sk_X509_free(chain);
return NULL;
}
if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) { if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) {
sk_X509_free(chain); sk_X509_free(chain);
return NULL; return NULL;

View File

@ -207,12 +207,23 @@ ASN1_SEQUENCE(MsCtlContent) = {
IMPLEMENT_ASN1_FUNCTIONS(MsCtlContent) IMPLEMENT_ASN1_FUNCTIONS(MsCtlContent)
#ifndef OPENSSL_NO_ENGINE
ASN1_SEQUENCE(EngineControl) = { ASN1_SEQUENCE(EngineControl) = {
ASN1_SIMPLE(EngineControl, cmd, ASN1_OCTET_STRING), ASN1_SIMPLE(EngineControl, cmd, ASN1_OCTET_STRING),
ASN1_SIMPLE(EngineControl, param, ASN1_OCTET_STRING) ASN1_SIMPLE(EngineControl, param, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(EngineControl) } ASN1_SEQUENCE_END(EngineControl)
IMPLEMENT_ASN1_FUNCTIONS(EngineControl) IMPLEMENT_ASN1_FUNCTIONS(EngineControl)
#endif /* OPENSSL_NO_ENGINE */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
DEFINE_STACK_OF(OSSL_PROVIDER)
static STACK_OF(OSSL_PROVIDER) *providers = NULL;
static void provider_free(OSSL_PROVIDER *prov);
static void providers_cleanup(void);
static int provider_load(const char *pname);
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
/* Prototypes */ /* Prototypes */
static ASN1_INTEGER *create_nonce(int bits); static ASN1_INTEGER *create_nonce(int bits);
@ -232,7 +243,10 @@ static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b);
static PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx); static PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx);
static void print_cert(X509 *cert, int i); static void print_cert(X509 *cert, int i);
static int x509_store_load_crlfile(X509_STORE *store, char *cafile, char *crlfile); static int x509_store_load_crlfile(X509_STORE *store, char *cafile, char *crlfile);
static void load_objects_from_store(const char *url, char *pass, EVP_PKEY **pkey, STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls);
#ifndef OPENSSL_NO_ENGINE
static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg); static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg);
#endif /* OPENSSL_NO_ENGINE */
/* /*
@ -3443,12 +3457,14 @@ static void free_options(GLOBAL_OPTIONS *options)
OPENSSL_free(options->https_crlfile); OPENSSL_free(options->https_crlfile);
OPENSSL_free(options->tsa_cafile); OPENSSL_free(options->tsa_cafile);
OPENSSL_free(options->tsa_crlfile); OPENSSL_free(options->tsa_crlfile);
if (options->pass) {
/* reset password */
memset(options->pass, 0, strlen(options->pass));
OPENSSL_free(options->pass);
}
/* If key is NULL nothing is done */ /* If key is NULL nothing is done */
EVP_PKEY_free(options->pkey); EVP_PKEY_free(options->pkey);
options->pkey = NULL; options->pkey = NULL;
/* If X509 structure is NULL nothing is done */
X509_free(options->cert);
options->cert = NULL;
/* Free up all elements of sk structure and sk itself */ /* Free up all elements of sk structure and sk itself */
sk_X509_pop_free(options->certs, X509_free); sk_X509_pop_free(options->certs, X509_free);
options->certs = NULL; options->certs = NULL;
@ -3456,7 +3472,9 @@ static void free_options(GLOBAL_OPTIONS *options)
options->xcerts = NULL; options->xcerts = NULL;
sk_X509_CRL_pop_free(options->crls, X509_CRL_free); sk_X509_CRL_pop_free(options->crls, X509_CRL_free);
options->crls = NULL; options->crls = NULL;
#ifndef OPENSSL_NO_ENGINE
sk_EngineControl_pop_free(options->engine_ctrls, EngineControl_free); sk_EngineControl_pop_free(options->engine_ctrls, EngineControl_free);
#endif /* OPENSSL_NO_ENGINE */
} }
/* /*
@ -3480,11 +3498,22 @@ static void usage(const char *argv0, const char *cmd)
printf("%1s[ --help ]\n\n", ""); printf("%1s[ --help ]\n\n", "");
} }
if (on_list(cmd, cmds_sign)) { if (on_list(cmd, cmds_sign)) {
printf("%1s[ sign ] ( -pkcs12 <pkcs12file>\n", ""); printf("%1s[ sign ] -pkcs12 <pkcs12file> | ( [ -certs <certfile> | -spc <certfile> ]\n", "");
printf("%13s | ( -certs <certfile> | -spc <certfile> ) -key <keyfile>\n", ""); #if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%13s | [ -pkcs11engine <engine> ] [ -login ] -pkcs11module <module>\n", ""); printf("%12s( -key <keyfile> | ( -key <pkcs11 key URI> -pkcs11module <module> [ -pkcs11cert <pkcs11 cert URI> ] )\n", "");
printf("%13s | [ -engineCtrl <command[:parameter]> ]\n", ""); #else /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
printf("%15s ( -pkcs11cert <pkcs11 cert id> | -certs <certfile> ) -key <pkcs11 key id> )\n", ""); printf("%12s-key <keyfile> )\n", "");
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s[ -provider <provider> | ", "");
#else /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
printf("%12s[ ", "");
#endif /* OPENSSL_NO_ENGINE */
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
printf("%s( -engine <engine> [ -login ] [ -engineCtrl <command[:parameter]> ] ) ] ) )\n", "");
#endif /* OPENSSL_NO_ENGINE */
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s[ -nolegacy ]\n", ""); printf("%12s[ -nolegacy ]\n", "");
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
@ -3618,11 +3647,18 @@ static void help_for(const char *argv0, const char *cmd)
const char *cmds_pass[] = {"sign", NULL}; const char *cmds_pass[] = {"sign", NULL};
const char *cmds_pem[] = {"sign", "extract-data", "extract-signature", NULL}; const char *cmds_pem[] = {"sign", "extract-data", "extract-signature", NULL};
const char *cmds_ph[] = {"sign", "extract-data", NULL}; const char *cmds_ph[] = {"sign", "extract-data", NULL};
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
const char *cmds_pkcs11cert[] = {"sign", NULL}; const char *cmds_pkcs11cert[] = {"sign", NULL};
const char *cmds_pkcs11engine[] = {"sign", NULL};
const char *cmds_pkcs11module[] = {"sign", NULL}; const char *cmds_pkcs11module[] = {"sign", NULL};
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
const char *cmds_provider[] = {"sign", NULL};
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
const char *cmds_engine[] = {"sign", NULL};
const char *cmds_engineCtrl[] = {"sign", NULL}; const char *cmds_engineCtrl[] = {"sign", NULL};
const char *cmds_login[] = {"sign", NULL}; const char *cmds_login[] = {"sign", NULL};
#endif /* OPENSSL_NO_ENGINE */
const char *cmds_pkcs12[] = {"sign", NULL}; const char *cmds_pkcs12[] = {"sign", NULL};
const char *cmds_readpass[] = {"sign", NULL}; const char *cmds_readpass[] = {"sign", NULL};
const char *cmds_require_leaf_hash[] = {"attach-signature", "verify", NULL}; const char *cmds_require_leaf_hash[] = {"attach-signature", "verify", NULL};
@ -3754,16 +3790,24 @@ static void help_for(const char *argv0, const char *cmd)
printf("%-24s= PKCS#7 output data format PEM to use (default: DER)\n", "-pem"); printf("%-24s= PKCS#7 output data format PEM to use (default: DER)\n", "-pem");
if (on_list(cmd, cmds_ph)) if (on_list(cmd, cmds_ph))
printf("%-24s= generate page hashes for executable files\n", "-ph"); printf("%-24s= generate page hashes for executable files\n", "-ph");
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
if (on_list(cmd, cmds_pkcs11cert)) if (on_list(cmd, cmds_pkcs11cert))
printf("%-24s= PKCS#11 URI identifies a certificate in the token\n", "-pkcs11cert"); printf("%-24s= PKCS#11 URI identifies a certificate in the token\n", "-pkcs11cert");
if (on_list(cmd, cmds_pkcs11engine))
printf("%-24s= PKCS#11 engine\n", "-pkcs11engine");
if (on_list(cmd, cmds_pkcs11module)) if (on_list(cmd, cmds_pkcs11module))
printf("%-24s= PKCS#11 module\n", "-pkcs11module"); printf("%-24s= PKCS#11 module\n", "-pkcs11module");
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
if (on_list(cmd, cmds_provider))
printf("%-24s= PKCS#11 provider\n", "-provider");
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
if (on_list(cmd, cmds_engine))
printf("%-24s= PKCS#11 engine\n", "-engine");
if (on_list(cmd, cmds_engineCtrl)) if (on_list(cmd, cmds_engineCtrl))
printf("%-24s= control hardware engine\n", "-engineCtrl"); printf("%-24s= control parameters for the PKCS#11 engine\n", "-engineCtrl");
if (on_list(cmd, cmds_login)) if (on_list(cmd, cmds_login))
printf("%-24s= force login to the token\n", "-login"); printf("%-24s= force login to the token for the PKCS#11 engine only\n", "-login");
#endif /* OPENSSL_NO_ENGINE */
if (on_list(cmd, cmds_pkcs12)) if (on_list(cmd, cmds_pkcs12))
printf("%-24s= PKCS#12 container with the certificate and the private key\n", "-pkcs12"); printf("%-24s= PKCS#12 container with the certificate and the private key\n", "-pkcs12");
if (on_list(cmd, cmds_readpass)) if (on_list(cmd, cmds_readpass))
@ -3915,42 +3959,6 @@ static int read_password(GLOBAL_OPTIONS *options)
return 1; /* OK */ return 1; /* OK */
} }
/*
* Parse a PKCS#12 container with certificates and a private key.
* If successful the private key will be written to options->pkey,
* the corresponding certificate to options->cert
* and any additional certificates to options->certs.
* [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success
*/
static int read_pkcs12file(GLOBAL_OPTIONS *options)
{
BIO *btmp;
PKCS12 *p12;
int ret = 0;
btmp = BIO_new_file(options->pkcs12file, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read PKCS#12 file: %s\n", options->pkcs12file);
return 0; /* FAILED */
}
p12 = d2i_PKCS12_bio(btmp, NULL);
if (!p12) {
fprintf(stderr, "Failed to extract PKCS#12 data: %s\n", options->pkcs12file);
goto out; /* FAILED */
}
if (!PKCS12_parse(p12, options->pass ? options->pass : "", &options->pkey, &options->cert, &options->certs)) {
fprintf(stderr, "Failed to parse PKCS#12 file: %s (Wrong password?)\n", options->pkcs12file);
PKCS12_free(p12);
goto out; /* FAILED */
}
PKCS12_free(p12);
ret = 1; /* OK */
out:
BIO_free(btmp);
return ret;
}
/* /*
* Obtain a copy of the whole X509_CRL chain * Obtain a copy of the whole X509_CRL chain
* [in] chain: STACK_OF(X509_CRL) structure * [in] chain: STACK_OF(X509_CRL) structure
@ -3958,13 +3966,15 @@ out:
*/ */
static STACK_OF(X509_CRL) *X509_CRL_chain_up_ref(STACK_OF(X509_CRL) *chain) static STACK_OF(X509_CRL) *X509_CRL_chain_up_ref(STACK_OF(X509_CRL) *chain)
{ {
STACK_OF(X509_CRL) *ret;
int i; int i;
ret = sk_X509_CRL_dup(chain); STACK_OF(X509_CRL) *ret = sk_X509_CRL_dup(chain);
if (ret == NULL) if (ret == NULL)
return NULL; return NULL;
for (i = 0; i < sk_X509_CRL_num(ret); i++) { for (i = 0; i < sk_X509_CRL_num(ret); i++) {
X509_CRL *x = sk_X509_CRL_value(ret, i); X509_CRL *x = sk_X509_CRL_value(ret, i);
if (!X509_CRL_up_ref(x)) if (!X509_CRL_up_ref(x))
goto err; goto err;
} }
@ -3976,177 +3986,67 @@ err:
return NULL; return NULL;
} }
#if OPENSSL_VERSION_NUMBER<0x1010108f
/* /*
* Load certificates from a file. * Load the private key from a file in DER format.
* Workaround for OpenSSL 1.1.1g and older
* [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success
*/
static int read_der_keyfile(GLOBAL_OPTIONS *options)
{
BIO *btmp = BIO_new_file(options->keyfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read private key file: %s\n", options->keyfile);
return 0; /* FAILED */
}
options->pkey = d2i_PrivateKey_bio(btmp, NULL);
BIO_free(btmp);
if (!options->pkey) {
fprintf(stderr, "Failed to decode private key file: %s\n", options->keyfile);
return 0; /* FAILED */
}
return 1; /* OK */
}
#endif /* OPENSSL_VERSION_NUMBER<0x1010108f */
/*
* Load certificates from .spc or .p7b certificate file (PKCS#7 structure)
* If successful all certificates will be written to options->certs * If successful all certificates will be written to options->certs
* and optional CRLs will be written to options->crls. * and optional CRLs will be written to options->crls.
* [in, out] options: structure holds the input data * [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success * [returns] 0 on error or 1 on success
*/ */
static int read_certfile(GLOBAL_OPTIONS *options) static int read_pkcs7_certfile(GLOBAL_OPTIONS *options)
{ {
BIO *btmp; PKCS7 *p7;
int ret = 0; BIO *btmp = BIO_new_file(options->certfile, "rb");
btmp = BIO_new_file(options->certfile, "rb");
if (!btmp) { if (!btmp) {
fprintf(stderr, "Failed to read certificate file: %s\n", options->certfile); fprintf(stderr, "Failed to read certificate from: %s\n",
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER >= 0x30000000L
options->certfile ? options->certfile : options->p11cert);
#else
options->certfile);
#endif
return 0; /* FAILED */ return 0; /* FAILED */
} }
/* .pem certificate file */ p7 = d2i_PKCS7_bio(btmp, NULL);
options->certs = X509_chain_read_certs(btmp, NULL); if (!p7) {
/* .der certificate file */
if (!options->certs) {
X509 *x = NULL;
(void)BIO_seek(btmp, 0);
if (d2i_X509_bio(btmp, &x)) {
options->certs = sk_X509_new_null();
if (!sk_X509_push(options->certs, x)) {
X509_free(x);
goto out; /* FAILED */
}
printf("Warning: The certificate file contains a single x509 certificate\n");
}
}
/* .spc or .p7b certificate file (PKCS#7 structure) */
if (!options->certs) {
PKCS7 *p7;
(void)BIO_seek(btmp, 0);
p7 = d2i_PKCS7_bio(btmp, NULL);
if (!p7)
goto out; /* FAILED */
options->certs = X509_chain_up_ref(p7->d.sign->cert);
/* additional CRLs may be supplied as part of a PKCS#7 signed data structure */
if (p7->d.sign->crl)
options->crls = X509_CRL_chain_up_ref(p7->d.sign->crl);
PKCS7_free(p7);
}
ret = 1; /* OK */
out:
if (ret == 0)
fprintf(stderr, "No certificate found\n"); fprintf(stderr, "No certificate found\n");
BIO_free(btmp); BIO_free(btmp);
return ret;
}
/*
* Load additional (cross) certificates from a .pem file
* [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success
*/
static int read_xcertfile(GLOBAL_OPTIONS *options)
{
BIO *btmp;
int ret = 0;
btmp = BIO_new_file(options->xcertfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read cross certificates file: %s\n", options->xcertfile);
return 0; /* FAILED */ return 0; /* FAILED */
} }
options->xcerts = X509_chain_read_certs(btmp, NULL); sk_X509_pop_free(options->certs, X509_free);
if (!options->xcerts) { options->certs = X509_chain_up_ref(p7->d.sign->cert);
fprintf(stderr, "Failed to read cross certificates file: %s\n", options->xcertfile); if (p7->d.sign->crl) {
goto out; /* FAILED */ printf("Loading Certificate Revocation List: %s\n", options->certfile);
sk_X509_CRL_pop_free(options->crls, X509_CRL_free);
options->crls = X509_CRL_chain_up_ref(p7->d.sign->crl);
} }
PKCS7_free(p7);
ret = 1; /* OK */
out:
BIO_free(btmp); BIO_free(btmp);
return ret;
}
/*
* Load the private key from a file
* [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success
*/
static int read_keyfile(GLOBAL_OPTIONS *options)
{
BIO *btmp;
int ret = 0;
btmp = BIO_new_file(options->keyfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read private key file: %s\n", options->keyfile);
return 0; /* FAILED */
}
if (((options->pkey = d2i_PrivateKey_bio(btmp, NULL)) == NULL &&
(BIO_seek(btmp, 0) == 0) &&
(options->pkey = PEM_read_bio_PrivateKey(btmp, NULL, NULL, options->pass ? options->pass : NULL)) == NULL &&
(BIO_seek(btmp, 0) == 0) &&
(options->pkey = PEM_read_bio_PrivateKey(btmp, NULL, NULL, NULL)) == NULL)) {
fprintf(stderr, "Failed to decode private key file: %s (Wrong password?)\n", options->keyfile);
goto out; /* FAILED */
}
ret = 1; /* OK */
out:
BIO_free(btmp);
return ret;
}
/*
* Decode Microsoft Private Key (PVK) file.
* PVK is a proprietary Microsoft format that stores a cryptographic private key.
* PVK files are often password-protected.
* A PVK file may have an associated .spc (PKCS7) certificate file.
* [in, out] options: structure holds the input data
* [returns] PVK file
*/
static char *find_pvk_key(GLOBAL_OPTIONS *options)
{
u_char magic[4];
/* Microsoft Private Key format Header Hexdump */
const u_char pvkhdr[4] = {0x1e, 0xf1, 0xb5, 0xb0};
char *pvkfile = NULL;
BIO *btmp;
if (!options->keyfile
#ifndef OPENSSL_NO_ENGINE
|| options->p11module
#endif /* OPENSSL_NO_ENGINE */
)
return NULL; /* FAILED */
btmp = BIO_new_file(options->keyfile, "rb");
if (!btmp)
return NULL; /* FAILED */
magic[0] = 0x00;
BIO_read(btmp, magic, 4);
if (!memcmp(magic, pvkhdr, 4)) {
pvkfile = options->keyfile;
options->keyfile = NULL;
}
BIO_free(btmp);
return pvkfile;
}
/*
* [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success
*/
static int read_pvk_key(GLOBAL_OPTIONS *options)
{
BIO *btmp;
btmp = BIO_new_file(options->pvkfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read private key file: %s\n", options->pvkfile);
return 0; /* FAILED */
}
options->pkey = b2i_PVK_bio(btmp, NULL, options->pass ? options->pass : NULL);
if (!options->pkey && options->askpass) {
(void)BIO_seek(btmp, 0);
options->pkey = b2i_PVK_bio(btmp, NULL, NULL);
}
BIO_free(btmp);
if (!options->pkey) {
fprintf(stderr, "Failed to decode private key file: %s\n", options->pvkfile);
return 0; /* FAILED */
}
return 1; /* OK */ return 1; /* OK */
} }
@ -4275,7 +4175,7 @@ static int read_token(GLOBAL_OPTIONS *options, ENGINE *engine)
ENGINE_finish(engine); ENGINE_finish(engine);
return 0; /* FAILED */ return 0; /* FAILED */
} else } else
options->cert = parms.cert; sk_X509_push(options->certs, parms.cert);
} }
options->pkey = ENGINE_load_private_key(engine, options->keyfile, NULL, NULL); options->pkey = ENGINE_load_private_key(engine, options->keyfile, NULL, NULL);
@ -4287,65 +4187,92 @@ static int read_token(GLOBAL_OPTIONS *options, ENGINE *engine)
} }
return 1; /* OK */ return 1; /* OK */
} }
static int engine_load(GLOBAL_OPTIONS *options)
{
ENGINE *engine;
if (options->p11engine)
engine = engine_dynamic(options);
else
engine = engine_pkcs11();
if (!engine)
return 0; /* FAILED */
printf("Engine \"%s\" set.\n", ENGINE_get_id(engine));
/* Load the private key and the signer certificate from the security token */
if (!read_token(options, engine))
return 0; /* FAILED */
return 1; /* OK */
}
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
/* /*
* Support for security token and various certificate and key file formats:
* PEM / DER / SPC / P7B / PVK
* .spc and .p7b files contain a PKCS#7 certificate structure;
* .pvk is a Microsoft-specific binary format for RSA and DSA private keys,
* it may be passphrase-protected and can have an associated .spc file.
* [in, out] options: structure holds the input data * [in, out] options: structure holds the input data
* [returns] 0 on error or 1 on success * [returns] 0 on error or 1 on success
*/ */
static int read_crypto_params(GLOBAL_OPTIONS *options) static int read_crypto_params(GLOBAL_OPTIONS *options)
{ {
int ret = 0; options->certs = sk_X509_new_null();
options->xcerts = sk_X509_new_null();
options->crls = sk_X509_CRL_new_null();
/* Microsoft Private Key format support */ /* Try to use PKCS#12 container with certificates and the private key ('-pkcs12' option) */
options->pvkfile = find_pvk_key(options); if (options->pkcs12file) {
if (options->pvkfile) { load_objects_from_store(options->pkcs12file, options->pass, &options->pkey, options->certs, options->crls);
if (!read_certfile(options) || !read_pvk_key(options))
goto out; /* FAILED */
/* PKCS#12 container with certificates and the private key ("-pkcs12" option) */
} else if (options->pkcs12file) {
if (!read_pkcs12file(options))
goto out; /* FAILED */
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
/* Security token */
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
/* PKCS11 engine and module support */ /* PKCS#11 'dynamic' engine */
} else if ((options->p11engine) || (options->p11module)) { } else if (options->p11engine && !engine_load(options)) {
ENGINE *engine; goto out;
if (options->p11engine)
engine = engine_dynamic(options);
else
engine = engine_pkcs11();
if (!engine)
goto out; /* FAILED */
printf("Engine \"%s\" set.\n", ENGINE_get_id(engine));
/* Load the private key and the signer certificate from the security token */
if (!read_token(options, engine))
goto out; /* FAILED */
/* Load the signer certificate and the whole certificate chain from a file */
if (options->certfile && !read_certfile(options))
goto out; /* FAILED */
/* PEM / DER / SPC file format support */
} else if (!read_certfile(options) || !read_keyfile(options))
goto out; /* FAILED */
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
} else if (options->p11module) {
/* Load additional (cross) certificates ("-ac" option) */ #if OPENSSL_VERSION_NUMBER>=0x30000000L
if (options->xcertfile && !read_xcertfile(options)) /* Try to load PKCS#11 provider first */
goto out; /* FAILED */ if ((options->provider && provider_load(options->provider)) || provider_load("pkcs11prov")) {
load_objects_from_store(options->keyfile, options->pass, &options->pkey, NULL, NULL);
ret = 1; /* OK */ load_objects_from_store(options->p11cert, options->pass, NULL, options->certs, NULL);
out: } else
/* reset password */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
if (options->pass) { #ifndef OPENSSL_NO_ENGINE
memset(options->pass, 0, strlen(options->pass)); /* try to find and load libp11 'pkcs11' engine */
OPENSSL_free(options->pass); if (!engine_load(options)) {
goto out;
#endif /* OPENSSL_NO_ENGINE */
}
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
} else {
/* Load the the private key ('-key' option) */
load_objects_from_store(options->keyfile, options->pass, &options->pkey, NULL, NULL);
} }
return ret; #if OPENSSL_VERSION_NUMBER<0x1010108f
/* Workaround for OpenSSL 1.1.1g and older, where the store API does not
* support loading private key in DER format. */
if (!options->pkey && !read_der_keyfile(options)) {
goto out;
}
#endif /* OPENSSL_VERSION_NUMBER<0x1010108f */
/* Load additional (cross) certificates ('-ac' option) */
load_objects_from_store(options->xcertfile, options->pass, NULL, options->xcerts, NULL);
/* Load the certificate chain ('-certs' option) */
load_objects_from_store(options->certfile, options->pass, NULL, options->certs, NULL);
/* OpenSSL store API does not support PKCS#7 format */
if (sk_X509_num(options->certs) == 0 && !read_pkcs7_certfile(options)) {
goto out;
}
out:
return (options->pkey && sk_X509_num(options->certs) > 0) ? 1 : 0;
} }
/* /*
@ -4374,6 +4301,83 @@ static char *get_cafile(void)
return NULL; return NULL;
} }
static int ui_read(UI *ui, UI_STRING *uis)
{
char *pass = (char *)UI_get0_user_data(ui);
int (*reader)(UI *ui, UI_STRING *uis) = NULL;
if (pass) {
UI_set_result(ui, uis, pass);
return 1;
}
if (!UI_OpenSSL()) {
return 0;
}
reader = UI_method_get_reader(UI_OpenSSL());
if (reader != NULL) {
return reader(ui, uis);
}
/* Default to the empty password if we've got nothing better */
UI_set_result(ui, uis, "");
return 1;
}
static UI_METHOD *ui_osslsigncode(void) {
static UI_METHOD *ui_method=NULL;
if (ui_method) /* already initialized */
return ui_method;
ui_method = UI_create_method("osslsigncode UI");
if (!ui_method) {
return NULL;
}
UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
UI_method_set_writer(ui_method, UI_method_get_writer(UI_OpenSSL()));
UI_method_set_reader(ui_method, ui_read);
UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
return ui_method;
}
/* store_type == 0 means here multiple types of credentials are to be loaded */
static void load_objects_from_store(const char *url, char *pass, EVP_PKEY **pkey, STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls) {
OSSL_STORE_CTX *store_ctx;
int type;
if (!url)
return;
store_ctx = OSSL_STORE_open(url, ui_osslsigncode(), pass, NULL, NULL);
if (!store_ctx)
return;
while (!OSSL_STORE_eof(store_ctx)) {
OSSL_STORE_INFO *object = OSSL_STORE_load(store_ctx);
if (!object)
continue;
type = OSSL_STORE_INFO_get_type(object);
switch (type) {
case OSSL_STORE_INFO_PKEY:
if (pkey)
*pkey = OSSL_STORE_INFO_get1_PKEY(object);
break;
case OSSL_STORE_INFO_CERT:
if (certs)
sk_X509_push(certs, OSSL_STORE_INFO_get1_CERT(object));
break;
case OSSL_STORE_INFO_CRL:
if (crls)
sk_X509_CRL_push(crls, OSSL_STORE_INFO_get1_CRL(object));
break;
default:
break; /* skip any other type */
}
OSSL_STORE_INFO_free(object);
}
OSSL_STORE_close(store_ctx);
}
static void print_version(void) static void print_version(void)
{ {
char *cafile = get_cafile(); char *cafile = get_cafile();
@ -4434,9 +4438,6 @@ static cmd_type_t get_command(char **argv)
} }
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
DEFINE_STACK_OF(OSSL_PROVIDER)
static STACK_OF(OSSL_PROVIDER) *providers = NULL;
static void provider_free(OSSL_PROVIDER *prov) static void provider_free(OSSL_PROVIDER *prov)
{ {
OSSL_PROVIDER_unload(prov); OSSL_PROVIDER_unload(prov);
@ -4446,11 +4447,12 @@ static void providers_cleanup(void)
{ {
sk_OSSL_PROVIDER_pop_free(providers, provider_free); sk_OSSL_PROVIDER_pop_free(providers, provider_free);
providers = NULL; providers = NULL;
UI_destroy_method(ui_osslsigncode());
} }
static int provider_load(OSSL_LIB_CTX *libctx, const char *pname) static int provider_load(const char *pname)
{ {
OSSL_PROVIDER *prov= OSSL_PROVIDER_load(libctx, pname); OSSL_PROVIDER *prov= OSSL_PROVIDER_load(NULL, pname);
if (prov == NULL) { if (prov == NULL) {
fprintf(stderr, "Unable to load provider: %s\n", pname); fprintf(stderr, "Unable to load provider: %s\n", pname);
return 0; /* FAILED */ return 0; /* FAILED */
@ -4469,10 +4471,10 @@ static int use_legacy(void)
{ {
/* load the legacy provider if not loaded already */ /* load the legacy provider if not loaded already */
if (!OSSL_PROVIDER_available(NULL, "legacy")) { if (!OSSL_PROVIDER_available(NULL, "legacy")) {
if (!provider_load(NULL, "legacy")) if (!provider_load("legacy"))
return 0; /* FAILED */ return 0; /* FAILED */
/* load the default provider explicitly */ /* load the default provider explicitly */
if (!provider_load(NULL, "default")) if (!provider_load("default"))
return 0; /* FAILED */ return 0; /* FAILED */
} }
return 1; /* OK */ return 1; /* OK */
@ -4523,7 +4525,9 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
/* Use legacy PKCS#12 container with RC2-40-CBC private key and certificate encryption algorithm */ /* Use legacy PKCS#12 container with RC2-40-CBC private key and certificate encryption algorithm */
options->legacy = 1; options->legacy = 1;
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
options->engine_ctrls = sk_EngineControl_new_null(); options->engine_ctrls = sk_EngineControl_new_null();
#endif /* OPENSSL_NO_ENGINE */
if (cmd == CMD_HELP) { if (cmd == CMD_HELP) {
return 0; /* FAILED */ return 0; /* FAILED */
@ -4579,25 +4583,35 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
} else if ((cmd == CMD_SIGN || cmd == CMD_EXTRACT || cmd == CMD_EXTRACT_DATA) } else if ((cmd == CMD_SIGN || cmd == CMD_EXTRACT || cmd == CMD_EXTRACT_DATA)
&& !strcmp(*argv, "-pem")) { && !strcmp(*argv, "-pem")) {
options->output_pkcs7 = 1; options->output_pkcs7 = 1;
#ifndef OPENSSL_NO_ENGINE #if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
} else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-pkcs11cert")) { } else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-pkcs11cert")) {
if (--argc < 1) { if (--argc < 1) {
usage(argv0, "all"); usage(argv0, "all");
return 0; /* FAILED */ return 0; /* FAILED */
} }
options->p11cert = *(++argv); options->p11cert = *(++argv);
} else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-pkcs11engine")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->p11engine = *(++argv);
} else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-pkcs11module")) { } else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-pkcs11module")) {
if (--argc < 1) { if (--argc < 1) {
usage(argv0, "all"); usage(argv0, "all");
return 0; /* FAILED */ return 0; /* FAILED */
} }
options->p11module = *(++argv); options->p11module = *(++argv);
#if OPENSSL_VERSION_NUMBER>=0x30000000L
#ifdef USE_WIN32
if (_putenv_s("PKCS11_MODULE_PATH", options->p11module))
#else
if (setenv("PKCS11_MODULE_PATH", options->p11module, 1))
#endif
return 0; /* FAILED */
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
} else if ((cmd == CMD_SIGN) && (!strcmp(*argv, "-engine") || !strcmp(*argv, "-pkcs11engine"))) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->p11engine = *(++argv);
} else if (!strcmp(*argv, "-engineCtrl")) { } else if (!strcmp(*argv, "-engineCtrl")) {
if (--argc < 1) { if (--argc < 1) {
usage(argv0, "all"); usage(argv0, "all");
@ -4608,6 +4622,12 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
options->login = 1; options->login = 1;
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
} else if (!strcmp(*argv, "-provider")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->provider = *(++argv);
} else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-nolegacy")) { } else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-nolegacy")) {
options->legacy = 0; options->legacy = 0;
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
@ -4888,9 +4908,15 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
!options->infile || !options->infile ||
(cmd != CMD_VERIFY && !options->outfile) || (cmd != CMD_VERIFY && !options->outfile) ||
(cmd == CMD_SIGN && !((options->certfile && options->keyfile) || (cmd == CMD_SIGN && !((options->certfile && options->keyfile) ||
#if OPENSSL_VERSION_NUMBER>=0x30000000L
options->provider ||
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
options->p11engine || options->p11module || options->p11engine ||
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
options->p11module ||
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
options->pkcs12file))) { options->pkcs12file))) {
if (failarg) if (failarg)
fprintf(stderr, "Unknown option: %s\n", failarg); fprintf(stderr, "Unknown option: %s\n", failarg);
@ -4911,6 +4937,7 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
return 1; /* OK */ return 1; /* OK */
} }
#ifndef OPENSSL_NO_ENGINE
static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg) static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg)
{ {
EngineControl *engine_ctrl = EngineControl_new(); EngineControl *engine_ctrl = EngineControl_new();
@ -4923,6 +4950,7 @@ static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg)
ASN1_STRING_set(engine_ctrl->cmd, arg, (int)strlen(arg)); ASN1_STRING_set(engine_ctrl->cmd, arg, (int)strlen(arg));
sk_EngineControl_push(options->engine_ctrls, engine_ctrl); sk_EngineControl_push(options->engine_ctrls, engine_ctrl);
} }
#endif /* OPENSSL_NO_ENGINE */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {

View File

@ -66,7 +66,9 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/safestack.h> #include <openssl/safestack.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/store.h>
#include <openssl/ts.h> #include <openssl/ts.h>
#include <openssl/ui.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> /* X509_PURPOSE */ #include <openssl/x509v3.h> /* X509_PURPOSE */
@ -244,6 +246,7 @@ typedef enum {
typedef unsigned char u_char; typedef unsigned char u_char;
#ifndef OPENSSL_NO_ENGINE
typedef struct { typedef struct {
ASN1_OCTET_STRING *cmd; ASN1_OCTET_STRING *cmd;
ASN1_OCTET_STRING *param; ASN1_OCTET_STRING *param;
@ -251,6 +254,7 @@ typedef struct {
DECLARE_ASN1_FUNCTIONS(EngineControl) DECLARE_ASN1_FUNCTIONS(EngineControl)
DEFINE_STACK_OF(EngineControl) DEFINE_STACK_OF(EngineControl)
#endif /* OPENSSL_NO_ENGINE */
typedef struct { typedef struct {
char *infile; char *infile;
@ -267,6 +271,7 @@ typedef struct {
char *p11module; char *p11module;
char *p11cert; char *p11cert;
int login; int login;
STACK_OF(EngineControl) *engine_ctrls;
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
int askpass; int askpass;
char *readpass; char *readpass;
@ -303,9 +308,9 @@ typedef struct {
int jp; int jp;
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
int legacy; int legacy;
char *provider;
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
EVP_PKEY *pkey; EVP_PKEY *pkey;
X509 *cert;
STACK_OF(X509) *certs; STACK_OF(X509) *certs;
STACK_OF(X509) *xcerts; STACK_OF(X509) *xcerts;
STACK_OF(X509_CRL) *crls; STACK_OF(X509_CRL) *crls;
@ -315,7 +320,6 @@ typedef struct {
char *tsa_keyfile; char *tsa_keyfile;
time_t tsa_time; time_t tsa_time;
int nested_number; int nested_number;
STACK_OF(EngineControl) *engine_ctrls;
} GLOBAL_OPTIONS; } GLOBAL_OPTIONS;
/* /*