1 /* verify.c - Verify a messages signature
2 * Copyright (C) 2001 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;
115 log_error (_("failed to allocated keyDB handle\n"));
116 rc = GNUPG_General_Error;
121 fp = fdopen ( dup (in_fd), "rb");
124 log_error ("fdopen() failed: %s\n", strerror (errno));
125 rc = seterr (IO_Error);
129 rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
132 log_error ("can't create reader: %s\n", gnupg_strerror (rc));
138 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
141 log_error ("can't create writer: %s\n", gnupg_strerror (rc));
146 cms = ksba_cms_new ();
149 rc = seterr (Out_Of_Core);
153 err = ksba_cms_set_reader_writer (cms, reader, writer);
156 log_debug ("ksba_cms_set_reader_writer failed: %s\n",
157 ksba_strerror (err));
158 rc = map_ksba_err (err);
162 data_md = gcry_md_open (0, 0);
165 rc = map_gcry_err (gcry_errno());
166 log_error ("md_open failed: %s\n", gcry_strerror (-1));
170 gcry_md_start_debug (data_md, "vrfy.data");
175 err = ksba_cms_parse (cms, &stopreason);
178 log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
179 rc = map_ksba_err (err);
183 if (stopreason == KSBA_SR_NEED_HASH)
186 log_debug ("Detached signature\n");
189 if (stopreason == KSBA_SR_NEED_HASH
190 || stopreason == KSBA_SR_BEGIN_DATA)
191 { /* We are now able to enable the hash algorithms */
192 for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
194 algo = gcry_md_map_name (algoid);
196 log_error ("unknown hash algorithm `%s'\n",
199 gcry_md_enable (data_md, algo);
205 log_error ("detached signature but no data given\n");
206 rc = GNUPG_Bad_Signature;
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);
247 ksba_cert_release (cert);
252 for (signer=0; signer < 1; signer++)
255 KsbaSexp sigval = NULL;
258 char *msgdigest = NULL;
261 err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
264 log_debug ("signer %d - issuer: `%s'\n", signer, issuer? issuer:"[NONE]");
265 log_debug ("signer %d - serial: ", signer);
266 gpgsm_dump_serial (serial);
269 err = ksba_cms_get_signing_time (cms, signer, &sigtime);
272 log_debug ("error getting signing time: %s\n", ksba_strerror (err));
273 sigtime = (time_t)-1;
275 log_debug ("signer %d - sigtime: ", signer);
276 gpgsm_dump_time (sigtime);
280 err = ksba_cms_get_message_digest (cms, signer,
281 &msgdigest, &msgdigestlen);
285 algoid = ksba_cms_get_digest_algo (cms, signer);
286 algo = gcry_md_map_name (algoid);
287 log_debug ("signer %d - digest algo: %d\n", signer, algo);
288 if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) )
290 log_debug ("digest algo %d has not been enabled\n", algo);
294 sigval = ksba_cms_get_sig_val (cms, signer);
297 log_error ("no signature value available\n");
300 log_debug ("signer %d - signature available", signer);
302 /* Find the certificate of the signer */
303 keydb_search_reset (kh);
304 rc = keydb_search_issuer_sn (kh, issuer, serial);
307 log_debug ("failed to find the certificate: %s\n",
312 rc = keydb_get_cert (kh, &cert);
315 log_debug ("failed to get cert: %s\n", gnupg_strerror (rc));
320 { /* Signed attributes are available. */
324 /* check that the message digest in the signed attributes
325 matches the one we calculated on the data */
326 s = gcry_md_read (data_md, algo);
327 if ( !s || !msgdigestlen
328 || gcry_md_get_algo_dlen (algo) != msgdigestlen
329 || !s || memcmp (s, msgdigest, msgdigestlen) )
331 log_error ("invalid signature: message digest attribute "
332 "does not match calculated one\n");
333 gpgsm_status (ctrl, STATUS_BADSIG, NULL);
337 md = gcry_md_open (algo, 0);
340 log_error ("md_open failed: %s\n", gcry_strerror (-1));
344 gcry_md_start_debug (md, "vrfy.attr");
346 ksba_cms_set_hash_function (cms, HASH_FNC, md);
347 rc = ksba_cms_hash_signed_attrs (cms, signer);
350 log_debug ("hashing signed attrs failed: %s\n",
355 rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
360 rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
365 log_error ("invalid signature: %s\n", gnupg_strerror (rc));
366 gpgsm_status (ctrl, STATUS_BADSIG, NULL);
369 log_debug ("signature okay - checking certs\n");
370 gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
372 char *buf, *fpr, *tstr;
374 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
375 tstr = strtimestamp (sigtime);
376 buf = xmalloc ( strlen(fpr) + strlen (tstr) + 100);
377 sprintf (buf, "%s %s %lu", fpr, tstr, (unsigned long)sigtime );
380 gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
384 rc = gpgsm_validate_path (cert);
387 log_error ("invalid certification path: %s\n", gnupg_strerror (rc));
388 if (rc == GNUPG_Bad_Certificate_Path
389 || rc == GNUPG_Bad_Certificate)
390 gpgsm_status (ctrl, STATUS_TRUST_NEVER, NULL);
392 gpgsm_status (ctrl, STATUS_TRUST_UNDEFINED, NULL);
395 log_info ("signature is good\n");
396 gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
405 ksba_cert_release (cert);
411 log_debug ("ksba error: %s\n", ksba_strerror (err));
412 rc = map_ksba_err (rc);
418 ksba_cms_release (cms);
419 gpgsm_destroy_reader (b64reader);
420 gpgsm_destroy_writer (b64writer);
422 gcry_md_close (data_md);