Modify OCSP nonce behaviour.
[openssl.git] / apps / ocsp.c
1 /* ocsp.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <string.h>
61 #include <openssl/pem.h>
62 #include <openssl/ocsp.h>
63 #include <openssl/err.h>
64 #include "apps.h"
65
66 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
67                                 STACK_OF(OCSP_CERTID) *ids);
68 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
69                                 STACK_OF(OCSP_CERTID) *ids);
70 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
71                                 STACK *names, STACK_OF(OCSP_CERTID) *ids);
72
73 #undef PROG
74 #define PROG ocsp_main
75
76 int MAIN(int, char **);
77
78 int MAIN(int argc, char **argv)
79         {
80         char **args;
81         char *host = NULL, *path = "/";
82         char *reqin = NULL, *respin = NULL;
83         char *reqout = NULL, *respout = NULL;
84         char *signfile = NULL, *keyfile = NULL;
85         char *outfile = NULL;
86         int add_nonce = 1, noverify = 0;
87         OCSP_REQUEST *req = NULL;
88         OCSP_RESPONSE *resp = NULL;
89         OCSP_BASICRESP *bs = NULL;
90         X509 *issuer = NULL, *cert = NULL;
91         X509 *signer = NULL;
92         EVP_PKEY *key = NULL;
93         BIO *cbio = NULL, *derbio = NULL;
94         BIO *out = NULL;
95         int req_text = 0, resp_text = 0;
96         char *CAfile = NULL, *CApath = NULL;
97         X509_STORE *store = NULL;
98         STACK_OF(X509) *sign_other = NULL, *verify_other = NULL;
99         char *sign_certfile = NULL, *verify_certfile = NULL;
100         unsigned long sign_flags = 0, verify_flags = 0;
101         int ret = 1;
102         int badarg = 0;
103         int i;
104         STACK *reqnames = NULL;
105         STACK_OF(OCSP_CERTID) *ids = NULL;
106         if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
107         ERR_load_crypto_strings();
108         args = argv + 1;
109         reqnames = sk_new_null();
110         ids = sk_OCSP_CERTID_new_null();
111         while (!badarg && *args && *args[0] == '-')
112                 {
113                 if (!strcmp(*args, "-out"))
114                         {
115                         if (args[1])
116                                 {
117                                 args++;
118                                 outfile = *args;
119                                 }
120                         else badarg = 1;
121                         }
122                 else if (!strcmp(*args, "-host"))
123                         {
124                         if (args[1])
125                                 {
126                                 args++;
127                                 host = *args;
128                                 }
129                         else badarg = 1;
130                         }
131                 else if (!strcmp(*args, "-noverify"))
132                         noverify = 1;
133                 else if (!strcmp(*args, "-nonce"))
134                         add_nonce = 2;
135                 else if (!strcmp(*args, "-no_nonce"))
136                         add_nonce = 0;
137                 else if (!strcmp(*args, "-no_certs"))
138                         sign_flags |= OCSP_NOCERTS;
139                 else if (!strcmp(*args, "-no_signature_verify"))
140                         verify_flags |= OCSP_NOSIGS;
141                 else if (!strcmp(*args, "-no_cert_verify"))
142                         verify_flags |= OCSP_NOVERIFY;
143                 else if (!strcmp(*args, "-no_chain"))
144                         verify_flags |= OCSP_NOCHAIN;
145                 else if (!strcmp(*args, "-no_cert_checks"))
146                         verify_flags |= OCSP_NOCHECKS;
147                 else if (!strcmp(*args, "-no_explicit"))
148                         verify_flags |= OCSP_NOEXPLICIT;
149                 else if (!strcmp(*args, "-trust_other"))
150                         verify_flags |= OCSP_TRUSTOTHER;
151                 else if (!strcmp(*args, "-no_intern"))
152                         verify_flags |= OCSP_NOINTERN;
153                 else if (!strcmp(*args, "-text"))
154                         {
155                         req_text = 1;
156                         resp_text = 1;
157                         }
158                 else if (!strcmp(*args, "-req_text"))
159                         req_text = 1;
160                 else if (!strcmp(*args, "-resp_text"))
161                         resp_text = 1;
162                 else if (!strcmp(*args, "-reqin"))
163                         {
164                         if (args[1])
165                                 {
166                                 args++;
167                                 reqin = *args;
168                                 }
169                         else badarg = 1;
170                         }
171                 else if (!strcmp(*args, "-respin"))
172                         {
173                         if (args[1])
174                                 {
175                                 args++;
176                                 respin = *args;
177                                 }
178                         else badarg = 1;
179                         }
180                 else if (!strcmp(*args, "-signer"))
181                         {
182                         if (args[1])
183                                 {
184                                 args++;
185                                 signfile = *args;
186                                 }
187                         else badarg = 1;
188                         }
189                 else if (!strcmp (*args, "-VAfile"))
190                         {
191                         if (args[1])
192                                 {
193                                 args++;
194                                 verify_certfile = *args;
195                                 verify_flags |= OCSP_TRUSTOTHER;
196                                 }
197                         else badarg = 1;
198                         }
199                 else if (!strcmp(*args, "-sign_other"))
200                         {
201                         if (args[1])
202                                 {
203                                 args++;
204                                 sign_certfile = *args;
205                                 }
206                         else badarg = 1;
207                         }
208                 else if (!strcmp(*args, "-verify_other"))
209                         {
210                         if (args[1])
211                                 {
212                                 args++;
213                                 verify_certfile = *args;
214                                 }
215                         else badarg = 1;
216                         }
217                 else if (!strcmp (*args, "-CAfile"))
218                         {
219                         if (args[1])
220                                 {
221                                 args++;
222                                 CAfile = *args;
223                                 }
224                         else badarg = 1;
225                         }
226                 else if (!strcmp (*args, "-CApath"))
227                         {
228                         if (args[1])
229                                 {
230                                 args++;
231                                 CApath = *args;
232                                 }
233                         else badarg = 1;
234                         }
235                  else if (!strcmp(*args, "-signkey"))
236                         {
237                         if (args[1])
238                                 {
239                                 args++;
240                                 keyfile = *args;
241                                 }
242                         else badarg = 1;
243                         }
244                 else if (!strcmp(*args, "-reqout"))
245                         {
246                         if (args[1])
247                                 {
248                                 args++;
249                                 reqout = *args;
250                                 }
251                         else badarg = 1;
252                         }
253                 else if (!strcmp(*args, "-respout"))
254                         {
255                         if (args[1])
256                                 {
257                                 args++;
258                                 respout = *args;
259                                 }
260                         else badarg = 1;
261                         }
262                  else if (!strcmp(*args, "-path"))
263                         {
264                         if (args[1])
265                                 {
266                                 args++;
267                                 path = *args;
268                                 }
269                         else badarg = 1;
270                         }
271                 else if (!strcmp(*args, "-issuer"))
272                         {
273                         if (args[1])
274                                 {
275                                 args++;
276                                 X509_free(issuer);
277                                 issuer = load_cert(bio_err, *args, FORMAT_PEM);
278                                 if(!issuer) goto end;
279                                 }
280                         else badarg = 1;
281                         }
282                 else if (!strcmp (*args, "-cert"))
283                         {
284                         if (args[1])
285                                 {
286                                 args++;
287                                 X509_free(cert);
288                                 cert = load_cert(bio_err, *args, FORMAT_PEM);
289                                 if(!cert) goto end;
290                                 if(!add_ocsp_cert(&req, cert, issuer, ids))
291                                         goto end;
292                                 if(!sk_push(reqnames, *args))
293                                         goto end;
294                                 }
295                         else badarg = 1;
296                         }
297                 else if (!strcmp(*args, "-serial"))
298                         {
299                         if (args[1])
300                                 {
301                                 args++;
302                                 if(!add_ocsp_serial(&req, *args, issuer, ids))
303                                         goto end;
304                                 if(!sk_push(reqnames, *args))
305                                         goto end;
306                                 }
307                         else badarg = 1;
308                         }
309                 else badarg = 1;
310                 args++;
311                 }
312
313         /* Have we anything to do? */
314         if (!req && !reqin && !respin) badarg = 1;
315
316         if (badarg)
317                 {
318                 BIO_printf (bio_err, "OCSP utility\n");
319                 BIO_printf (bio_err, "Usage ocsp [options]\n");
320                 BIO_printf (bio_err, "where options are\n");
321                 BIO_printf (bio_err, "-out file          output filename\n");
322                 BIO_printf (bio_err, "-issuer file       issuer certificate\n");
323                 BIO_printf (bio_err, "-cert file         certificate to check\n");
324                 BIO_printf (bio_err, "-serial n          serial number to check\n");
325                 BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
326                 BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
327                 BIO_printf (bio_err, "-sign_certs file   additional certificates to include in signed request\n");
328                 BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
329                 BIO_printf (bio_err, "-req_text          print text form of request\n");
330                 BIO_printf (bio_err, "-resp_text         print text form of response\n");
331                 BIO_printf (bio_err, "-text              print text form of request and response\n");
332                 BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
333                 BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
334                 BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
335                 BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
336                 BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
337                 BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
338                 BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
339                 BIO_printf (bio_err, "-path              path to use in OCSP request\n");
340                 BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
341                 BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
342                 BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
343                 BIO_printf (bio_err, "-noverify          don't verify response at all\n");
344                 BIO_printf (bio_err, "-verify_certs file additional certificates to search for signer\n");
345                 BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
346                 BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
347                 BIO_printf (bio_err, "-no_sig_verify     don't check signature on response\n");
348                 BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
349                 BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
350                 BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
351                 goto end;
352                 }
353
354         if(outfile) out = BIO_new_file(outfile, "w");
355         else out = BIO_new_fp(stdout, BIO_NOCLOSE);
356
357         if(!out)
358                 {
359                 BIO_printf(bio_err, "Error opening output file\n");
360                 goto end;
361                 }
362
363         if (!req && (add_nonce != 2)) add_nonce = 0;
364
365         if (!req && reqin)
366                 {
367                 derbio = BIO_new_file(reqin, "rb");
368                 if (!derbio)
369                         {
370                         BIO_printf(bio_err, "Error Opening OCSP request file\n");
371                         goto end;
372                         }
373                 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
374                 BIO_free(derbio);
375                 if(!req)
376                         {
377                         BIO_printf(bio_err, "Error reading OCSP request\n");
378                         goto end;
379                         }
380                 }
381
382         if (!req && (signfile || reqout || host || add_nonce))
383                 {
384                 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
385                 goto end;
386                 }
387
388         if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
389
390         if (signfile)
391                 {
392                 if (!keyfile) keyfile = signfile;
393                 signer = load_cert(bio_err, signfile, FORMAT_PEM);
394                 if (!signer)
395                         {
396                         BIO_printf(bio_err, "Error loading signer certificate\n");
397                         goto end;
398                         }
399                 if (sign_certfile)
400                         {
401                         sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM);
402                         if (!sign_other) goto end;
403                         }
404                 key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL);
405                 if (!key)
406                         {
407                         BIO_printf(bio_err, "Error loading signer private key\n");
408                         goto end;
409                         }
410                 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
411                         {
412                         BIO_printf(bio_err, "Error signing OCSP request\n");
413                         goto end;
414                         }
415                 }
416
417         if (reqout)
418                 {
419                 derbio = BIO_new_file(reqout, "wb");
420                 if (!derbio)
421                         {
422                         BIO_printf(bio_err, "Error opening file %s\n", reqout);
423                         goto end;
424                         }
425                 i2d_OCSP_REQUEST_bio(derbio, req);
426                 BIO_free(derbio);
427                 }
428
429         if (req_text && req) OCSP_REQUEST_print(out, req, 0);
430
431         if (host)
432                 {
433                 cbio = BIO_new_connect(host);
434                 if (!cbio)
435                         {
436                         BIO_printf(bio_err, "Error creating connect BIO\n");
437                         goto end;
438                         }
439                 if (BIO_do_connect(cbio) <= 0)
440                         {
441                         BIO_printf(bio_err, "Error connecting BIO\n");
442                         goto end;
443                         }
444                 resp = OCSP_sendreq_bio(cbio, path, req);
445                 BIO_free(cbio);
446                 cbio = NULL;
447                 if (!resp)
448                         {
449                         BIO_printf(bio_err, "Error querying OCSP responsder\n");
450                         goto end;
451                         }
452                 }
453         else if (respin)
454                 {
455                 derbio = BIO_new_file(respin, "rb");
456                 if (!derbio)
457                         {
458                         BIO_printf(bio_err, "Error Opening OCSP response file\n");
459                         goto end;
460                         }
461                 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
462                 BIO_free(derbio);
463                 if(!resp)
464                         {
465                         BIO_printf(bio_err, "Error reading OCSP response\n");
466                         goto end;
467                         }
468         
469                 }
470         else
471                 {
472                 ret = 0;
473                 goto end;
474                 }
475
476         if (respout)
477                 {
478                 derbio = BIO_new_file(respout, "wb");
479                 if(!derbio)
480                         {
481                         BIO_printf(bio_err, "Error opening file %s\n", respout);
482                         goto end;
483                         }
484                 i2d_OCSP_RESPONSE_bio(derbio, resp);
485                 BIO_free(derbio);
486                 }
487
488         i = OCSP_response_status(resp);
489
490         if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
491                 {
492                 BIO_printf(out, "Responder Error: %s (%ld)\n",
493                                 OCSP_response_status_str(i), i);
494                 ret = 0;
495                 goto end;
496                 }
497
498         if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
499
500         store = setup_verify(bio_err, CAfile, CApath);
501         if(!store) goto end;
502         if (verify_certfile)
503                 {
504                 verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM);
505                 if (!verify_other) goto end;
506                 }
507
508         bs = OCSP_response_get1_basic(resp);
509
510         if (!bs)
511                 {
512                 BIO_printf(bio_err, "Error parsing response\n");
513                 goto end;
514                 }
515
516         if (!noverify)
517                 {
518                 if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
519                         {
520                         if (i == -1)
521                                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
522                         else
523                                 {
524                                 BIO_printf(bio_err, "Nonce Verify error\n");
525                                 goto end;
526                                 }
527                         }
528
529                 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
530                 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
531
532                 if(i <= 0)
533                         {
534                         BIO_printf(bio_err, "Response Verify Failure\n", i);
535                         ERR_print_errors(bio_err);
536                         }
537                 else
538                         BIO_printf(bio_err, "Response verify OK\n");
539
540                 }
541
542         if (!print_ocsp_summary(out, bs, req, reqnames, ids))
543                 goto end;
544
545         ret = 0;
546
547 end:
548         ERR_print_errors(bio_err);
549         X509_free(signer);
550         X509_STORE_free(store);
551         EVP_PKEY_free(key);
552         X509_free(issuer);
553         X509_free(cert);
554         BIO_free(cbio);
555         BIO_free(out);
556         OCSP_REQUEST_free(req);
557         OCSP_RESPONSE_free(resp);
558         OCSP_BASICRESP_free(bs);
559         sk_free(reqnames);
560         sk_OCSP_CERTID_free(ids);
561         sk_X509_pop_free(sign_other, X509_free);
562         sk_X509_pop_free(verify_other, X509_free);
563
564         EXIT(ret);
565 }
566
567 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
568                                 STACK_OF(OCSP_CERTID) *ids)
569         {
570         OCSP_CERTID *id;
571         if(!issuer)
572                 {
573                 BIO_printf(bio_err, "No issuer certificate specified\n");
574                 return 0;
575                 }
576         if(!*req) *req = OCSP_REQUEST_new();
577         if(!*req) goto err;
578         id = OCSP_cert_to_id(NULL, cert, issuer);
579         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
580         if(!OCSP_request_add0_id(*req, id)) goto err;
581         return 1;
582
583         err:
584         BIO_printf(bio_err, "Error Creating OCSP request\n");
585         return 0;
586         }
587
588 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
589                                 STACK_OF(OCSP_CERTID) *ids)
590         {
591         OCSP_CERTID *id;
592         X509_NAME *iname;
593         ASN1_BIT_STRING *ikey;
594         ASN1_INTEGER *sno;
595         if(!issuer)
596                 {
597                 BIO_printf(bio_err, "No issuer certificate specified\n");
598                 return 0;
599                 }
600         if(!*req) *req = OCSP_REQUEST_new();
601         if(!*req) goto err;
602         iname = X509_get_subject_name(issuer);
603         ikey = X509_get0_pubkey_bitstr(issuer);
604         sno = s2i_ASN1_INTEGER(NULL, serial);
605         if(!sno)
606                 {
607                 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
608                 return 0;
609                 }
610         id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
611         ASN1_INTEGER_free(sno);
612         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
613         if(!OCSP_request_add0_id(*req, id)) goto err;
614         return 1;
615
616         err:
617         BIO_printf(bio_err, "Error Creating OCSP request\n");
618         return 0;
619         }
620
621 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
622                                         STACK *names, STACK_OF(OCSP_CERTID) *ids)
623         {
624         OCSP_CERTID *id;
625         char *name;
626         int i;
627
628         int status, reason;
629
630         ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
631
632         if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
633                 return 1;
634
635         for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
636                 {
637                 id = sk_OCSP_CERTID_value(ids, i);
638                 name = sk_value(names, i);
639                 BIO_printf(out, "%s: ", name);
640
641                 if(!OCSP_resp_find_status(bs, id, &status, &reason,
642                                         &rev, &thisupd, &nextupd))
643                         {
644                         BIO_puts(out, "ERROR: No Status found.\n");
645                         continue;
646                         }
647                 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
648
649                 BIO_puts(out, "\tThis Update: ");
650                 ASN1_GENERALIZEDTIME_print(out, thisupd);
651                 BIO_puts(out, "\n");
652
653                 if(nextupd)
654                         {
655                         BIO_puts(out, "\tNext Update: ");
656                         ASN1_GENERALIZEDTIME_print(out, thisupd);
657                         BIO_puts(out, "\n");
658                         }
659
660                 if (status != V_OCSP_CERTSTATUS_REVOKED)
661                         continue;
662
663                 if (reason != -1)
664                         BIO_printf(out, "\tReason: %s\n",
665                                 OCSP_crl_reason_str(reason));
666
667                 BIO_puts(out, "\tRevocation Time: ");
668                 ASN1_GENERALIZEDTIME_print(out, rev);
669                 BIO_puts(out, "\n");
670                 }
671
672         return 1;
673         }
674