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,
39 strtimestamp_r (ksba_isotime_t atime
)
41 char *buffer
= xmalloc (15);
43 if (!atime
|| !*atime
)
44 strcpy (buffer
, "none");
46 sprintf (buffer
, "%.4s-%.2s-%.2s", atime
, atime
+4, atime
+6);
52 /* Hash the data for a detached signature */
54 hash_data (int fd
, gcry_md_hd_t md
)
60 fp
= fdopen ( dup (fd
), "rb");
63 log_error ("fdopen(%d) failed: %s\n", fd
, strerror (errno
));
69 nread
= fread (buffer
, 1, DIM(buffer
), fp
);
70 gcry_md_write (md
, buffer
, nread
);
74 log_error ("read error on fd %d: %s\n", fd
, strerror (errno
));
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. */
85 gpgsm_verify (ctrl_t ctrl
, int in_fd
, int data_fd
, FILE *out_fp
)
88 Base64Context b64reader
= NULL
;
89 Base64Context b64writer
= NULL
;
91 ksba_writer_t writer
= NULL
;
92 ksba_cms_t cms
= NULL
;
93 ksba_stop_reason_t stopreason
;
96 gcry_md_hd_t data_md
= NULL
;
107 log_error (_("failed to allocated keyDB handle\n"));
108 rc
= gpg_error (GPG_ERR_GENERAL
);
113 fp
= fdopen ( dup (in_fd
), "rb");
116 rc
= gpg_error (gpg_err_code_from_errno (errno
));
117 log_error ("fdopen() failed: %s\n", strerror (errno
));
121 rc
= gpgsm_create_reader (&b64reader
, ctrl
, fp
, 0, &reader
);
124 log_error ("can't create reader: %s\n", gpg_strerror (rc
));
130 rc
= gpgsm_create_writer (&b64writer
, ctrl
, out_fp
, &writer
);
133 log_error ("can't create writer: %s\n", gpg_strerror (rc
));
138 rc
= ksba_cms_new (&cms
);
142 rc
= ksba_cms_set_reader_writer (cms
, reader
, writer
);
145 log_error ("ksba_cms_set_reader_writer failed: %s\n",
150 rc
= gcry_md_open (&data_md
, 0, 0);
153 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
157 gcry_md_start_debug (data_md
, "vrfy.data");
162 rc
= ksba_cms_parse (cms
, &stopreason
);
165 log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc
));
169 if (stopreason
== KSBA_SR_NEED_HASH
)
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
);
184 log_error ("unknown hash algorithm `%s'\n",
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"));
192 gcry_md_enable (data_md
, algo
);
197 log_info ("detached signature w/o data "
198 "- assuming certs-only\n");
200 hash_data (data_fd
, data_md
);
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
);
216 rc
= gpgsm_finish_writer (b64writer
);
219 log_error ("write failed: %s\n", gpg_strerror (rc
));
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
);
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
237 keydb_store_cert (cert
, 0, NULL
);
238 ksba_cert_release (cert
);
242 for (signer
=0; ; signer
++)
245 ksba_sexp_t sigval
= NULL
;
246 ksba_isotime_t sigtime
, keyexptime
;
248 char *msgdigest
= NULL
;
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");
262 if (signer
&& rc
== -1)
267 gpgsm_status (ctrl
, STATUS_NEWSIG
, NULL
);
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
);
278 rc
= ksba_cms_get_signing_time (cms
, signer
, sigtime
);
279 if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
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
);
293 algoid
= ksba_cms_get_digest_algo (cms
, signer
);
294 algo
= gcry_md_map_name (algoid
);
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
,
302 log_error ("digest algo %d has not been enabled\n", algo
);
306 else if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
313 else /* real error */
316 rc
= ksba_cms_get_sigattr_oids (cms
, signer
,
317 "1.2.840.113549.1.9.3", &ctattr
);
323 log_debug ("signer %d - content-type attribute: %s",
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");
340 log_error ("error getting content-type attribute: %s\n",
347 sigval
= ksba_cms_get_sig_val (cms
, signer
);
350 log_error ("no signature value available\n");
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
);
363 log_error ("certificate not found\n");
364 rc
= gpg_error (GPG_ERR_NO_PUBKEY
);
367 log_error ("failed to find the certificate: %s\n",
371 sprintf (numbuf
, "%d", rc
);
373 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.findkey",
376 /* fixme: we might want to append the issuer and serial
377 using our standard notation */
381 rc
= keydb_get_cert (kh
, &cert
);
384 log_error ("failed to get cert: %s\n", gpg_strerror (rc
));
388 log_info (_("Signature made "));
390 gpgsm_dump_time (sigtime
);
392 log_printf (_("[date not given]"));
393 log_printf (_(" using certificate ID %08lX\n"),
394 gpgsm_get_short_fingerprint (cert
));
398 { /* Signed attributes are available. */
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
) )
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
);
419 rc
= gcry_md_open (&md
, algo
, 0);
422 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
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
);
432 log_error ("hashing signed attrs failed: %s\n",
437 rc
= gpgsm_check_cms_signature (cert
, sigval
, md
, algo
);
442 rc
= gpgsm_check_cms_signature (cert
, sigval
, data_md
, algo
);
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
);
455 rc
= gpgsm_cert_use_verify_p (cert
); /*(this displays an info message)*/
458 gpgsm_status_with_err_code (ctrl
, STATUS_ERROR
, "verify.keyusage",
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
);
476 gpgsm_status (ctrl
, STATUS_GOODSIG
, 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" );
488 gpgsm_status (ctrl
, STATUS_VALIDSIG
, 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
,
502 gpgsm_status_with_err_code (ctrl
, STATUS_TRUST_UNDEFINED
, NULL
,
507 for (i
=0; (p
= ksba_cert_get_subject (cert
, i
)); i
++)
509 log_info (!i
? _("Good signature from")
512 gpgsm_print_name (log_get_stream (), p
);
517 gpgsm_status (ctrl
, STATUS_TRUST_FULLY
, NULL
);
526 ksba_cert_release (cert
);
532 ksba_cms_release (cms
);
533 gpgsm_destroy_reader (b64reader
);
534 gpgsm_destroy_writer (b64writer
);
536 gcry_md_close (data_md
);
543 sprintf (numbuf
, "%d", rc
);
544 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.leave",