1
0
mirror of https://github.com/mtrojnar/osslsigncode.git synced 2025-04-09 10:38:05 -05:00

Built-in TSA response generation ()

This commit is contained in:
Małgorzata Olszówka (she/her) 2023-07-28 16:03:04 +02:00 committed by GitHub
parent adcfd9a33f
commit c04b229ce2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 325 additions and 69 deletions

@ -2,6 +2,9 @@
### 2.7 (unreleased)
- added a built-in TSA response generation (-TSA-certs, -TSA-key
and -TSA-time options)
### 2.6 (2023.05.29)
- modular architecture implemented to simplify adding file formats

@ -183,21 +183,6 @@ IMPLEMENT_ASN1_FUNCTIONS(TimeStampRequest)
/* RFC3161 Time stamping */
ASN1_SEQUENCE(PKIStatusInfo) = {
ASN1_SIMPLE(PKIStatusInfo, status, ASN1_INTEGER),
ASN1_SEQUENCE_OF_OPT(PKIStatusInfo, statusString, ASN1_UTF8STRING),
ASN1_OPT(PKIStatusInfo, failInfo, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END(PKIStatusInfo)
IMPLEMENT_ASN1_FUNCTIONS(PKIStatusInfo)
ASN1_SEQUENCE(TimeStampResp) = {
ASN1_SIMPLE(TimeStampResp, status, PKIStatusInfo),
ASN1_OPT(TimeStampResp, token, PKCS7)
} ASN1_SEQUENCE_END(TimeStampResp)
IMPLEMENT_ASN1_FUNCTIONS(TimeStampResp)
ASN1_SEQUENCE(TimeStampReq) = {
ASN1_SIMPLE(TimeStampReq, version, ASN1_INTEGER),
ASN1_SIMPLE(TimeStampReq, messageImprint, MessageImprint),
@ -406,19 +391,19 @@ static BIO *bio_encode_authenticode_request(PKCS7 *p7)
}
/*
* Decode a RFC 3161 response from BIO.
* If successful the RFC 3161 timestamp will be written into
* the PKCS7 SignerInfo structure as an unauthorized attribute - cont[1].
* [in, out] p7: new PKCS#7 signature
* [in] bin: BIO with http data
* [in] response: RFC3161 response
* [in] verbose: additional output mode
* [returns] 1 on error or 0 on success
*/
static int decode_rfc3161_response(PKCS7 *p7, BIO *bin, int verbose)
static int attach_rfc3161_response(PKCS7 *p7, TS_RESP *response, int verbose)
{
PKCS7_SIGNER_INFO *si;
STACK_OF(X509_ATTRIBUTE) *attrs;
TimeStampResp *reply;
TS_STATUS_INFO *status;
PKCS7 *token;
u_char *p;
int i, len;
STACK_OF(PKCS7_SIGNER_INFO) *signer_info = PKCS7_get_signer_info(p7);
@ -428,32 +413,31 @@ static int decode_rfc3161_response(PKCS7 *p7, BIO *bin, int verbose)
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
if (!si)
return 1; /* FAILED */
if (!response)
return 1; /* FAILED */
reply = ASN1_item_d2i_bio(ASN1_ITEM_rptr(TimeStampResp), bin, NULL);
if (!reply || !reply->status)
return 1; /* FAILED */
if (ASN1_INTEGER_get(reply->status->status) != 0) {
status = TS_RESP_get_status_info(response);
if (ASN1_INTEGER_get(TS_STATUS_INFO_get0_status(status)) != 0) {
if (verbose) {
printf("Timestamping failed: status %ld\n", ASN1_INTEGER_get(reply->status->status));
for (i = 0; i < sk_ASN1_UTF8STRING_num(reply->status->statusString); i++) {
ASN1_UTF8STRING *status = sk_ASN1_UTF8STRING_value(reply->status->statusString, i);
printf("%s\n", ASN1_STRING_get0_data(status));
const STACK_OF(ASN1_UTF8STRING) *reasons = TS_STATUS_INFO_get0_text(status);
printf("Timestamping failed: status %ld\n", ASN1_INTEGER_get(TS_STATUS_INFO_get0_status(status)));
for (i = 0; i < sk_ASN1_UTF8STRING_num(reasons); i++) {
ASN1_UTF8STRING *reason = sk_ASN1_UTF8STRING_value(reasons, i);
printf("%s\n", ASN1_STRING_get0_data(reason));
}
}
TimeStampResp_free(reply);
return 1; /* FAILED */
}
if (((len = i2d_PKCS7(reply->token, NULL)) <= 0) || (p = OPENSSL_malloc((size_t)len)) == NULL) {
token = TS_RESP_get_token(response);
if (((len = i2d_PKCS7(token, NULL)) <= 0) || (p = OPENSSL_malloc((size_t)len)) == NULL) {
if (verbose) {
printf("Failed to convert pkcs7: %d\n", len);
ERR_print_errors_fp(stdout);
}
TimeStampResp_free(reply);
return 1; /* FAILED */
}
len = i2d_PKCS7(reply->token, &p);
len = i2d_PKCS7(token, &p);
p -= len;
TimeStampResp_free(reply);
attrs = sk_X509_ATTRIBUTE_new_null();
attrs = X509at_add1_attr_by_txt(&attrs, SPC_RFC3161_OBJID, V_ASN1_SET, p, len);
@ -465,26 +449,22 @@ static int decode_rfc3161_response(PKCS7 *p7, BIO *bin, int verbose)
}
/*
* Decode an authenticode response from BIO.
* If successful the authenticode timestamp will be written into
* the PKCS7 SignerInfo structure as an unauthorized attribute - cont[1]:
* p7->d.sign->signer_info->unauth_attr
* [in, out] p7: new PKCS#7 signature
* [in] bin: base64 BIO with http data
* [in] resp: PKCS#7 authenticode response
* [in] verbose: additional output mode
* [returns] 1 on error or 0 on success
*/
static int decode_authenticode_response(PKCS7 *p7, BIO *b64_bin, int verbose)
static int attach_authenticode_response(PKCS7 *p7, PKCS7 *resp, int verbose)
{
PKCS7 *resp;
PKCS7_SIGNER_INFO *info, *si;
STACK_OF(X509_ATTRIBUTE) *attrs;
u_char *p;
int len, i;
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
resp = d2i_PKCS7_bio(b64_bin, NULL);
if (!resp) {
return 1; /* FAILED */
}
@ -689,15 +669,25 @@ static int add_timestamp(PKCS7 *p7, FILE_FORMAT_CTX *ctx, char *url, int rfc3161
if (bin) {
if (rfc3161) {
res = decode_rfc3161_response(p7, bin, verbose);
/* decode a RFC 3161 response from BIO */
TS_RESP *response = d2i_TS_RESP_bio(bin, NULL);
BIO_free_all(bin);
res = attach_rfc3161_response(p7, response, verbose);
TS_RESP_free(response);
} else {
BIO *b64 = BIO_new(BIO_f_base64());
/* decode an authenticode response from BIO */
PKCS7 *response;
BIO *b64, *b64_bin;
b64 = BIO_new(BIO_f_base64());
if (!blob_has_nl)
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO *b64_bin = BIO_push(b64, bin);
res = decode_authenticode_response(p7, b64_bin, verbose);
b64_bin = BIO_push(b64, bin);
response = d2i_PKCS7_bio(b64_bin, NULL);
BIO_free_all(b64_bin);
res = attach_authenticode_response(p7, response, verbose);
}
if (res && verbose) {
if (http_code != -1) {
@ -744,6 +734,236 @@ static int add_timestamp_rfc3161(PKCS7 *p7, FILE_FORMAT_CTX *ctx)
}
#endif /* ENABLE_CURL */
/*
* [in] resp_ctx: a response context that can be used for generating responses
* [in] data: unused
* [returns] hexadecimal serial number
*/
static ASN1_INTEGER *serial_cb(TS_RESP_CTX *resp_ctx, void *data)
{
int ret = 0;
uint64_t buf;
ASN1_INTEGER *serial = NULL;
/* squash unused parameter warning */
(void)data;
if (RAND_bytes((unsigned char *)&buf, sizeof buf) <= 0) {
printf("RAND_bytes failed\n");
goto out;
}
serial = ASN1_INTEGER_new();
if (!serial)
goto out;
ASN1_INTEGER_set_uint64(serial, buf);
ret = 1;
out:
if (!ret) {
TS_RESP_CTX_set_status_info(resp_ctx, TS_STATUS_REJECTION,
"Error during serial number generation.");
TS_RESP_CTX_add_failure_info(resp_ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE);
ASN1_INTEGER_free(serial);
return NULL; /* FAILED */
}
return serial;
}
/*
* This must return the seconds and microseconds since Jan 1, 1970 in the sec
* and usec variables allocated by the caller.
* [in] resp_ctx: a response context that can be used for generating responses
* [in] data: timestamping time
* [out] sec: total of seconds since Jan 1, 1970
* [out] usec: microseconds (unused)
* [returns] 0 on error or 1 on success
*/
static int time_cb(TS_RESP_CTX *resp_ctx, void *data, long *sec, long *usec)
{
time_t *time = (time_t *)data;
if(!*time) {
TS_RESP_CTX_set_status_info(resp_ctx, TS_STATUS_REJECTION,
"Time is not available.");
TS_RESP_CTX_add_failure_info(resp_ctx, TS_INFO_TIME_NOT_AVAILABLE);
return 0; /* FAILED */
}
*sec = (long int)*time;
*usec = 0;
return 1; /* OK */
}
/*
* [in] ctx: structure holds input and output data
* [in] signer_cert: the signer certificate of the TSA in PEM format
* [in] signer_key: the private key of the TSA in PEM format
* [in] chain: the certificate chain that will all be included in the response
* [in] bout: timestamp request
* [returns] RFC3161 response
*/
static TS_RESP *get_rfc3161_response(FILE_FORMAT_CTX *ctx, X509 *signer_cert,
EVP_PKEY *signer_key, STACK_OF(X509) *chain, BIO *bout)
{
TS_RESP_CTX *resp_ctx = NULL;
TS_RESP *response = NULL;
ASN1_OBJECT *policy_obj = NULL;
resp_ctx = TS_RESP_CTX_new();
if (!resp_ctx)
goto out;
TS_RESP_CTX_set_serial_cb(resp_ctx, serial_cb, NULL);
if (!TS_RESP_CTX_set_signer_cert(resp_ctx, signer_cert)) {
goto out;
}
if (!TS_RESP_CTX_set_signer_key(resp_ctx, signer_key)) {
goto out;
}
if (!TS_RESP_CTX_set_certs(resp_ctx, chain)) {
goto out;
}
/* message digest algorithm that the TSA accepts */
if (!TS_RESP_CTX_add_md(resp_ctx, ctx->options->md)) {
goto out;
}
/* default policy to use when the request does not mandate any policy
* tsa_policy1 = 1.2.3.4.1 */
policy_obj = OBJ_txt2obj(TSA_POLICY1, 0);
if (!policy_obj) {
goto out;
}
if (!TS_RESP_CTX_set_def_policy(resp_ctx, policy_obj)) {
goto out;
}
/* the accuracy of the time source of the TSA in seconds, milliseconds
* and microseconds; e.g. secs:1, millisecs:500, microsecs:100;
* 0 means not specified */
if (!TS_RESP_CTX_set_accuracy(resp_ctx, 1, 500, 100)) {
goto out;
}
if (ctx->options->tsa_time) {
TS_RESP_CTX_set_time_cb(resp_ctx, time_cb, &(ctx->options->tsa_time));
}
/* generate RFC3161 response with embedded TimeStampToken */
response = TS_RESP_create_response(resp_ctx, bout);
if (!response) {
printf("Failed to create RFC3161 response\n");
}
out:
ASN1_OBJECT_free(policy_obj);
TS_RESP_CTX_free(resp_ctx);
return response;
}
/*
* [in] bin: certfile BIO
* [in] certpass: NULL
* [returns] pointer to STACK_OF(X509) structure
*/
static STACK_OF(X509) *X509_chain_read_certs(BIO *bin, char *certpass)
{
STACK_OF(X509) *certs = sk_X509_new_null();
X509 *x509;
(void)BIO_seek(bin, 0);
x509 = PEM_read_bio_X509(bin, NULL, NULL, certpass);
while (x509) {
sk_X509_push(certs, x509);
x509 = PEM_read_bio_X509(bin, NULL, NULL, certpass);
}
ERR_clear_error();
if (!sk_X509_num(certs)) {
sk_X509_free(certs);
return NULL;
}
return certs;
}
/*
* [in, out] p7: new PKCS#7 signature
* [in] ctx: structure holds input and output data
* [returns] 1 on error or 0 on success
*/
static int add_timestamp_builtin(PKCS7 *p7, FILE_FORMAT_CTX *ctx)
{
BIO *btmp, *bout;
STACK_OF(X509) *chain;
X509 *signer_cert = NULL;
EVP_PKEY *signer_key;
TS_RESP *response = NULL;
int i, res = 1;
btmp = BIO_new_file(ctx->options->tsa_certfile, "rb");
if (!btmp) {
printf("Failed to read Time-Stamp Authority certificate file: %s\n", ctx->options->tsa_certfile);
return 0; /* FAILED */
}
/* .pem certificate file */
chain = X509_chain_read_certs(btmp, NULL);
BIO_free(btmp);
btmp = BIO_new_file(ctx->options->tsa_keyfile, "rb");
if (!btmp) {
printf("Failed to read private key file: %s\n", ctx->options->tsa_keyfile);
return 0; /* FAILED */
}
signer_key = PEM_read_bio_PrivateKey(btmp, NULL, NULL, NULL);
BIO_free(btmp);
if(!chain || !signer_key) {
printf("Failed to load Time-Stamp Authority crypto parameters\n");
return 0; /* FAILED */
}
/* find the signer's certificate located somewhere in the whole certificate chain */
for (i=0; i<sk_X509_num(chain); i++) {
X509 *cert = sk_X509_value(chain, i);
if (X509_check_private_key(cert, signer_key)) {
signer_cert = cert;
break;
}
}
if(!signer_cert) {
printf("Failed to checking the consistency of a TSA private key with a public key in any X509 certificate\n");
goto out;
}
/* The TSA signing certificate must have exactly one extended key usage
* assigned to it: timeStamping. The extended key usage must also be critical,
* otherwise the certificate is going to be refused. */
/* check X509_PURPOSE_TIMESTAMP_SIGN certificate purpose */
if (X509_check_purpose(signer_cert, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) {
printf("Unsupported TSA signer's certificate purpose X509_PURPOSE_TIMESTAMP_SIGN\n");
goto out;
}
/* check extended key usage flag XKU_TIMESTAMP */
if (!(X509_get_extended_key_usage(signer_cert) & XKU_TIMESTAMP)) {
printf("Unsupported Signer's certificate purpose XKU_TIMESTAMP\n");
goto out;
}
/* encode timestamp request */
bout = bio_encode_rfc3161_request(p7, ctx->options->md);
if (!bout) {
printf("Failed to encode timestamp request\n");
goto out;
}
response = get_rfc3161_response(ctx, signer_cert, signer_key, chain, bout);
BIO_free_all(bout);
if (response) {
res = attach_rfc3161_response(p7, response, ctx->options->verbose);
if (res) {
printf("Failed to convert timestamp reply\n");
ERR_print_errors_fp(stdout);
}
} else {
printf("Failed to obtain RFC3161 response\n");
}
out:
sk_X509_pop_free(chain, X509_free);
EVP_PKEY_free(signer_key);
TS_RESP_free(response);
return res;
}
/*
* If successful the unauthenticated blob will be written into
* the PKCS7 SignerInfo structure as an unauthorized attribute - cont[1]:
@ -801,6 +1021,10 @@ static int add_timestamp_and_blob(PKCS7 *p7, FILE_FORMAT_CTX *ctx)
"Use the \"-t\" option to add the Authenticode Time-Stamp Authority or choose another one RFC3161 Time-Stamp Authority");
return 1; /* FAILED */
}
if (ctx->options->tsa_certfile && ctx->options->tsa_keyfile && add_timestamp_builtin(p7, ctx)) {
printf("Built-in timestamping failed\n");
return 1; /* FAILED */
}
#endif /* ENABLE_CURL */
if (ctx->options->addBlob && !add_unauthenticated_blob(p7)) {
printf("Adding unauthenticated blob failed\n");
@ -1224,6 +1448,18 @@ static STACK_OF(X509_CRL) *x509_crl_list_get(PKCS7 *p7, X509_CRL *crl)
return crls;
}
static void print_timestamp_serial_number(const ASN1_INTEGER *serial)
{
BIGNUM *serialbn;
char *number;
serialbn = ASN1_INTEGER_to_BN(serial, NULL);
number = BN_bn2hex(serialbn);
printf("Timestamp serial number: %s\n", number);
BN_free(serialbn);
OPENSSL_free(number);
}
/*
* Compare the hash provided from the TSTInfo object against the hash computed
* from the signature created by the signing certificate's private key
@ -1256,6 +1492,7 @@ static int verify_timestamp_token(PKCS7 *p7, CMS_ContentInfo *timestamp)
p = (*pos)->data;
token = d2i_TimeStampToken(NULL, &p, (*pos)->length);
if (token) {
print_timestamp_serial_number(token->serial);
/* compute a hash from the encrypted message digest value of the file */
md_nid = OBJ_obj2nid(token->messageImprint->digestAlgorithm->algorithm);
md = EVP_get_digestbynid(md_nid);
@ -1269,7 +1506,6 @@ static int verify_timestamp_token(PKCS7 *p7, CMS_ContentInfo *timestamp)
BIO_write(bhash, si->enc_digest->data, si->enc_digest->length);
BIO_gets(bhash, (char*)mdbuf, EVP_MD_size(md));
BIO_free_all(bhash);
/* compare the provided hash against the computed hash */
hash = token->messageImprint->digest;
/* hash->length == EVP_MD_size(md) */
@ -1353,8 +1589,7 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
crl = x509_crl_get(url);
OPENSSL_free(url);
if (!crl && !ctx->options->tsa_crlfile) {
printf("Use the \"-TSA-CRLfile\" option to add one or more Time-Stamp Authority CRLs in PEM format.\n\n");
goto out;
printf("Use the \"-TSA-CRLfile\" option to add one or more Time-Stamp Authority CRLs in PEM format.\n");
}
}
#endif /* ENABLE_CURL */
@ -1465,7 +1700,7 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
crl = x509_crl_get(url);
OPENSSL_free(url);
if (!crl && !ctx->options->crlfile) {
printf("Use the \"-CRLfile\" option to add one or more CRLs in PEM format.\n\n");
printf("Use the \"-CRLfile\" option to add one or more CRLs in PEM format.\n");
goto out;
}
}
@ -2441,6 +2676,8 @@ static void usage(const char *argv0, const char *cmd)
printf("%12s[ -t <timestampurl> [ -t ... ] [ -p <proxy> ] [ -noverifypeer ]\n", "");
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
#endif /* ENABLE_CURL */
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
printf("%12s[ -TSA-time <unix-time> ]\n", "");
printf("%12s[ -time <unix-time> ]\n", "");
printf("%12s[ -addUnauthenticatedBlob ]\n", "");
printf("%12s[ -nest ]\n", "");
@ -2454,6 +2691,8 @@ static void usage(const char *argv0, const char *cmd)
printf("%12s[ -t <timestampurl> [ -t ... ] [ -p <proxy> ] [ -noverifypeer ]\n", "");
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
#endif /* ENABLE_CURL */
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
printf("%12s[ -TSA-time <unix-time> ]\n", "");
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
printf("%12s[ -verbose ]\n", "");
printf("%12s[ -add-msi-dse ]\n", "");
@ -2551,6 +2790,9 @@ static void help_for(const char *argv0, const char *cmd)
const char *cmds_ts[] = {"add", "sign", NULL};
#endif /* ENABLE_CURL */
const char *cmds_CAfileTSA[] = {"attach-signature", "verify", NULL};
const char *cmds_certsTSA[] = {"add", "sign", NULL};
const char *cmds_keyTSA[] = {"add", "sign", NULL};
const char *cmds_timeTSA[] = {"add", "sign", NULL};
const char *cmds_verbose[] = {"add", "sign", "verify", NULL};
if (on_list(cmd, cmds_all)) {
@ -2700,34 +2942,17 @@ static void help_for(const char *argv0, const char *cmd)
printf("%-24s= the file containing one or more Time-Stamp Authority certificates in PEM format\n", "-TSA-CAfile");
if (on_list(cmd, cmds_CRLfileTSA))
printf("%-24s= the file containing one or more Time-Stamp Authority CRLs in PEM format\n", "-TSA-CRLfile");
if (on_list(cmd, cmds_certsTSA))
printf("%-24s= Time-Stamp Authority signing certificate\n", "-TSA-certs");
if (on_list(cmd, cmds_keyTSA))
printf("%-24s= Time-Stamp Authority private key or PKCS#11 URI identifies a key in the token\n", "-TSA-key");
if (on_list(cmd, cmds_timeTSA))
printf("%-24s= the unix-time to set the Time-Stamp Authority signing\n", "-TSA-time");
if (on_list(cmd, cmds_verbose))
printf("%-24s= include additional output in the log\n", "-verbose");
usage(argv0, cmd);
}
/*
* [in] bin: certfile BIO
* [in] certpass: NULL
* [returns] pointer to STACK_OF(X509) structure
*/
static STACK_OF(X509) *X509_chain_read_certs(BIO *bin, char *certpass)
{
STACK_OF(X509) *certs = sk_X509_new_null();
X509 *x509;
(void)BIO_seek(bin, 0);
x509 = PEM_read_bio_X509(bin, NULL, NULL, certpass);
while (x509) {
sk_X509_push(certs, x509);
x509 = PEM_read_bio_X509(bin, NULL, NULL, certpass);
}
ERR_clear_error();
if (!sk_X509_num(certs)) {
sk_X509_free(certs);
return NULL;
}
return certs;
}
#ifdef PROVIDE_ASKPASS
/*
* [in] prompt: "Password: "
@ -3608,6 +3833,24 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
return 0; /* FAILED */
}
options->leafhash = (*++argv);
} else if ((cmd == CMD_SIGN || cmd == CMD_ADD) && !strcmp(*argv, "-TSA-certs")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->tsa_certfile = *(++argv);
} else if ((cmd == CMD_SIGN || cmd == CMD_ADD) && !strcmp(*argv, "-TSA-key")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->tsa_keyfile = *(++argv);
} else if ((cmd == CMD_SIGN || cmd == CMD_ADD) && !strcmp(*argv, "-TSA-time")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
options->tsa_time = (time_t)strtoull(*(++argv), NULL, 10);
} else if ((cmd == CMD_ADD) && !strcmp(*argv, "--help")) {
help_for(argv0, "add");
cmd = CMD_HELP;
@ -3673,6 +3916,8 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
if (argc > 0 ||
#ifdef ENABLE_CURL
(options->nturl && options->ntsurl) ||
(options->nturl && options->tsa_certfile && options->tsa_keyfile) ||
(options->ntsurl && options->tsa_certfile && options->tsa_keyfile) ||
#endif
!options->infile ||
(cmd != CMD_VERIFY && !options->outfile) ||

@ -60,7 +60,9 @@
#if OPENSSL_VERSION_NUMBER>=0x30000000L
#include <openssl/provider.h>
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#include <openssl/rand.h>
#include <openssl/safestack.h>
#include <openssl/ts.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h> /* X509_PURPOSE */
@ -210,6 +212,9 @@
#define DO_EXIT_1(x, y) { printf(x, y); goto err_cleanup; }
#define DO_EXIT_2(x, y, z) { printf(x, y, z); goto err_cleanup; }
/* Default policy if request did not specify it. */
#define TSA_POLICY1 "1.2.3.4.1"
typedef enum {
CMD_SIGN,
CMD_EXTRACT,
@ -278,6 +283,9 @@ typedef struct {
cmd_type_t cmd;
char *indata;
PKCS7 *prevsig;
char *tsa_certfile;
char *tsa_keyfile;
time_t tsa_time;
} GLOBAL_OPTIONS;
/*