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",