e445688728011e75d7baf908508c7e84b459ee52
[gnupg.git] / sm / verify.c
1 /* verify.c - Verify a messages signature
2  *      Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h> 
26 #include <time.h>
27 #include <assert.h>
28
29 #include "gpgsm.h"
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "keydb.h"
34 #include "i18n.h"
35
36 static char *
37 strtimestamp_r (ksba_isotime_t atime)
38 {
39   char *buffer = xmalloc (15);
40   
41   if (!atime || !*atime)
42     strcpy (buffer, "none");
43   else
44     sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
45   return buffer;
46 }
47
48
49
50 /* Hash the data for a detached signature */
51 static void
52 hash_data (int fd, gcry_md_hd_t md)
53 {
54   FILE *fp;
55   char buffer[4096];
56   int nread;
57
58   fp = fdopen ( dup (fd), "rb");
59   if (!fp)
60     {
61       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
62       return;
63     }
64
65   do 
66     {
67       nread = fread (buffer, 1, DIM(buffer), fp);
68       gcry_md_write (md, buffer, nread);
69     }
70   while (nread);
71   if (ferror (fp))
72       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
73   fclose (fp);
74 }
75
76
77
78 \f
79 /* Perform a verify operation.  To verify detached signatures, data_fd
80    must be different than -1.  With OUT_FP given and a non-detached
81    signature, the signed material is written to that stream. */
82 int
83 gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
84 {
85   int i, rc;
86   Base64Context b64reader = NULL;
87   Base64Context b64writer = NULL;
88   ksba_reader_t reader;
89   ksba_writer_t writer = NULL;
90   ksba_cms_t cms = NULL;
91   ksba_stop_reason_t stopreason;
92   ksba_cert_t cert;
93   KEYDB_HANDLE kh;
94   gcry_md_hd_t data_md = NULL;
95   int signer;
96   const char *algoid;
97   int algo;
98   int is_detached;
99   FILE *fp = NULL;
100   char *p;
101
102   kh = keydb_new (0);
103   if (!kh)
104     {
105       log_error (_("failed to allocated keyDB handle\n"));
106       rc = gpg_error (GPG_ERR_GENERAL);
107       goto leave;
108     }
109
110
111   fp = fdopen ( dup (in_fd), "rb");
112   if (!fp)
113     {
114       rc = gpg_error (gpg_err_code_from_errno (errno));
115       log_error ("fdopen() failed: %s\n", strerror (errno));
116       goto leave;
117     }
118
119   rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
120   if (rc)
121     {
122       log_error ("can't create reader: %s\n", gpg_strerror (rc));
123       goto leave;
124     }
125
126   if (out_fp)
127     {
128       rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
129       if (rc)
130         {
131           log_error ("can't create writer: %s\n", gpg_strerror (rc));
132           goto leave;
133         }
134     }
135
136   rc = ksba_cms_new (&cms);
137   if (rc)
138     goto leave;
139
140   rc = ksba_cms_set_reader_writer (cms, reader, writer);
141   if (rc)
142     {
143       log_error ("ksba_cms_set_reader_writer failed: %s\n",
144                  gpg_strerror (rc));
145       goto leave;
146     }
147
148   rc = gcry_md_open (&data_md, 0, 0);
149   if (rc)
150     {
151       log_error ("md_open failed: %s\n", gpg_strerror (rc));
152       goto leave;
153     }
154   if (DBG_HASHING)
155     gcry_md_start_debug (data_md, "vrfy.data");
156
157   is_detached = 0;
158   do 
159     {
160       rc = ksba_cms_parse (cms, &stopreason);
161       if (rc)
162         {
163           log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
164           goto leave;
165         }
166
167       if (stopreason == KSBA_SR_NEED_HASH)
168         {
169           is_detached = 1;
170           if (opt.verbose)
171             log_info ("detached signature\n");
172         }
173
174       if (stopreason == KSBA_SR_NEED_HASH
175           || stopreason == KSBA_SR_BEGIN_DATA)
176         { /* We are now able to enable the hash algorithms */
177           for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
178             {
179               algo = gcry_md_map_name (algoid);
180               if (!algo)
181                 {
182                   log_error ("unknown hash algorithm `%s'\n",
183                              algoid? algoid:"?");
184                   if (algoid
185                       && (  !strcmp (algoid, "1.2.840.113549.1.1.2")
186                           ||!strcmp (algoid, "1.2.840.113549.2.2")))
187                     log_info (_("(this is the MD2 algorithm)\n"));
188                 }
189               else
190                 gcry_md_enable (data_md, algo);
191             }
192           if (is_detached)
193             {
194               if (data_fd == -1)
195                 log_info ("detached signature w/o data "
196                           "- assuming certs-only\n");
197               else
198                 hash_data (data_fd, data_md);  
199             }
200           else
201             {
202               ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
203             }
204         }
205       else if (stopreason == KSBA_SR_END_DATA)
206         { /* The data bas been hashed */
207
208         }
209     }
210   while (stopreason != KSBA_SR_READY);   
211
212   if (b64writer)
213     {
214       rc = gpgsm_finish_writer (b64writer);
215       if (rc) 
216         {
217           log_error ("write failed: %s\n", gpg_strerror (rc));
218           goto leave;
219         }
220     }
221
222   if (data_fd != -1 && !is_detached)
223     {
224       log_error ("data given for a non-detached signature\n");
225       rc = gpg_error (GPG_ERR_CONFLICT);
226       goto leave;
227     }
228
229   for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
230     {
231       /* Fixme: it might be better to check the validity of the
232          certificate first before entering it into the DB.  This way
233          we would avoid cluttering the DB with invalid
234          certificates. */
235       keydb_store_cert (cert, 0, NULL);
236       ksba_cert_release (cert);
237     }
238
239   cert = NULL;
240   for (signer=0; ; signer++)
241     {
242       char *issuer = NULL;
243       ksba_sexp_t sigval = NULL;
244       ksba_isotime_t sigtime, keyexptime;
245       ksba_sexp_t serial;
246       char *msgdigest = NULL;
247       size_t msgdigestlen;
248       char *ctattr;
249
250       rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
251       if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
252           && data_fd == -1 && is_detached)
253         {
254           log_info ("certs-only message accepted\n");
255           rc = 0;
256           break;
257         }
258       if (rc)
259         {
260           if (signer && rc == -1)
261             rc = 0;
262           break;
263         }
264
265       gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
266
267       if (DBG_X509)
268         {
269           log_debug ("signer %d - issuer: `%s'\n",
270                      signer, issuer? issuer:"[NONE]");
271           log_debug ("signer %d - serial: ", signer);
272           gpgsm_dump_serial (serial);
273           log_printf ("\n");
274         }
275
276       rc = ksba_cms_get_signing_time (cms, signer, sigtime);
277       if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
278         *sigtime = 0;
279       else if (rc)
280         {
281           log_error ("error getting signing time: %s\n", gpg_strerror (rc));
282           *sigtime = 0; /* (we can't encode an error in the time string.) */
283         }
284
285       rc = ksba_cms_get_message_digest (cms, signer,
286                                         &msgdigest, &msgdigestlen);
287       if (!rc)
288         {
289           size_t is_enabled;
290
291           algoid = ksba_cms_get_digest_algo (cms, signer);
292           algo = gcry_md_map_name (algoid);
293           if (DBG_X509)
294             log_debug ("signer %d - digest algo: %d\n", signer, algo);
295           is_enabled = sizeof algo;
296           if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
297                              &algo, &is_enabled)
298                || !is_enabled)
299             {
300               log_error ("digest algo %d has not been enabled\n", algo);
301               goto next_signer;
302             }
303         }
304       else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
305         {
306           assert (!msgdigest);
307           rc = 0;
308           algoid = NULL;
309           algo = 0; 
310         }
311       else /* real error */
312         break;
313
314       rc = ksba_cms_get_sigattr_oids (cms, signer,
315                                       "1.2.840.113549.1.9.3", &ctattr);
316       if (!rc) 
317         {
318           const char *s;
319
320           if (DBG_X509)
321             log_debug ("signer %d - content-type attribute: %s",
322                        signer, ctattr);
323
324           s = ksba_cms_get_content_oid (cms, 1);
325           if (!s || strcmp (ctattr, s))
326             {
327               log_error ("content-type attribute does not match "
328                          "actual content-type\n");
329               ksba_free (ctattr);
330               ctattr = NULL;
331               goto next_signer;
332             }
333           ksba_free (ctattr);
334           ctattr = NULL;
335         }
336       else if (rc != -1)
337         {
338           log_error ("error getting content-type attribute: %s\n",
339                      gpg_strerror (rc));
340           goto next_signer;
341         }
342       rc = 0;
343
344
345       sigval = ksba_cms_get_sig_val (cms, signer);
346       if (!sigval)
347         {
348           log_error ("no signature value available\n");
349           goto next_signer;
350         }
351       if (DBG_X509)
352         log_debug ("signer %d - signature available", signer);
353
354       /* Find the certificate of the signer */
355       keydb_search_reset (kh);
356       rc = keydb_search_issuer_sn (kh, issuer, serial);
357       if (rc)
358         {
359           if (rc == -1)
360             {
361               log_error ("certificate not found\n");
362               rc = gpg_error (GPG_ERR_NO_PUBKEY);
363             }
364           else
365             log_error ("failed to find the certificate: %s\n",
366                        gpg_strerror(rc));
367           {
368             char numbuf[50];
369             sprintf (numbuf, "%d", rc);
370
371             gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
372                            numbuf, NULL);
373           }
374           /* fixme: we might want to append the issuer and serial
375              using our standard notation */
376           goto next_signer;
377         }
378
379       rc = keydb_get_cert (kh, &cert);
380       if (rc)
381         {
382           log_error ("failed to get cert: %s\n", gpg_strerror (rc));
383           goto next_signer;
384         }
385
386       log_info (_("Signature made "));
387       if (*sigtime)
388         gpgsm_dump_time (sigtime);
389       else
390         log_printf (_("[date not given]"));
391       log_printf (_(" using certificate ID %08lX\n"),
392                   gpgsm_get_short_fingerprint (cert));
393
394
395       if (msgdigest)
396         { /* Signed attributes are available. */
397           gcry_md_hd_t md;
398           unsigned char *s;
399
400           /* check that the message digest in the signed attributes
401              matches the one we calculated on the data */
402           s = gcry_md_read (data_md, algo);
403           if ( !s || !msgdigestlen
404                || gcry_md_get_algo_dlen (algo) != msgdigestlen
405                || !s || memcmp (s, msgdigest, msgdigestlen) )
406             {
407               char *fpr;
408
409               log_error ("invalid signature: message digest attribute "
410                          "does not match calculated one\n");
411               fpr = gpgsm_fpr_and_name_for_status (cert);
412               gpgsm_status (ctrl, STATUS_BADSIG, fpr);
413               xfree (fpr);
414               goto next_signer; 
415             }
416             
417           rc = gcry_md_open (&md, algo, 0);
418           if (rc)
419             {
420               log_error ("md_open failed: %s\n", gpg_strerror (rc));
421               goto next_signer;
422             }
423           if (DBG_HASHING)
424             gcry_md_start_debug (md, "vrfy.attr");
425
426           ksba_cms_set_hash_function (cms, HASH_FNC, md);
427           rc = ksba_cms_hash_signed_attrs (cms, signer);
428           if (rc)
429             {
430               log_error ("hashing signed attrs failed: %s\n",
431                          gpg_strerror (rc));
432               gcry_md_close (md);
433               goto next_signer;
434             }
435           rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
436           gcry_md_close (md);
437         }
438       else
439         {
440           rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
441         }
442
443       if (rc)
444         {
445           char *fpr;
446
447           log_error ("invalid signature: %s\n", gpg_strerror (rc));
448           fpr = gpgsm_fpr_and_name_for_status (cert);
449           gpgsm_status (ctrl, STATUS_BADSIG, fpr);
450           xfree (fpr);
451           goto next_signer;
452         }
453       rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
454       if (rc)
455         {
456           gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
457                                       gpg_err_code (rc));
458           rc = 0;
459         }
460
461       if (DBG_X509)
462         log_debug ("signature okay - checking certs\n");
463       rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
464       {
465         char *fpr, *buf, *tstr;
466
467         fpr = gpgsm_fpr_and_name_for_status (cert);
468         if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
469           {
470             gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
471             rc = 0;
472           }
473         else
474           gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
475         
476         xfree (fpr);
477
478         fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
479         tstr = strtimestamp_r (sigtime);
480         buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
481         sprintf (buf, "%s %s %s %s", fpr, tstr,
482                  *sigtime? sigtime : "0",
483                  *keyexptime? keyexptime : "0" );
484         xfree (tstr);
485         xfree (fpr);
486         gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
487         xfree (buf);
488       }
489
490       if (rc) /* of validate_chain */
491         {
492           log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
493           if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
494               || gpg_err_code (rc) == GPG_ERR_BAD_CERT
495               || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
496               || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
497             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
498                                         gpg_err_code (rc));
499           else
500             gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, 
501                                         gpg_err_code (rc));
502           goto next_signer;
503         }
504
505       for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
506         {
507           log_info (!i? _("Good signature from")
508                       : _("                aka"));
509           log_printf (" \"");
510           gpgsm_print_name (log_get_stream (), p);
511           log_printf ("\"\n");
512           ksba_free (p);
513         }
514
515       gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
516           
517
518     next_signer:
519       rc = 0;
520       xfree (issuer);
521       xfree (serial);
522       xfree (sigval);
523       xfree (msgdigest);
524       ksba_cert_release (cert);
525       cert = NULL;
526     }
527   rc = 0;
528
529  leave:
530   ksba_cms_release (cms);
531   gpgsm_destroy_reader (b64reader);
532   gpgsm_destroy_writer (b64writer);
533   keydb_release (kh); 
534   gcry_md_close (data_md);
535   if (fp)
536     fclose (fp);
537
538   if (rc)
539     {
540       char numbuf[50];
541       sprintf (numbuf, "%d", rc );
542       gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
543                      numbuf, NULL);
544     }
545
546   return rc;
547 }
548