aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/call-agent.c2
-rw-r--r--sm/call-dirmngr.c36
-rw-r--r--sm/certchain.c3
-rw-r--r--sm/certdump.c9
-rw-r--r--sm/certlist.c6
-rw-r--r--sm/decrypt.c8
-rw-r--r--sm/gpgsm.c17
-rw-r--r--sm/gpgsm.h8
-rw-r--r--sm/keydb.c28
-rw-r--r--sm/sign.c272
-rw-r--r--sm/verify.c10
11 files changed, 362 insertions, 37 deletions
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 06319cf62..698039504 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -890,6 +890,8 @@ istrusted_status_cb (void *opaque, const char *line)
flags->chain_model = 1;
else if (has_leading_keyword (line, "qual"))
flags->qualified = 1;
+ else if (has_leading_keyword (line, "de-vs"))
+ flags->de_vs = 1;
}
return 0;
}
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index cc958ccf8..86beeedc1 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -362,7 +362,7 @@ inq_certificate (void *opaque, const char *line)
}
else
{
- log_error ("unsupported inquiry '%s'\n", line);
+ log_error ("unsupported certificate inquiry '%s'\n", line);
return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
}
@@ -386,8 +386,8 @@ inq_certificate (void *opaque, const char *line)
int err;
ksba_cert_t cert;
-
- err = gpgsm_find_cert (parm->ctrl, line, ski, &cert, 1);
+ err = gpgsm_find_cert (parm->ctrl, line, ski, &cert,
+ FIND_CERT_ALLOW_AMBIG|FIND_CERT_WITH_EPHEM);
if (err)
{
log_error ("certificate not found: %s\n", gpg_strerror (err));
@@ -521,6 +521,7 @@ isvalid_status_cb (void *opaque, const char *line)
GPG_ERR_CERTIFICATE_REVOKED
GPG_ERR_NO_CRL_KNOWN
+ GPG_ERR_INV_CRL_OBJ
GPG_ERR_CRL_TOO_OLD
Values for USE_OCSP:
@@ -1014,7 +1015,8 @@ run_command_inq_cb (void *opaque, const char *line)
if (!*line)
return gpg_error (GPG_ERR_ASS_PARAMETER);
- err = gpgsm_find_cert (parm->ctrl, line, NULL, &cert, 1);
+ err = gpgsm_find_cert (parm->ctrl, line, NULL, &cert,
+ FIND_CERT_ALLOW_AMBIG);
if (err)
{
log_error ("certificate not found: %s\n", gpg_strerror (err));
@@ -1035,9 +1037,33 @@ run_command_inq_cb (void *opaque, const char *line)
line = s;
log_info ("dirmngr: %s\n", line);
}
+ else if ((s = has_leading_keyword (line, "ISTRUSTED")))
+ {
+ /* The server is asking us whether the certificate is a trusted
+ root certificate. */
+ char fpr[41];
+ struct rootca_flags_s rootca_flags;
+ int n;
+
+ line = s;
+
+ for (s=line,n=0; hexdigitp (s); s++, n++)
+ ;
+ if (*s || n != 40)
+ return gpg_error (GPG_ERR_ASS_PARAMETER);
+ for (s=line, n=0; n < 40; s++, n++)
+ fpr[n] = (*s >= 'a')? (*s & 0xdf): *s;
+ fpr[n] = 0;
+
+ if (!gpgsm_agent_istrusted (parm->ctrl, NULL, fpr, &rootca_flags))
+ rc = assuan_send_data (parm->ctx, "1", 1);
+ else
+ rc = 0;
+ return rc;
+ }
else
{
- log_error ("unsupported inquiry '%s'\n", line);
+ log_error ("unsupported command inquiry '%s'\n", line);
rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
}
diff --git a/sm/certchain.c b/sm/certchain.c
index cbb6e1127..7b782190b 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -122,6 +122,7 @@ do_list (int is_error, int listmode, estream_t fp, const char *format, ...)
}
else
{
+ es_fflush (es_stdout);
log_logv (is_error? GPGRT_LOGLVL_ERROR: GPGRT_LOGLVL_INFO,
format, arg_ptr);
log_printf ("\n");
@@ -1480,6 +1481,7 @@ ask_marktrusted (ctrl_t ctrl, ksba_cert_t cert, int listmode)
int success = 0;
fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
+ es_fflush (es_stdout);
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
xfree (fpr);
@@ -2277,6 +2279,7 @@ gpgsm_basic_cert_check (ctrl_t ctrl, ksba_cert_t cert)
{
if (!opt.quiet)
{
+ es_fflush (es_stdout);
log_info ("issuer certificate (#/");
gpgsm_dump_string (issuer);
log_printf (") not found\n");
diff --git a/sm/certdump.c b/sm/certdump.c
index 3ad0edbe3..03bfd4106 100644
--- a/sm/certdump.c
+++ b/sm/certdump.c
@@ -728,7 +728,14 @@ gpgsm_es_print_name2 (estream_t fp, const char *name, int translate)
void
gpgsm_es_print_name (estream_t fp, const char *name)
{
- gpgsm_es_print_name2 (fp, name, 1);
+ if (opt.no_pretty_dn)
+ {
+ if (!name)
+ name = "[error]";
+ es_write_sanitized (fp, name, strlen (name), NULL, NULL);
+ }
+ else
+ gpgsm_es_print_name2 (fp, name, 1);
}
diff --git a/sm/certlist.c b/sm/certlist.c
index b5f9f7874..fdf31a198 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -508,11 +508,12 @@ gpgsm_release_certlist (certlist_t list)
int
gpgsm_find_cert (ctrl_t ctrl,
const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert,
- int allow_ambiguous)
+ unsigned int flags)
{
int rc;
KEYDB_SEARCH_DESC desc;
KEYDB_HANDLE kh = NULL;
+ int allow_ambiguous = (flags & FIND_CERT_ALLOW_AMBIG);
*r_cert = NULL;
rc = classify_user_id (name, &desc, 0);
@@ -523,6 +524,9 @@ gpgsm_find_cert (ctrl_t ctrl,
rc = gpg_error (GPG_ERR_ENOMEM);
else
{
+ if ((flags & FIND_CERT_WITH_EPHEM))
+ keydb_set_ephemeral (kh, 1);
+
nextone:
rc = keydb_search (ctrl, kh, &desc, 1);
if (!rc)
diff --git a/sm/decrypt.c b/sm/decrypt.c
index 3702cd893..68b362b45 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -37,14 +37,6 @@
#include "../common/tlv.h"
#include "../common/compliance.h"
-/* We can provide an enum value which is only availabale with KSBA
- * 1.6.0 so that we can compile even against older versions. Some
- * calls will of course return an error in this case. This value is
- * currently not used because the cipher mode is sufficient here. */
-/* #if KSBA_VERSION_NUMBER < 0x010600 /\* 1.6.0 *\/ */
-/* # define KSBA_CT_AUTHENVELOPED_DATA 10 */
-/* #endif */
-
struct decrypt_filter_parm_s
{
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index f8b3856c2..aeb6ad7a9 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -114,6 +114,7 @@ enum cmd_and_opt_values {
oNoLogFile,
oAuditLog,
oHtmlAuditLog,
+ oLogTime,
oEnableSpecialFilenames,
@@ -169,6 +170,7 @@ enum cmd_and_opt_values {
oWithKeyScreening,
oAnswerYes,
oAnswerNo,
+ oNoPrettyDN,
oKeyring,
oDefaultKey,
oDefRecipient,
@@ -288,6 +290,7 @@ static gpgrt_opt_t opts[] = {
N_("|FILE|write server mode logs to FILE")),
ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
+ ARGPARSE_s_n (oLogTime, "log-time", "@"),
ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
@@ -383,7 +386,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"),
ARGPARSE_s_n (oWithSecret, "with-secret", "@"),
ARGPARSE_s_n (oWithKeyScreening,"with-key-screening", "@"),
-
+ ARGPARSE_s_n (oNoPrettyDN, "no-pretty-dn", "@"),
ARGPARSE_header ("Security", N_("Options controlling the security")),
@@ -499,6 +502,9 @@ static int maybe_setuid = 1;
static const char *debug_level;
static unsigned int debug_value;
+/* Helper for --log-time; */
+static int opt_log_time;
+
/* Default value for include-certs. We need an extra macro for
gpgconf-list because the variable will be changed by the command
line option.
@@ -1247,6 +1253,7 @@ main ( int argc, char **argv)
case oLogFile: logfile = pargs.r.ret_str; break;
case oNoLogFile: logfile = NULL; break;
+ case oLogTime: opt_log_time = 1; break;
case oAuditLog: auditlog = pargs.r.ret_str; break;
case oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
@@ -1312,6 +1319,10 @@ main ( int argc, char **argv)
opt.with_key_screening = 1;
break;
+ case oNoPrettyDN:
+ opt.no_pretty_dn = 1;
+ break;
+
case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oChUid: break; /* Command line only (see above). */
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
@@ -1579,6 +1590,10 @@ main ( int argc, char **argv)
log_set_file (logfile);
log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
}
+ else if (opt_log_time)
+ log_set_prefix (NULL, (GPGRT_LOG_WITH_PREFIX|GPGRT_LOG_NO_REGISTRY
+ |GPGRT_LOG_WITH_TIME));
+
if (gnupg_faked_time_p ())
{
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index ced2d679f..cef39ff2a 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -85,6 +85,8 @@ struct
int with_key_screening; /* Option --with-key-screening active. */
+ int no_pretty_dn; /* Option --no-pretty-dn */
+
int pinentry_mode;
int request_origin;
@@ -293,6 +295,7 @@ struct rootca_flags_s
unsigned int relax:1; /* Relax checking of root certificates. */
unsigned int chain_model:1; /* Root requires the use of the chain model. */
unsigned int qualified:1; /* Root CA used for qualfied signatures. */
+ unsigned int de_vs:1; /* Root CA is de-vs compliant. */
};
@@ -404,8 +407,11 @@ int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
certlist_t *listaddr, int is_encrypt_to);
void gpgsm_release_certlist (certlist_t list);
+
+#define FIND_CERT_ALLOW_AMBIG 1
+#define FIND_CERT_WITH_EPHEM 2
int gpgsm_find_cert (ctrl_t ctrl, const char *name, ksba_sexp_t keyid,
- ksba_cert_t *r_cert, int allow_ambiguous);
+ ksba_cert_t *r_cert, unsigned int flags);
/*-- keylist.c --*/
gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names,
diff --git a/sm/keydb.c b/sm/keydb.c
index fbe28f2b9..a12dba19f 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -33,6 +33,7 @@
#include "keydb.h"
#include "../common/i18n.h"
#include "../common/asshelp.h"
+#include "../common/comopt.h"
#include "../kbx/kbx-client-util.h"
@@ -242,8 +243,23 @@ maybe_create_keybox (char *filename, int force, int *r_created)
*last_slash_in_filename = save_slash;
goto leave;
}
+ *last_slash_in_filename = save_slash;
+
+ if (!opt.use_keyboxd
+ && !parse_comopt (GNUPG_MODULE_NAME_GPG, 0)
+ && comopt.use_keyboxd)
+ {
+ /* The above try_make_homedir created a new default hoemdir
+ * and also wrote a new common.conf. Thus we now see that
+ * use-keyboxd has been set. Let's set this option and
+ * return a dedicated error code. */
+ opt.use_keyboxd = comopt.use_keyboxd;
+ rc = gpg_error (GPG_ERR_TRUE);
+ goto leave;
+ }
}
- *last_slash_in_filename = save_slash;
+ else
+ *last_slash_in_filename = save_slash;
/* To avoid races with other instances of gpg trying to create or
update the keybox (it is removed during an update for a short
@@ -459,9 +475,13 @@ keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created)
leave:
if (err)
{
- log_error ("keyblock resource '%s': %s\n", filename, gpg_strerror (err));
- gpgsm_status_with_error (ctrl, STATUS_ERROR,
- "add_keyblock_resource", err);
+ if (gpg_err_code (err) != GPG_ERR_TRUE)
+ {
+ log_error ("keyblock resource '%s': %s\n",
+ filename, gpg_strerror (err));
+ gpgsm_status_with_error (ctrl, STATUS_ERROR,
+ "add_keyblock_resource", err);
+ }
}
else
any_registered = 1;
diff --git a/sm/sign.c b/sm/sign.c
index 9290fc17b..b3b7e1883 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -1,6 +1,8 @@
/* sign.c - Sign a message
* Copyright (C) 2001, 2002, 2003, 2008,
* 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2003-2012, 2016-2017, 2019,
+ * 2020, 2022-2023 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -16,6 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
@@ -32,6 +35,7 @@
#include "keydb.h"
#include "../common/i18n.h"
+#include "../common/tlv.h"
/* Hash the data and return if something was hashed. Return -1 on error. */
@@ -300,7 +304,6 @@ add_certificate_list (ctrl_t ctrl, ksba_cms_t cms, ksba_cert_t cert)
}
-#if KSBA_VERSION_NUMBER >= 0x010400 && 0 /* 1.4.0 */
static gpg_error_t
add_signed_attribute (ksba_cms_t cms, const char *attrstr)
{
@@ -378,7 +381,12 @@ add_signed_attribute (ksba_cms_t cms, const char *attrstr)
}
/* Store the data in the CMS object for all signers. */
+#if 0
err = ksba_cms_add_attribute (cms, -1, fields[0], 0, der, derlen);
+#else
+ (void)cms;
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif
if (err)
{
log_error ("invalid attribute specification '%s': %s\n",
@@ -391,7 +399,218 @@ add_signed_attribute (ksba_cms_t cms, const char *attrstr)
xfree (fields);
return err;
}
-#endif /*ksba >= 1.4.0 */
+
+
+
+/* This function takes a binary detached signature in (BLOB,BLOBLEN)
+ * and writes it to OUT_FP. The core of the function is to replace
+ * NDEF length sequences in the input to those with fixed inputs.
+ * This helps certain other implementations to properly verify
+ * detached signature. Moreover, it allows our own trailing zero
+ * stripping code - which we need for PDF signatures - to work
+ * correctly.
+ *
+ * Example start of a detached signature as created by us:
+ * 0 NDEF: SEQUENCE { -- 1st sequence
+ * 2 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+ * 13 NDEF: [0] { -- 2nd sequence
+ * 15 NDEF: SEQUENCE { -- 3rd sequence
+ * 17 1: INTEGER 1 -- version
+ * 20 15: SET { -- set of algorithms
+ * 22 13: SEQUENCE {
+ * 24 9: OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
+ * 35 0: NULL
+ * : }
+ * : }
+ * 37 NDEF: SEQUENCE { -- 4th pretty short sequence
+ * 39 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+ * : }
+ * 52 869: [0] {
+ * Our goal is to replace the NDEF by fixed length tags.
+ */
+static gpg_error_t
+write_detached_signature (ctrl_t ctrl, const void *blob, size_t bloblen,
+ estream_t out_fp)
+{
+ gpg_error_t err;
+ const unsigned char *p;
+ size_t n, objlen, hdrlen;
+ int class, tag, cons, ndef;
+ const unsigned char *p_ctoid, *p_version, *p_algoset, *p_dataoid;
+ size_t n_ctoid, n_version, n_algoset, n_dataoid;
+ const unsigned char *p_certset, *p_signerinfos;
+ size_t n_certset, n_signerinfos;
+ int i;
+ ksba_der_t dbld;
+ unsigned char *finalder = NULL;
+ size_t finalderlen;
+
+ (void)ctrl;
+
+ p = blob;
+ n = bloblen;
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No 1st sequence. */
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No signedData OID. */
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ p_ctoid = p;
+ n_ctoid = objlen;
+ p += objlen;
+ n -= objlen;
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_CONTEXT && tag == 0 && cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No 2nd sequence. */
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No 3rd sequence. */
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_INTEGER))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No version. */
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ p_version = p;
+ n_version = objlen;
+ p += objlen;
+ n -= objlen;
+
+ p_algoset = p;
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_SET && cons && !ndef))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No set of algorithms. */
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ n_algoset = hdrlen + objlen;
+ p += objlen;
+ n -= objlen;
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No 4th sequence. */
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !cons))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No data OID. */
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ p_dataoid = p;
+ n_dataoid = objlen;
+ p += objlen;
+ n -= objlen;
+
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_NONE && !cons && !objlen))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No End tag. */
+
+ /* certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * Note: We ignore the following
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+ * because gpgsm does not create them. */
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,&objlen,&hdrlen)))
+ return err;
+ if (class == CLASS_CONTEXT && tag == 0 && cons)
+ {
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ p_certset = p;
+ n_certset = objlen;
+ p += objlen;
+ n -= objlen;
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,
+ &objlen,&hdrlen)))
+ return err;
+ }
+ else
+ {
+ p_certset = NULL;
+ n_certset = 0;
+ }
+
+ /* SignerInfos ::= SET OF SignerInfo */
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_SET && cons && !ndef))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No set of signerInfos. */
+ if (objlen > n)
+ return gpg_error (GPG_ERR_BAD_BER); /* Object larger than data. */
+ p_signerinfos = p;
+ n_signerinfos = objlen;
+ p += objlen;
+ n -= objlen;
+
+ /* For the fun of it check the 3 end tags. */
+ for (i=0; i < 3; i++)
+ {
+ if ((err=parse_ber_header (&p,&n,&class,&tag,&cons,&ndef,
+ &objlen,&hdrlen)))
+ return err;
+ if (!(class == CLASS_UNIVERSAL && tag == TAG_NONE && !cons && !objlen))
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* No End tag. */
+ }
+ if (n)
+ return gpg_error (GPG_ERR_INV_CMS_OBJ); /* Garbage */
+
+ /*---- From here on we jump to leave on error. ----*/
+
+ /* Now create a new object from the collected data. */
+ dbld = ksba_der_builder_new (16); /* (pre-allocate 16 items) */
+ if (!dbld)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ ksba_der_add_tag (dbld, 0, KSBA_TYPE_SEQUENCE);
+ ksba_der_add_val ( dbld, 0, KSBA_TYPE_OBJECT_ID, p_ctoid, n_ctoid);
+ ksba_der_add_tag ( dbld, KSBA_CLASS_CONTEXT, 0);
+ ksba_der_add_tag ( dbld, 0, KSBA_TYPE_SEQUENCE);
+ ksba_der_add_val ( dbld, 0, KSBA_TYPE_INTEGER, p_version, n_version);
+ ksba_der_add_der ( dbld, p_algoset, n_algoset);
+ ksba_der_add_tag ( dbld, 0, KSBA_TYPE_SEQUENCE);
+ ksba_der_add_val ( dbld, 0, KSBA_TYPE_OBJECT_ID, p_dataoid, n_dataoid);
+ ksba_der_add_end ( dbld);
+ if (p_certset)
+ {
+ ksba_der_add_tag ( dbld, KSBA_CLASS_CONTEXT, 0);
+ ksba_der_add_der ( dbld, p_certset, n_certset);
+ ksba_der_add_end ( dbld);
+ }
+ ksba_der_add_tag ( dbld, 0, KSBA_TYPE_SET);
+ ksba_der_add_der ( dbld, p_signerinfos, n_signerinfos);
+ ksba_der_add_end ( dbld);
+ ksba_der_add_end ( dbld);
+ ksba_der_add_end ( dbld);
+ ksba_der_add_end (dbld);
+
+ err = ksba_der_builder_get (dbld, &finalder, &finalderlen);
+ if (err)
+ goto leave;
+
+ if (es_fwrite (finalder, finalderlen, 1, out_fp) != 1)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+
+ leave:
+ ksba_der_release (dbld);
+ ksba_free (finalder);
+ return err;
+}
@@ -409,6 +628,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
gpg_error_t err;
gnupg_ksba_io_t b64writer = NULL;
ksba_writer_t writer;
+ estream_t sig_fp = NULL; /* Used for detached signatures. */
ksba_cms_t cms = NULL;
ksba_stop_reason_t stopreason;
KEYDB_HANDLE kh = NULL;
@@ -419,6 +639,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
ksba_isotime_t signed_at;
certlist_t cl;
int release_signerlist = 0;
+ int binary_detached = detached && !ctrl->create_pem && !ctrl->create_base64;
audit_set_type (ctrl->audit, AUDIT_TYPE_SIGN);
@@ -441,11 +662,25 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave;
}
+ /* Note that in detached mode the b64 write is actually a binary
+ * writer because we need to fixup the created signature later.
+ * Note that we do this only for binary output because we have no
+ * PEM writer interface outside of the ksba create writer code. */
ctrl->pem_name = "SIGNED MESSAGE";
- rc = gnupg_ksba_create_writer
- (&b64writer, ((ctrl->create_pem? GNUPG_KSBA_IO_PEM : 0)
- | (ctrl->create_base64? GNUPG_KSBA_IO_BASE64 : 0)),
- ctrl->pem_name, out_fp, &writer);
+ if (binary_detached)
+ {
+ sig_fp = es_fopenmem (0, "w+");
+ rc = sig_fp? 0 : gpg_error_from_syserror ();
+ if (!rc)
+ rc = gnupg_ksba_create_writer (&b64writer, 0, NULL, sig_fp, &writer);
+ }
+ else
+ {
+ rc = gnupg_ksba_create_writer
+ (&b64writer, ((ctrl->create_pem? GNUPG_KSBA_IO_PEM : 0)
+ | (ctrl->create_base64? GNUPG_KSBA_IO_BASE64 : 0)),
+ ctrl->pem_name, out_fp, &writer);
+ }
if (rc)
{
log_error ("can't create writer: %s\n", gpg_strerror (rc));
@@ -474,9 +709,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
if (!err)
err = ksba_cms_set_content_type
(cms, 1,
-#if KSBA_VERSION_NUMBER >= 0x010400 && 0
opt.authenticode? KSBA_CT_SPC_IND_DATA_CTX :
-#endif
KSBA_CT_DATA
);
if (err)
@@ -758,8 +991,6 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
}
}
- /* We can add signed attributes only when build against libksba 1.4. */
-#if KSBA_VERSION_NUMBER >= 0x010400 && 0 /* 1.4.0 */
{
strlist_t sl;
@@ -767,10 +998,6 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
if ((err = add_signed_attribute (cms, sl->d)))
goto leave;
}
-#else
- if (opt.attributes)
- log_info ("Note: option --attribute is ignored by this version\n");
-#endif /*ksba >= 1.4.0 */
/* We need to write at least a minimal list of our capabilities to
@@ -949,6 +1176,22 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave;
}
+ if (binary_detached)
+ {
+ void *blob = NULL;
+ size_t bloblen;
+
+ rc = es_fclose_snatch (sig_fp, &blob, &bloblen);
+ sig_fp = NULL;
+ if (rc)
+ goto leave;
+ rc = write_detached_signature (ctrl, blob, bloblen, out_fp);
+ xfree (blob);
+ if (rc)
+ goto leave;
+ }
+
+
audit_log (ctrl->audit, AUDIT_SIGNING_DONE);
log_info ("signature created\n");
@@ -962,5 +1205,6 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
gnupg_ksba_destroy_writer (b64writer);
keydb_release (kh);
gcry_md_close (data_md);
+ es_fclose (sig_fp);
return rc;
}
diff --git a/sm/verify.c b/sm/verify.c
index 9f1216f83..a07d1c9c7 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -105,12 +105,17 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
int signer;
const char *algoid;
int algo;
- int is_detached;
+ int is_detached, maybe_detached;
estream_t in_fp = NULL;
char *p;
audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);
+ /* Although we detect detached signatures during the parsing phase,
+ * we need to know it earlier and thus accept the caller idea of
+ * what to verify. */
+ maybe_detached = (data_fd != -1);
+
kh = keydb_new (ctrl);
if (!kh)
{
@@ -131,7 +136,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
rc = gnupg_ksba_create_reader
(&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0)
| (ctrl->is_base64? GNUPG_KSBA_IO_BASE64 : 0)
- | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0)),
+ | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0)
+ | (maybe_detached? GNUPG_KSBA_IO_STRIP : 0)),
in_fp, &reader);
if (rc)
{