diff options
Diffstat (limited to '')
-rw-r--r-- | sm/verify.c | 550 |
1 files changed, 0 insertions, 550 deletions
diff --git a/sm/verify.c b/sm/verify.c deleted file mode 100644 index 6dd4f4e5b..000000000 --- a/sm/verify.c +++ /dev/null @@ -1,550 +0,0 @@ -/* verify.c - Verify a messages signature - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> -#include <assert.h> - -#include "gpgsm.h" -#include <gcrypt.h> -#include <ksba.h> - -#include "keydb.h" -#include "i18n.h" - -static char * -strtimestamp_r (time_t atime) -{ - char *buffer = xmalloc (15); - - if (atime < 0) - strcpy (buffer, "????" "-??" "-??"); - else if (!atime) - strcpy (buffer, "none"); - else - { - struct tm *tp; - - tp = gmtime( &atime ); - sprintf (buffer, "%04d-%02d-%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday); - } - return buffer; -} - - - -/* Hash the data for a detached signature */ -static void -hash_data (int fd, gcry_md_hd_t md) -{ - FILE *fp; - char buffer[4096]; - int nread; - - fp = fdopen ( dup (fd), "rb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - return; - } - - do - { - nread = fread (buffer, 1, DIM(buffer), fp); - gcry_md_write (md, buffer, nread); - } - while (nread); - if (ferror (fp)) - log_error ("read error on fd %d: %s\n", fd, strerror (errno)); - fclose (fp); -} - - - - -/* Perform a verify operation. To verify detached signatures, data_fd - must be different than -1. With OUT_FP given and a non-detached - signature, the signed material is written to that stream. */ -int -gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) -{ - int i, rc; - Base64Context b64reader = NULL; - Base64Context b64writer = NULL; - KsbaError err; - KsbaReader reader; - KsbaWriter writer = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KsbaCert cert; - KEYDB_HANDLE kh; - gcry_md_hd_t data_md = NULL; - int signer; - const char *algoid; - int algo; - int is_detached; - FILE *fp = NULL; - char *p; - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = gpg_error (GPG_ERR_GENERAL); - goto leave; - } - - - fp = fdopen ( dup (in_fd), "rb"); - if (!fp) - { - rc = gpg_error (gpg_err_code_from_errno (errno)); - log_error ("fdopen() failed: %s\n", strerror (errno)); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gpg_strerror (rc)); - goto leave; - } - - if (out_fp) - { - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gpg_strerror (rc)); - goto leave; - } - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = gpg_error (GPG_ERR_ENOMEM); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - rc = gcry_md_open (&data_md, 0, 0); - if (rc) - { - log_error ("md_open failed: %s\n", gpg_strerror (rc)); - goto leave; - } - if (DBG_HASHING) - gcry_md_start_debug (data_md, "vrfy.data"); - - is_detached = 0; - do - { - err = ksba_cms_parse (cms, &stopreason); - if (err) - { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - if (stopreason == KSBA_SR_NEED_HASH) - { - is_detached = 1; - if (opt.verbose) - log_info ("detached signature\n"); - } - - if (stopreason == KSBA_SR_NEED_HASH - || stopreason == KSBA_SR_BEGIN_DATA) - { /* We are now able to enable the hash algorithms */ - for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) - { - algo = gcry_md_map_name (algoid); - if (!algo) - log_error ("unknown hash algorithm `%s'\n", - algoid? algoid:"?"); - else - gcry_md_enable (data_md, algo); - } - if (is_detached) - { - if (data_fd == -1) - log_info ("detached signature w/o data " - "- assuming certs-only\n"); - else - hash_data (data_fd, data_md); - } - else - { - ksba_cms_set_hash_function (cms, HASH_FNC, data_md); - } - } - else if (stopreason == KSBA_SR_END_DATA) - { /* The data bas been hashed */ - - } - } - while (stopreason != KSBA_SR_READY); - - if (b64writer) - { - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gpg_strerror (rc)); - goto leave; - } - } - - if (data_fd != -1 && !is_detached) - { - log_error ("data given for a non-detached signature\n"); - rc = gpg_error (GPG_ERR_CONFLICT); - goto leave; - } - - for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) - { - /* Fixme: it might be better to check the validity of the - certificate first before entering it into the DB. This way - we would avoid cluttering the DB with invalid - certificates. */ - keydb_store_cert (cert, 0, NULL); - ksba_cert_release (cert); - } - - cert = NULL; - err = 0; - for (signer=0; ; signer++) - { - char *issuer = NULL; - KsbaSexp sigval = NULL; - time_t sigtime, keyexptime; - KsbaSexp serial; - char *msgdigest = NULL; - size_t msgdigestlen; - char *ctattr; - - err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); - if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached) - { - log_info ("certs-only message accepted\n"); - err = 0; - break; - } - if (err) - { - if (signer && err == -1) - err = 0; - break; - } - if (DBG_X509) - { - log_debug ("signer %d - issuer: `%s'\n", - signer, issuer? issuer:"[NONE]"); - log_debug ("signer %d - serial: ", signer); - gpgsm_dump_serial (serial); - log_printf ("\n"); - } - - err = ksba_cms_get_signing_time (cms, signer, &sigtime); - if (err == KSBA_No_Data) - sigtime = 0; - else if (err) - { - log_error ("error getting signing time: %s\n", ksba_strerror (err)); - sigtime = (time_t)-1; - } - - err = ksba_cms_get_message_digest (cms, signer, - &msgdigest, &msgdigestlen); - if (!err) - { - algoid = ksba_cms_get_digest_algo (cms, signer); - algo = gcry_md_map_name (algoid); - if (DBG_X509) - log_debug ("signer %d - digest algo: %d\n", signer, algo); - if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) ) - { - log_error ("digest algo %d has not been enabled\n", algo); - goto next_signer; - } - } - else if (err == KSBA_No_Data) - { - assert (!msgdigest); - err = 0; - algoid = NULL; - algo = 0; - } - else /* real error */ - break; - - err = ksba_cms_get_sigattr_oids (cms, signer, - "1.2.840.113549.1.9.3",&ctattr); - if (!err) - { - const char *s; - - if (DBG_X509) - log_debug ("signer %d - content-type attribute: %s", signer, ctattr); - s = ksba_cms_get_content_oid (cms, 1); - if (!s || strcmp (ctattr, s)) - { - log_error ("content-type attribute does not match " - "actual content-type\n"); - ksba_free (ctattr); - ctattr = NULL; - goto next_signer; - } - ksba_free (ctattr); - ctattr = NULL; - } - else if (err != -1) - { - log_error ("error getting content-type attribute: %s\n", - ksba_strerror (err)); - goto next_signer; - } - err = 0; - - - sigval = ksba_cms_get_sig_val (cms, signer); - if (!sigval) - { - log_error ("no signature value available\n"); - goto next_signer; - } - if (DBG_X509) - log_debug ("signer %d - signature available", signer); - - /* Find the certificate of the signer */ - keydb_search_reset (kh); - rc = keydb_search_issuer_sn (kh, issuer, serial); - if (rc) - { - if (rc == -1) - { - log_error ("certificate not found\n"); - rc = gpg_error (GPG_ERR_NO_PUBKEY); - } - else - log_error ("failed to find the certificate: %s\n", - gpg_strerror(rc)); - { - char numbuf[50]; - sprintf (numbuf, "%d", rc); - - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", - numbuf, NULL); - } - /* fixme: we might want to append the issuer and serial - using our standard notation */ - goto next_signer; - } - - rc = keydb_get_cert (kh, &cert); - if (rc) - { - log_error ("failed to get cert: %s\n", gpg_strerror (rc)); - goto next_signer; - } - - log_info (_("Signature made ")); - if (sigtime) - gpgsm_dump_time (sigtime); - else - log_printf (_("[date not given]")); - log_printf (_(" using certificate ID %08lX\n"), - gpgsm_get_short_fingerprint (cert)); - - - if (msgdigest) - { /* Signed attributes are available. */ - gcry_md_hd_t md; - unsigned char *s; - - /* check that the message digest in the signed attributes - matches the one we calculated on the data */ - s = gcry_md_read (data_md, algo); - if ( !s || !msgdigestlen - || gcry_md_get_algo_dlen (algo) != msgdigestlen - || !s || memcmp (s, msgdigest, msgdigestlen) ) - { - char *fpr; - - log_error ("invalid signature: message digest attribute " - "does not match calculated one\n"); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status (ctrl, STATUS_BADSIG, fpr); - xfree (fpr); - goto next_signer; - } - - rc = gcry_md_open (&md, algo, 0); - if (rc) - { - log_error ("md_open failed: %s\n", gpg_strerror (rc)); - goto next_signer; - } - if (DBG_HASHING) - gcry_md_start_debug (md, "vrfy.attr"); - - ksba_cms_set_hash_function (cms, HASH_FNC, md); - rc = ksba_cms_hash_signed_attrs (cms, signer); - if (rc) - { - log_error ("hashing signed attrs failed: %s\n", - ksba_strerror (rc)); - gcry_md_close (md); - goto next_signer; - } - rc = gpgsm_check_cms_signature (cert, sigval, md, algo); - gcry_md_close (md); - } - else - { - rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo); - } - - if (rc) - { - char *fpr; - - log_error ("invalid signature: %s\n", gpg_strerror (rc)); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status (ctrl, STATUS_BADSIG, fpr); - xfree (fpr); - goto next_signer; - } - rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/ - if (rc) - { - gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage", - gpg_err_code (rc)); - rc = 0; - } - - if (DBG_X509) - log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, &keyexptime); - if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) - { - gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); - rc = 0; - } - else - gpgsm_status (ctrl, STATUS_GOODSIG, NULL); - - { - char *buf, *fpr, *tstr; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - tstr = strtimestamp_r (sigtime); - buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); - sprintf (buf, "%s %s %lu %lu", fpr, tstr, - (unsigned long)sigtime, (unsigned long)keyexptime ); - xfree (tstr); - xfree (fpr); - gpgsm_status (ctrl, STATUS_VALIDSIG, buf); - xfree (buf); - } - - if (rc) /* of validate_chain */ - { - log_error ("invalid certification chain: %s\n", gpg_strerror (rc)); - if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN - || gpg_err_code (rc) == GPG_ERR_BAD_CERT - || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT - || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED) - gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL, - gpg_err_code (rc)); - else - gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, - gpg_err_code (rc)); - goto next_signer; - } - - for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) - { - log_info (!i? _("Good signature from") - : _(" aka")); - log_printf (" \""); - gpgsm_print_name (log_get_stream (), p); - log_printf ("\"\n"); - ksba_free (p); - } - - gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL); - - - next_signer: - rc = 0; - xfree (issuer); - xfree (serial); - xfree (sigval); - xfree (msgdigest); - ksba_cert_release (cert); - cert = NULL; - } - rc = 0; - if (err) - { - log_error ("ksba error: %s\n", ksba_strerror (err)); - rc = map_ksba_err (rc); - } - - - - leave: - ksba_cms_release (cms); - gpgsm_destroy_reader (b64reader); - gpgsm_destroy_writer (b64writer); - keydb_release (kh); - gcry_md_close (data_md); - if (fp) - fclose (fp); - - if (rc) - { - char numbuf[50]; - sprintf (numbuf, "%d", rc ); - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", - numbuf, NULL); - } - - return rc; -} - |