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 3 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, see <http://www.gnu.org/licenses/>.
37 strtimestamp_r (ksba_isotime_t atime
)
39 char *buffer
= xmalloc (15);
41 if (!atime
|| !*atime
)
42 strcpy (buffer
, "none");
44 sprintf (buffer
, "%.4s-%.2s-%.2s", atime
, atime
+4, atime
+6);
50 /* Hash the data for a detached signature */
52 hash_data (int fd
, gcry_md_hd_t md
)
58 fp
= fdopen ( dup (fd
), "rb");
61 log_error ("fdopen(%d) failed: %s\n", fd
, strerror (errno
));
67 nread
= fread (buffer
, 1, DIM(buffer
), fp
);
68 gcry_md_write (md
, buffer
, nread
);
72 log_error ("read error on fd %d: %s\n", fd
, strerror (errno
));
79 /* Perform a verify operation. To verify detached signatures, data_fd
80 must be different than -1. With OUT_FP given and a non-detached
81 signature, the signed material is written to that stream. */
83 gpgsm_verify (ctrl_t ctrl
, int in_fd
, int data_fd
, FILE *out_fp
)
86 Base64Context b64reader
= NULL
;
87 Base64Context b64writer
= NULL
;
89 ksba_writer_t writer
= NULL
;
90 ksba_cms_t cms
= NULL
;
91 ksba_stop_reason_t stopreason
;
94 gcry_md_hd_t data_md
= NULL
;
105 log_error (_("failed to allocated keyDB handle\n"));
106 rc
= gpg_error (GPG_ERR_GENERAL
);
111 fp
= fdopen ( dup (in_fd
), "rb");
114 rc
= gpg_error (gpg_err_code_from_errno (errno
));
115 log_error ("fdopen() failed: %s\n", strerror (errno
));
119 rc
= gpgsm_create_reader (&b64reader
, ctrl
, fp
, 0, &reader
);
122 log_error ("can't create reader: %s\n", gpg_strerror (rc
));
128 rc
= gpgsm_create_writer (&b64writer
, ctrl
, out_fp
, NULL
, &writer
);
131 log_error ("can't create writer: %s\n", gpg_strerror (rc
));
136 rc
= ksba_cms_new (&cms
);
140 rc
= ksba_cms_set_reader_writer (cms
, reader
, writer
);
143 log_error ("ksba_cms_set_reader_writer failed: %s\n",
148 rc
= gcry_md_open (&data_md
, 0, 0);
151 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
155 gcry_md_start_debug (data_md
, "vrfy.data");
160 rc
= ksba_cms_parse (cms
, &stopreason
);
163 log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc
));
167 if (stopreason
== KSBA_SR_NEED_HASH
)
171 log_info ("detached signature\n");
174 if (stopreason
== KSBA_SR_NEED_HASH
175 || stopreason
== KSBA_SR_BEGIN_DATA
)
176 { /* We are now able to enable the hash algorithms */
177 for (i
=0; (algoid
=ksba_cms_get_digest_algo_list (cms
, i
)); i
++)
179 algo
= gcry_md_map_name (algoid
);
182 log_error ("unknown hash algorithm `%s'\n",
185 && ( !strcmp (algoid
, "1.2.840.113549.1.1.2")
186 ||!strcmp (algoid
, "1.2.840.113549.2.2")))
187 log_info (_("(this is the MD2 algorithm)\n"));
190 gcry_md_enable (data_md
, algo
);
195 log_info ("detached signature w/o data "
196 "- assuming certs-only\n");
198 hash_data (data_fd
, data_md
);
202 ksba_cms_set_hash_function (cms
, HASH_FNC
, data_md
);
205 else if (stopreason
== KSBA_SR_END_DATA
)
206 { /* The data bas been hashed */
210 while (stopreason
!= KSBA_SR_READY
);
214 rc
= gpgsm_finish_writer (b64writer
);
217 log_error ("write failed: %s\n", gpg_strerror (rc
));
222 if (data_fd
!= -1 && !is_detached
)
224 log_error ("data given for a non-detached signature\n");
225 rc
= gpg_error (GPG_ERR_CONFLICT
);
229 for (i
=0; (cert
=ksba_cms_get_cert (cms
, i
)); i
++)
231 /* Fixme: it might be better to check the validity of the
232 certificate first before entering it into the DB. This way
233 we would avoid cluttering the DB with invalid
235 keydb_store_cert (cert
, 0, NULL
);
236 ksba_cert_release (cert
);
240 for (signer
=0; ; signer
++)
243 ksba_sexp_t sigval
= NULL
;
244 ksba_isotime_t sigtime
, keyexptime
;
246 char *msgdigest
= NULL
;
250 rc
= ksba_cms_get_issuer_serial (cms
, signer
, &issuer
, &serial
);
251 if (!signer
&& gpg_err_code (rc
) == GPG_ERR_NO_DATA
252 && data_fd
== -1 && is_detached
)
254 log_info ("certs-only message accepted\n");
260 if (signer
&& rc
== -1)
265 gpgsm_status (ctrl
, STATUS_NEWSIG
, NULL
);
269 log_debug ("signer %d - issuer: `%s'\n",
270 signer
, issuer
? issuer
:"[NONE]");
271 log_debug ("signer %d - serial: ", signer
);
272 gpgsm_dump_serial (serial
);
276 rc
= ksba_cms_get_signing_time (cms
, signer
, sigtime
);
277 if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
281 log_error ("error getting signing time: %s\n", gpg_strerror (rc
));
282 *sigtime
= 0; /* (we can't encode an error in the time string.) */
285 rc
= ksba_cms_get_message_digest (cms
, signer
,
286 &msgdigest
, &msgdigestlen
);
291 algoid
= ksba_cms_get_digest_algo (cms
, signer
);
292 algo
= gcry_md_map_name (algoid
);
294 log_debug ("signer %d - digest algo: %d\n", signer
, algo
);
295 is_enabled
= sizeof algo
;
296 if ( gcry_md_info (data_md
, GCRYCTL_IS_ALGO_ENABLED
,
300 log_error ("digest algo %d has not been enabled\n", algo
);
304 else if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
311 else /* real error */
314 rc
= ksba_cms_get_sigattr_oids (cms
, signer
,
315 "1.2.840.113549.1.9.3", &ctattr
);
321 log_debug ("signer %d - content-type attribute: %s",
324 s
= ksba_cms_get_content_oid (cms
, 1);
325 if (!s
|| strcmp (ctattr
, s
))
327 log_error ("content-type attribute does not match "
328 "actual content-type\n");
338 log_error ("error getting content-type attribute: %s\n",
345 sigval
= ksba_cms_get_sig_val (cms
, signer
);
348 log_error ("no signature value available\n");
352 log_debug ("signer %d - signature available", signer
);
354 /* Find the certificate of the signer */
355 keydb_search_reset (kh
);
356 rc
= keydb_search_issuer_sn (kh
, issuer
, serial
);
361 log_error ("certificate not found\n");
362 rc
= gpg_error (GPG_ERR_NO_PUBKEY
);
365 log_error ("failed to find the certificate: %s\n",
369 sprintf (numbuf
, "%d", rc
);
371 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.findkey",
374 /* fixme: we might want to append the issuer and serial
375 using our standard notation */
379 rc
= keydb_get_cert (kh
, &cert
);
382 log_error ("failed to get cert: %s\n", gpg_strerror (rc
));
386 log_info (_("Signature made "));
388 gpgsm_dump_time (sigtime
);
390 log_printf (_("[date not given]"));
391 log_printf (_(" using certificate ID %08lX\n"),
392 gpgsm_get_short_fingerprint (cert
));
396 { /* Signed attributes are available. */
400 /* check that the message digest in the signed attributes
401 matches the one we calculated on the data */
402 s
= gcry_md_read (data_md
, algo
);
403 if ( !s
|| !msgdigestlen
404 || gcry_md_get_algo_dlen (algo
) != msgdigestlen
405 || !s
|| memcmp (s
, msgdigest
, msgdigestlen
) )
409 log_error ("invalid signature: message digest attribute "
410 "does not match calculated one\n");
411 fpr
= gpgsm_fpr_and_name_for_status (cert
);
412 gpgsm_status (ctrl
, STATUS_BADSIG
, fpr
);
417 rc
= gcry_md_open (&md
, algo
, 0);
420 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
424 gcry_md_start_debug (md
, "vrfy.attr");
426 ksba_cms_set_hash_function (cms
, HASH_FNC
, md
);
427 rc
= ksba_cms_hash_signed_attrs (cms
, signer
);
430 log_error ("hashing signed attrs failed: %s\n",
435 rc
= gpgsm_check_cms_signature (cert
, sigval
, md
, algo
);
440 rc
= gpgsm_check_cms_signature (cert
, sigval
, data_md
, algo
);
447 log_error ("invalid signature: %s\n", gpg_strerror (rc
));
448 fpr
= gpgsm_fpr_and_name_for_status (cert
);
449 gpgsm_status (ctrl
, STATUS_BADSIG
, fpr
);
453 rc
= gpgsm_cert_use_verify_p (cert
); /*(this displays an info message)*/
456 gpgsm_status_with_err_code (ctrl
, STATUS_ERROR
, "verify.keyusage",
462 log_debug ("signature okay - checking certs\n");
463 rc
= gpgsm_validate_chain (ctrl
, cert
, keyexptime
, 0, NULL
, 0);
465 char *fpr
, *buf
, *tstr
;
467 fpr
= gpgsm_fpr_and_name_for_status (cert
);
468 if (gpg_err_code (rc
) == GPG_ERR_CERT_EXPIRED
)
470 gpgsm_status (ctrl
, STATUS_EXPKEYSIG
, fpr
);
474 gpgsm_status (ctrl
, STATUS_GOODSIG
, fpr
);
478 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
479 tstr
= strtimestamp_r (sigtime
);
480 buf
= xmalloc ( strlen(fpr
) + strlen (tstr
) + 120);
481 sprintf (buf
, "%s %s %s %s", fpr
, tstr
,
482 *sigtime
? sigtime
: "0",
483 *keyexptime
? keyexptime
: "0" );
486 gpgsm_status (ctrl
, STATUS_VALIDSIG
, buf
);
490 if (rc
) /* of validate_chain */
492 log_error ("invalid certification chain: %s\n", gpg_strerror (rc
));
493 if (gpg_err_code (rc
) == GPG_ERR_BAD_CERT_CHAIN
494 || gpg_err_code (rc
) == GPG_ERR_BAD_CERT
495 || gpg_err_code (rc
) == GPG_ERR_BAD_CA_CERT
496 || gpg_err_code (rc
) == GPG_ERR_CERT_REVOKED
)
497 gpgsm_status_with_err_code (ctrl
, STATUS_TRUST_NEVER
, NULL
,
500 gpgsm_status_with_err_code (ctrl
, STATUS_TRUST_UNDEFINED
, NULL
,
505 for (i
=0; (p
= ksba_cert_get_subject (cert
, i
)); i
++)
507 log_info (!i
? _("Good signature from")
510 gpgsm_print_name (log_get_stream (), p
);
515 gpgsm_status (ctrl
, STATUS_TRUST_FULLY
, NULL
);
524 ksba_cert_release (cert
);
530 ksba_cms_release (cms
);
531 gpgsm_destroy_reader (b64reader
);
532 gpgsm_destroy_writer (b64writer
);
534 gcry_md_close (data_md
);
541 sprintf (numbuf
, "%d", rc
);
542 gpgsm_status2 (ctrl
, STATUS_ERROR
, "verify.leave",