summaryrefslogtreecommitdiff
path: root/src/usr.bin/openssl/ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/openssl/ts.c')
-rw-r--r--src/usr.bin/openssl/ts.c438
1 files changed, 285 insertions, 153 deletions
diff --git a/src/usr.bin/openssl/ts.c b/src/usr.bin/openssl/ts.c
index 40c1a49b23..e4d299d726 100644
--- a/src/usr.bin/openssl/ts.c
+++ b/src/usr.bin/openssl/ts.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ts.c,v 1.17 2021/12/12 20:22:59 tb Exp $ */ 1/* $OpenBSD: ts.c,v 1.18 2022/03/24 11:27:45 inoguchi Exp $ */
2/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL 2/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
3 * project 2002. 3 * project 2002.
4 */ 4 */
@@ -116,38 +116,271 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
116static X509_STORE *create_cert_store(char *ca_path, char *ca_file); 116static X509_STORE *create_cert_store(char *ca_path, char *ca_file);
117static int verify_cb(int ok, X509_STORE_CTX * ctx); 117static int verify_cb(int ok, X509_STORE_CTX * ctx);
118 118
119enum mode {
120 CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY
121};
122
123static struct {
124 char *ca_file;
125 char *ca_path;
126 int cert;
127 char *chain;
128 char *configfile;
129 char *data;
130 char *digest;
131 char *in;
132 char *inkey;
133 const EVP_MD *md;
134 int mode;
135 int no_nonce;
136 char *out;
137 char *passin;
138 char *policy;
139 char *queryfile;
140 char *section;
141 char *signer;
142 int text;
143 int token_in;
144 int token_out;
145 char *untrusted;
146} ts_config;
147
148static int
149ts_opt_md(int argc, char **argv, int *argsused)
150{
151 char *name = argv[0];
152
153 if (*name++ != '-')
154 return (1);
155
156 if ((ts_config.md = EVP_get_digestbyname(name)) == NULL)
157 return (1);
158
159 *argsused = 1;
160 return (0);
161}
162
163static int
164ts_opt_query(void)
165{
166 if (ts_config.mode != CMD_NONE)
167 return (1);
168 ts_config.mode = CMD_QUERY;
169 return (0);
170}
171
172static int
173ts_opt_reply(void)
174{
175 if (ts_config.mode != CMD_NONE)
176 return (1);
177 ts_config.mode = CMD_REPLY;
178 return (0);
179}
180
181static int
182ts_opt_verify(void)
183{
184 if (ts_config.mode != CMD_NONE)
185 return (1);
186 ts_config.mode = CMD_VERIFY;
187 return (0);
188}
189
190static const struct option ts_options[] = {
191 {
192 .name = "CAfile",
193 .argname = "file",
194 .desc = "Certificate Authority file",
195 .type = OPTION_ARG,
196 .opt.arg = &ts_config.ca_file,
197 },
198 {
199 .name = "CApath",
200 .argname = "path",
201 .desc = "Certificate Authority path",
202 .type = OPTION_ARG,
203 .opt.arg = &ts_config.ca_path,
204 },
205 {
206 .name = "cert",
207 .desc = "Include signing certificate in the response",
208 .type = OPTION_FLAG,
209 .opt.flag = &ts_config.cert,
210 },
211 {
212 .name = "chain",
213 .argname = "file",
214 .desc = "PEM certificates that will be included in the response",
215 .type = OPTION_ARG,
216 .opt.arg = &ts_config.chain,
217 },
218 {
219 .name = "config",
220 .argname = "file",
221 .desc = "Specify an alternative configuration file",
222 .type = OPTION_ARG,
223 .opt.arg = &ts_config.configfile,
224 },
225 {
226 .name = "data",
227 .argname = "file",
228 .desc = "Data file for which the time stamp request needs to be created",
229 .type = OPTION_ARG,
230 .opt.arg = &ts_config.data,
231 },
232 {
233 .name = "digest",
234 .argname = "arg",
235 .desc = "Specify the message imprint explicitly without the data file",
236 .type = OPTION_ARG,
237 .opt.arg = &ts_config.digest,
238 },
239 {
240 .name = "in",
241 .argname = "file",
242 .desc = "Input file",
243 .type = OPTION_ARG,
244 .opt.arg = &ts_config.in,
245 },
246 {
247 .name = "inkey",
248 .argname = "file",
249 .desc = "Input key file",
250 .type = OPTION_ARG,
251 .opt.arg = &ts_config.inkey,
252 },
253 {
254 .name = "no_nonce",
255 .desc = "Specify no nonce in the request",
256 .type = OPTION_FLAG,
257 .opt.flag = &ts_config.no_nonce,
258 },
259 {
260 .name = "out",
261 .argname = "file",
262 .desc = "Output file",
263 .type = OPTION_ARG,
264 .opt.arg = &ts_config.out,
265 },
266 {
267 .name = "passin",
268 .argname = "src",
269 .desc = "Private key password source",
270 .type = OPTION_ARG,
271 .opt.arg = &ts_config.passin,
272 },
273 {
274 .name = "policy",
275 .argname = "object_id",
276 .desc = "Policy for the TSA to use when creating the time stamp token",
277 .type = OPTION_ARG,
278 .opt.arg = &ts_config.policy,
279 },
280 {
281 .name = "query",
282 .desc = "Create and print a time stamp request",
283 .type = OPTION_FUNC,
284 .opt.func = ts_opt_query,
285 },
286 {
287 .name = "queryfile",
288 .argname = "file",
289 .desc = "File containing a DER-encoded time stamp request",
290 .type = OPTION_ARG,
291 .opt.arg = &ts_config.queryfile,
292 },
293 {
294 .name = "reply",
295 .desc = "Create a time stamp response",
296 .type = OPTION_FUNC,
297 .opt.func = ts_opt_reply,
298 },
299 {
300 .name = "section",
301 .argname = "arg",
302 .desc = "TSA section containing the settings for response generation",
303 .type = OPTION_ARG,
304 .opt.arg = &ts_config.section,
305 },
306 {
307 .name = "signer",
308 .argname = "file",
309 .desc = "Signer certificate file",
310 .type = OPTION_ARG,
311 .opt.arg = &ts_config.signer,
312 },
313 {
314 .name = "text",
315 .desc = "Output in human-readable text format",
316 .type = OPTION_FLAG,
317 .opt.flag = &ts_config.text,
318 },
319 {
320 .name = "token_in",
321 .desc = "Input is a DER-encoded time stamp token",
322 .type = OPTION_FLAG,
323 .opt.flag = &ts_config.token_in,
324 },
325 {
326 .name = "token_out",
327 .desc = "Output is a DER-encoded time stamp token",
328 .type = OPTION_FLAG,
329 .opt.flag = &ts_config.token_out,
330 },
331 {
332 .name = "untrusted",
333 .argname = "file",
334 .desc = "File containing untrusted certificates",
335 .type = OPTION_ARG,
336 .opt.arg = &ts_config.untrusted,
337 },
338 {
339 .name = "verify",
340 .desc = "Verify a time stamp response",
341 .type = OPTION_FUNC,
342 .opt.func = ts_opt_verify,
343 },
344 {
345 .name = NULL,
346 .desc = "",
347 .type = OPTION_ARGV_FUNC,
348 .opt.argvfunc = ts_opt_md,
349 },
350 { NULL },
351};
352
353static void
354ts_usage(void)
355{
356 fprintf(stderr, "usage:\n"
357 "ts -query [-md4 | -md5 | -ripemd160 | -sha1] [-cert]\n"
358 " [-config configfile] [-data file_to_hash]\n"
359 " [-digest digest_bytes] [-in request.tsq] [-no_nonce]\n"
360 " [-out request.tsq] [-policy object_id] [-text]\n");
361 fprintf(stderr, "\n"
362 "ts -reply [-chain certs_file.pem] [-config configfile]\n"
363 " [-in response.tsr] [-inkey private.pem] [-out response.tsr]\n"
364 " [-passin arg] [-policy object_id] [-queryfile request.tsq]\n"
365 " [-section tsa_section] [-signer tsa_cert.pem] [-text]\n"
366 " [-token_in] [-token_out]\n");
367 fprintf(stderr, "\n"
368 "ts -verify [-CAfile trusted_certs.pem]\n"
369 " [-CApath trusted_cert_path] [-data file_to_hash]\n"
370 " [-digest digest_bytes] [-in response.tsr]\n"
371 " [-queryfile request.tsq] [-token_in]\n"
372 " [-untrusted cert_file.pem]\n");
373 fprintf(stderr, "\n");
374 options_usage(ts_options);
375 fprintf(stderr, "\n");
376}
377
119int 378int
120ts_main(int argc, char **argv) 379ts_main(int argc, char **argv)
121{ 380{
122 int ret = 1; 381 int ret = 1;
123 char *configfile = NULL;
124 char *section = NULL;
125 CONF *conf = NULL; 382 CONF *conf = NULL;
126 enum mode {
127 CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY
128 } mode = CMD_NONE;
129 char *data = NULL;
130 char *digest = NULL;
131 const EVP_MD *md = NULL;
132 char *policy = NULL;
133 int no_nonce = 0;
134 int cert = 0;
135 char *in = NULL;
136 char *out = NULL;
137 int text = 0;
138 char *queryfile = NULL;
139 char *passin = NULL; /* Password source. */
140 char *password = NULL; /* Password itself. */ 383 char *password = NULL; /* Password itself. */
141 char *inkey = NULL;
142 char *signer = NULL;
143 char *chain = NULL;
144 char *ca_path = NULL;
145 char *ca_file = NULL;
146 char *untrusted = NULL;
147 /* Input is ContentInfo instead of TimeStampResp. */
148 int token_in = 0;
149 /* Output is ContentInfo instead of TimeStampResp. */
150 int token_out = 0;
151 384
152 if (single_execution) { 385 if (single_execution) {
153 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { 386 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
@@ -156,98 +389,15 @@ ts_main(int argc, char **argv)
156 } 389 }
157 } 390 }
158 391
159 for (argc--, argv++; argc > 0; argc--, argv++) { 392 memset(&ts_config, 0, sizeof(ts_config));
160 if (strcmp(*argv, "-config") == 0) { 393 ts_config.mode = CMD_NONE;
161 if (argc-- < 1) 394
162 goto usage; 395 if (options_parse(argc, argv, ts_options, NULL, NULL) != 0)
163 configfile = *++argv; 396 goto usage;
164 } else if (strcmp(*argv, "-section") == 0) {
165 if (argc-- < 1)
166 goto usage;
167 section = *++argv;
168 } else if (strcmp(*argv, "-query") == 0) {
169 if (mode != CMD_NONE)
170 goto usage;
171 mode = CMD_QUERY;
172 } else if (strcmp(*argv, "-data") == 0) {
173 if (argc-- < 1)
174 goto usage;
175 data = *++argv;
176 } else if (strcmp(*argv, "-digest") == 0) {
177 if (argc-- < 1)
178 goto usage;
179 digest = *++argv;
180 } else if (strcmp(*argv, "-policy") == 0) {
181 if (argc-- < 1)
182 goto usage;
183 policy = *++argv;
184 } else if (strcmp(*argv, "-no_nonce") == 0) {
185 no_nonce = 1;
186 } else if (strcmp(*argv, "-cert") == 0) {
187 cert = 1;
188 } else if (strcmp(*argv, "-in") == 0) {
189 if (argc-- < 1)
190 goto usage;
191 in = *++argv;
192 } else if (strcmp(*argv, "-token_in") == 0) {
193 token_in = 1;
194 } else if (strcmp(*argv, "-out") == 0) {
195 if (argc-- < 1)
196 goto usage;
197 out = *++argv;
198 } else if (strcmp(*argv, "-token_out") == 0) {
199 token_out = 1;
200 } else if (strcmp(*argv, "-text") == 0) {
201 text = 1;
202 } else if (strcmp(*argv, "-reply") == 0) {
203 if (mode != CMD_NONE)
204 goto usage;
205 mode = CMD_REPLY;
206 } else if (strcmp(*argv, "-queryfile") == 0) {
207 if (argc-- < 1)
208 goto usage;
209 queryfile = *++argv;
210 } else if (strcmp(*argv, "-passin") == 0) {
211 if (argc-- < 1)
212 goto usage;
213 passin = *++argv;
214 } else if (strcmp(*argv, "-inkey") == 0) {
215 if (argc-- < 1)
216 goto usage;
217 inkey = *++argv;
218 } else if (strcmp(*argv, "-signer") == 0) {
219 if (argc-- < 1)
220 goto usage;
221 signer = *++argv;
222 } else if (strcmp(*argv, "-chain") == 0) {
223 if (argc-- < 1)
224 goto usage;
225 chain = *++argv;
226 } else if (strcmp(*argv, "-verify") == 0) {
227 if (mode != CMD_NONE)
228 goto usage;
229 mode = CMD_VERIFY;
230 } else if (strcmp(*argv, "-CApath") == 0) {
231 if (argc-- < 1)
232 goto usage;
233 ca_path = *++argv;
234 } else if (strcmp(*argv, "-CAfile") == 0) {
235 if (argc-- < 1)
236 goto usage;
237 ca_file = *++argv;
238 } else if (strcmp(*argv, "-untrusted") == 0) {
239 if (argc-- < 1)
240 goto usage;
241 untrusted = *++argv;
242 } else if ((md = EVP_get_digestbyname(*argv + 1)) != NULL) {
243 /* empty. */
244 } else
245 goto usage;
246 }
247 397
248 /* Get the password if required. */ 398 /* Get the password if required. */
249 if (mode == CMD_REPLY && passin && 399 if (ts_config.mode == CMD_REPLY && ts_config.passin &&
250 !app_passwd(bio_err, passin, NULL, &password, NULL)) { 400 !app_passwd(bio_err, ts_config.passin, NULL, &password, NULL)) {
251 BIO_printf(bio_err, "Error getting password.\n"); 401 BIO_printf(bio_err, "Error getting password.\n");
252 goto cleanup; 402 goto cleanup;
253 } 403 }
@@ -255,7 +405,7 @@ ts_main(int argc, char **argv)
255 * Check consistency of parameters and execute the appropriate 405 * Check consistency of parameters and execute the appropriate
256 * function. 406 * function.
257 */ 407 */
258 switch (mode) { 408 switch (ts_config.mode) {
259 case CMD_NONE: 409 case CMD_NONE:
260 goto usage; 410 goto usage;
261 case CMD_QUERY: 411 case CMD_QUERY:
@@ -263,64 +413,46 @@ ts_main(int argc, char **argv)
263 * Data file and message imprint cannot be specified at the 413 * Data file and message imprint cannot be specified at the
264 * same time. 414 * same time.
265 */ 415 */
266 ret = data != NULL && digest != NULL; 416 ret = ts_config.data != NULL && ts_config.digest != NULL;
267 if (ret) 417 if (ret)
268 goto usage; 418 goto usage;
269 /* Load the config file for possible policy OIDs. */ 419 /* Load the config file for possible policy OIDs. */
270 conf = load_config_file(configfile); 420 conf = load_config_file(ts_config.configfile);
271 ret = !query_command(data, digest, md, policy, no_nonce, cert, 421 ret = !query_command(ts_config.data, ts_config.digest, ts_config.md, ts_config.policy, ts_config.no_nonce, ts_config.cert,
272 in, out, text); 422 ts_config.in, ts_config.out, ts_config.text);
273 break; 423 break;
274 case CMD_REPLY: 424 case CMD_REPLY:
275 conf = load_config_file(configfile); 425 conf = load_config_file(ts_config.configfile);
276 if (in == NULL) { 426 if (ts_config.in == NULL) {
277 ret = !(queryfile != NULL && conf != NULL && !token_in); 427 ret = !(ts_config.queryfile != NULL && conf != NULL && !ts_config.token_in);
278 if (ret) 428 if (ret)
279 goto usage; 429 goto usage;
280 } else { 430 } else {
281 /* 'in' and 'queryfile' are exclusive. */ 431 /* 'in' and 'queryfile' are exclusive. */
282 ret = !(queryfile == NULL); 432 ret = !(ts_config.queryfile == NULL);
283 if (ret) 433 if (ret)
284 goto usage; 434 goto usage;
285 } 435 }
286 436
287 ret = !reply_command(conf, section, queryfile, 437 ret = !reply_command(conf, ts_config.section, ts_config.queryfile,
288 password, inkey, signer, chain, policy, 438 password, ts_config.inkey, ts_config.signer, ts_config.chain, ts_config.policy,
289 in, token_in, out, token_out, text); 439 ts_config.in, ts_config.token_in, ts_config.out, ts_config.token_out, ts_config.text);
290 break; 440 break;
291 case CMD_VERIFY: 441 case CMD_VERIFY:
292 ret = !(((queryfile && !data && !digest) || 442 ret = !(((ts_config.queryfile && !ts_config.data && !ts_config.digest) ||
293 (!queryfile && data && !digest) || 443 (!ts_config.queryfile && ts_config.data && !ts_config.digest) ||
294 (!queryfile && !data && digest)) && in != NULL); 444 (!ts_config.queryfile && !ts_config.data && ts_config.digest)) && ts_config.in != NULL);
295 if (ret) 445 if (ret)
296 goto usage; 446 goto usage;
297 447
298 ret = !verify_command(data, digest, queryfile, in, token_in, 448 ret = !verify_command(ts_config.data, ts_config.digest, ts_config.queryfile, ts_config.in, ts_config.token_in,
299 ca_path, ca_file, untrusted); 449 ts_config.ca_path, ts_config.ca_file, ts_config.untrusted);
300 } 450 }
301 451
302 goto cleanup; 452 goto cleanup;
303 453
304 usage: 454 usage:
305 BIO_printf(bio_err, "usage:\n" 455 ts_usage();
306 "ts -query [-config configfile] "
307 "[-data file_to_hash] [-digest digest_bytes]"
308 "[-md4|-md5|-sha1|-ripemd160] "
309 "[-policy object_id] [-no_nonce] [-cert] "
310 "[-in request.tsq] [-out request.tsq] [-text]\n");
311 BIO_printf(bio_err, "or\n"
312 "ts -reply [-config configfile] [-section tsa_section] "
313 "[-queryfile request.tsq] [-passin password] "
314 "[-signer tsa_cert.pem] [-inkey private_key.pem] "
315 "[-chain certs_file.pem] [-policy object_id] "
316 "[-in response.tsr] [-token_in] "
317 "[-out response.tsr] [-token_out] [-text]\n");
318 BIO_printf(bio_err, "or\n"
319 "ts -verify [-data file_to_hash] [-digest digest_bytes] "
320 "[-queryfile request.tsq] "
321 "-in response.tsr [-token_in] "
322 "-CApath ca_path -CAfile ca_file.pem "
323 "-untrusted cert_file.pem\n");
324 456
325 cleanup: 457 cleanup:
326 /* Clean up. */ 458 /* Clean up. */