sm: Add yet inactive options to support authenticode
authorWerner Koch <wk@gnupg.org>
Tue, 30 Apr 2019 06:25:59 +0000 (08:25 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 30 Apr 2019 06:28:54 +0000 (08:28 +0200)
* sm/gpgsm.c (opts): New options --authenticode and --attribute.
* sm/gpgsm.h (opt): Add vars authenticode and attribute_list.
* sm/sign.c (add_signed_attribute): New but inactive.
(gpgsm_sign): Use new options.
--

Because libksba 1.4 is not yet ready the new code is not yet active.

Signed-off-by: Werner Koch <wk@gnupg.org>
g10/sig-check.c
sm/gpgsm.c
sm/gpgsm.h
sm/sign.c

index e7f97de..4c172d6 100644 (file)
@@ -1076,7 +1076,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
  * signature packet's data structure.
  *
  * TODO: add r_revoked here as well.  It has the same problems as
- * r_expiredate and r_expired and the cache */
+ * r_expiredate and r_expired and the cache [nw].  Which problems [wk]? */
 int
 check_key_signature2 (ctrl_t ctrl,
                       kbnode_t root, kbnode_t node, PKT_public_key *check_pk,
index 020072a..b9694b2 100644 (file)
@@ -192,6 +192,8 @@ enum cmd_and_opt_values {
   oNoRandomSeedFile,
   oNoCommonCertsImport,
   oIgnoreCertExtension,
+  oAuthenticode,
+  oAttribute,
   oNoAutostart
  };
 
@@ -402,6 +404,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
   ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"),
   ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
+  ARGPARSE_s_n (oAuthenticode, "authenticode", "@"),
+  ARGPARSE_s_s (oAttribute,    "attribute", "@"),
 
   /* Command aliases.  */
   ARGPARSE_c (aListKeys, "list-key", "@"),
@@ -1460,6 +1464,12 @@ main ( int argc, char **argv)
           add_to_strlist (&opt.ignored_cert_extensions, pargs.r.ret_str);
           break;
 
+        case oAuthenticode: opt.authenticode = 1; break;
+
+        case oAttribute:
+          add_to_strlist (&opt.attributes, pargs.r.ret_str);
+          break;
+
         case oNoAutostart: opt.autostart = 0; break;
 
         case oCompliance:
index 7a5e491..c15d8dc 100644 (file)
@@ -149,6 +149,21 @@ struct
   strlist_t ignored_cert_extensions;
 
   enum gnupg_compliance_mode compliance;
+
+  /* Enable creation of authenticode signatures.  */
+  int authenticode;
+
+  /* A list of extra attributes put into a signed data object.  For a
+   * signed each attribute each string has the format:
+   *   <oid>:s:<hex_or_filename>
+   * and for an unsigned attribute
+   *   <oid>:u:<hex_or_filename>
+   * The OID is in the usual dotted decimal for. The HEX_OR_FILENAME
+   * is either a list of hex digits or a filename with the DER encoded
+   * value.  A filename is detected by the presence of a slash in the
+   * HEX_OR_FILENAME.  The actual value needs to be encoded as a SET OF
+   * attribute values.  */
+  strlist_t attributes;
 } opt;
 
 /* Debug values and macros.  */
index 24ecad3..0604642 100644 (file)
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -302,6 +302,99 @@ 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)
+{
+  gpg_error_t err;
+  char **fields = NULL;
+  const char *s;
+  int i;
+  unsigned char *der = NULL;
+  size_t derlen;
+
+  fields = strtokenize (attrstr, ":");
+  if (!fields)
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("strtokenize failed: %s\n", gpg_strerror (err));
+      goto leave;
+    }
+
+  for (i=0; fields[i]; i++)
+    ;
+  if (i != 3)
+    {
+      err = gpg_error (GPG_ERR_SYNTAX);
+      log_error ("invalid attribute specification '%s': %s\n",
+                 attrstr, i < 3 ? "not enough fields":"too many fields");
+      goto leave;
+    }
+  if (!ascii_strcasecmp (fields[1], "u"))
+    {
+      err = 0;
+      goto leave; /* Skip unsigned attruibutes.  */
+    }
+  if (ascii_strcasecmp (fields[1], "s"))
+    {
+      err = gpg_error (GPG_ERR_SYNTAX);
+      log_error ("invalid attribute specification '%s': %s\n",
+                 attrstr, "type is not 's' or 'u'");
+      goto leave;
+    }
+  /* Check that the OID is valid.  */
+  err = ksba_oid_from_str (fields[0], &der, &derlen);
+  if (err)
+    {
+      log_error ("invalid attribute specification '%s': %s\n",
+                 attrstr, gpg_strerror (err));
+      goto leave;
+    }
+  xfree (der);
+  der = NULL;
+
+  if (strchr (fields[2], '/'))
+    {
+      /* FIXME: read from file. */
+    }
+  else /* Directly given in hex.  */
+    {
+      for (i=0, s = fields[2]; hexdigitp (s); s++, i++)
+        ;
+      if (*s || !i || (i&1))
+        {
+          log_error ("invalid attribute specification '%s': %s\n",
+                     attrstr, "invalid hex encoding of the data");
+          err = gpg_error (GPG_ERR_SYNTAX);
+          goto leave;
+        }
+      der = xtrystrdup (fields[2]);
+      if (!der)
+        {
+          err = gpg_error_from_syserror ();
+          log_error ("malloc failed: %s\n", gpg_strerror (err));
+          goto leave;
+        }
+      for (s=fields[2], derlen=0; s[0] && s[1]; s += 2)
+        der[derlen++] = xtoi_2 (s);
+    }
+
+  /* Store the data in the CMS object for all signers.  */
+  err = ksba_cms_add_attribute (cms, -1, fields[0], 0, der, derlen);
+  if (err)
+    {
+      log_error ("invalid attribute specification '%s': %s\n",
+                 attrstr, gpg_strerror (err));
+      goto leave;
+    }
+
+ leave:
+  xfree (der);
+  xfree (fields);
+  return err;
+}
+#endif /*ksba >= 1.4.0 */
+
 
 \f
 /* Perform a sign operation.
@@ -377,10 +470,17 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       goto leave;
     }
 
-  /* We are going to create signed data with data as encap. content */
+  /* We are going to create signed data with data as encap. content.
+   * In authenticode mode we use spcIndirectDataContext instead.  */
   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
   if (!err)
-    err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
+    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)
     {
       log_debug ("ksba_cms_set_content_type failed: %s\n",
@@ -643,6 +743,20 @@ 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;
+
+    for (sl = opt.attributes; sl; sl = sl->next)
+      if ((err = add_signed_attribute (cms, sl->d)))
+        goto leave;
+  }
+#else
+  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
      try to convince some MUAs to use 3DES and not the crippled
      RC2. Our list is: