From 08538fc0a57a9317da22958beeab3ff8af4b2ded Mon Sep 17 00:00:00 2001 From: fbroda Date: Tue, 15 Mar 2016 10:08:49 +0100 Subject: [PATCH] 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 Reviewed-by: Richard Levitte --- apps/ts.c | 61 ++++++++++++++++++++++++++++--------- doc/apps/ts.pod | 62 +++++++++++++++++++++++++++++++------- test/recipes/80-test_tsa.t | 4 +-- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/apps/ts.c b/apps/ts.c index ee04bb5ad8..b287e26a78 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -110,22 +110,25 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial); /* Verify related functions. */ static int verify_command(char *data, char *digest, char *queryfile, 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, char *queryfile, char *CApath, char *CAfile, - char *untrusted); -static X509_STORE *create_cert_store(char *CApath, char *CAfile); + char *untrusted, + 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); typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 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_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER, OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED, - OPT_MD + OPT_MD, OPT_V_ENUM } OPTION_CHOICE; OPTIONS ts_options[] = { @@ -137,7 +140,7 @@ OPTIONS ts_options[] = { {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"}, {"rand", OPT_RAND, 's', "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"}, {"cert", OPT_CERT, '-', "Put cert request into query"}, {"in", OPT_IN, '<', "Input file"}, @@ -159,6 +162,9 @@ OPTIONS ts_options[] = { #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"}, + OPT_V_OPTIONS, + {OPT_HELP_STR, 1, '-', "\n"}, {NULL} }; @@ -168,13 +174,13 @@ OPTIONS ts_options[] = { static char* opt_helplist[] = { "Typical uses:", "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]", " or", "ts -reply [-config file] [-section tsa_section]", " [-queryfile file] [-passin password]", " [-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]", #ifndef OPENSSL_NO_ENGINE " [-text]", @@ -185,6 +191,7 @@ static char* opt_helplist[] = { "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem", " [-data file] [-digest hexstring]", " [-queryfile file] -in file [-token_in]", + " [[options specific to 'ts -verify']]", NULL, }; @@ -200,11 +207,16 @@ int ts_main(int argc, char **argv) const EVP_MD *md = NULL; OPTION_CHOICE o, mode = OPT_ERR; int ret = 1, no_nonce = 0, cert = 0, text = 0; + int vpmtouched = 0; + X509_VERIFY_PARAM *vpm = NULL; /* Input is ContentInfo instead of TimeStampResp. */ int token_in = 0; /* Output is ContentInfo instead of TimeStampResp. */ int token_out = 0; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; + prog = opt_init(argc, argv, ts_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -241,7 +253,7 @@ int ts_main(int argc, char **argv) case OPT_RAND: rnd = opt_arg(); break; - case OPT_POLICY: + case OPT_TSPOLICY: policy = opt_arg(); break; case OPT_NO_NONCE: @@ -296,9 +308,15 @@ int ts_main(int argc, char **argv) if (!opt_md(opt_unknown(), &md)) goto opthelp; break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; } } argc = opt_num_rest(); + argv = opt_rest(); if (mode == OPT_ERR || argc != 0) goto opthelp; @@ -328,12 +346,16 @@ int ts_main(int argc, char **argv) case OPT_ERR: goto opthelp; case OPT_QUERY: + if (vpmtouched) + goto opthelp; if ((data != NULL) && (digest != NULL)) goto opthelp; ret = !query_command(data, digest, md, policy, no_nonce, cert, in, out, text); break; case OPT_REPLY: + if (vpmtouched) + goto opthelp; if ((in != NULL) && (queryfile != NULL)) goto opthelp; if (in == NULL) { @@ -348,10 +370,12 @@ int ts_main(int argc, char **argv) if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest)) goto opthelp; ret = !verify_command(data, digest, queryfile, in, token_in, - CApath, CAfile, untrusted); + CApath, CAfile, untrusted, + vpmtouched ? vpm : NULL); } end: + X509_VERIFY_PARAM_free(vpm); app_RAND_write_file(NULL); NCONF_free(conf); 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, 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; 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, - CApath, CAfile, untrusted)) == NULL) + CApath, CAfile, untrusted, + vpm)) == NULL) goto end; 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, char *queryfile, char *CApath, char *CAfile, - char *untrusted) + char *untrusted, + X509_VERIFY_PARAM *vpm) { TS_VERIFY_CTX *ctx = 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); /* 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) goto err; @@ -951,7 +978,7 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, 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_LOOKUP *lookup = NULL; @@ -984,6 +1011,10 @@ static X509_STORE *create_cert_store(char *CApath, char *CAfile) goto err; } } + + if (vpm != NULL) + X509_STORE_set1_param(cert_ctx, vpm); + return cert_ctx; err: diff --git a/doc/apps/ts.pod b/doc/apps/ts.pod index c6adf521eb..93ea9e059a 100644 --- a/doc/apps/ts.pod +++ b/doc/apps/ts.pod @@ -8,13 +8,12 @@ ts - Time Stamping Authority tool (client/server) B B B<-query> -[B<-help>] [B<-rand> file:file...] [B<-config> configfile] [B<-data> file_to_hash] [B<-digest> digest_bytes] [B<-[digest]>] -[B<-policy> object_id] +[B<-tspolicy> object_id] [B<-no_nonce>] [B<-cert>] [B<-in> request.tsq] @@ -31,7 +30,7 @@ B<-reply> [B<-inkey> private.pem] [B<-sha1|-sha224|-sha256|-sha384|-sha512>] [B<-chain> certs_file.pem] -[B<-policy> object_id] +[B<-tspolicy> object_id] [B<-in> response.tsr] [B<-token_in>] [B<-out> response.tsr] @@ -49,6 +48,37 @@ B<-verify> [B<-CApath> trusted_cert_path] [B<-CAfile> trusted_certs.pem] [B<-untrusted> cert_file.pem] +[I] + +I +[-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 @@ -100,10 +130,6 @@ request with the following options: =over 4 -=item B<-help> - -Print out a usage message. - =item B<-rand> file:file... 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 command can be used. 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 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 chain automatically. (Optional) -=item B<-policy> object_id +=item B<-tspolicy> object_id The default policy to use for the response unless the client 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. (Optional) +=item I + +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. + =back =head1 CONFIGURATION FILE OPTIONS @@ -415,7 +455,7 @@ B<-sha1|-sha224|-sha256|-sha384|-sha512> command line option. (Optional) =item B 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 @@ -501,7 +541,7 @@ specifies a policy id (assuming the tsa_policy1 name is defined in the OID section of the config file): 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 diff --git a/test/recipes/80-test_tsa.t b/test/recipes/80-test_tsa.t index 229f17e95d..477de2db2a 100644 --- a/test/recipes/80-test_tsa.t +++ b/test/recipes/80-test_tsa.t @@ -98,7 +98,7 @@ indir "tsa" => sub skip "failed", 16 unless ok(run(app([@RUN, "-query", "-data", $testtsa, - "-policy", "tsa_policy1", "-cert", + "-tspolicy", "tsa_policy1", "-cert", "-out", "req1.tsq"])), 'creating req1.req time stamp request for file testtsa'); @@ -132,7 +132,7 @@ indir "tsa" => sub skip "failed", 10 unless ok(run(app([@RUN, "-query", "-data", $testtsa, - "-policy", "tsa_policy2", "-no_nonce", + "-tspolicy", "tsa_policy2", "-no_nonce", "-out", "req2.tsq"])), 'creating req2.req time stamp request for file testtsa');