2007-07-05 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / verify.c
blobe445688728011e75d7baf908508c7e84b459ee52
1 /* verify.c - Verify a messages signature
2 * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
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>
29 #include "gpgsm.h"
30 #include <gcrypt.h>
31 #include <ksba.h>
33 #include "keydb.h"
34 #include "i18n.h"
36 static char *
37 strtimestamp_r (ksba_isotime_t atime)
39 char *buffer = xmalloc (15);
41 if (!atime || !*atime)
42 strcpy (buffer, "none");
43 else
44 sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
45 return buffer;
50 /* Hash the data for a detached signature */
51 static void
52 hash_data (int fd, gcry_md_hd_t md)
54 FILE *fp;
55 char buffer[4096];
56 int nread;
58 fp = fdopen ( dup (fd), "rb");
59 if (!fp)
61 log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
62 return;
65 do
67 nread = fread (buffer, 1, DIM(buffer), fp);
68 gcry_md_write (md, buffer, nread);
70 while (nread);
71 if (ferror (fp))
72 log_error ("read error on fd %d: %s\n", fd, strerror (errno));
73 fclose (fp);
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)
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;
102 kh = keydb_new (0);
103 if (!kh)
105 log_error (_("failed to allocated keyDB handle\n"));
106 rc = gpg_error (GPG_ERR_GENERAL);
107 goto leave;
111 fp = fdopen ( dup (in_fd), "rb");
112 if (!fp)
114 rc = gpg_error (gpg_err_code_from_errno (errno));
115 log_error ("fdopen() failed: %s\n", strerror (errno));
116 goto leave;
119 rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
120 if (rc)
122 log_error ("can't create reader: %s\n", gpg_strerror (rc));
123 goto leave;
126 if (out_fp)
128 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
129 if (rc)
131 log_error ("can't create writer: %s\n", gpg_strerror (rc));
132 goto leave;
136 rc = ksba_cms_new (&cms);
137 if (rc)
138 goto leave;
140 rc = ksba_cms_set_reader_writer (cms, reader, writer);
141 if (rc)
143 log_error ("ksba_cms_set_reader_writer failed: %s\n",
144 gpg_strerror (rc));
145 goto leave;
148 rc = gcry_md_open (&data_md, 0, 0);
149 if (rc)
151 log_error ("md_open failed: %s\n", gpg_strerror (rc));
152 goto leave;
154 if (DBG_HASHING)
155 gcry_md_start_debug (data_md, "vrfy.data");
157 is_detached = 0;
160 rc = ksba_cms_parse (cms, &stopreason);
161 if (rc)
163 log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
164 goto leave;
167 if (stopreason == KSBA_SR_NEED_HASH)
169 is_detached = 1;
170 if (opt.verbose)
171 log_info ("detached signature\n");
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++)
179 algo = gcry_md_map_name (algoid);
180 if (!algo)
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"));
189 else
190 gcry_md_enable (data_md, algo);
192 if (is_detached)
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);
200 else
202 ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
205 else if (stopreason == KSBA_SR_END_DATA)
206 { /* The data bas been hashed */
210 while (stopreason != KSBA_SR_READY);
212 if (b64writer)
214 rc = gpgsm_finish_writer (b64writer);
215 if (rc)
217 log_error ("write failed: %s\n", gpg_strerror (rc));
218 goto leave;
222 if (data_fd != -1 && !is_detached)
224 log_error ("data given for a non-detached signature\n");
225 rc = gpg_error (GPG_ERR_CONFLICT);
226 goto leave;
229 for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
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);
239 cert = NULL;
240 for (signer=0; ; signer++)
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;
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)
254 log_info ("certs-only message accepted\n");
255 rc = 0;
256 break;
258 if (rc)
260 if (signer && rc == -1)
261 rc = 0;
262 break;
265 gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
267 if (DBG_X509)
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");
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)
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.) */
285 rc = ksba_cms_get_message_digest (cms, signer,
286 &msgdigest, &msgdigestlen);
287 if (!rc)
289 size_t is_enabled;
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)
300 log_error ("digest algo %d has not been enabled\n", algo);
301 goto next_signer;
304 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
306 assert (!msgdigest);
307 rc = 0;
308 algoid = NULL;
309 algo = 0;
311 else /* real error */
312 break;
314 rc = ksba_cms_get_sigattr_oids (cms, signer,
315 "1.2.840.113549.1.9.3", &ctattr);
316 if (!rc)
318 const char *s;
320 if (DBG_X509)
321 log_debug ("signer %d - content-type attribute: %s",
322 signer, ctattr);
324 s = ksba_cms_get_content_oid (cms, 1);
325 if (!s || strcmp (ctattr, s))
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;
333 ksba_free (ctattr);
334 ctattr = NULL;
336 else if (rc != -1)
338 log_error ("error getting content-type attribute: %s\n",
339 gpg_strerror (rc));
340 goto next_signer;
342 rc = 0;
345 sigval = ksba_cms_get_sig_val (cms, signer);
346 if (!sigval)
348 log_error ("no signature value available\n");
349 goto next_signer;
351 if (DBG_X509)
352 log_debug ("signer %d - signature available", signer);
354 /* Find the certificate of the signer */
355 keydb_search_reset (kh);
356 rc = keydb_search_issuer_sn (kh, issuer, serial);
357 if (rc)
359 if (rc == -1)
361 log_error ("certificate not found\n");
362 rc = gpg_error (GPG_ERR_NO_PUBKEY);
364 else
365 log_error ("failed to find the certificate: %s\n",
366 gpg_strerror(rc));
368 char numbuf[50];
369 sprintf (numbuf, "%d", rc);
371 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
372 numbuf, NULL);
374 /* fixme: we might want to append the issuer and serial
375 using our standard notation */
376 goto next_signer;
379 rc = keydb_get_cert (kh, &cert);
380 if (rc)
382 log_error ("failed to get cert: %s\n", gpg_strerror (rc));
383 goto next_signer;
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));
395 if (msgdigest)
396 { /* Signed attributes are available. */
397 gcry_md_hd_t md;
398 unsigned char *s;
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) )
407 char *fpr;
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;
417 rc = gcry_md_open (&md, algo, 0);
418 if (rc)
420 log_error ("md_open failed: %s\n", gpg_strerror (rc));
421 goto next_signer;
423 if (DBG_HASHING)
424 gcry_md_start_debug (md, "vrfy.attr");
426 ksba_cms_set_hash_function (cms, HASH_FNC, md);
427 rc = ksba_cms_hash_signed_attrs (cms, signer);
428 if (rc)
430 log_error ("hashing signed attrs failed: %s\n",
431 gpg_strerror (rc));
432 gcry_md_close (md);
433 goto next_signer;
435 rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
436 gcry_md_close (md);
438 else
440 rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
443 if (rc)
445 char *fpr;
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;
453 rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
454 if (rc)
456 gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
457 gpg_err_code (rc));
458 rc = 0;
461 if (DBG_X509)
462 log_debug ("signature okay - checking certs\n");
463 rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
465 char *fpr, *buf, *tstr;
467 fpr = gpgsm_fpr_and_name_for_status (cert);
468 if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
470 gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
471 rc = 0;
473 else
474 gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
476 xfree (fpr);
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);
490 if (rc) /* of validate_chain */
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;
505 for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
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);
515 gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
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;
527 rc = 0;
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);
538 if (rc)
540 char numbuf[50];
541 sprintf (numbuf, "%d", rc );
542 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
543 numbuf, NULL);
546 return rc;