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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
38 strtimestamp_r (ksba_isotime_t atime
)
40 char *buffer
= xmalloc (15);
42 if (!atime
|| !*atime
)
43 strcpy (buffer
, "none");
45 sprintf (buffer
, "%.4s-%.2s-%.2s", atime
, atime
+4, atime
+6);
51 /* Hash the data for a detached signature */
53 hash_data (int fd
, gcry_md_hd_t md
)
59 fp
= fdopen ( dup (fd
), "rb");
62 log_error ("fdopen(%d) failed: %s\n", fd
, strerror (errno
));
68 nread
= fread (buffer
, 1, DIM(buffer
), fp
);
69 gcry_md_write (md
, buffer
, nread
);
73 log_error ("read error on fd %d: %s\n", fd
, strerror (errno
));
80 /* Perform a verify operation. To verify detached signatures, data_fd
81 must be different than -1. With OUT_FP given and a non-detached
82 signature, the signed material is written to that stream. */
84 gpgsm_verify (CTRL ctrl
, int in_fd
, int data_fd
, FILE *out_fp
)
87 Base64Context b64reader
= NULL
;
88 Base64Context b64writer
= NULL
;
90 ksba_writer_t writer
= NULL
;
91 ksba_cms_t cms
= NULL
;
92 ksba_stop_reason_t stopreason
;
95 gcry_md_hd_t data_md
= NULL
;
106 log_error (_("failed to allocated keyDB handle\n"));
107 rc
= gpg_error (GPG_ERR_GENERAL
);
112 fp
= fdopen ( dup (in_fd
), "rb");
115 rc
= gpg_error (gpg_err_code_from_errno (errno
));
116 log_error ("fdopen() failed: %s\n", strerror (errno
));
120 rc
= gpgsm_create_reader (&b64reader
, ctrl
, fp
, 0, &reader
);
123 log_error ("can't create reader: %s\n", gpg_strerror (rc
));
129 rc
= gpgsm_create_writer (&b64writer
, ctrl
, out_fp
, &writer
);
132 log_error ("can't create writer: %s\n", gpg_strerror (rc
));
137 rc
= ksba_cms_new (&cms
);
141 rc
= ksba_cms_set_reader_writer (cms
, reader
, writer
);
144 log_error ("ksba_cms_set_reader_writer failed: %s\n",
149 rc
= gcry_md_open (&data_md
, 0, 0);
152 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
156 gcry_md_start_debug (data_md
, "vrfy.data");
161 rc
= ksba_cms_parse (cms
, &stopreason
);
164 log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc
));
168 if (stopreason
== KSBA_SR_NEED_HASH
)
172 log_info ("detached signature\n");
175 if (stopreason
== KSBA_SR_NEED_HASH
176 || stopreason
== KSBA_SR_BEGIN_DATA
)
177 { /* We are now able to enable the hash algorithms */
178 for (i
=0; (algoid
=ksba_cms_get_digest_algo_list (cms
, i
)); i
++)
180 algo
= gcry_md_map_name (algoid
);
182 log_error ("unknown hash algorithm `%s'\n",
185 gcry_md_enable (data_md
, algo
);
190 log_info ("detached signature w/o data "
191 "- assuming certs-only\n");
193 hash_data (data_fd
, data_md
);
197 ksba_cms_set_hash_function (cms
, HASH_FNC
, data_md
);
200 else if (stopreason
== KSBA_SR_END_DATA
)
201 { /* The data bas been hashed */
205 while (stopreason
!= KSBA_SR_READY
);
209 rc
= gpgsm_finish_writer (b64writer
);
212 log_error ("write failed: %s\n", gpg_strerror (rc
));
217 if (data_fd
!= -1 && !is_detached
)
219 log_error ("data given for a non-detached signature\n");
220 rc
= gpg_error (GPG_ERR_CONFLICT
);
224 for (i
=0; (cert
=ksba_cms_get_cert (cms
, i
)); i
++)
226 /* Fixme: it might be better to check the validity of the
227 certificate first before entering it into the DB. This way
228 we would avoid cluttering the DB with invalid
230 keydb_store_cert (cert
, 0, NULL
);
231 ksba_cert_release (cert
);
235 for (signer
=0; ; signer
++)
238 ksba_sexp_t sigval
= NULL
;
239 ksba_isotime_t sigtime
, keyexptime
;
241 char *msgdigest
= NULL
;
245 rc
= ksba_cms_get_issuer_serial (cms
, signer
, &issuer
, &serial
);
246 if (!signer
&& gpg_err_code (rc
) == GPG_ERR_NO_DATA
247 && data_fd
== -1 && is_detached
)
249 log_info ("certs-only message accepted\n");
255 if (signer
&& rc
== -1)
260 gpgsm_status (ctrl
, STATUS_NEWSIG
, NULL
);
264 log_debug ("signer %d - issuer: `%s'\n",
265 signer
, issuer
? issuer
:"[NONE]");
266 log_debug ("signer %d - serial: ", signer
);
267 gpgsm_dump_serial (serial
);
271 rc
= ksba_cms_get_signing_time (cms
, signer
, sigtime
);
272 if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
276 log_error ("error getting signing time: %s\n", gpg_strerror (rc
));
277 *sigtime
= 0; /* (we can't encode an error in the time string.) */
280 rc
= ksba_cms_get_message_digest (cms
, signer
,
281 &msgdigest
, &msgdigestlen
);
286 algoid
= ksba_cms_get_digest_algo (cms
, signer
);
287 algo
= gcry_md_map_name (algoid
);
289 log_debug ("signer %d - digest algo: %d\n", signer
, algo
);
290 is_enabled
= sizeof algo
;
291 if ( gcry_md_info (data_md
, GCRYCTL_IS_ALGO_ENABLED
,
295 log_error ("digest algo %d has not been enabled\n", algo
);
299 else if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
306 else /* real error */
309 rc
= ksba_cms_get_sigattr_oids (cms
, signer
,
310 "1.2.840.113549.1.9.3", &ctattr
);
316 log_debug ("signer %d - content-type attribute: %s",
319 s
= ksba_cms_get_content_oid (cms
, 1);
320 if (!s
|| strcmp (ctattr
, s
))
322 log_error ("content-type attribute does not match "
323 "actual content-type\n");
333 log_error ("error getting content-type attribute: %s\n",
340 sigval
= ksba_cms_get_sig_val (cms
, signer
);
343 log_error ("no signature value available\n");
347 log_debug ("signer %d - signature available", signer
);
349 /* Find the certificate of the signer */
350 keydb_search_reset (kh
);
351 rc
= keydb_search_issuer_sn (kh
, issuer
, serial
);
356 log_error ("certificate not found\n");
357 rc
= gpg_error (GPG_ERR_NO_PUBKEY
);
360 log_error ("failed to find the certificate: %s\n",
364 sprintf (numbuf
, "%d", rc
);
366 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.findkey",
369 /* fixme: we might want to append the issuer and serial
370 using our standard notation */
374 rc
= keydb_get_cert (kh
, &cert
);
377 log_error ("failed to get cert: %s\n", gpg_strerror (rc
));
381 log_info (_("Signature made "));
383 gpgsm_dump_time (sigtime
);
385 log_printf (_("[date not given]"));
386 log_printf (_(" using certificate ID %08lX\n"),
387 gpgsm_get_short_fingerprint (cert
));
391 { /* Signed attributes are available. */
395 /* check that the message digest in the signed attributes
396 matches the one we calculated on the data */
397 s
= gcry_md_read (data_md
, algo
);
398 if ( !s
|| !msgdigestlen
399 || gcry_md_get_algo_dlen (algo
) != msgdigestlen
400 || !s
|| memcmp (s
, msgdigest
, msgdigestlen
) )
404 log_error ("invalid signature: message digest attribute "
405 "does not match calculated one\n");
406 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
407 gpgsm_status (ctrl
, STATUS_BADSIG
, fpr
);
412 rc
= gcry_md_open (&md
, algo
, 0);
415 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
419 gcry_md_start_debug (md
, "vrfy.attr");
421 ksba_cms_set_hash_function (cms
, HASH_FNC
, md
);
422 rc
= ksba_cms_hash_signed_attrs (cms
, signer
);
425 log_error ("hashing signed attrs failed: %s\n",
430 rc
= gpgsm_check_cms_signature (cert
, sigval
, md
, algo
);
435 rc
= gpgsm_check_cms_signature (cert
, sigval
, data_md
, algo
);
442 log_error ("invalid signature: %s\n", gpg_strerror (rc
));
443 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
444 gpgsm_status (ctrl
, STATUS_BADSIG
, fpr
);
448 rc
= gpgsm_cert_use_verify_p (cert
); /*(this displays an info message)*/
451 gpgsm_status_with_err_code (ctrl
, STATUS_ERROR
, "verify.keyusage",
457 log_debug ("signature okay - checking certs\n");
458 rc
= gpgsm_validate_chain (ctrl
, cert
, keyexptime
, 0, NULL
, 0);
459 if (gpg_err_code (rc
) == GPG_ERR_CERT_EXPIRED
)
461 gpgsm_status (ctrl
, STATUS_EXPKEYSIG
, NULL
);
465 gpgsm_status (ctrl
, STATUS_GOODSIG
, NULL
);
468 char *buf
, *fpr
, *tstr
;
470 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
471 tstr
= strtimestamp_r (sigtime
);
472 buf
= xmalloc ( strlen(fpr
) + strlen (tstr
) + 120);
473 sprintf (buf
, "%s %s %s %s", fpr
, tstr
,
474 *sigtime
? sigtime
: "0",
475 *keyexptime
? keyexptime
: "0" );
478 gpgsm_status (ctrl
, STATUS_VALIDSIG
, buf
);
482 if (rc
) /* of validate_chain */
484 log_error ("invalid certification chain: %s\n", gpg_strerror (rc
));
485 if (gpg_err_code (rc
) == GPG_ERR_BAD_CERT_CHAIN
486 || gpg_err_code (rc
) == GPG_ERR_BAD_CERT
487 || gpg_err_code (rc
) == GPG_ERR_BAD_CA_CERT
488 || gpg_err_code (rc
) == GPG_ERR_CERT_REVOKED
)
489 gpgsm_status_with_err_code (ctrl
, STATUS_TRUST_NEVER
, NULL
,
492 gpgsm_status_with_err_code (ctrl
, STATUS_TRUST_UNDEFINED
, NULL
,
497 for (i
=0; (p
= ksba_cert_get_subject (cert
, i
)); i
++)
499 log_info (!i
? _("Good signature from")
502 gpgsm_print_name (log_get_stream (), p
);
507 gpgsm_status (ctrl
, STATUS_TRUST_FULLY
, NULL
);
516 ksba_cert_release (cert
);
522 ksba_cms_release (cms
);
523 gpgsm_destroy_reader (b64reader
);
524 gpgsm_destroy_writer (b64writer
);
526 gcry_md_close (data_md
);
533 sprintf (numbuf
, "%d", rc
);
534 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.leave",