2006-12-21 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / verify.c
bloba34b5b05c705b9728c189d4d42b841d38f4b9308
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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 * USA.
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <assert.h>
31 #include "gpgsm.h"
32 #include <gcrypt.h>
33 #include <ksba.h>
35 #include "keydb.h"
36 #include "i18n.h"
38 static char *
39 strtimestamp_r (ksba_isotime_t atime)
41 char *buffer = xmalloc (15);
43 if (!atime || !*atime)
44 strcpy (buffer, "none");
45 else
46 sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
47 return buffer;
52 /* Hash the data for a detached signature */
53 static void
54 hash_data (int fd, gcry_md_hd_t md)
56 FILE *fp;
57 char buffer[4096];
58 int nread;
60 fp = fdopen ( dup (fd), "rb");
61 if (!fp)
63 log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
64 return;
67 do
69 nread = fread (buffer, 1, DIM(buffer), fp);
70 gcry_md_write (md, buffer, nread);
72 while (nread);
73 if (ferror (fp))
74 log_error ("read error on fd %d: %s\n", fd, strerror (errno));
75 fclose (fp);
81 /* Perform a verify operation. To verify detached signatures, data_fd
82 must be different than -1. With OUT_FP given and a non-detached
83 signature, the signed material is written to that stream. */
84 int
85 gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
87 int i, rc;
88 Base64Context b64reader = NULL;
89 Base64Context b64writer = NULL;
90 ksba_reader_t reader;
91 ksba_writer_t writer = NULL;
92 ksba_cms_t cms = NULL;
93 ksba_stop_reason_t stopreason;
94 ksba_cert_t cert;
95 KEYDB_HANDLE kh;
96 gcry_md_hd_t data_md = NULL;
97 int signer;
98 const char *algoid;
99 int algo;
100 int is_detached;
101 FILE *fp = NULL;
102 char *p;
104 kh = keydb_new (0);
105 if (!kh)
107 log_error (_("failed to allocated keyDB handle\n"));
108 rc = gpg_error (GPG_ERR_GENERAL);
109 goto leave;
113 fp = fdopen ( dup (in_fd), "rb");
114 if (!fp)
116 rc = gpg_error (gpg_err_code_from_errno (errno));
117 log_error ("fdopen() failed: %s\n", strerror (errno));
118 goto leave;
121 rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
122 if (rc)
124 log_error ("can't create reader: %s\n", gpg_strerror (rc));
125 goto leave;
128 if (out_fp)
130 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
131 if (rc)
133 log_error ("can't create writer: %s\n", gpg_strerror (rc));
134 goto leave;
138 rc = ksba_cms_new (&cms);
139 if (rc)
140 goto leave;
142 rc = ksba_cms_set_reader_writer (cms, reader, writer);
143 if (rc)
145 log_error ("ksba_cms_set_reader_writer failed: %s\n",
146 gpg_strerror (rc));
147 goto leave;
150 rc = gcry_md_open (&data_md, 0, 0);
151 if (rc)
153 log_error ("md_open failed: %s\n", gpg_strerror (rc));
154 goto leave;
156 if (DBG_HASHING)
157 gcry_md_start_debug (data_md, "vrfy.data");
159 is_detached = 0;
162 rc = ksba_cms_parse (cms, &stopreason);
163 if (rc)
165 log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
166 goto leave;
169 if (stopreason == KSBA_SR_NEED_HASH)
171 is_detached = 1;
172 if (opt.verbose)
173 log_info ("detached signature\n");
176 if (stopreason == KSBA_SR_NEED_HASH
177 || stopreason == KSBA_SR_BEGIN_DATA)
178 { /* We are now able to enable the hash algorithms */
179 for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
181 algo = gcry_md_map_name (algoid);
182 if (!algo)
184 log_error ("unknown hash algorithm `%s'\n",
185 algoid? algoid:"?");
186 if (algoid
187 && ( !strcmp (algoid, "1.2.840.113549.1.1.2")
188 ||!strcmp (algoid, "1.2.840.113549.2.2")))
189 log_info (_("(this is the MD2 algorithm)\n"));
191 else
192 gcry_md_enable (data_md, algo);
194 if (is_detached)
196 if (data_fd == -1)
197 log_info ("detached signature w/o data "
198 "- assuming certs-only\n");
199 else
200 hash_data (data_fd, data_md);
202 else
204 ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
207 else if (stopreason == KSBA_SR_END_DATA)
208 { /* The data bas been hashed */
212 while (stopreason != KSBA_SR_READY);
214 if (b64writer)
216 rc = gpgsm_finish_writer (b64writer);
217 if (rc)
219 log_error ("write failed: %s\n", gpg_strerror (rc));
220 goto leave;
224 if (data_fd != -1 && !is_detached)
226 log_error ("data given for a non-detached signature\n");
227 rc = gpg_error (GPG_ERR_CONFLICT);
228 goto leave;
231 for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
233 /* Fixme: it might be better to check the validity of the
234 certificate first before entering it into the DB. This way
235 we would avoid cluttering the DB with invalid
236 certificates. */
237 keydb_store_cert (cert, 0, NULL);
238 ksba_cert_release (cert);
241 cert = NULL;
242 for (signer=0; ; signer++)
244 char *issuer = NULL;
245 ksba_sexp_t sigval = NULL;
246 ksba_isotime_t sigtime, keyexptime;
247 ksba_sexp_t serial;
248 char *msgdigest = NULL;
249 size_t msgdigestlen;
250 char *ctattr;
252 rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
253 if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
254 && data_fd == -1 && is_detached)
256 log_info ("certs-only message accepted\n");
257 rc = 0;
258 break;
260 if (rc)
262 if (signer && rc == -1)
263 rc = 0;
264 break;
267 gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
269 if (DBG_X509)
271 log_debug ("signer %d - issuer: `%s'\n",
272 signer, issuer? issuer:"[NONE]");
273 log_debug ("signer %d - serial: ", signer);
274 gpgsm_dump_serial (serial);
275 log_printf ("\n");
278 rc = ksba_cms_get_signing_time (cms, signer, sigtime);
279 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
280 *sigtime = 0;
281 else if (rc)
283 log_error ("error getting signing time: %s\n", gpg_strerror (rc));
284 *sigtime = 0; /* (we can't encode an error in the time string.) */
287 rc = ksba_cms_get_message_digest (cms, signer,
288 &msgdigest, &msgdigestlen);
289 if (!rc)
291 size_t is_enabled;
293 algoid = ksba_cms_get_digest_algo (cms, signer);
294 algo = gcry_md_map_name (algoid);
295 if (DBG_X509)
296 log_debug ("signer %d - digest algo: %d\n", signer, algo);
297 is_enabled = sizeof algo;
298 if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
299 &algo, &is_enabled)
300 || !is_enabled)
302 log_error ("digest algo %d has not been enabled\n", algo);
303 goto next_signer;
306 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
308 assert (!msgdigest);
309 rc = 0;
310 algoid = NULL;
311 algo = 0;
313 else /* real error */
314 break;
316 rc = ksba_cms_get_sigattr_oids (cms, signer,
317 "1.2.840.113549.1.9.3", &ctattr);
318 if (!rc)
320 const char *s;
322 if (DBG_X509)
323 log_debug ("signer %d - content-type attribute: %s",
324 signer, ctattr);
326 s = ksba_cms_get_content_oid (cms, 1);
327 if (!s || strcmp (ctattr, s))
329 log_error ("content-type attribute does not match "
330 "actual content-type\n");
331 ksba_free (ctattr);
332 ctattr = NULL;
333 goto next_signer;
335 ksba_free (ctattr);
336 ctattr = NULL;
338 else if (rc != -1)
340 log_error ("error getting content-type attribute: %s\n",
341 gpg_strerror (rc));
342 goto next_signer;
344 rc = 0;
347 sigval = ksba_cms_get_sig_val (cms, signer);
348 if (!sigval)
350 log_error ("no signature value available\n");
351 goto next_signer;
353 if (DBG_X509)
354 log_debug ("signer %d - signature available", signer);
356 /* Find the certificate of the signer */
357 keydb_search_reset (kh);
358 rc = keydb_search_issuer_sn (kh, issuer, serial);
359 if (rc)
361 if (rc == -1)
363 log_error ("certificate not found\n");
364 rc = gpg_error (GPG_ERR_NO_PUBKEY);
366 else
367 log_error ("failed to find the certificate: %s\n",
368 gpg_strerror(rc));
370 char numbuf[50];
371 sprintf (numbuf, "%d", rc);
373 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
374 numbuf, NULL);
376 /* fixme: we might want to append the issuer and serial
377 using our standard notation */
378 goto next_signer;
381 rc = keydb_get_cert (kh, &cert);
382 if (rc)
384 log_error ("failed to get cert: %s\n", gpg_strerror (rc));
385 goto next_signer;
388 log_info (_("Signature made "));
389 if (*sigtime)
390 gpgsm_dump_time (sigtime);
391 else
392 log_printf (_("[date not given]"));
393 log_printf (_(" using certificate ID %08lX\n"),
394 gpgsm_get_short_fingerprint (cert));
397 if (msgdigest)
398 { /* Signed attributes are available. */
399 gcry_md_hd_t md;
400 unsigned char *s;
402 /* check that the message digest in the signed attributes
403 matches the one we calculated on the data */
404 s = gcry_md_read (data_md, algo);
405 if ( !s || !msgdigestlen
406 || gcry_md_get_algo_dlen (algo) != msgdigestlen
407 || !s || memcmp (s, msgdigest, msgdigestlen) )
409 char *fpr;
411 log_error ("invalid signature: message digest attribute "
412 "does not match calculated one\n");
413 fpr = gpgsm_fpr_and_name_for_status (cert);
414 gpgsm_status (ctrl, STATUS_BADSIG, fpr);
415 xfree (fpr);
416 goto next_signer;
419 rc = gcry_md_open (&md, algo, 0);
420 if (rc)
422 log_error ("md_open failed: %s\n", gpg_strerror (rc));
423 goto next_signer;
425 if (DBG_HASHING)
426 gcry_md_start_debug (md, "vrfy.attr");
428 ksba_cms_set_hash_function (cms, HASH_FNC, md);
429 rc = ksba_cms_hash_signed_attrs (cms, signer);
430 if (rc)
432 log_error ("hashing signed attrs failed: %s\n",
433 gpg_strerror (rc));
434 gcry_md_close (md);
435 goto next_signer;
437 rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
438 gcry_md_close (md);
440 else
442 rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
445 if (rc)
447 char *fpr;
449 log_error ("invalid signature: %s\n", gpg_strerror (rc));
450 fpr = gpgsm_fpr_and_name_for_status (cert);
451 gpgsm_status (ctrl, STATUS_BADSIG, fpr);
452 xfree (fpr);
453 goto next_signer;
455 rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
456 if (rc)
458 gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
459 gpg_err_code (rc));
460 rc = 0;
463 if (DBG_X509)
464 log_debug ("signature okay - checking certs\n");
465 rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
467 char *fpr, *buf, *tstr;
469 fpr = gpgsm_fpr_and_name_for_status (cert);
470 if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
472 gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
473 rc = 0;
475 else
476 gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
478 xfree (fpr);
480 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
481 tstr = strtimestamp_r (sigtime);
482 buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
483 sprintf (buf, "%s %s %s %s", fpr, tstr,
484 *sigtime? sigtime : "0",
485 *keyexptime? keyexptime : "0" );
486 xfree (tstr);
487 xfree (fpr);
488 gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
489 xfree (buf);
492 if (rc) /* of validate_chain */
494 log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
495 if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
496 || gpg_err_code (rc) == GPG_ERR_BAD_CERT
497 || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
498 || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
499 gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
500 gpg_err_code (rc));
501 else
502 gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL,
503 gpg_err_code (rc));
504 goto next_signer;
507 for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
509 log_info (!i? _("Good signature from")
510 : _(" aka"));
511 log_printf (" \"");
512 gpgsm_print_name (log_get_stream (), p);
513 log_printf ("\"\n");
514 ksba_free (p);
517 gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
520 next_signer:
521 rc = 0;
522 xfree (issuer);
523 xfree (serial);
524 xfree (sigval);
525 xfree (msgdigest);
526 ksba_cert_release (cert);
527 cert = NULL;
529 rc = 0;
531 leave:
532 ksba_cms_release (cms);
533 gpgsm_destroy_reader (b64reader);
534 gpgsm_destroy_writer (b64writer);
535 keydb_release (kh);
536 gcry_md_close (data_md);
537 if (fp)
538 fclose (fp);
540 if (rc)
542 char numbuf[50];
543 sprintf (numbuf, "%d", rc );
544 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
545 numbuf, NULL);
548 return rc;