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
);
204 log_info ("detached signature w/o data "
205 "- assuming certs-only\n");
207 hash_data (data_fd
, data_md
);
211 ksba_cms_set_hash_function (cms
, HASH_FNC
, data_md
);
214 else if (stopreason
== KSBA_SR_END_DATA
)
215 { /* The data bas been hashed */
219 while (stopreason
!= KSBA_SR_READY
);
223 rc
= gpgsm_finish_writer (b64writer
);
226 log_error ("write failed: %s\n", gnupg_strerror (rc
));
231 if (data_fd
!= -1 && !is_detached
)
233 log_error ("data given for a non-detached signature\n");
238 for (i
=0; (cert
=ksba_cms_get_cert (cms
, i
)); i
++)
240 /* Fixme: it might be better to check the validity of the
241 certificate first before entering it into the DB. This way
242 we would avoid cluttering the DB with invalid
244 keydb_store_cert (cert
);
245 ksba_cert_release (cert
);
250 for (signer
=0; signer
< 1; signer
++)
253 KsbaSexp sigval
= NULL
;
256 char *msgdigest
= NULL
;
259 err
= ksba_cms_get_issuer_serial (cms
, signer
, &issuer
, &serial
);
260 if (!signer
&& err
== KSBA_No_Data
&& data_fd
== -1 && is_detached
)
262 log_info ("certs-only message accepted\n");
268 log_debug ("signer %d - issuer: `%s'\n", signer
, issuer
? issuer
:"[NONE]");
269 log_debug ("signer %d - serial: ", signer
);
270 gpgsm_dump_serial (serial
);
273 err
= ksba_cms_get_signing_time (cms
, signer
, &sigtime
);
276 log_debug ("error getting signing time: %s\n", ksba_strerror (err
));
277 sigtime
= (time_t)-1;
279 log_debug ("signer %d - sigtime: ", signer
);
280 gpgsm_dump_time (sigtime
);
284 err
= ksba_cms_get_message_digest (cms
, signer
,
285 &msgdigest
, &msgdigestlen
);
289 algoid
= ksba_cms_get_digest_algo (cms
, signer
);
290 algo
= gcry_md_map_name (algoid
);
291 log_debug ("signer %d - digest algo: %d\n", signer
, algo
);
292 if ( !gcry_md_info (data_md
, GCRYCTL_IS_ALGO_ENABLED
, &algo
, NULL
) )
294 log_debug ("digest algo %d has not been enabled\n", algo
);
298 sigval
= ksba_cms_get_sig_val (cms
, signer
);
301 log_error ("no signature value available\n");
304 log_debug ("signer %d - signature available", signer
);
306 /* Find the certificate of the signer */
307 keydb_search_reset (kh
);
308 rc
= keydb_search_issuer_sn (kh
, issuer
, serial
);
311 log_debug ("failed to find the certificate: %s\n",
316 rc
= keydb_get_cert (kh
, &cert
);
319 log_debug ("failed to get cert: %s\n", gnupg_strerror (rc
));
324 { /* Signed attributes are available. */
328 /* check that the message digest in the signed attributes
329 matches the one we calculated on the data */
330 s
= gcry_md_read (data_md
, algo
);
331 if ( !s
|| !msgdigestlen
332 || gcry_md_get_algo_dlen (algo
) != msgdigestlen
333 || !s
|| memcmp (s
, msgdigest
, msgdigestlen
) )
335 log_error ("invalid signature: message digest attribute "
336 "does not match calculated one\n");
337 gpgsm_status (ctrl
, STATUS_BADSIG
, NULL
);
341 md
= gcry_md_open (algo
, 0);
344 log_error ("md_open failed: %s\n", gcry_strerror (-1));
348 gcry_md_start_debug (md
, "vrfy.attr");
350 ksba_cms_set_hash_function (cms
, HASH_FNC
, md
);
351 rc
= ksba_cms_hash_signed_attrs (cms
, signer
);
354 log_debug ("hashing signed attrs failed: %s\n",
359 rc
= gpgsm_check_cms_signature (cert
, sigval
, md
, algo
);
364 rc
= gpgsm_check_cms_signature (cert
, sigval
, data_md
, algo
);
369 log_error ("invalid signature: %s\n", gnupg_strerror (rc
));
370 gpgsm_status (ctrl
, STATUS_BADSIG
, NULL
);
373 gpgsm_cert_use_verify_p (cert
); /* this displays an info message */
374 log_debug ("signature okay - checking certs\n");
375 gpgsm_status (ctrl
, STATUS_GOODSIG
, NULL
);
377 char *buf
, *fpr
, *tstr
;
379 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
380 tstr
= strtimestamp (sigtime
);
381 buf
= xmalloc ( strlen(fpr
) + strlen (tstr
) + 100);
382 sprintf (buf
, "%s %s %lu", fpr
, tstr
, (unsigned long)sigtime
);
385 gpgsm_status (ctrl
, STATUS_VALIDSIG
, buf
);
389 rc
= gpgsm_validate_path (cert
);
392 log_error ("invalid certification path: %s\n", gnupg_strerror (rc
));
393 if (rc
== GNUPG_Bad_Certificate_Path
394 || rc
== GNUPG_Bad_Certificate
)
395 gpgsm_status (ctrl
, STATUS_TRUST_NEVER
, NULL
);
397 gpgsm_status (ctrl
, STATUS_TRUST_UNDEFINED
, NULL
);
400 log_info ("signature is good\n");
401 gpgsm_status (ctrl
, STATUS_TRUST_FULLY
, NULL
);
410 ksba_cert_release (cert
);
416 log_debug ("ksba error: %s\n", ksba_strerror (err
));
417 rc
= map_ksba_err (rc
);
423 ksba_cms_release (cms
);
424 gpgsm_destroy_reader (b64reader
);
425 gpgsm_destroy_writer (b64writer
);
427 gcry_md_close (data_md
);