xref: /minix3/crypto/external/bsd/openssl/dist/apps/ts.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1ebfedea0SLionel Sambuc /* apps/ts.c */
2*0a6a1f1dSLionel Sambuc /*
3*0a6a1f1dSLionel Sambuc  * Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL project
4*0a6a1f1dSLionel Sambuc  * 2002.
5ebfedea0SLionel Sambuc  */
6ebfedea0SLionel Sambuc /* ====================================================================
7ebfedea0SLionel Sambuc  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
8ebfedea0SLionel Sambuc  *
9ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
10ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
11ebfedea0SLionel Sambuc  * are met:
12ebfedea0SLionel Sambuc  *
13ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15ebfedea0SLionel Sambuc  *
16ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
17ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in
18ebfedea0SLionel Sambuc  *    the documentation and/or other materials provided with the
19ebfedea0SLionel Sambuc  *    distribution.
20ebfedea0SLionel Sambuc  *
21ebfedea0SLionel Sambuc  * 3. All advertising materials mentioning features or use of this
22ebfedea0SLionel Sambuc  *    software must display the following acknowledgment:
23ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
24ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25ebfedea0SLionel Sambuc  *
26ebfedea0SLionel Sambuc  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27ebfedea0SLionel Sambuc  *    endorse or promote products derived from this software without
28ebfedea0SLionel Sambuc  *    prior written permission. For written permission, please contact
29ebfedea0SLionel Sambuc  *    licensing@OpenSSL.org.
30ebfedea0SLionel Sambuc  *
31ebfedea0SLionel Sambuc  * 5. Products derived from this software may not be called "OpenSSL"
32ebfedea0SLionel Sambuc  *    nor may "OpenSSL" appear in their names without prior written
33ebfedea0SLionel Sambuc  *    permission of the OpenSSL Project.
34ebfedea0SLionel Sambuc  *
35ebfedea0SLionel Sambuc  * 6. Redistributions of any form whatsoever must retain the following
36ebfedea0SLionel Sambuc  *    acknowledgment:
37ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
38ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39ebfedea0SLionel Sambuc  *
40ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41ebfedea0SLionel Sambuc  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44ebfedea0SLionel Sambuc  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45ebfedea0SLionel Sambuc  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46ebfedea0SLionel Sambuc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47ebfedea0SLionel Sambuc  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49ebfedea0SLionel Sambuc  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51ebfedea0SLionel Sambuc  * OF THE POSSIBILITY OF SUCH DAMAGE.
52ebfedea0SLionel Sambuc  * ====================================================================
53ebfedea0SLionel Sambuc  *
54ebfedea0SLionel Sambuc  * This product includes cryptographic software written by Eric Young
55ebfedea0SLionel Sambuc  * (eay@cryptsoft.com).  This product includes software written by Tim
56ebfedea0SLionel Sambuc  * Hudson (tjh@cryptsoft.com).
57ebfedea0SLionel Sambuc  *
58ebfedea0SLionel Sambuc  */
59ebfedea0SLionel Sambuc 
60ebfedea0SLionel Sambuc #include <stdio.h>
61ebfedea0SLionel Sambuc #include <stdlib.h>
62ebfedea0SLionel Sambuc #include <string.h>
63ebfedea0SLionel Sambuc #include "apps.h"
64ebfedea0SLionel Sambuc #include <openssl/bio.h>
65ebfedea0SLionel Sambuc #include <openssl/err.h>
66ebfedea0SLionel Sambuc #include <openssl/pem.h>
67ebfedea0SLionel Sambuc #include <openssl/rand.h>
68ebfedea0SLionel Sambuc #include <openssl/ts.h>
69ebfedea0SLionel Sambuc #include <openssl/bn.h>
70ebfedea0SLionel Sambuc 
71ebfedea0SLionel Sambuc #undef PROG
72ebfedea0SLionel Sambuc #define PROG    ts_main
73ebfedea0SLionel Sambuc 
74ebfedea0SLionel Sambuc /* Length of the nonce of the request in bits (must be a multiple of 8). */
75ebfedea0SLionel Sambuc #define NONCE_LENGTH            64
76ebfedea0SLionel Sambuc 
77ebfedea0SLionel Sambuc /* Macro definitions for the configuration file. */
78ebfedea0SLionel Sambuc #define ENV_OID_FILE            "oid_file"
79ebfedea0SLionel Sambuc 
80ebfedea0SLionel Sambuc /* Local function declarations. */
81ebfedea0SLionel Sambuc 
82ebfedea0SLionel Sambuc static ASN1_OBJECT *txt2obj(const char *oid);
83ebfedea0SLionel Sambuc static CONF *load_config_file(const char *configfile);
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc /* Query related functions. */
86ebfedea0SLionel Sambuc static int query_command(const char *data, char *digest,
87ebfedea0SLionel Sambuc                          const EVP_MD *md, const char *policy, int no_nonce,
88ebfedea0SLionel Sambuc                          int cert, const char *in, const char *out, int text);
89ebfedea0SLionel Sambuc static BIO *BIO_open_with_default(const char *file, const char *mode,
90ebfedea0SLionel Sambuc                                   FILE *default_fp);
91ebfedea0SLionel Sambuc static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md,
92ebfedea0SLionel Sambuc                             const char *policy, int no_nonce, int cert);
93ebfedea0SLionel Sambuc static int create_digest(BIO *input, char *digest,
94ebfedea0SLionel Sambuc                          const EVP_MD *md, unsigned char **md_value);
95ebfedea0SLionel Sambuc static ASN1_INTEGER *create_nonce(int bits);
96ebfedea0SLionel Sambuc 
97ebfedea0SLionel Sambuc /* Reply related functions. */
98ebfedea0SLionel Sambuc static int reply_command(CONF *conf, char *section, char *engine,
99ebfedea0SLionel Sambuc                          char *queryfile, char *passin, char *inkey,
100ebfedea0SLionel Sambuc                          char *signer, char *chain, const char *policy,
101ebfedea0SLionel Sambuc                          char *in, int token_in, char *out, int token_out,
102ebfedea0SLionel Sambuc                          int text);
103ebfedea0SLionel Sambuc static TS_RESP *read_PKCS7(BIO *in_bio);
104ebfedea0SLionel Sambuc static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
105ebfedea0SLionel Sambuc                                 char *queryfile, char *passin, char *inkey,
106*0a6a1f1dSLionel Sambuc                                 char *signer, char *chain,
107*0a6a1f1dSLionel Sambuc                                 const char *policy);
108ebfedea0SLionel Sambuc static ASN1_INTEGER *MS_CALLBACK serial_cb(TS_RESP_CTX *ctx, void *data);
109ebfedea0SLionel Sambuc static ASN1_INTEGER *next_serial(const char *serialfile);
110ebfedea0SLionel Sambuc static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
111ebfedea0SLionel Sambuc 
112ebfedea0SLionel Sambuc /* Verify related functions. */
113ebfedea0SLionel Sambuc static int verify_command(char *data, char *digest, char *queryfile,
114ebfedea0SLionel Sambuc                           char *in, int token_in,
115ebfedea0SLionel Sambuc                           char *ca_path, char *ca_file, char *untrusted);
116ebfedea0SLionel Sambuc static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
117ebfedea0SLionel Sambuc                                         char *queryfile,
118ebfedea0SLionel Sambuc                                         char *ca_path, char *ca_file,
119ebfedea0SLionel Sambuc                                         char *untrusted);
120ebfedea0SLionel Sambuc static X509_STORE *create_cert_store(char *ca_path, char *ca_file);
121ebfedea0SLionel Sambuc static int MS_CALLBACK verify_cb(int ok, X509_STORE_CTX *ctx);
122ebfedea0SLionel Sambuc 
123ebfedea0SLionel Sambuc /* Main function definition. */
124ebfedea0SLionel Sambuc int MAIN(int, char **);
125ebfedea0SLionel Sambuc 
MAIN(int argc,char ** argv)126ebfedea0SLionel Sambuc int MAIN(int argc, char **argv)
127ebfedea0SLionel Sambuc {
128ebfedea0SLionel Sambuc     int ret = 1;
129ebfedea0SLionel Sambuc     char *configfile = NULL;
130ebfedea0SLionel Sambuc     char *section = NULL;
131ebfedea0SLionel Sambuc     CONF *conf = NULL;
132ebfedea0SLionel Sambuc     enum mode {
133ebfedea0SLionel Sambuc         CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY
134ebfedea0SLionel Sambuc     } mode = CMD_NONE;
135ebfedea0SLionel Sambuc     char *data = NULL;
136ebfedea0SLionel Sambuc     char *digest = NULL;
137ebfedea0SLionel Sambuc     const EVP_MD *md = NULL;
138ebfedea0SLionel Sambuc     char *rnd = NULL;
139ebfedea0SLionel Sambuc     char *policy = NULL;
140ebfedea0SLionel Sambuc     int no_nonce = 0;
141ebfedea0SLionel Sambuc     int cert = 0;
142ebfedea0SLionel Sambuc     char *in = NULL;
143ebfedea0SLionel Sambuc     char *out = NULL;
144ebfedea0SLionel Sambuc     int text = 0;
145ebfedea0SLionel Sambuc     char *queryfile = NULL;
146ebfedea0SLionel Sambuc     char *passin = NULL;        /* Password source. */
147ebfedea0SLionel Sambuc     char *password = NULL;      /* Password itself. */
148ebfedea0SLionel Sambuc     char *inkey = NULL;
149ebfedea0SLionel Sambuc     char *signer = NULL;
150ebfedea0SLionel Sambuc     char *chain = NULL;
151ebfedea0SLionel Sambuc     char *ca_path = NULL;
152ebfedea0SLionel Sambuc     char *ca_file = NULL;
153ebfedea0SLionel Sambuc     char *untrusted = NULL;
154ebfedea0SLionel Sambuc     char *engine = NULL;
155ebfedea0SLionel Sambuc     /* Input is ContentInfo instead of TimeStampResp. */
156ebfedea0SLionel Sambuc     int token_in = 0;
157ebfedea0SLionel Sambuc     /* Output is ContentInfo instead of TimeStampResp. */
158ebfedea0SLionel Sambuc     int token_out = 0;
159ebfedea0SLionel Sambuc     int free_bio_err = 0;
160ebfedea0SLionel Sambuc 
161ebfedea0SLionel Sambuc     ERR_load_crypto_strings();
162ebfedea0SLionel Sambuc     apps_startup();
163ebfedea0SLionel Sambuc 
164*0a6a1f1dSLionel Sambuc     if (bio_err == NULL && (bio_err = BIO_new(BIO_s_file())) != NULL) {
165ebfedea0SLionel Sambuc         free_bio_err = 1;
166ebfedea0SLionel Sambuc         BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
167ebfedea0SLionel Sambuc     }
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc     if (!load_config(bio_err, NULL))
170ebfedea0SLionel Sambuc         goto cleanup;
171ebfedea0SLionel Sambuc 
172*0a6a1f1dSLionel Sambuc     for (argc--, argv++; argc > 0; argc--, argv++) {
173*0a6a1f1dSLionel Sambuc         if (strcmp(*argv, "-config") == 0) {
174*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
175*0a6a1f1dSLionel Sambuc                 goto usage;
176ebfedea0SLionel Sambuc             configfile = *++argv;
177*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-section") == 0) {
178*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
179*0a6a1f1dSLionel Sambuc                 goto usage;
180ebfedea0SLionel Sambuc             section = *++argv;
181*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-query") == 0) {
182*0a6a1f1dSLionel Sambuc             if (mode != CMD_NONE)
183*0a6a1f1dSLionel Sambuc                 goto usage;
184ebfedea0SLionel Sambuc             mode = CMD_QUERY;
185*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-data") == 0) {
186*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
187*0a6a1f1dSLionel Sambuc                 goto usage;
188ebfedea0SLionel Sambuc             data = *++argv;
189*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-digest") == 0) {
190*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
191*0a6a1f1dSLionel Sambuc                 goto usage;
192ebfedea0SLionel Sambuc             digest = *++argv;
193*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-rand") == 0) {
194*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
195*0a6a1f1dSLionel Sambuc                 goto usage;
196ebfedea0SLionel Sambuc             rnd = *++argv;
197*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-policy") == 0) {
198*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
199*0a6a1f1dSLionel Sambuc                 goto usage;
200ebfedea0SLionel Sambuc             policy = *++argv;
201*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-no_nonce") == 0) {
202ebfedea0SLionel Sambuc             no_nonce = 1;
203*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-cert") == 0) {
204ebfedea0SLionel Sambuc             cert = 1;
205*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-in") == 0) {
206*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
207*0a6a1f1dSLionel Sambuc                 goto usage;
208ebfedea0SLionel Sambuc             in = *++argv;
209*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-token_in") == 0) {
210ebfedea0SLionel Sambuc             token_in = 1;
211*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-out") == 0) {
212*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
213*0a6a1f1dSLionel Sambuc                 goto usage;
214ebfedea0SLionel Sambuc             out = *++argv;
215*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-token_out") == 0) {
216ebfedea0SLionel Sambuc             token_out = 1;
217*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-text") == 0) {
218ebfedea0SLionel Sambuc             text = 1;
219*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-reply") == 0) {
220*0a6a1f1dSLionel Sambuc             if (mode != CMD_NONE)
221*0a6a1f1dSLionel Sambuc                 goto usage;
222ebfedea0SLionel Sambuc             mode = CMD_REPLY;
223*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-queryfile") == 0) {
224*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
225*0a6a1f1dSLionel Sambuc                 goto usage;
226ebfedea0SLionel Sambuc             queryfile = *++argv;
227*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-passin") == 0) {
228*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
229*0a6a1f1dSLionel Sambuc                 goto usage;
230ebfedea0SLionel Sambuc             passin = *++argv;
231*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-inkey") == 0) {
232*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
233*0a6a1f1dSLionel Sambuc                 goto usage;
234ebfedea0SLionel Sambuc             inkey = *++argv;
235*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-signer") == 0) {
236*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
237*0a6a1f1dSLionel Sambuc                 goto usage;
238ebfedea0SLionel Sambuc             signer = *++argv;
239*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-chain") == 0) {
240*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
241*0a6a1f1dSLionel Sambuc                 goto usage;
242ebfedea0SLionel Sambuc             chain = *++argv;
243*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-verify") == 0) {
244*0a6a1f1dSLionel Sambuc             if (mode != CMD_NONE)
245*0a6a1f1dSLionel Sambuc                 goto usage;
246ebfedea0SLionel Sambuc             mode = CMD_VERIFY;
247*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-CApath") == 0) {
248*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
249*0a6a1f1dSLionel Sambuc                 goto usage;
250ebfedea0SLionel Sambuc             ca_path = *++argv;
251*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-CAfile") == 0) {
252*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
253*0a6a1f1dSLionel Sambuc                 goto usage;
254ebfedea0SLionel Sambuc             ca_file = *++argv;
255*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-untrusted") == 0) {
256*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
257*0a6a1f1dSLionel Sambuc                 goto usage;
258ebfedea0SLionel Sambuc             untrusted = *++argv;
259*0a6a1f1dSLionel Sambuc         } else if (strcmp(*argv, "-engine") == 0) {
260*0a6a1f1dSLionel Sambuc             if (argc-- < 1)
261*0a6a1f1dSLionel Sambuc                 goto usage;
262ebfedea0SLionel Sambuc             engine = *++argv;
263*0a6a1f1dSLionel Sambuc         } else if ((md = EVP_get_digestbyname(*argv + 1)) != NULL) {
264ebfedea0SLionel Sambuc             /* empty. */
265*0a6a1f1dSLionel Sambuc         } else
266ebfedea0SLionel Sambuc             goto usage;
267ebfedea0SLionel Sambuc     }
268ebfedea0SLionel Sambuc 
269ebfedea0SLionel Sambuc     /* Seed the random number generator if it is going to be used. */
270*0a6a1f1dSLionel Sambuc     if (mode == CMD_QUERY && !no_nonce) {
271ebfedea0SLionel Sambuc         if (!app_RAND_load_file(NULL, bio_err, 1) && rnd == NULL)
272ebfedea0SLionel Sambuc             BIO_printf(bio_err, "warning, not much extra random "
273ebfedea0SLionel Sambuc                        "data, consider using the -rand option\n");
274ebfedea0SLionel Sambuc         if (rnd != NULL)
275ebfedea0SLionel Sambuc             BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
276ebfedea0SLionel Sambuc                        app_RAND_load_files(rnd));
277ebfedea0SLionel Sambuc     }
278ebfedea0SLionel Sambuc 
279ebfedea0SLionel Sambuc     /* Get the password if required. */
280ebfedea0SLionel Sambuc     if (mode == CMD_REPLY && passin &&
281*0a6a1f1dSLionel Sambuc         !app_passwd(bio_err, passin, NULL, &password, NULL)) {
282ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Error getting password.\n");
283ebfedea0SLionel Sambuc         goto cleanup;
284ebfedea0SLionel Sambuc     }
285ebfedea0SLionel Sambuc 
286*0a6a1f1dSLionel Sambuc     /*
287*0a6a1f1dSLionel Sambuc      * Check consistency of parameters and execute the appropriate function.
288*0a6a1f1dSLionel Sambuc      */
289*0a6a1f1dSLionel Sambuc     switch (mode) {
290ebfedea0SLionel Sambuc     case CMD_NONE:
291ebfedea0SLionel Sambuc         goto usage;
292ebfedea0SLionel Sambuc     case CMD_QUERY:
293*0a6a1f1dSLionel Sambuc         /*
294*0a6a1f1dSLionel Sambuc          * Data file and message imprint cannot be specified at the same
295*0a6a1f1dSLionel Sambuc          * time.
296*0a6a1f1dSLionel Sambuc          */
297ebfedea0SLionel Sambuc         ret = data != NULL && digest != NULL;
298*0a6a1f1dSLionel Sambuc         if (ret)
299*0a6a1f1dSLionel Sambuc             goto usage;
300ebfedea0SLionel Sambuc         /* Load the config file for possible policy OIDs. */
301ebfedea0SLionel Sambuc         conf = load_config_file(configfile);
302ebfedea0SLionel Sambuc         ret = !query_command(data, digest, md, policy, no_nonce, cert,
303ebfedea0SLionel Sambuc                              in, out, text);
304ebfedea0SLionel Sambuc         break;
305ebfedea0SLionel Sambuc     case CMD_REPLY:
306ebfedea0SLionel Sambuc         conf = load_config_file(configfile);
307*0a6a1f1dSLionel Sambuc         if (in == NULL) {
308ebfedea0SLionel Sambuc             ret = !(queryfile != NULL && conf != NULL && !token_in);
309*0a6a1f1dSLionel Sambuc             if (ret)
310*0a6a1f1dSLionel Sambuc                 goto usage;
311*0a6a1f1dSLionel Sambuc         } else {
312ebfedea0SLionel Sambuc             /* 'in' and 'queryfile' are exclusive. */
313ebfedea0SLionel Sambuc             ret = !(queryfile == NULL);
314*0a6a1f1dSLionel Sambuc             if (ret)
315*0a6a1f1dSLionel Sambuc                 goto usage;
316ebfedea0SLionel Sambuc         }
317ebfedea0SLionel Sambuc 
318ebfedea0SLionel Sambuc         ret = !reply_command(conf, section, engine, queryfile,
319ebfedea0SLionel Sambuc                              password, inkey, signer, chain, policy,
320ebfedea0SLionel Sambuc                              in, token_in, out, token_out, text);
321ebfedea0SLionel Sambuc         break;
322ebfedea0SLionel Sambuc     case CMD_VERIFY:
323ebfedea0SLionel Sambuc         ret = !(((queryfile && !data && !digest)
324ebfedea0SLionel Sambuc                  || (!queryfile && data && !digest)
325ebfedea0SLionel Sambuc                  || (!queryfile && !data && digest))
326ebfedea0SLionel Sambuc                 && in != NULL);
327*0a6a1f1dSLionel Sambuc         if (ret)
328*0a6a1f1dSLionel Sambuc             goto usage;
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc         ret = !verify_command(data, digest, queryfile, in, token_in,
331ebfedea0SLionel Sambuc                               ca_path, ca_file, untrusted);
332ebfedea0SLionel Sambuc     }
333ebfedea0SLionel Sambuc 
334ebfedea0SLionel Sambuc     goto cleanup;
335ebfedea0SLionel Sambuc 
336ebfedea0SLionel Sambuc  usage:
337ebfedea0SLionel Sambuc     BIO_printf(bio_err, "usage:\n"
338ebfedea0SLionel Sambuc                "ts -query [-rand file%cfile%c...] [-config configfile] "
339ebfedea0SLionel Sambuc                "[-data file_to_hash] [-digest digest_bytes]"
340ebfedea0SLionel Sambuc                "[-md2|-md4|-md5|-sha|-sha1|-mdc2|-ripemd160] "
341ebfedea0SLionel Sambuc                "[-policy object_id] [-no_nonce] [-cert] "
342ebfedea0SLionel Sambuc                "[-in request.tsq] [-out request.tsq] [-text]\n",
343ebfedea0SLionel Sambuc                LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
344ebfedea0SLionel Sambuc     BIO_printf(bio_err, "or\n"
345ebfedea0SLionel Sambuc                "ts -reply [-config configfile] [-section tsa_section] "
346ebfedea0SLionel Sambuc                "[-queryfile request.tsq] [-passin password] "
347ebfedea0SLionel Sambuc                "[-signer tsa_cert.pem] [-inkey private_key.pem] "
348ebfedea0SLionel Sambuc                "[-chain certs_file.pem] [-policy object_id] "
349ebfedea0SLionel Sambuc                "[-in response.tsr] [-token_in] "
350ebfedea0SLionel Sambuc                "[-out response.tsr] [-token_out] [-text] [-engine id]\n");
351ebfedea0SLionel Sambuc     BIO_printf(bio_err, "or\n"
352ebfedea0SLionel Sambuc                "ts -verify [-data file_to_hash] [-digest digest_bytes] "
353ebfedea0SLionel Sambuc                "[-queryfile request.tsq] "
354ebfedea0SLionel Sambuc                "-in response.tsr [-token_in] "
355ebfedea0SLionel Sambuc                "-CApath ca_path -CAfile ca_file.pem "
356ebfedea0SLionel Sambuc                "-untrusted cert_file.pem\n");
357ebfedea0SLionel Sambuc  cleanup:
358ebfedea0SLionel Sambuc     /* Clean up. */
359ebfedea0SLionel Sambuc     app_RAND_write_file(NULL, bio_err);
360ebfedea0SLionel Sambuc     NCONF_free(conf);
361ebfedea0SLionel Sambuc     OPENSSL_free(password);
362ebfedea0SLionel Sambuc     OBJ_cleanup();
363*0a6a1f1dSLionel Sambuc     if (free_bio_err) {
364ebfedea0SLionel Sambuc         BIO_free_all(bio_err);
365ebfedea0SLionel Sambuc         bio_err = NULL;
366ebfedea0SLionel Sambuc     }
367ebfedea0SLionel Sambuc 
368ebfedea0SLionel Sambuc     OPENSSL_EXIT(ret);
369ebfedea0SLionel Sambuc }
370ebfedea0SLionel Sambuc 
371ebfedea0SLionel Sambuc /*
372ebfedea0SLionel Sambuc  * Configuration file-related function definitions.
373ebfedea0SLionel Sambuc  */
374ebfedea0SLionel Sambuc 
txt2obj(const char * oid)375ebfedea0SLionel Sambuc static ASN1_OBJECT *txt2obj(const char *oid)
376ebfedea0SLionel Sambuc {
377ebfedea0SLionel Sambuc     ASN1_OBJECT *oid_obj = NULL;
378ebfedea0SLionel Sambuc 
379ebfedea0SLionel Sambuc     if (!(oid_obj = OBJ_txt2obj(oid, 0)))
380ebfedea0SLionel Sambuc         BIO_printf(bio_err, "cannot convert %s to OID\n", oid);
381ebfedea0SLionel Sambuc 
382ebfedea0SLionel Sambuc     return oid_obj;
383ebfedea0SLionel Sambuc }
384ebfedea0SLionel Sambuc 
load_config_file(const char * configfile)385ebfedea0SLionel Sambuc static CONF *load_config_file(const char *configfile)
386ebfedea0SLionel Sambuc {
387ebfedea0SLionel Sambuc     CONF *conf = NULL;
388ebfedea0SLionel Sambuc     long errorline = -1;
389ebfedea0SLionel Sambuc 
390*0a6a1f1dSLionel Sambuc     if (!configfile)
391*0a6a1f1dSLionel Sambuc         configfile = getenv("OPENSSL_CONF");
392*0a6a1f1dSLionel Sambuc     if (!configfile)
393*0a6a1f1dSLionel Sambuc         configfile = getenv("SSLEAY_CONF");
394ebfedea0SLionel Sambuc 
395ebfedea0SLionel Sambuc     if (configfile &&
396ebfedea0SLionel Sambuc         (!(conf = NCONF_new(NULL)) ||
397*0a6a1f1dSLionel Sambuc          NCONF_load(conf, configfile, &errorline) <= 0)) {
398ebfedea0SLionel Sambuc         if (errorline <= 0)
399ebfedea0SLionel Sambuc             BIO_printf(bio_err, "error loading the config file "
400ebfedea0SLionel Sambuc                        "'%s'\n", configfile);
401ebfedea0SLionel Sambuc         else
402ebfedea0SLionel Sambuc             BIO_printf(bio_err, "error on line %ld of config file "
403ebfedea0SLionel Sambuc                        "'%s'\n", errorline, configfile);
404ebfedea0SLionel Sambuc     }
405ebfedea0SLionel Sambuc 
406*0a6a1f1dSLionel Sambuc     if (conf != NULL) {
407ebfedea0SLionel Sambuc         const char *p;
408ebfedea0SLionel Sambuc 
409ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Using configuration from %s\n", configfile);
410ebfedea0SLionel Sambuc         p = NCONF_get_string(conf, NULL, ENV_OID_FILE);
411*0a6a1f1dSLionel Sambuc         if (p != NULL) {
412ebfedea0SLionel Sambuc             BIO *oid_bio = BIO_new_file(p, "r");
413ebfedea0SLionel Sambuc             if (!oid_bio)
414ebfedea0SLionel Sambuc                 ERR_print_errors(bio_err);
415*0a6a1f1dSLionel Sambuc             else {
416ebfedea0SLionel Sambuc                 OBJ_create_objects(oid_bio);
417ebfedea0SLionel Sambuc                 BIO_free_all(oid_bio);
418ebfedea0SLionel Sambuc             }
419*0a6a1f1dSLionel Sambuc         } else
420ebfedea0SLionel Sambuc             ERR_clear_error();
421ebfedea0SLionel Sambuc         if (!add_oid_section(bio_err, conf))
422ebfedea0SLionel Sambuc             ERR_print_errors(bio_err);
423ebfedea0SLionel Sambuc     }
424ebfedea0SLionel Sambuc     return conf;
425ebfedea0SLionel Sambuc }
426ebfedea0SLionel Sambuc 
427ebfedea0SLionel Sambuc /*
428ebfedea0SLionel Sambuc  * Query-related method definitions.
429ebfedea0SLionel Sambuc  */
430ebfedea0SLionel Sambuc 
query_command(const char * data,char * digest,const EVP_MD * md,const char * policy,int no_nonce,int cert,const char * in,const char * out,int text)431ebfedea0SLionel Sambuc static int query_command(const char *data, char *digest, const EVP_MD *md,
432ebfedea0SLionel Sambuc                          const char *policy, int no_nonce,
433ebfedea0SLionel Sambuc                          int cert, const char *in, const char *out, int text)
434ebfedea0SLionel Sambuc {
435ebfedea0SLionel Sambuc     int ret = 0;
436ebfedea0SLionel Sambuc     TS_REQ *query = NULL;
437ebfedea0SLionel Sambuc     BIO *in_bio = NULL;
438ebfedea0SLionel Sambuc     BIO *data_bio = NULL;
439ebfedea0SLionel Sambuc     BIO *out_bio = NULL;
440ebfedea0SLionel Sambuc 
441ebfedea0SLionel Sambuc     /* Build query object either from file or from scratch. */
442*0a6a1f1dSLionel Sambuc     if (in != NULL) {
443*0a6a1f1dSLionel Sambuc         if ((in_bio = BIO_new_file(in, "rb")) == NULL)
444*0a6a1f1dSLionel Sambuc             goto end;
445ebfedea0SLionel Sambuc         query = d2i_TS_REQ_bio(in_bio, NULL);
446*0a6a1f1dSLionel Sambuc     } else {
447*0a6a1f1dSLionel Sambuc         /*
448*0a6a1f1dSLionel Sambuc          * Open the file if no explicit digest bytes were specified.
449*0a6a1f1dSLionel Sambuc          */
450*0a6a1f1dSLionel Sambuc         if (!digest && !(data_bio = BIO_open_with_default(data, "rb", stdin)))
451ebfedea0SLionel Sambuc             goto end;
452ebfedea0SLionel Sambuc         /* Creating the query object. */
453*0a6a1f1dSLionel Sambuc         query = create_query(data_bio, digest, md, policy, no_nonce, cert);
454ebfedea0SLionel Sambuc         /* Saving the random number generator state. */
455ebfedea0SLionel Sambuc     }
456*0a6a1f1dSLionel Sambuc     if (query == NULL)
457*0a6a1f1dSLionel Sambuc         goto end;
458ebfedea0SLionel Sambuc 
459ebfedea0SLionel Sambuc     /* Write query either in ASN.1 or in text format. */
460ebfedea0SLionel Sambuc     if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL)
461ebfedea0SLionel Sambuc         goto end;
462*0a6a1f1dSLionel Sambuc     if (text) {
463ebfedea0SLionel Sambuc         /* Text output. */
464ebfedea0SLionel Sambuc         if (!TS_REQ_print_bio(out_bio, query))
465ebfedea0SLionel Sambuc             goto end;
466*0a6a1f1dSLionel Sambuc     } else {
467ebfedea0SLionel Sambuc         /* ASN.1 output. */
468ebfedea0SLionel Sambuc         if (!i2d_TS_REQ_bio(out_bio, query))
469ebfedea0SLionel Sambuc             goto end;
470ebfedea0SLionel Sambuc     }
471ebfedea0SLionel Sambuc 
472ebfedea0SLionel Sambuc     ret = 1;
473ebfedea0SLionel Sambuc 
474ebfedea0SLionel Sambuc  end:
475ebfedea0SLionel Sambuc     ERR_print_errors(bio_err);
476ebfedea0SLionel Sambuc 
477ebfedea0SLionel Sambuc     /* Clean up. */
478ebfedea0SLionel Sambuc     BIO_free_all(in_bio);
479ebfedea0SLionel Sambuc     BIO_free_all(data_bio);
480ebfedea0SLionel Sambuc     BIO_free_all(out_bio);
481ebfedea0SLionel Sambuc     TS_REQ_free(query);
482ebfedea0SLionel Sambuc 
483ebfedea0SLionel Sambuc     return ret;
484ebfedea0SLionel Sambuc }
485ebfedea0SLionel Sambuc 
BIO_open_with_default(const char * file,const char * mode,FILE * default_fp)486ebfedea0SLionel Sambuc static BIO *BIO_open_with_default(const char *file, const char *mode,
487ebfedea0SLionel Sambuc                                   FILE *default_fp)
488ebfedea0SLionel Sambuc {
489*0a6a1f1dSLionel Sambuc     return file == NULL ? BIO_new_fp(default_fp, BIO_NOCLOSE)
490ebfedea0SLionel Sambuc         : BIO_new_file(file, mode);
491ebfedea0SLionel Sambuc }
492ebfedea0SLionel Sambuc 
create_query(BIO * data_bio,char * digest,const EVP_MD * md,const char * policy,int no_nonce,int cert)493ebfedea0SLionel Sambuc static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md,
494ebfedea0SLionel Sambuc                             const char *policy, int no_nonce, int cert)
495ebfedea0SLionel Sambuc {
496ebfedea0SLionel Sambuc     int ret = 0;
497ebfedea0SLionel Sambuc     TS_REQ *ts_req = NULL;
498ebfedea0SLionel Sambuc     int len;
499ebfedea0SLionel Sambuc     TS_MSG_IMPRINT *msg_imprint = NULL;
500ebfedea0SLionel Sambuc     X509_ALGOR *algo = NULL;
501ebfedea0SLionel Sambuc     unsigned char *data = NULL;
502ebfedea0SLionel Sambuc     ASN1_OBJECT *policy_obj = NULL;
503ebfedea0SLionel Sambuc     ASN1_INTEGER *nonce_asn1 = NULL;
504ebfedea0SLionel Sambuc 
505ebfedea0SLionel Sambuc     /* Setting default message digest. */
506*0a6a1f1dSLionel Sambuc     if (!md && !(md = EVP_get_digestbyname("sha1")))
507*0a6a1f1dSLionel Sambuc         goto err;
508ebfedea0SLionel Sambuc 
509ebfedea0SLionel Sambuc     /* Creating request object. */
510*0a6a1f1dSLionel Sambuc     if (!(ts_req = TS_REQ_new()))
511*0a6a1f1dSLionel Sambuc         goto err;
512ebfedea0SLionel Sambuc 
513ebfedea0SLionel Sambuc     /* Setting version. */
514*0a6a1f1dSLionel Sambuc     if (!TS_REQ_set_version(ts_req, 1))
515*0a6a1f1dSLionel Sambuc         goto err;
516ebfedea0SLionel Sambuc 
517ebfedea0SLionel Sambuc     /* Creating and adding MSG_IMPRINT object. */
518*0a6a1f1dSLionel Sambuc     if (!(msg_imprint = TS_MSG_IMPRINT_new()))
519*0a6a1f1dSLionel Sambuc         goto err;
520ebfedea0SLionel Sambuc 
521ebfedea0SLionel Sambuc     /* Adding algorithm. */
522*0a6a1f1dSLionel Sambuc     if (!(algo = X509_ALGOR_new()))
523*0a6a1f1dSLionel Sambuc         goto err;
524*0a6a1f1dSLionel Sambuc     if (!(algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))))
525*0a6a1f1dSLionel Sambuc         goto err;
526*0a6a1f1dSLionel Sambuc     if (!(algo->parameter = ASN1_TYPE_new()))
527*0a6a1f1dSLionel Sambuc         goto err;
528ebfedea0SLionel Sambuc     algo->parameter->type = V_ASN1_NULL;
529*0a6a1f1dSLionel Sambuc     if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo))
530*0a6a1f1dSLionel Sambuc         goto err;
531ebfedea0SLionel Sambuc 
532ebfedea0SLionel Sambuc     /* Adding message digest. */
533ebfedea0SLionel Sambuc     if ((len = create_digest(data_bio, digest, md, &data)) == 0)
534ebfedea0SLionel Sambuc         goto err;
535*0a6a1f1dSLionel Sambuc     if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len))
536*0a6a1f1dSLionel Sambuc         goto err;
537ebfedea0SLionel Sambuc 
538*0a6a1f1dSLionel Sambuc     if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint))
539*0a6a1f1dSLionel Sambuc         goto err;
540ebfedea0SLionel Sambuc 
541ebfedea0SLionel Sambuc     /* Setting policy if requested. */
542*0a6a1f1dSLionel Sambuc     if (policy && !(policy_obj = txt2obj(policy)))
543*0a6a1f1dSLionel Sambuc         goto err;
544*0a6a1f1dSLionel Sambuc     if (policy_obj && !TS_REQ_set_policy_id(ts_req, policy_obj))
545*0a6a1f1dSLionel Sambuc         goto err;
546ebfedea0SLionel Sambuc 
547ebfedea0SLionel Sambuc     /* Setting nonce if requested. */
548*0a6a1f1dSLionel Sambuc     if (!no_nonce && !(nonce_asn1 = create_nonce(NONCE_LENGTH)))
549*0a6a1f1dSLionel Sambuc         goto err;
550*0a6a1f1dSLionel Sambuc     if (nonce_asn1 && !TS_REQ_set_nonce(ts_req, nonce_asn1))
551*0a6a1f1dSLionel Sambuc         goto err;
552ebfedea0SLionel Sambuc 
553ebfedea0SLionel Sambuc     /* Setting certificate request flag if requested. */
554*0a6a1f1dSLionel Sambuc     if (!TS_REQ_set_cert_req(ts_req, cert))
555*0a6a1f1dSLionel Sambuc         goto err;
556ebfedea0SLionel Sambuc 
557ebfedea0SLionel Sambuc     ret = 1;
558ebfedea0SLionel Sambuc  err:
559*0a6a1f1dSLionel Sambuc     if (!ret) {
560ebfedea0SLionel Sambuc         TS_REQ_free(ts_req);
561ebfedea0SLionel Sambuc         ts_req = NULL;
562ebfedea0SLionel Sambuc         BIO_printf(bio_err, "could not create query\n");
563ebfedea0SLionel Sambuc     }
564ebfedea0SLionel Sambuc     TS_MSG_IMPRINT_free(msg_imprint);
565ebfedea0SLionel Sambuc     X509_ALGOR_free(algo);
566ebfedea0SLionel Sambuc     OPENSSL_free(data);
567ebfedea0SLionel Sambuc     ASN1_OBJECT_free(policy_obj);
568ebfedea0SLionel Sambuc     ASN1_INTEGER_free(nonce_asn1);
569ebfedea0SLionel Sambuc     return ts_req;
570ebfedea0SLionel Sambuc }
571ebfedea0SLionel Sambuc 
create_digest(BIO * input,char * digest,const EVP_MD * md,unsigned char ** md_value)572ebfedea0SLionel Sambuc static int create_digest(BIO *input, char *digest, const EVP_MD *md,
573ebfedea0SLionel Sambuc                          unsigned char **md_value)
574ebfedea0SLionel Sambuc {
575ebfedea0SLionel Sambuc     int md_value_len;
576ebfedea0SLionel Sambuc 
577ebfedea0SLionel Sambuc     md_value_len = EVP_MD_size(md);
578ebfedea0SLionel Sambuc     if (md_value_len < 0)
579ebfedea0SLionel Sambuc         goto err;
580*0a6a1f1dSLionel Sambuc     if (input) {
581ebfedea0SLionel Sambuc         /* Digest must be computed from an input file. */
582ebfedea0SLionel Sambuc         EVP_MD_CTX md_ctx;
583ebfedea0SLionel Sambuc         unsigned char buffer[4096];
584ebfedea0SLionel Sambuc         int length;
585ebfedea0SLionel Sambuc 
586ebfedea0SLionel Sambuc         *md_value = OPENSSL_malloc(md_value_len);
587*0a6a1f1dSLionel Sambuc         if (*md_value == 0)
588*0a6a1f1dSLionel Sambuc             goto err;
589ebfedea0SLionel Sambuc 
590ebfedea0SLionel Sambuc         EVP_DigestInit(&md_ctx, md);
591*0a6a1f1dSLionel Sambuc         while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) {
592ebfedea0SLionel Sambuc             EVP_DigestUpdate(&md_ctx, buffer, length);
593ebfedea0SLionel Sambuc         }
594ebfedea0SLionel Sambuc         EVP_DigestFinal(&md_ctx, *md_value, NULL);
595*0a6a1f1dSLionel Sambuc     } else {
596ebfedea0SLionel Sambuc         /* Digest bytes are specified with digest. */
597ebfedea0SLionel Sambuc         long digest_len;
598ebfedea0SLionel Sambuc         *md_value = string_to_hex(digest, &digest_len);
599*0a6a1f1dSLionel Sambuc         if (!*md_value || md_value_len != digest_len) {
600ebfedea0SLionel Sambuc             OPENSSL_free(*md_value);
601ebfedea0SLionel Sambuc             *md_value = NULL;
602ebfedea0SLionel Sambuc             BIO_printf(bio_err, "bad digest, %d bytes "
603ebfedea0SLionel Sambuc                        "must be specified\n", md_value_len);
604ebfedea0SLionel Sambuc             goto err;
605ebfedea0SLionel Sambuc         }
606ebfedea0SLionel Sambuc     }
607ebfedea0SLionel Sambuc 
608ebfedea0SLionel Sambuc     return md_value_len;
609ebfedea0SLionel Sambuc  err:
610ebfedea0SLionel Sambuc     return 0;
611ebfedea0SLionel Sambuc }
612ebfedea0SLionel Sambuc 
create_nonce(int bits)613ebfedea0SLionel Sambuc static ASN1_INTEGER *create_nonce(int bits)
614ebfedea0SLionel Sambuc {
615ebfedea0SLionel Sambuc     unsigned char buf[20];
616ebfedea0SLionel Sambuc     ASN1_INTEGER *nonce = NULL;
617ebfedea0SLionel Sambuc     int len = (bits - 1) / 8 + 1;
618ebfedea0SLionel Sambuc     int i;
619ebfedea0SLionel Sambuc 
620ebfedea0SLionel Sambuc     /* Generating random byte sequence. */
621*0a6a1f1dSLionel Sambuc     if (len > (int)sizeof(buf))
622*0a6a1f1dSLionel Sambuc         goto err;
623*0a6a1f1dSLionel Sambuc     if (RAND_bytes(buf, len) <= 0)
624*0a6a1f1dSLionel Sambuc         goto err;
625ebfedea0SLionel Sambuc 
626ebfedea0SLionel Sambuc     /* Find the first non-zero byte and creating ASN1_INTEGER object. */
627ebfedea0SLionel Sambuc     for (i = 0; i < len && !buf[i]; ++i) ;
628*0a6a1f1dSLionel Sambuc     if (!(nonce = ASN1_INTEGER_new()))
629*0a6a1f1dSLionel Sambuc         goto err;
630ebfedea0SLionel Sambuc     OPENSSL_free(nonce->data);
631ebfedea0SLionel Sambuc     /* Allocate at least one byte. */
632ebfedea0SLionel Sambuc     nonce->length = len - i;
633*0a6a1f1dSLionel Sambuc     if (!(nonce->data = OPENSSL_malloc(nonce->length + 1)))
634*0a6a1f1dSLionel Sambuc         goto err;
635ebfedea0SLionel Sambuc     memcpy(nonce->data, buf + i, nonce->length);
636ebfedea0SLionel Sambuc 
637ebfedea0SLionel Sambuc     return nonce;
638ebfedea0SLionel Sambuc  err:
639ebfedea0SLionel Sambuc     BIO_printf(bio_err, "could not create nonce\n");
640ebfedea0SLionel Sambuc     ASN1_INTEGER_free(nonce);
641ebfedea0SLionel Sambuc     return NULL;
642ebfedea0SLionel Sambuc }
643*0a6a1f1dSLionel Sambuc 
644ebfedea0SLionel Sambuc /*
645ebfedea0SLionel Sambuc  * Reply-related method definitions.
646ebfedea0SLionel Sambuc  */
647ebfedea0SLionel Sambuc 
reply_command(CONF * conf,char * section,char * engine,char * queryfile,char * passin,char * inkey,char * signer,char * chain,const char * policy,char * in,int token_in,char * out,int token_out,int text)648ebfedea0SLionel Sambuc static int reply_command(CONF *conf, char *section, char *engine,
649ebfedea0SLionel Sambuc                          char *queryfile, char *passin, char *inkey,
650ebfedea0SLionel Sambuc                          char *signer, char *chain, const char *policy,
651ebfedea0SLionel Sambuc                          char *in, int token_in,
652ebfedea0SLionel Sambuc                          char *out, int token_out, int text)
653ebfedea0SLionel Sambuc {
654ebfedea0SLionel Sambuc     int ret = 0;
655ebfedea0SLionel Sambuc     TS_RESP *response = NULL;
656ebfedea0SLionel Sambuc     BIO *in_bio = NULL;
657ebfedea0SLionel Sambuc     BIO *query_bio = NULL;
658ebfedea0SLionel Sambuc     BIO *inkey_bio = NULL;
659ebfedea0SLionel Sambuc     BIO *signer_bio = NULL;
660ebfedea0SLionel Sambuc     BIO *out_bio = NULL;
661ebfedea0SLionel Sambuc 
662ebfedea0SLionel Sambuc     /* Build response object either from response or query. */
663*0a6a1f1dSLionel Sambuc     if (in != NULL) {
664*0a6a1f1dSLionel Sambuc         if ((in_bio = BIO_new_file(in, "rb")) == NULL)
665*0a6a1f1dSLionel Sambuc             goto end;
666*0a6a1f1dSLionel Sambuc         if (token_in) {
667*0a6a1f1dSLionel Sambuc             /*
668*0a6a1f1dSLionel Sambuc              * We have a ContentInfo (PKCS7) object, add 'granted' status
669*0a6a1f1dSLionel Sambuc              * info around it.
670*0a6a1f1dSLionel Sambuc              */
671ebfedea0SLionel Sambuc             response = read_PKCS7(in_bio);
672*0a6a1f1dSLionel Sambuc         } else {
673ebfedea0SLionel Sambuc             /* We have a ready-made TS_RESP object. */
674ebfedea0SLionel Sambuc             response = d2i_TS_RESP_bio(in_bio, NULL);
675ebfedea0SLionel Sambuc         }
676*0a6a1f1dSLionel Sambuc     } else {
677ebfedea0SLionel Sambuc         response = create_response(conf, section, engine, queryfile,
678*0a6a1f1dSLionel Sambuc                                    passin, inkey, signer, chain, policy);
679ebfedea0SLionel Sambuc         if (response)
680ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Response has been generated.\n");
681ebfedea0SLionel Sambuc         else
682ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Response is not generated.\n");
683ebfedea0SLionel Sambuc     }
684*0a6a1f1dSLionel Sambuc     if (response == NULL)
685*0a6a1f1dSLionel Sambuc         goto end;
686ebfedea0SLionel Sambuc 
687ebfedea0SLionel Sambuc     /* Write response either in ASN.1 or text format. */
688ebfedea0SLionel Sambuc     if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL)
689ebfedea0SLionel Sambuc         goto end;
690*0a6a1f1dSLionel Sambuc     if (text) {
691ebfedea0SLionel Sambuc         /* Text output. */
692*0a6a1f1dSLionel Sambuc         if (token_out) {
693ebfedea0SLionel Sambuc             TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
694*0a6a1f1dSLionel Sambuc             if (!TS_TST_INFO_print_bio(out_bio, tst_info))
695*0a6a1f1dSLionel Sambuc                 goto end;
696*0a6a1f1dSLionel Sambuc         } else {
697*0a6a1f1dSLionel Sambuc             if (!TS_RESP_print_bio(out_bio, response))
698*0a6a1f1dSLionel Sambuc                 goto end;
699ebfedea0SLionel Sambuc         }
700*0a6a1f1dSLionel Sambuc     } else {
701ebfedea0SLionel Sambuc         /* ASN.1 DER output. */
702*0a6a1f1dSLionel Sambuc         if (token_out) {
703ebfedea0SLionel Sambuc             PKCS7 *token = TS_RESP_get_token(response);
704*0a6a1f1dSLionel Sambuc             if (!i2d_PKCS7_bio(out_bio, token))
705*0a6a1f1dSLionel Sambuc                 goto end;
706*0a6a1f1dSLionel Sambuc         } else {
707*0a6a1f1dSLionel Sambuc             if (!i2d_TS_RESP_bio(out_bio, response))
708*0a6a1f1dSLionel Sambuc                 goto end;
709ebfedea0SLionel Sambuc         }
710ebfedea0SLionel Sambuc     }
711ebfedea0SLionel Sambuc 
712ebfedea0SLionel Sambuc     ret = 1;
713ebfedea0SLionel Sambuc 
714ebfedea0SLionel Sambuc  end:
715ebfedea0SLionel Sambuc     ERR_print_errors(bio_err);
716ebfedea0SLionel Sambuc 
717ebfedea0SLionel Sambuc     /* Clean up. */
718ebfedea0SLionel Sambuc     BIO_free_all(in_bio);
719ebfedea0SLionel Sambuc     BIO_free_all(query_bio);
720ebfedea0SLionel Sambuc     BIO_free_all(inkey_bio);
721ebfedea0SLionel Sambuc     BIO_free_all(signer_bio);
722ebfedea0SLionel Sambuc     BIO_free_all(out_bio);
723ebfedea0SLionel Sambuc     TS_RESP_free(response);
724ebfedea0SLionel Sambuc 
725ebfedea0SLionel Sambuc     return ret;
726ebfedea0SLionel Sambuc }
727ebfedea0SLionel Sambuc 
728ebfedea0SLionel Sambuc /* Reads a PKCS7 token and adds default 'granted' status info to it. */
read_PKCS7(BIO * in_bio)729ebfedea0SLionel Sambuc static TS_RESP *read_PKCS7(BIO *in_bio)
730ebfedea0SLionel Sambuc {
731ebfedea0SLionel Sambuc     int ret = 0;
732ebfedea0SLionel Sambuc     PKCS7 *token = NULL;
733ebfedea0SLionel Sambuc     TS_TST_INFO *tst_info = NULL;
734ebfedea0SLionel Sambuc     TS_RESP *resp = NULL;
735ebfedea0SLionel Sambuc     TS_STATUS_INFO *si = NULL;
736ebfedea0SLionel Sambuc 
737ebfedea0SLionel Sambuc     /* Read PKCS7 object and extract the signed time stamp info. */
738*0a6a1f1dSLionel Sambuc     if (!(token = d2i_PKCS7_bio(in_bio, NULL)))
739*0a6a1f1dSLionel Sambuc         goto end;
740*0a6a1f1dSLionel Sambuc     if (!(tst_info = PKCS7_to_TS_TST_INFO(token)))
741*0a6a1f1dSLionel Sambuc         goto end;
742ebfedea0SLionel Sambuc 
743ebfedea0SLionel Sambuc     /* Creating response object. */
744*0a6a1f1dSLionel Sambuc     if (!(resp = TS_RESP_new()))
745*0a6a1f1dSLionel Sambuc         goto end;
746ebfedea0SLionel Sambuc 
747ebfedea0SLionel Sambuc     /* Create granted status info. */
748*0a6a1f1dSLionel Sambuc     if (!(si = TS_STATUS_INFO_new()))
749*0a6a1f1dSLionel Sambuc         goto end;
750*0a6a1f1dSLionel Sambuc     if (!(ASN1_INTEGER_set(si->status, TS_STATUS_GRANTED)))
751*0a6a1f1dSLionel Sambuc         goto end;
752*0a6a1f1dSLionel Sambuc     if (!TS_RESP_set_status_info(resp, si))
753*0a6a1f1dSLionel Sambuc         goto end;
754ebfedea0SLionel Sambuc 
755ebfedea0SLionel Sambuc     /* Setting encapsulated token. */
756ebfedea0SLionel Sambuc     TS_RESP_set_tst_info(resp, token, tst_info);
757ebfedea0SLionel Sambuc     token = NULL;               /* Ownership is lost. */
758ebfedea0SLionel Sambuc     tst_info = NULL;            /* Ownership is lost. */
759ebfedea0SLionel Sambuc 
760ebfedea0SLionel Sambuc     ret = 1;
761ebfedea0SLionel Sambuc  end:
762ebfedea0SLionel Sambuc     PKCS7_free(token);
763ebfedea0SLionel Sambuc     TS_TST_INFO_free(tst_info);
764*0a6a1f1dSLionel Sambuc     if (!ret) {
765ebfedea0SLionel Sambuc         TS_RESP_free(resp);
766ebfedea0SLionel Sambuc         resp = NULL;
767ebfedea0SLionel Sambuc     }
768ebfedea0SLionel Sambuc     TS_STATUS_INFO_free(si);
769ebfedea0SLionel Sambuc     return resp;
770ebfedea0SLionel Sambuc }
771ebfedea0SLionel Sambuc 
create_response(CONF * conf,const char * section,char * engine,char * queryfile,char * passin,char * inkey,char * signer,char * chain,const char * policy)772ebfedea0SLionel Sambuc static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
773ebfedea0SLionel Sambuc                                 char *queryfile, char *passin, char *inkey,
774ebfedea0SLionel Sambuc                                 char *signer, char *chain, const char *policy)
775ebfedea0SLionel Sambuc {
776ebfedea0SLionel Sambuc     int ret = 0;
777ebfedea0SLionel Sambuc     TS_RESP *response = NULL;
778ebfedea0SLionel Sambuc     BIO *query_bio = NULL;
779ebfedea0SLionel Sambuc     TS_RESP_CTX *resp_ctx = NULL;
780ebfedea0SLionel Sambuc 
781ebfedea0SLionel Sambuc     if (!(query_bio = BIO_new_file(queryfile, "rb")))
782ebfedea0SLionel Sambuc         goto end;
783ebfedea0SLionel Sambuc 
784ebfedea0SLionel Sambuc     /* Getting TSA configuration section. */
785ebfedea0SLionel Sambuc     if (!(section = TS_CONF_get_tsa_section(conf, section)))
786ebfedea0SLionel Sambuc         goto end;
787ebfedea0SLionel Sambuc 
788ebfedea0SLionel Sambuc     /* Setting up response generation context. */
789*0a6a1f1dSLionel Sambuc     if (!(resp_ctx = TS_RESP_CTX_new()))
790*0a6a1f1dSLionel Sambuc         goto end;
791ebfedea0SLionel Sambuc 
792ebfedea0SLionel Sambuc     /* Setting serial number provider callback. */
793*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx))
794*0a6a1f1dSLionel Sambuc         goto end;
795ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_ENGINE
796ebfedea0SLionel Sambuc     /* Setting default OpenSSL engine. */
797*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_crypto_device(conf, section, engine))
798*0a6a1f1dSLionel Sambuc         goto end;
799ebfedea0SLionel Sambuc #endif
800ebfedea0SLionel Sambuc 
801ebfedea0SLionel Sambuc     /* Setting TSA signer certificate. */
802*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx))
803*0a6a1f1dSLionel Sambuc         goto end;
804ebfedea0SLionel Sambuc 
805ebfedea0SLionel Sambuc     /* Setting TSA signer certificate chain. */
806*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_certs(conf, section, chain, resp_ctx))
807*0a6a1f1dSLionel Sambuc         goto end;
808ebfedea0SLionel Sambuc 
809ebfedea0SLionel Sambuc     /* Setting TSA signer private key. */
810ebfedea0SLionel Sambuc     if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
811ebfedea0SLionel Sambuc         goto end;
812ebfedea0SLionel Sambuc 
813ebfedea0SLionel Sambuc     /* Setting default policy OID. */
814*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx))
815*0a6a1f1dSLionel Sambuc         goto end;
816ebfedea0SLionel Sambuc 
817ebfedea0SLionel Sambuc     /* Setting acceptable policy OIDs. */
818*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_policies(conf, section, resp_ctx))
819*0a6a1f1dSLionel Sambuc         goto end;
820ebfedea0SLionel Sambuc 
821ebfedea0SLionel Sambuc     /* Setting the acceptable one-way hash algorithms. */
822*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_digests(conf, section, resp_ctx))
823*0a6a1f1dSLionel Sambuc         goto end;
824ebfedea0SLionel Sambuc 
825ebfedea0SLionel Sambuc     /* Setting guaranteed time stamp accuracy. */
826*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_accuracy(conf, section, resp_ctx))
827*0a6a1f1dSLionel Sambuc         goto end;
828ebfedea0SLionel Sambuc 
829ebfedea0SLionel Sambuc     /* Setting the precision of the time. */
830ebfedea0SLionel Sambuc     if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx))
831ebfedea0SLionel Sambuc         goto end;
832ebfedea0SLionel Sambuc 
833ebfedea0SLionel Sambuc     /* Setting the ordering flaf if requested. */
834*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_ordering(conf, section, resp_ctx))
835*0a6a1f1dSLionel Sambuc         goto end;
836ebfedea0SLionel Sambuc 
837ebfedea0SLionel Sambuc     /* Setting the TSA name required flag if requested. */
838*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_tsa_name(conf, section, resp_ctx))
839*0a6a1f1dSLionel Sambuc         goto end;
840ebfedea0SLionel Sambuc 
841ebfedea0SLionel Sambuc     /* Setting the ESS cert id chain flag if requested. */
842*0a6a1f1dSLionel Sambuc     if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx))
843*0a6a1f1dSLionel Sambuc         goto end;
844ebfedea0SLionel Sambuc 
845ebfedea0SLionel Sambuc     /* Creating the response. */
846ebfedea0SLionel Sambuc     if (!(response = TS_RESP_create_response(resp_ctx, query_bio)))
847ebfedea0SLionel Sambuc         goto end;
848ebfedea0SLionel Sambuc 
849ebfedea0SLionel Sambuc     ret = 1;
850ebfedea0SLionel Sambuc  end:
851*0a6a1f1dSLionel Sambuc     if (!ret) {
852ebfedea0SLionel Sambuc         TS_RESP_free(response);
853ebfedea0SLionel Sambuc         response = NULL;
854ebfedea0SLionel Sambuc     }
855ebfedea0SLionel Sambuc     TS_RESP_CTX_free(resp_ctx);
856ebfedea0SLionel Sambuc     BIO_free_all(query_bio);
857ebfedea0SLionel Sambuc 
858ebfedea0SLionel Sambuc     return response;
859ebfedea0SLionel Sambuc }
860ebfedea0SLionel Sambuc 
serial_cb(TS_RESP_CTX * ctx,void * data)861ebfedea0SLionel Sambuc static ASN1_INTEGER *MS_CALLBACK serial_cb(TS_RESP_CTX *ctx, void *data)
862ebfedea0SLionel Sambuc {
863ebfedea0SLionel Sambuc     const char *serial_file = (const char *)data;
864ebfedea0SLionel Sambuc     ASN1_INTEGER *serial = next_serial(serial_file);
865ebfedea0SLionel Sambuc 
866*0a6a1f1dSLionel Sambuc     if (!serial) {
867ebfedea0SLionel Sambuc         TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
868ebfedea0SLionel Sambuc                                     "Error during serial number "
869ebfedea0SLionel Sambuc                                     "generation.");
870*0a6a1f1dSLionel Sambuc         TS_RESP_CTX_add_failure_info(ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE);
871*0a6a1f1dSLionel Sambuc     } else
872ebfedea0SLionel Sambuc         save_ts_serial(serial_file, serial);
873ebfedea0SLionel Sambuc 
874ebfedea0SLionel Sambuc     return serial;
875ebfedea0SLionel Sambuc }
876ebfedea0SLionel Sambuc 
next_serial(const char * serialfile)877ebfedea0SLionel Sambuc static ASN1_INTEGER *next_serial(const char *serialfile)
878ebfedea0SLionel Sambuc {
879ebfedea0SLionel Sambuc     int ret = 0;
880ebfedea0SLionel Sambuc     BIO *in = NULL;
881ebfedea0SLionel Sambuc     ASN1_INTEGER *serial = NULL;
882ebfedea0SLionel Sambuc     BIGNUM *bn = NULL;
883ebfedea0SLionel Sambuc 
884*0a6a1f1dSLionel Sambuc     if (!(serial = ASN1_INTEGER_new()))
885*0a6a1f1dSLionel Sambuc         goto err;
886ebfedea0SLionel Sambuc 
887*0a6a1f1dSLionel Sambuc     if (!(in = BIO_new_file(serialfile, "r"))) {
888ebfedea0SLionel Sambuc         ERR_clear_error();
889ebfedea0SLionel Sambuc         BIO_printf(bio_err, "Warning: could not open file %s for "
890ebfedea0SLionel Sambuc                    "reading, using serial number: 1\n", serialfile);
891*0a6a1f1dSLionel Sambuc         if (!ASN1_INTEGER_set(serial, 1))
892*0a6a1f1dSLionel Sambuc             goto err;
893*0a6a1f1dSLionel Sambuc     } else {
894ebfedea0SLionel Sambuc         char buf[1024];
895*0a6a1f1dSLionel Sambuc         if (!a2i_ASN1_INTEGER(in, serial, buf, sizeof(buf))) {
896ebfedea0SLionel Sambuc             BIO_printf(bio_err, "unable to load number from %s\n",
897ebfedea0SLionel Sambuc                        serialfile);
898ebfedea0SLionel Sambuc             goto err;
899ebfedea0SLionel Sambuc         }
900*0a6a1f1dSLionel Sambuc         if (!(bn = ASN1_INTEGER_to_BN(serial, NULL)))
901*0a6a1f1dSLionel Sambuc             goto err;
902ebfedea0SLionel Sambuc         ASN1_INTEGER_free(serial);
903ebfedea0SLionel Sambuc         serial = NULL;
904*0a6a1f1dSLionel Sambuc         if (!BN_add_word(bn, 1))
905*0a6a1f1dSLionel Sambuc             goto err;
906*0a6a1f1dSLionel Sambuc         if (!(serial = BN_to_ASN1_INTEGER(bn, NULL)))
907*0a6a1f1dSLionel Sambuc             goto err;
908ebfedea0SLionel Sambuc     }
909ebfedea0SLionel Sambuc     ret = 1;
910ebfedea0SLionel Sambuc  err:
911*0a6a1f1dSLionel Sambuc     if (!ret) {
912ebfedea0SLionel Sambuc         ASN1_INTEGER_free(serial);
913ebfedea0SLionel Sambuc         serial = NULL;
914ebfedea0SLionel Sambuc     }
915ebfedea0SLionel Sambuc     BIO_free_all(in);
916ebfedea0SLionel Sambuc     BN_free(bn);
917ebfedea0SLionel Sambuc     return serial;
918ebfedea0SLionel Sambuc }
919ebfedea0SLionel Sambuc 
save_ts_serial(const char * serialfile,ASN1_INTEGER * serial)920ebfedea0SLionel Sambuc static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
921ebfedea0SLionel Sambuc {
922ebfedea0SLionel Sambuc     int ret = 0;
923ebfedea0SLionel Sambuc     BIO *out = NULL;
924ebfedea0SLionel Sambuc 
925*0a6a1f1dSLionel Sambuc     if (!(out = BIO_new_file(serialfile, "w")))
926*0a6a1f1dSLionel Sambuc         goto err;
927*0a6a1f1dSLionel Sambuc     if (i2a_ASN1_INTEGER(out, serial) <= 0)
928*0a6a1f1dSLionel Sambuc         goto err;
929*0a6a1f1dSLionel Sambuc     if (BIO_puts(out, "\n") <= 0)
930*0a6a1f1dSLionel Sambuc         goto err;
931ebfedea0SLionel Sambuc     ret = 1;
932ebfedea0SLionel Sambuc  err:
933ebfedea0SLionel Sambuc     if (!ret)
934ebfedea0SLionel Sambuc         BIO_printf(bio_err, "could not save serial number to %s\n",
935ebfedea0SLionel Sambuc                    serialfile);
936ebfedea0SLionel Sambuc     BIO_free_all(out);
937ebfedea0SLionel Sambuc     return ret;
938ebfedea0SLionel Sambuc }
939ebfedea0SLionel Sambuc 
940ebfedea0SLionel Sambuc /*
941ebfedea0SLionel Sambuc  * Verify-related method definitions.
942ebfedea0SLionel Sambuc  */
943ebfedea0SLionel Sambuc 
verify_command(char * data,char * digest,char * queryfile,char * in,int token_in,char * ca_path,char * ca_file,char * untrusted)944ebfedea0SLionel Sambuc static int verify_command(char *data, char *digest, char *queryfile,
945ebfedea0SLionel Sambuc                           char *in, int token_in,
946ebfedea0SLionel Sambuc                           char *ca_path, char *ca_file, char *untrusted)
947ebfedea0SLionel Sambuc {
948ebfedea0SLionel Sambuc     BIO *in_bio = NULL;
949ebfedea0SLionel Sambuc     PKCS7 *token = NULL;
950ebfedea0SLionel Sambuc     TS_RESP *response = NULL;
951ebfedea0SLionel Sambuc     TS_VERIFY_CTX *verify_ctx = NULL;
952ebfedea0SLionel Sambuc     int ret = 0;
953ebfedea0SLionel Sambuc 
954ebfedea0SLionel Sambuc     /* Decode the token (PKCS7) or response (TS_RESP) files. */
955*0a6a1f1dSLionel Sambuc     if (!(in_bio = BIO_new_file(in, "rb")))
956*0a6a1f1dSLionel Sambuc         goto end;
957*0a6a1f1dSLionel Sambuc     if (token_in) {
958*0a6a1f1dSLionel Sambuc         if (!(token = d2i_PKCS7_bio(in_bio, NULL)))
959*0a6a1f1dSLionel Sambuc             goto end;
960*0a6a1f1dSLionel Sambuc     } else {
961*0a6a1f1dSLionel Sambuc         if (!(response = d2i_TS_RESP_bio(in_bio, NULL)))
962*0a6a1f1dSLionel Sambuc             goto end;
963ebfedea0SLionel Sambuc     }
964ebfedea0SLionel Sambuc 
965ebfedea0SLionel Sambuc     if (!(verify_ctx = create_verify_ctx(data, digest, queryfile,
966ebfedea0SLionel Sambuc                                          ca_path, ca_file, untrusted)))
967ebfedea0SLionel Sambuc         goto end;
968ebfedea0SLionel Sambuc 
969ebfedea0SLionel Sambuc     /* Checking the token or response against the request. */
970ebfedea0SLionel Sambuc     ret = token_in ?
971ebfedea0SLionel Sambuc         TS_RESP_verify_token(verify_ctx, token) :
972ebfedea0SLionel Sambuc         TS_RESP_verify_response(verify_ctx, response);
973ebfedea0SLionel Sambuc 
974ebfedea0SLionel Sambuc  end:
975ebfedea0SLionel Sambuc     printf("Verification: ");
976ebfedea0SLionel Sambuc     if (ret)
977ebfedea0SLionel Sambuc         printf("OK\n");
978*0a6a1f1dSLionel Sambuc     else {
979ebfedea0SLionel Sambuc         printf("FAILED\n");
980ebfedea0SLionel Sambuc         /* Print errors, if there are any. */
981ebfedea0SLionel Sambuc         ERR_print_errors(bio_err);
982ebfedea0SLionel Sambuc     }
983ebfedea0SLionel Sambuc 
984ebfedea0SLionel Sambuc     /* Clean up. */
985ebfedea0SLionel Sambuc     BIO_free_all(in_bio);
986ebfedea0SLionel Sambuc     PKCS7_free(token);
987ebfedea0SLionel Sambuc     TS_RESP_free(response);
988ebfedea0SLionel Sambuc     TS_VERIFY_CTX_free(verify_ctx);
989ebfedea0SLionel Sambuc     return ret;
990ebfedea0SLionel Sambuc }
991ebfedea0SLionel Sambuc 
create_verify_ctx(char * data,char * digest,char * queryfile,char * ca_path,char * ca_file,char * untrusted)992ebfedea0SLionel Sambuc static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
993ebfedea0SLionel Sambuc                                         char *queryfile,
994ebfedea0SLionel Sambuc                                         char *ca_path, char *ca_file,
995ebfedea0SLionel Sambuc                                         char *untrusted)
996ebfedea0SLionel Sambuc {
997ebfedea0SLionel Sambuc     TS_VERIFY_CTX *ctx = NULL;
998ebfedea0SLionel Sambuc     BIO *input = NULL;
999ebfedea0SLionel Sambuc     TS_REQ *request = NULL;
1000ebfedea0SLionel Sambuc     int ret = 0;
1001ebfedea0SLionel Sambuc 
1002*0a6a1f1dSLionel Sambuc     if (data != NULL || digest != NULL) {
1003*0a6a1f1dSLionel Sambuc         if (!(ctx = TS_VERIFY_CTX_new()))
1004*0a6a1f1dSLionel Sambuc             goto err;
1005ebfedea0SLionel Sambuc         ctx->flags = TS_VFY_VERSION | TS_VFY_SIGNER;
1006*0a6a1f1dSLionel Sambuc         if (data != NULL) {
1007ebfedea0SLionel Sambuc             ctx->flags |= TS_VFY_DATA;
1008*0a6a1f1dSLionel Sambuc             if (!(ctx->data = BIO_new_file(data, "rb")))
1009*0a6a1f1dSLionel Sambuc                 goto err;
1010*0a6a1f1dSLionel Sambuc         } else if (digest != NULL) {
1011ebfedea0SLionel Sambuc             long imprint_len;
1012ebfedea0SLionel Sambuc             ctx->flags |= TS_VFY_IMPRINT;
1013*0a6a1f1dSLionel Sambuc             if (!(ctx->imprint = string_to_hex(digest, &imprint_len))) {
1014ebfedea0SLionel Sambuc                 BIO_printf(bio_err, "invalid digest string\n");
1015ebfedea0SLionel Sambuc                 goto err;
1016ebfedea0SLionel Sambuc             }
1017ebfedea0SLionel Sambuc             ctx->imprint_len = imprint_len;
1018ebfedea0SLionel Sambuc         }
1019ebfedea0SLionel Sambuc 
1020*0a6a1f1dSLionel Sambuc     } else if (queryfile != NULL) {
1021*0a6a1f1dSLionel Sambuc         /*
1022*0a6a1f1dSLionel Sambuc          * The request has just to be read, decoded and converted to a verify
1023*0a6a1f1dSLionel Sambuc          * context object.
1024*0a6a1f1dSLionel Sambuc          */
1025*0a6a1f1dSLionel Sambuc         if (!(input = BIO_new_file(queryfile, "rb")))
1026*0a6a1f1dSLionel Sambuc             goto err;
1027*0a6a1f1dSLionel Sambuc         if (!(request = d2i_TS_REQ_bio(input, NULL)))
1028*0a6a1f1dSLionel Sambuc             goto err;
1029*0a6a1f1dSLionel Sambuc         if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)))
1030*0a6a1f1dSLionel Sambuc             goto err;
1031*0a6a1f1dSLionel Sambuc     } else
1032ebfedea0SLionel Sambuc         return NULL;
1033ebfedea0SLionel Sambuc 
1034ebfedea0SLionel Sambuc     /* Add the signature verification flag and arguments. */
1035ebfedea0SLionel Sambuc     ctx->flags |= TS_VFY_SIGNATURE;
1036ebfedea0SLionel Sambuc 
1037ebfedea0SLionel Sambuc     /* Initialising the X509_STORE object. */
1038*0a6a1f1dSLionel Sambuc     if (!(ctx->store = create_cert_store(ca_path, ca_file)))
1039*0a6a1f1dSLionel Sambuc         goto err;
1040ebfedea0SLionel Sambuc 
1041ebfedea0SLionel Sambuc     /* Loading untrusted certificates. */
1042ebfedea0SLionel Sambuc     if (untrusted && !(ctx->certs = TS_CONF_load_certs(untrusted)))
1043ebfedea0SLionel Sambuc         goto err;
1044ebfedea0SLionel Sambuc 
1045ebfedea0SLionel Sambuc     ret = 1;
1046ebfedea0SLionel Sambuc  err:
1047*0a6a1f1dSLionel Sambuc     if (!ret) {
1048ebfedea0SLionel Sambuc         TS_VERIFY_CTX_free(ctx);
1049ebfedea0SLionel Sambuc         ctx = NULL;
1050ebfedea0SLionel Sambuc     }
1051ebfedea0SLionel Sambuc     BIO_free_all(input);
1052ebfedea0SLionel Sambuc     TS_REQ_free(request);
1053ebfedea0SLionel Sambuc     return ctx;
1054ebfedea0SLionel Sambuc }
1055ebfedea0SLionel Sambuc 
create_cert_store(char * ca_path,char * ca_file)1056ebfedea0SLionel Sambuc static X509_STORE *create_cert_store(char *ca_path, char *ca_file)
1057ebfedea0SLionel Sambuc {
1058ebfedea0SLionel Sambuc     X509_STORE *cert_ctx = NULL;
1059ebfedea0SLionel Sambuc     X509_LOOKUP *lookup = NULL;
1060ebfedea0SLionel Sambuc     int i;
1061ebfedea0SLionel Sambuc 
1062ebfedea0SLionel Sambuc     /* Creating the X509_STORE object. */
1063ebfedea0SLionel Sambuc     cert_ctx = X509_STORE_new();
1064ebfedea0SLionel Sambuc 
1065ebfedea0SLionel Sambuc     /* Setting the callback for certificate chain verification. */
1066ebfedea0SLionel Sambuc     X509_STORE_set_verify_cb(cert_ctx, verify_cb);
1067ebfedea0SLionel Sambuc 
1068ebfedea0SLionel Sambuc     /* Adding a trusted certificate directory source. */
1069*0a6a1f1dSLionel Sambuc     if (ca_path) {
1070*0a6a1f1dSLionel Sambuc         lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
1071*0a6a1f1dSLionel Sambuc         if (lookup == NULL) {
1072ebfedea0SLionel Sambuc             BIO_printf(bio_err, "memory allocation failure\n");
1073ebfedea0SLionel Sambuc             goto err;
1074ebfedea0SLionel Sambuc         }
1075ebfedea0SLionel Sambuc         i = X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM);
1076*0a6a1f1dSLionel Sambuc         if (!i) {
1077*0a6a1f1dSLionel Sambuc             BIO_printf(bio_err, "Error loading directory %s\n", ca_path);
1078ebfedea0SLionel Sambuc             goto err;
1079ebfedea0SLionel Sambuc         }
1080ebfedea0SLionel Sambuc     }
1081ebfedea0SLionel Sambuc 
1082ebfedea0SLionel Sambuc     /* Adding a trusted certificate file source. */
1083*0a6a1f1dSLionel Sambuc     if (ca_file) {
1084ebfedea0SLionel Sambuc         lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
1085*0a6a1f1dSLionel Sambuc         if (lookup == NULL) {
1086ebfedea0SLionel Sambuc             BIO_printf(bio_err, "memory allocation failure\n");
1087ebfedea0SLionel Sambuc             goto err;
1088ebfedea0SLionel Sambuc         }
1089ebfedea0SLionel Sambuc         i = X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM);
1090*0a6a1f1dSLionel Sambuc         if (!i) {
1091ebfedea0SLionel Sambuc             BIO_printf(bio_err, "Error loading file %s\n", ca_file);
1092ebfedea0SLionel Sambuc             goto err;
1093ebfedea0SLionel Sambuc         }
1094ebfedea0SLionel Sambuc     }
1095ebfedea0SLionel Sambuc 
1096ebfedea0SLionel Sambuc     return cert_ctx;
1097ebfedea0SLionel Sambuc  err:
1098ebfedea0SLionel Sambuc     X509_STORE_free(cert_ctx);
1099ebfedea0SLionel Sambuc     return NULL;
1100ebfedea0SLionel Sambuc }
1101ebfedea0SLionel Sambuc 
verify_cb(int ok,X509_STORE_CTX * ctx)1102ebfedea0SLionel Sambuc static int MS_CALLBACK verify_cb(int ok, X509_STORE_CTX *ctx)
1103ebfedea0SLionel Sambuc {
1104*0a6a1f1dSLionel Sambuc     /*-
1105ebfedea0SLionel Sambuc     char buf[256];
1106ebfedea0SLionel Sambuc 
1107ebfedea0SLionel Sambuc     if (!ok)
1108ebfedea0SLionel Sambuc             {
1109ebfedea0SLionel Sambuc             X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
1110ebfedea0SLionel Sambuc                               buf, sizeof(buf));
1111ebfedea0SLionel Sambuc             printf("%s\n", buf);
1112ebfedea0SLionel Sambuc             printf("error %d at %d depth lookup: %s\n",
1113ebfedea0SLionel Sambuc                    ctx->error, ctx->error_depth,
1114ebfedea0SLionel Sambuc                     X509_verify_cert_error_string(ctx->error));
1115ebfedea0SLionel Sambuc             }
1116ebfedea0SLionel Sambuc     */
1117ebfedea0SLionel Sambuc 
1118ebfedea0SLionel Sambuc     return ok;
1119ebfedea0SLionel Sambuc }
1120