1 /* verify.c - Verify a messages signature
2 * Copyright (C) 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
37 /* fixme: Move this to jnlib */
39 strtimestamp (time_t atime)
41 char *buffer = xmalloc (15);
44 strcpy (buffer, "????" "-??" "-??");
46 strcpy (buffer, "none");
51 tp = gmtime( &atime );
52 sprintf (buffer, "%04d-%02d-%02d",
53 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday);
60 /* Hash the data for a detached signature */
62 hash_data (int fd, GCRY_MD_HD md)
68 fp = fdopen ( dup (fd), "rb");
71 log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
77 nread = fread (buffer, 1, DIM(buffer), fp);
78 gcry_md_write (md, buffer, nread);
82 log_error ("read error on fd %d: %s\n", fd, strerror (errno));
89 /* Perform a verify operation. To verify detached signatures, data_fd
90 must be different than -1. With OUT_FP given and a non-detached
91 signature, the signed material is written to that stream. */
93 gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
96 Base64Context b64reader = NULL;
97 Base64Context b64writer = NULL;
100 KsbaWriter writer = NULL;
102 KsbaStopReason stopreason;
105 GCRY_MD_HD data_md = NULL;
116 log_error (_("failed to allocated keyDB handle\n"));
117 rc = GNUPG_General_Error;
122 fp = fdopen ( dup (in_fd), "rb");
125 log_error ("fdopen() failed: %s\n", strerror (errno));
126 rc = seterr (IO_Error);
130 rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
133 log_error ("can't create reader: %s\n", gnupg_strerror (rc));
139 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
142 log_error ("can't create writer: %s\n", gnupg_strerror (rc));
147 cms = ksba_cms_new ();
150 rc = seterr (Out_Of_Core);
154 err = ksba_cms_set_reader_writer (cms, reader, writer);
157 log_error ("ksba_cms_set_reader_writer failed: %s\n",
158 ksba_strerror (err));
159 rc = map_ksba_err (err);
163 data_md = gcry_md_open (0, 0);
166 rc = map_gcry_err (gcry_errno());
167 log_error ("md_open failed: %s\n", gcry_strerror (-1));
171 gcry_md_start_debug (data_md, "vrfy.data");
176 err = ksba_cms_parse (cms, &stopreason);
179 log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
180 rc = map_ksba_err (err);
184 if (stopreason == KSBA_SR_NEED_HASH)
188 log_info ("detached signature\n");
191 if (stopreason == KSBA_SR_NEED_HASH
192 || stopreason == KSBA_SR_BEGIN_DATA)
193 { /* We are now able to enable the hash algorithms */
194 for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
196 algo = gcry_md_map_name (algoid);
198 log_error ("unknown hash algorithm `%s'\n",
201 gcry_md_enable (data_md, algo);
206 log_info ("detached signature w/o data "
207 "- assuming certs-only\n");
209 hash_data (data_fd, data_md);
213 ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
216 else if (stopreason == KSBA_SR_END_DATA)
217 { /* The data bas been hashed */
221 while (stopreason != KSBA_SR_READY);
225 rc = gpgsm_finish_writer (b64writer);
228 log_error ("write failed: %s\n", gnupg_strerror (rc));
233 if (data_fd != -1 && !is_detached)
235 log_error ("data given for a non-detached signature\n");
240 for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
242 /* Fixme: it might be better to check the validity of the
243 certificate first before entering it into the DB. This way
244 we would avoid cluttering the DB with invalid
246 keydb_store_cert (cert, 0, NULL);
247 ksba_cert_release (cert);
252 for (signer=0; ; signer++)
255 KsbaSexp sigval = NULL;
256 time_t sigtime, keyexptime;
258 char *msgdigest = NULL;
261 err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
262 if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached)
264 log_info ("certs-only message accepted\n");
270 if (signer && err == -1)
276 log_debug ("signer %d - issuer: `%s'\n",
277 signer, issuer? issuer:"[NONE]");
278 log_debug ("signer %d - serial: ", signer);
279 gpgsm_dump_serial (serial);
283 err = ksba_cms_get_signing_time (cms, signer, &sigtime);
286 log_error ("error getting signing time: %s\n", ksba_strerror (err));
287 sigtime = (time_t)-1;
292 err = ksba_cms_get_message_digest (cms, signer,
293 &msgdigest, &msgdigestlen);
297 algoid = ksba_cms_get_digest_algo (cms, signer);
298 algo = gcry_md_map_name (algoid);
300 log_debug ("signer %d - digest algo: %d\n", signer, algo);
301 if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) )
303 log_error ("digest algo %d has not been enabled\n", algo);
307 sigval = ksba_cms_get_sig_val (cms, signer);
310 log_error ("no signature value available\n");
314 log_debug ("signer %d - signature available", signer);
316 /* Find the certificate of the signer */
317 keydb_search_reset (kh);
318 rc = keydb_search_issuer_sn (kh, issuer, serial);
323 log_error ("certificate not found\n");
324 rc = GNUPG_No_Public_Key;
327 log_error ("failed to find the certificate: %s\n",
329 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
330 gnupg_error_token (rc), NULL);
331 /* fixme: we might want to append the issuer and serial
332 using our standard notation */
336 rc = keydb_get_cert (kh, &cert);
339 log_error ("failed to get cert: %s\n", gnupg_strerror (rc));
343 log_info (_("Signature made "));
345 gpgsm_dump_time (sigtime);
347 log_printf (_("[date not given]"));
348 log_printf (_(" using certificate ID %08lX\n"),
349 gpgsm_get_short_fingerprint (cert));
353 { /* Signed attributes are available. */
357 /* check that the message digest in the signed attributes
358 matches the one we calculated on the data */
359 s = gcry_md_read (data_md, algo);
360 if ( !s || !msgdigestlen
361 || gcry_md_get_algo_dlen (algo) != msgdigestlen
362 || !s || memcmp (s, msgdigest, msgdigestlen) )
366 log_error ("invalid signature: message digest attribute "
367 "does not match calculated one\n");
368 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
369 gpgsm_status (ctrl, STATUS_BADSIG, fpr);
374 md = gcry_md_open (algo, 0);
377 log_error ("md_open failed: %s\n", gcry_strerror (-1));
381 gcry_md_start_debug (md, "vrfy.attr");
383 ksba_cms_set_hash_function (cms, HASH_FNC, md);
384 rc = ksba_cms_hash_signed_attrs (cms, signer);
387 log_error ("hashing signed attrs failed: %s\n",
392 rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
397 rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
404 log_error ("invalid signature: %s\n", gnupg_strerror (rc));
405 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
406 gpgsm_status (ctrl, STATUS_BADSIG, fpr);
410 rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
413 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.keyusage",
414 gnupg_error_token (rc), NULL);
419 log_debug ("signature okay - checking certs\n");
420 rc = gpgsm_validate_chain (ctrl, cert, &keyexptime);
421 if (rc == GNUPG_Certificate_Expired)
423 gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);
427 gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
430 char *buf, *fpr, *tstr;
432 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
433 tstr = strtimestamp (sigtime);
434 buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
435 sprintf (buf, "%s %s %lu %lu", fpr, tstr,
436 (unsigned long)sigtime, (unsigned long)keyexptime );
439 gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
443 if (rc) /* of validate_chain */
445 log_error ("invalid certification chain: %s\n", gnupg_strerror (rc));
446 if (rc == GNUPG_Bad_Certificate_Path
447 || rc == GNUPG_Bad_Certificate
448 || rc == GNUPG_Bad_CA_Certificate
449 || rc == GNUPG_Certificate_Revoked)
450 gpgsm_status (ctrl, STATUS_TRUST_NEVER, gnupg_error_token (rc));
452 gpgsm_status (ctrl, STATUS_TRUST_UNDEFINED, gnupg_error_token (rc));
456 for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
458 log_info (!i? _("Good signature from")
461 gpgsm_print_name (log_get_stream (), p);
466 gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
475 ksba_cert_release (cert);
481 log_error ("ksba error: %s\n", ksba_strerror (err));
482 rc = map_ksba_err (rc);
488 ksba_cms_release (cms);
489 gpgsm_destroy_reader (b64reader);
490 gpgsm_destroy_writer (b64writer);
492 gcry_md_close (data_md);
497 gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
498 gnupg_error_token (rc), NULL);