Merge branch 'STABLE-BRANCH-2-2' into master
[gnupg.git] / sm / verify.c
1 /* verify.c - Verify a messages signature
2  * Copyright (C) 2001, 2002, 2003, 2007,
3  *               2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <time.h>
28 #include <assert.h>
29
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
33
34 #include "keydb.h"
35 #include "../common/i18n.h"
36 #include "../common/compliance.h"
37
38 static char *
39 strtimestamp_r (ksba_isotime_t atime)
40 {
41   char *buffer = xmalloc (15);
42
43   if (!atime || !*atime)
44     strcpy (buffer, "none");
45   else
46     sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
47   return buffer;
48 }
49
50
51
52 /* Hash the data for a detached signature.  Returns 0 on success.  */
53 static gpg_error_t
54 hash_data (int fd, gcry_md_hd_t md)
55 {
56   gpg_error_t err = 0;
57   estream_t fp;
58   char buffer[4096];
59   int nread;
60
61   fp = es_fdopen_nc (fd, "rb");
62   if (!fp)
63     {
64       err = gpg_error_from_syserror ();
65       log_error ("fdopen(%d) failed: %s\n", fd, gpg_strerror (err));
66       return err;
67     }
68
69   do
70     {
71       nread = es_fread (buffer, 1, DIM(buffer), fp);
72       gcry_md_write (md, buffer, nread);
73     }
74   while (nread);
75   if (es_ferror (fp))
76     {
77       err = gpg_error_from_syserror ();
78       log_error ("read error on fd %d: %s\n", fd, gpg_strerror (err));
79     }
80   es_fclose (fp);
81   return err;
82 }
83
84
85
86 \f
87 /* Perform a verify operation.  To verify detached signatures, DATA_FD
88    must be different than -1.  With OUT_FP given and a non-detached
89    signature, the signed material is written to that stream.  */
90 int
91 gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
92 {
93   int i, rc;
94   gnupg_ksba_io_t b64reader = NULL;
95   gnupg_ksba_io_t b64writer = NULL;
96   ksba_reader_t reader;
97   ksba_writer_t writer = NULL;
98   ksba_cms_t cms = NULL;
99   ksba_stop_reason_t stopreason;
100   ksba_cert_t cert;
101   KEYDB_HANDLE kh;
102   gcry_md_hd_t data_md = NULL;
103   int signer;
104   const char *algoid;
105   int algo;
106   int is_detached;
107   estream_t in_fp = NULL;
108   char *p;
109
110   audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);
111
112   kh = keydb_new ();
113   if (!kh)
114     {
115       log_error (_("failed to allocate keyDB handle\n"));
116       rc = gpg_error (GPG_ERR_GENERAL);
117       goto leave;
118     }
119
120
121   in_fp = es_fdopen_nc (in_fd, "rb");
122   if (!in_fp)
123     {
124       rc = gpg_error_from_syserror ();
125       log_error ("fdopen() failed: %s\n", strerror (errno));
126       goto leave;
127     }
128
129   rc = gnupg_ksba_create_reader
130     (&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0)
131                   | (ctrl->is_base64? GNUPG_KSBA_IO_BASE64 : 0)
132                   | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0)),
133      in_fp, &reader);
134   if (rc)
135     {
136       log_error ("can't create reader: %s\n", gpg_strerror (rc));
137       goto leave;
138     }
139
140   if (out_fp)
141     {
142       rc = gnupg_ksba_create_writer
143         (&b64writer, ((ctrl->create_pem? GNUPG_KSBA_IO_PEM : 0)
144                       | (ctrl->create_base64? GNUPG_KSBA_IO_BASE64 : 0)),
145          ctrl->pem_name, out_fp, &writer);
146       if (rc)
147         {
148           log_error ("can't create writer: %s\n", gpg_strerror (rc));
149           goto leave;
150         }
151     }
152
153   rc = ksba_cms_new (&cms);
154   if (rc)
155     goto leave;
156
157   rc = ksba_cms_set_reader_writer (cms, reader, writer);
158   if (rc)
159     {
160       log_error ("ksba_cms_set_reader_writer failed: %s\n",
161                  gpg_strerror (rc));
162       goto leave;
163     }
164
165   rc = gcry_md_open (&data_md, 0, 0);
166   if (rc)
167     {
168       log_error ("md_open failed: %s\n", gpg_strerror (rc));
169       goto leave;
170     }
171   if (DBG_HASHING)
172     gcry_md_debug (data_md, "vrfy.data");
173
174   audit_log (ctrl->audit, AUDIT_SETUP_READY);
175
176   is_detached = 0;
177   do
178     {
179       rc = ksba_cms_parse (cms, &stopreason);
180       if (rc)
181         {
182           log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
183           goto leave;
184         }
185
186       if (stopreason == KSBA_SR_NEED_HASH)
187         {
188           is_detached = 1;
189           audit_log (ctrl->audit, AUDIT_DETACHED_SIGNATURE);
190           if (opt.verbose)
191             log_info ("detached signature\n");
192         }
193
194       if (stopreason == KSBA_SR_NEED_HASH
195           || stopreason == KSBA_SR_BEGIN_DATA)
196         {
197           audit_log (ctrl->audit, AUDIT_GOT_DATA);
198
199           /* We are now able to enable the hash algorithms */
200           for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
201             {
202               algo = gcry_md_map_name (algoid);
203               if (!algo)
204                 {
205                   log_error ("unknown hash algorithm '%s'\n",
206                              algoid? algoid:"?");
207                   if (algoid
208                       && (  !strcmp (algoid, "1.2.840.113549.1.1.2")
209                           ||!strcmp (algoid, "1.2.840.113549.2.2")))
210                     log_info (_("(this is the MD2 algorithm)\n"));
211                   audit_log_s (ctrl->audit, AUDIT_BAD_DATA_HASH_ALGO, algoid);
212                 }
213               else
214                 {
215                   if (DBG_X509)
216                     log_debug ("enabling hash algorithm %d (%s)\n",
217                                algo, algoid? algoid:"");
218                   gcry_md_enable (data_md, algo);
219                   audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
220                 }
221             }
222           if (opt.extra_digest_algo)
223             {
224               if (DBG_X509)
225                 log_debug ("enabling extra hash algorithm %d\n",
226                            opt.extra_digest_algo);
227               gcry_md_enable (data_md, opt.extra_digest_algo);
228               audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO,
229                            opt.extra_digest_algo);
230             }
231           if (is_detached)
232             {
233               if (data_fd == -1)
234                 {
235                   log_info ("detached signature w/o data "
236                             "- assuming certs-only\n");
237                   audit_log (ctrl->audit, AUDIT_CERT_ONLY_SIG);
238                 }
239               else
240                 audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING,
241                               hash_data (data_fd, data_md));
242             }
243           else
244             {
245               ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
246             }
247         }
248       else if (stopreason == KSBA_SR_END_DATA)
249         { /* The data bas been hashed */
250           audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
251         }
252     }
253   while (stopreason != KSBA_SR_READY);
254
255   if (b64writer)
256     {
257       rc = gnupg_ksba_finish_writer (b64writer);
258       if (rc)
259         {
260           log_error ("write failed: %s\n", gpg_strerror (rc));
261           audit_log_ok (ctrl->audit, AUDIT_WRITE_ERROR, rc);
262           goto leave;
263         }
264     }
265
266   if (data_fd != -1 && !is_detached)
267     {
268       log_error ("data given for a non-detached signature\n");
269       rc = gpg_error (GPG_ERR_CONFLICT);
270       audit_log (ctrl->audit, AUDIT_USAGE_ERROR);
271       goto leave;
272     }
273
274   for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
275     {
276       /* Fixme: it might be better to check the validity of the
277          certificate first before entering it into the DB.  This way
278          we would avoid cluttering the DB with invalid
279          certificates. */
280       audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert,
281                       keydb_store_cert (ctrl, cert, 0, NULL));
282       ksba_cert_release (cert);
283     }
284
285   cert = NULL;
286   for (signer=0; ; signer++)
287     {
288       char *issuer = NULL;
289       ksba_sexp_t sigval = NULL;
290       ksba_isotime_t sigtime, keyexptime;
291       ksba_sexp_t serial;
292       char *msgdigest = NULL;
293       size_t msgdigestlen;
294       char *ctattr;
295       int sigval_hash_algo;
296       int info_pkalgo;
297       unsigned int verifyflags;
298
299       rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
300       if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
301           && data_fd == -1 && is_detached)
302         {
303           log_info ("certs-only message accepted\n");
304           rc = 0;
305           break;
306         }
307       if (rc)
308         {
309           if (signer && rc == -1)
310             rc = 0;
311           break;
312         }
313
314       gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
315       audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);
316
317       if (DBG_X509)
318         {
319           log_debug ("signer %d - issuer: '%s'\n",
320                      signer, issuer? issuer:"[NONE]");
321           log_debug ("signer %d - serial: ", signer);
322           gpgsm_dump_serial (serial);
323           log_printf ("\n");
324         }
325       if (ctrl->audit)
326         {
327           char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
328           audit_log_s (ctrl->audit, AUDIT_SIG_NAME, tmpstr);
329           xfree (tmpstr);
330         }
331
332       rc = ksba_cms_get_signing_time (cms, signer, sigtime);
333       if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
334         *sigtime = 0;
335       else if (rc)
336         {
337           log_error ("error getting signing time: %s\n", gpg_strerror (rc));
338           *sigtime = 0; /* (we can't encode an error in the time string.) */
339         }
340
341       rc = ksba_cms_get_message_digest (cms, signer,
342                                         &msgdigest, &msgdigestlen);
343       if (!rc)
344         {
345           algoid = ksba_cms_get_digest_algo (cms, signer);
346           algo = gcry_md_map_name (algoid);
347           if (DBG_X509)
348             log_debug ("signer %d - digest algo: %d\n", signer, algo);
349           if (! gcry_md_is_enabled (data_md, algo))
350             {
351               log_error ("digest algo %d (%s) has not been enabled\n",
352                          algo, algoid?algoid:"");
353               audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported");
354               goto next_signer;
355             }
356         }
357       else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
358         {
359           assert (!msgdigest);
360           rc = 0;
361           algoid = NULL;
362           algo = 0;
363         }
364       else /* real error */
365         {
366           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
367           break;
368         }
369
370       rc = ksba_cms_get_sigattr_oids (cms, signer,
371                                       "1.2.840.113549.1.9.3", &ctattr);
372       if (!rc)
373         {
374           const char *s;
375
376           if (DBG_X509)
377             log_debug ("signer %d - content-type attribute: %s",
378                        signer, ctattr);
379
380           s = ksba_cms_get_content_oid (cms, 1);
381           if (!s || strcmp (ctattr, s))
382             {
383               log_error ("content-type attribute does not match "
384                          "actual content-type\n");
385               ksba_free (ctattr);
386               ctattr = NULL;
387               audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
388               goto next_signer;
389             }
390           ksba_free (ctattr);
391           ctattr = NULL;
392         }
393       else if (rc != -1)
394         {
395           log_error ("error getting content-type attribute: %s\n",
396                      gpg_strerror (rc));
397           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
398           goto next_signer;
399         }
400       rc = 0;
401
402
403       sigval = ksba_cms_get_sig_val (cms, signer);
404       if (!sigval)
405         {
406           log_error ("no signature value available\n");
407           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
408           goto next_signer;
409         }
410       sigval_hash_algo = hash_algo_from_sigval (sigval);
411       if (DBG_X509)
412         {
413           log_debug ("signer %d - signature available (sigval hash=%d)",
414                      signer, sigval_hash_algo);
415 /*           log_printhex ("sigval    ", sigval, */
416 /*                         gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */
417         }
418       if (!sigval_hash_algo)
419         sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */
420
421       /* Find the certificate of the signer */
422       keydb_search_reset (kh);
423       rc = keydb_search_issuer_sn (ctrl, kh, issuer, serial);
424       if (rc)
425         {
426           if (rc == -1)
427             {
428               log_error ("certificate not found\n");
429               rc = gpg_error (GPG_ERR_NO_PUBKEY);
430             }
431           else
432             log_error ("failed to find the certificate: %s\n",
433                        gpg_strerror(rc));
434           {
435             char numbuf[50];
436             sprintf (numbuf, "%d", rc);
437
438             gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
439                            numbuf, NULL);
440           }
441           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "no-cert");
442           goto next_signer;
443         }
444
445       rc = keydb_get_cert (kh, &cert);
446       if (rc)
447         {
448           log_error ("failed to get cert: %s\n", gpg_strerror (rc));
449           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
450           goto next_signer;
451         }
452
453       /* Check compliance.  */
454       {
455         unsigned int nbits;
456         int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
457
458         if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
459                                    pk_algo, NULL, nbits, NULL))
460           {
461             char  kidstr[10+1];
462
463             snprintf (kidstr, sizeof kidstr, "0x%08lX",
464                       gpgsm_get_short_fingerprint (cert, NULL));
465             log_error (_("key %s may not be used for signing in %s mode\n"),
466                        kidstr,
467                        gnupg_compliance_option_string (opt.compliance));
468             goto next_signer;
469           }
470
471         if (! gnupg_digest_is_allowed (opt.compliance, 0, sigval_hash_algo))
472           {
473             log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
474                        gcry_md_algo_name (sigval_hash_algo),
475                        gnupg_compliance_option_string (opt.compliance));
476             goto next_signer;
477           }
478
479         /* Check compliance with CO_DE_VS.  */
480         if (gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL)
481             && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
482           gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
483                         gnupg_status_compliance_flag (CO_DE_VS));
484       }
485
486       log_info (_("Signature made "));
487       if (*sigtime)
488         dump_isotime (sigtime);
489       else
490         log_printf (_("[date not given]"));
491       log_printf (_(" using certificate ID 0x%08lX\n"),
492                   gpgsm_get_short_fingerprint (cert, NULL));
493
494       audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
495
496       if (msgdigest)
497         { /* Signed attributes are available. */
498           gcry_md_hd_t md;
499           unsigned char *s;
500
501           /* Check that the message digest in the signed attributes
502              matches the one we calculated on the data.  */
503           s = gcry_md_read (data_md, algo);
504           if ( !s || !msgdigestlen
505                || gcry_md_get_algo_dlen (algo) != msgdigestlen
506                || memcmp (s, msgdigest, msgdigestlen) )
507             {
508               char *fpr;
509
510               log_error (_("invalid signature: message digest attribute "
511                            "does not match computed one\n"));
512               if (DBG_X509)
513                 {
514                   if (msgdigest)
515                     log_printhex (msgdigest, msgdigestlen, "message:  ");
516                   if (s)
517                     log_printhex (s, gcry_md_get_algo_dlen (algo),
518                                   "computed: ");
519                 }
520               fpr = gpgsm_fpr_and_name_for_status (cert);
521               gpgsm_status (ctrl, STATUS_BADSIG, fpr);
522               xfree (fpr);
523               audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
524               goto next_signer;
525             }
526
527           audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
528           rc = gcry_md_open (&md, sigval_hash_algo, 0);
529           if (rc)
530             {
531               log_error ("md_open failed: %s\n", gpg_strerror (rc));
532               audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
533               goto next_signer;
534             }
535           if (DBG_HASHING)
536             gcry_md_debug (md, "vrfy.attr");
537
538           ksba_cms_set_hash_function (cms, HASH_FNC, md);
539           rc = ksba_cms_hash_signed_attrs (cms, signer);
540           if (rc)
541             {
542               log_error ("hashing signed attrs failed: %s\n",
543                          gpg_strerror (rc));
544               gcry_md_close (md);
545               audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
546               goto next_signer;
547             }
548           rc = gpgsm_check_cms_signature (cert, sigval, md,
549                                           sigval_hash_algo, &info_pkalgo);
550           gcry_md_close (md);
551         }
552       else
553         {
554           rc = gpgsm_check_cms_signature (cert, sigval, data_md,
555                                           algo, &info_pkalgo);
556         }
557
558       if (rc)
559         {
560           char *fpr;
561
562           log_error ("invalid signature: %s\n", gpg_strerror (rc));
563           fpr = gpgsm_fpr_and_name_for_status (cert);
564           gpgsm_status (ctrl, STATUS_BADSIG, fpr);
565           xfree (fpr);
566           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
567           goto next_signer;
568         }
569       rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
570       if (rc)
571         {
572           gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
573                                       gpg_err_code (rc));
574           rc = 0;
575         }
576
577       if (DBG_X509)
578         log_debug ("signature okay - checking certs\n");
579       audit_log (ctrl->audit, AUDIT_VALIDATE_CHAIN);
580       rc = gpgsm_validate_chain (ctrl, cert,
581                                  *sigtime? sigtime : "19700101T000000",
582                                  keyexptime, 0,
583                                  NULL, 0, &verifyflags);
584       {
585         char *fpr, *buf, *tstr;
586
587         fpr = gpgsm_fpr_and_name_for_status (cert);
588         if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
589           {
590             gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
591             rc = 0;
592           }
593         else
594           gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
595
596         xfree (fpr);
597
598         fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
599         tstr = strtimestamp_r (sigtime);
600         buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr,
601                          *sigtime? sigtime : "0",
602                          *keyexptime? keyexptime : "0",
603                          info_pkalgo, algo);
604         xfree (tstr);
605         xfree (fpr);
606         gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
607         xfree (buf);
608       }
609
610       audit_log_ok (ctrl->audit, AUDIT_CHAIN_STATUS, rc);
611       if (rc) /* of validate_chain */
612         {
613           log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
614           if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
615               || gpg_err_code (rc) == GPG_ERR_BAD_CERT
616               || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
617               || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
618             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
619                                         gpg_err_code (rc));
620           else
621             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL,
622                                         gpg_err_code (rc));
623           audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
624           goto next_signer;
625         }
626
627       audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "good");
628
629       for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
630         {
631           log_info (!i? _("Good signature from")
632                       : _("                aka"));
633           log_printf (" \"");
634           gpgsm_es_print_name (log_get_stream (), p);
635           log_printf ("\"\n");
636           ksba_free (p);
637         }
638
639       /* Print a note if this is a qualified signature.  */
640       {
641         size_t qualbuflen;
642         char qualbuffer[1];
643
644         rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer,
645                                       sizeof (qualbuffer), &qualbuflen);
646         if (!rc && qualbuflen)
647           {
648             if (*qualbuffer)
649               {
650                 log_info (_("This is a qualified signature\n"));
651                 if (!opt.qualsig_approval)
652                   log_info
653                     (_("Note, that this software is not officially approved "
654                        "to create or verify such signatures.\n"));
655               }
656           }
657         else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
658           log_error ("get_user_data(is_qualified) failed: %s\n",
659                      gpg_strerror (rc));
660       }
661
662       gpgsm_status (ctrl, STATUS_TRUST_FULLY,
663                     (verifyflags & VALIDATE_FLAG_STEED)?
664                     "0 steed":
665                     (verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
666                     "0 chain": "0 shell");
667
668     next_signer:
669       rc = 0;
670       xfree (issuer);
671       xfree (serial);
672       xfree (sigval);
673       xfree (msgdigest);
674       ksba_cert_release (cert);
675       cert = NULL;
676     }
677   rc = 0;
678
679  leave:
680   ksba_cms_release (cms);
681   gnupg_ksba_destroy_reader (b64reader);
682   gnupg_ksba_destroy_writer (b64writer);
683   keydb_release (kh);
684   gcry_md_close (data_md);
685   es_fclose (in_fp);
686
687   if (rc)
688     {
689       char numbuf[50];
690       sprintf (numbuf, "%d", rc );
691       gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
692                      numbuf, NULL);
693     }
694
695   return rc;
696 }