General verify options to openssl ts

This commit adds the general verify options of ocsp, verify,
cms, etc. to the openssl timestamping app as suggested by
Stephen N. Henson in [openssl.org #4287]. The conflicting
"-policy" option of "openssl ts" has been renamed to
"-tspolicy". Documentation and tests have been updated.

CAVE: This will break code, which currently uses the "-policy"
option.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
fbroda 2016-03-15 10:08:49 +01:00 committed by Richard Levitte
parent 3ddd1d0458
commit 08538fc0a5
3 changed files with 99 additions and 28 deletions

View File

@ -110,22 +110,25 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
/* Verify related functions. */ /* Verify related functions. */
static int verify_command(char *data, char *digest, char *queryfile, static int verify_command(char *data, char *digest, char *queryfile,
char *in, int token_in, char *in, int token_in,
char *CApath, char *CAfile, char *untrusted); char *CApath, char *CAfile, char *untrusted,
X509_VERIFY_PARAM *vpm);
static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
char *queryfile, char *queryfile,
char *CApath, char *CAfile, char *CApath, char *CAfile,
char *untrusted); char *untrusted,
static X509_STORE *create_cert_store(char *CApath, char *CAfile); X509_VERIFY_PARAM *vpm);
static X509_STORE *create_cert_store(char *CApath, char *CAfile,
X509_VERIFY_PARAM *vpm);
static int verify_cb(int ok, X509_STORE_CTX *ctx); static int verify_cb(int ok, X509_STORE_CTX *ctx);
typedef enum OPTION_choice { typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA, OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA,
OPT_DIGEST, OPT_RAND, OPT_POLICY, OPT_NO_NONCE, OPT_CERT, OPT_DIGEST, OPT_RAND, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT,
OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT, OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER, OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED, OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED,
OPT_MD OPT_MD, OPT_V_ENUM
} OPTION_CHOICE; } OPTION_CHOICE;
OPTIONS ts_options[] = { OPTIONS ts_options[] = {
@ -137,7 +140,7 @@ OPTIONS ts_options[] = {
{"digest", OPT_DIGEST, 's', "Digest (as a hex string)"}, {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"},
{"rand", OPT_RAND, 's', {"rand", OPT_RAND, 's',
"Load the file(s) into the random number generator"}, "Load the file(s) into the random number generator"},
{"policy", OPT_POLICY, 's', "Policy OID to use"}, {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
{"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"}, {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
{"cert", OPT_CERT, '-', "Put cert request into query"}, {"cert", OPT_CERT, '-', "Put cert request into query"},
{"in", OPT_IN, '<', "Input file"}, {"in", OPT_IN, '<', "Input file"},
@ -159,6 +162,9 @@ OPTIONS ts_options[] = {
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif #endif
{OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"},
OPT_V_OPTIONS,
{OPT_HELP_STR, 1, '-', "\n"},
{NULL} {NULL}
}; };
@ -168,13 +174,13 @@ OPTIONS ts_options[] = {
static char* opt_helplist[] = { static char* opt_helplist[] = {
"Typical uses:", "Typical uses:",
"ts -query [-rand file...] [-config file] [-data file]", "ts -query [-rand file...] [-config file] [-data file]",
" [-digest hexstring] [-policy oid] [-no_nonce] [-cert]", " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]",
" [-in file] [-out file] [-text]", " [-in file] [-out file] [-text]",
" or", " or",
"ts -reply [-config file] [-section tsa_section]", "ts -reply [-config file] [-section tsa_section]",
" [-queryfile file] [-passin password]", " [-queryfile file] [-passin password]",
" [-signer tsa_cert.pem] [-inkey private_key.pem]", " [-signer tsa_cert.pem] [-inkey private_key.pem]",
" [-chain certs_file.pem] [-policy oid]", " [-chain certs_file.pem] [-tspolicy oid]",
" [-in file] [-token_in] [-out file] [-token_out]", " [-in file] [-token_in] [-out file] [-token_out]",
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
" [-text]", " [-text]",
@ -185,6 +191,7 @@ static char* opt_helplist[] = {
"ts -verify -CApath dir -CAfile file.pem -untrusted file.pem", "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem",
" [-data file] [-digest hexstring]", " [-data file] [-digest hexstring]",
" [-queryfile file] -in file [-token_in]", " [-queryfile file] -in file [-token_in]",
" [[options specific to 'ts -verify']]",
NULL, NULL,
}; };
@ -200,11 +207,16 @@ int ts_main(int argc, char **argv)
const EVP_MD *md = NULL; const EVP_MD *md = NULL;
OPTION_CHOICE o, mode = OPT_ERR; OPTION_CHOICE o, mode = OPT_ERR;
int ret = 1, no_nonce = 0, cert = 0, text = 0; int ret = 1, no_nonce = 0, cert = 0, text = 0;
int vpmtouched = 0;
X509_VERIFY_PARAM *vpm = NULL;
/* Input is ContentInfo instead of TimeStampResp. */ /* Input is ContentInfo instead of TimeStampResp. */
int token_in = 0; int token_in = 0;
/* Output is ContentInfo instead of TimeStampResp. */ /* Output is ContentInfo instead of TimeStampResp. */
int token_out = 0; int token_out = 0;
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
goto end;
prog = opt_init(argc, argv, ts_options); prog = opt_init(argc, argv, ts_options);
while ((o = opt_next()) != OPT_EOF) { while ((o = opt_next()) != OPT_EOF) {
switch (o) { switch (o) {
@ -241,7 +253,7 @@ int ts_main(int argc, char **argv)
case OPT_RAND: case OPT_RAND:
rnd = opt_arg(); rnd = opt_arg();
break; break;
case OPT_POLICY: case OPT_TSPOLICY:
policy = opt_arg(); policy = opt_arg();
break; break;
case OPT_NO_NONCE: case OPT_NO_NONCE:
@ -296,9 +308,15 @@ int ts_main(int argc, char **argv)
if (!opt_md(opt_unknown(), &md)) if (!opt_md(opt_unknown(), &md))
goto opthelp; goto opthelp;
break; break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
} }
} }
argc = opt_num_rest(); argc = opt_num_rest();
argv = opt_rest();
if (mode == OPT_ERR || argc != 0) if (mode == OPT_ERR || argc != 0)
goto opthelp; goto opthelp;
@ -328,12 +346,16 @@ int ts_main(int argc, char **argv)
case OPT_ERR: case OPT_ERR:
goto opthelp; goto opthelp;
case OPT_QUERY: case OPT_QUERY:
if (vpmtouched)
goto opthelp;
if ((data != NULL) && (digest != NULL)) if ((data != NULL) && (digest != NULL))
goto opthelp; goto opthelp;
ret = !query_command(data, digest, md, policy, no_nonce, cert, ret = !query_command(data, digest, md, policy, no_nonce, cert,
in, out, text); in, out, text);
break; break;
case OPT_REPLY: case OPT_REPLY:
if (vpmtouched)
goto opthelp;
if ((in != NULL) && (queryfile != NULL)) if ((in != NULL) && (queryfile != NULL))
goto opthelp; goto opthelp;
if (in == NULL) { if (in == NULL) {
@ -348,10 +370,12 @@ int ts_main(int argc, char **argv)
if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest)) if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
goto opthelp; goto opthelp;
ret = !verify_command(data, digest, queryfile, in, token_in, ret = !verify_command(data, digest, queryfile, in, token_in,
CApath, CAfile, untrusted); CApath, CAfile, untrusted,
vpmtouched ? vpm : NULL);
} }
end: end:
X509_VERIFY_PARAM_free(vpm);
app_RAND_write_file(NULL); app_RAND_write_file(NULL);
NCONF_free(conf); NCONF_free(conf);
OPENSSL_free(password); OPENSSL_free(password);
@ -846,7 +870,8 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
static int verify_command(char *data, char *digest, char *queryfile, static int verify_command(char *data, char *digest, char *queryfile,
char *in, int token_in, char *in, int token_in,
char *CApath, char *CAfile, char *untrusted) char *CApath, char *CAfile, char *untrusted,
X509_VERIFY_PARAM *vpm)
{ {
BIO *in_bio = NULL; BIO *in_bio = NULL;
PKCS7 *token = NULL; PKCS7 *token = NULL;
@ -865,7 +890,8 @@ static int verify_command(char *data, char *digest, char *queryfile,
} }
if ((verify_ctx = create_verify_ctx(data, digest, queryfile, if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
CApath, CAfile, untrusted)) == NULL) CApath, CAfile, untrusted,
vpm)) == NULL)
goto end; goto end;
ret = token_in ret = token_in
@ -891,7 +917,8 @@ static int verify_command(char *data, char *digest, char *queryfile,
static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
char *queryfile, char *queryfile,
char *CApath, char *CAfile, char *CApath, char *CAfile,
char *untrusted) char *untrusted,
X509_VERIFY_PARAM *vpm)
{ {
TS_VERIFY_CTX *ctx = NULL; TS_VERIFY_CTX *ctx = NULL;
BIO *input = NULL; BIO *input = NULL;
@ -931,7 +958,7 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE); TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE);
/* Initialising the X509_STORE object. */ /* Initialising the X509_STORE object. */
if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile)) if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm))
== NULL) == NULL)
goto err; goto err;
@ -951,7 +978,7 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
return ctx; return ctx;
} }
static X509_STORE *create_cert_store(char *CApath, char *CAfile) static X509_STORE *create_cert_store(char *CApath, char *CAfile, X509_VERIFY_PARAM *vpm)
{ {
X509_STORE *cert_ctx = NULL; X509_STORE *cert_ctx = NULL;
X509_LOOKUP *lookup = NULL; X509_LOOKUP *lookup = NULL;
@ -984,6 +1011,10 @@ static X509_STORE *create_cert_store(char *CApath, char *CAfile)
goto err; goto err;
} }
} }
if (vpm != NULL)
X509_STORE_set1_param(cert_ctx, vpm);
return cert_ctx; return cert_ctx;
err: err:

View File

@ -8,13 +8,12 @@ ts - Time Stamping Authority tool (client/server)
B<openssl> B<ts> B<openssl> B<ts>
B<-query> B<-query>
[B<-help>]
[B<-rand> file:file...] [B<-rand> file:file...]
[B<-config> configfile] [B<-config> configfile]
[B<-data> file_to_hash] [B<-data> file_to_hash]
[B<-digest> digest_bytes] [B<-digest> digest_bytes]
[B<-[digest]>] [B<-[digest]>]
[B<-policy> object_id] [B<-tspolicy> object_id]
[B<-no_nonce>] [B<-no_nonce>]
[B<-cert>] [B<-cert>]
[B<-in> request.tsq] [B<-in> request.tsq]
@ -31,7 +30,7 @@ B<-reply>
[B<-inkey> private.pem] [B<-inkey> private.pem]
[B<-sha1|-sha224|-sha256|-sha384|-sha512>] [B<-sha1|-sha224|-sha256|-sha384|-sha512>]
[B<-chain> certs_file.pem] [B<-chain> certs_file.pem]
[B<-policy> object_id] [B<-tspolicy> object_id]
[B<-in> response.tsr] [B<-in> response.tsr]
[B<-token_in>] [B<-token_in>]
[B<-out> response.tsr] [B<-out> response.tsr]
@ -49,6 +48,37 @@ B<-verify>
[B<-CApath> trusted_cert_path] [B<-CApath> trusted_cert_path]
[B<-CAfile> trusted_certs.pem] [B<-CAfile> trusted_certs.pem]
[B<-untrusted> cert_file.pem] [B<-untrusted> cert_file.pem]
[I<verify options>]
I<verify options:>
[-attime timestamp]
[-check_ss_sig]
[-crl_check]
[-crl_check_all]
[-explicit_policy]
[-extended_crl]
[-ignore_critical]
[-inhibit_any]
[-inhibit_map]
[-issuer_checks]
[-no_alt_chains]
[-no_check_time]
[-partial_chain]
[-policy arg]
[-policy_check]
[-policy_print]
[-purpose purpose]
[-suiteB_128]
[-suiteB_128_only]
[-suiteB_192]
[-trusted_first]
[-use_deltas]
[-verify_depth num]
[-verify_email email]
[-verify_hostname hostname]
[-verify_ip ip]
[-verify_name name]
[-x509_strict]
=head1 DESCRIPTION =head1 DESCRIPTION
@ -100,10 +130,6 @@ request with the following options:
=over 4 =over 4
=item B<-help>
Print out a usage message.
=item B<-rand> file:file... =item B<-rand> file:file...
The files containing random data for seeding the random number The files containing random data for seeding the random number
@ -136,7 +162,7 @@ The message digest to apply to the data file.
Any digest supported by the OpenSSL B<dgst> command can be used. Any digest supported by the OpenSSL B<dgst> command can be used.
The default is SHA-1. (Optional) The default is SHA-1. (Optional)
=item B<-policy> object_id =item B<-tspolicy> object_id
The policy that the client expects the TSA to use for creating the The policy that the client expects the TSA to use for creating the
time stamp token. Either the dotted OID notation or OID names defined time stamp token. Either the dotted OID notation or OID names defined
@ -235,7 +261,7 @@ contain the certificate chain for the signer certificate from its
issuer upwards. The B<-reply> command does not build a certificate issuer upwards. The B<-reply> command does not build a certificate
chain automatically. (Optional) chain automatically. (Optional)
=item B<-policy> object_id =item B<-tspolicy> object_id
The default policy to use for the response unless the client The default policy to use for the response unless the client
explicitly requires a particular TSA policy. The OID can be specified explicitly requires a particular TSA policy. The OID can be specified
@ -343,6 +369,20 @@ certificate. This file must contain the TSA signing certificate and
all intermediate CA certificates unless the response includes them. all intermediate CA certificates unless the response includes them.
(Optional) (Optional)
=item I<verify options>
The options [-attime timestamp], [-check_ss_sig], [-crl_check],
[-crl_check_all], [-explicit_policy], [-extended_crl],
[-ignore_critical], [-inhibit_any], [-inhibit_map],
[-issuer_checks], [-no_alt_chains], [-no_check_time],
[-partial_chain], [-policy arg], [-policy_check],
[-policy_print], [-purpose purpose], [-suiteB_128],
[-suiteB_128_only], [-suiteB_192], [-trusted_first],
[-use_deltas], [-verify_depth num], [-verify_email email],
[-verify_hostname hostname], [-verify_ip ip], [-verify_name name],
and [-x509_strict] can be used to control timestamp verification.
See L<verify(1)>.
=back =back
=head1 CONFIGURATION FILE OPTIONS =head1 CONFIGURATION FILE OPTIONS
@ -415,7 +455,7 @@ B<-sha1|-sha224|-sha256|-sha384|-sha512> command line option. (Optional)
=item B<default_policy> =item B<default_policy>
The default policy to use when the request does not mandate any The default policy to use when the request does not mandate any
policy. The same as the B<-policy> command line option. (Optional) policy. The same as the B<-tspolicy> command line option. (Optional)
=item B<other_policies> =item B<other_policies>
@ -501,7 +541,7 @@ specifies a policy id (assuming the tsa_policy1 name is defined in the
OID section of the config file): OID section of the config file):
openssl ts -query -data design2.txt -md5 \ openssl ts -query -data design2.txt -md5 \
-policy tsa_policy1 -cert -out design2.tsq -tspolicy tsa_policy1 -cert -out design2.tsq
=head2 Time Stamp Response =head2 Time Stamp Response

View File

@ -98,7 +98,7 @@ indir "tsa" => sub
skip "failed", 16 skip "failed", 16
unless ok(run(app([@RUN, "-query", "-data", $testtsa, unless ok(run(app([@RUN, "-query", "-data", $testtsa,
"-policy", "tsa_policy1", "-cert", "-tspolicy", "tsa_policy1", "-cert",
"-out", "req1.tsq"])), "-out", "req1.tsq"])),
'creating req1.req time stamp request for file testtsa'); 'creating req1.req time stamp request for file testtsa');
@ -132,7 +132,7 @@ indir "tsa" => sub
skip "failed", 10 skip "failed", 10
unless ok(run(app([@RUN, "-query", "-data", $testtsa, unless ok(run(app([@RUN, "-query", "-data", $testtsa,
"-policy", "tsa_policy2", "-no_nonce", "-tspolicy", "tsa_policy2", "-no_nonce",
"-out", "req2.tsq"])), "-out", "req2.tsq"])),
'creating req2.req time stamp request for file testtsa'); 'creating req2.req time stamp request for file testtsa');