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