* certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509.
[gnupg.git] / sm / sign.c
index 38d8ca9..5deef60 100644 (file)
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -61,9 +61,9 @@ hash_data (int fd, gcry_md_hd_t md)
 }
 
 static int
-hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer)
+hash_and_copy_data (int fd, gcry_md_hd_t md, ksba_writer_t writer)
 {
-  KsbaError err;
+  gpg_error_t err;
   FILE *fp;
   char buffer[4096];
   int nread;
@@ -126,10 +126,10 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer)
 /* Get the default certificate which is defined as the first one our
    keyDB returns and has a secret key available. */
 int
-gpgsm_get_default_cert (KsbaCert *r_cert)
+gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert)
 {
   KEYDB_HANDLE hd;
-  KsbaCert cert = NULL;
+  ksba_cert_t cert = NULL;
   int rc;
   char *p;
 
@@ -156,7 +156,7 @@ gpgsm_get_default_cert (KsbaCert *r_cert)
       p = gpgsm_get_keygrip_hexstring (cert);
       if (p)
         {
-          if (!gpgsm_agent_havekey (p))
+          if (!gpgsm_agent_havekey (ctrl, p))
             {
               xfree (p);
               keydb_release (hd);
@@ -179,17 +179,17 @@ gpgsm_get_default_cert (KsbaCert *r_cert)
 }
 
 
-static KsbaCert
-get_default_signer (void)
+static ksba_cert_t
+get_default_signer (ctrl_t ctrl)
 {
   KEYDB_SEARCH_DESC desc;
-  KsbaCert cert = NULL;
+  ksba_cert_t cert = NULL;
   KEYDB_HANDLE kh = NULL;
   int rc;
 
   if (!opt.local_user)
     {
-      rc = gpgsm_get_default_cert (&cert);
+      rc = gpgsm_get_default_cert (ctrl, &cert);
       if (rc)
         {
           if (rc != -1)
@@ -233,17 +233,18 @@ get_default_signer (void)
    other certificate up in the chain to the Root-CA to the CMS
    object. */
 static int 
-add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
+add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert)
 {
-  KsbaError err;
+  gpg_error_t err;
   int rc = 0;
-  KsbaCert next = NULL;
+  ksba_cert_t next = NULL;
   int n;
   int not_root = 0;
 
   ksba_cert_ref (cert);
 
   n = ctrl->include_certs;
+  log_debug ("adding certificates at level %d\n", n);
   if (n == -2)
     {
       not_root = 1;
@@ -252,6 +253,8 @@ add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
   if (n < 0 || n > 50)
     n = 50; /* We better apply an upper bound */
 
+  /* First add my own certificate unless we don't want any certificate
+     included at all. */
   if (n)
     {
       if (not_root && gpgsm_is_root_cert (cert))
@@ -260,7 +263,12 @@ add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
         err = ksba_cms_add_cert (cms, cert);
       if (err)
         goto ksba_failure;
+      if (n>0)
+        n--;
     }
+  /* Walk the chain to include all other certificates.  Note that a -1
+     used for N makes sure that there is no limit and all certs get
+     included. */
   while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) )
     {
       if (not_root && gpgsm_is_root_cert (next))
@@ -296,11 +304,11 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
             int data_fd, int detached, FILE *out_fp)
 {
   int i, rc;
-  KsbaError err;
+  gpg_error_t err;
   Base64Context b64writer = NULL;
-  KsbaWriter writer;
-  KsbaCMS cms = NULL;
-  KsbaStopReason stopreason;
+  ksba_writer_t writer;
+  ksba_cms_t cms = NULL;
+  ksba_stop_reason_t stopreason;
   KEYDB_HANDLE kh = NULL;
   gcry_md_hd_t data_md = NULL;
   int signer;
@@ -357,7 +365,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
   /* If no list of signers is given, use a default one. */
   if (!signerlist)
     {
-      KsbaCert cert = get_default_signer ();
+      ksba_cert_t cert = get_default_signer (ctrl);
       if (!cert)
         {
           log_error ("no default signer found\n");
@@ -370,7 +378,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
          valid. */
       rc = gpgsm_cert_use_sign_p (cert);
       if (!rc)
-        rc = gpgsm_validate_chain (ctrl, cert, NULL);
+        rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
       if (rc)
         goto leave;
 
@@ -448,8 +456,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
       unsigned char *digest;
       size_t digest_len;
       /* Fixme do this for all signers and get the algo to use from
-         the signer's certificate - does not make mich sense, bu we
-         should do this consistent as we have already done it above */
+         the signer's certificate - does not make mich sense, but we
+         should do this consistent as we have already done it above. */
       algo = GCRY_MD_SHA1; 
       hash_data (data_fd, data_md);
       digest = gcry_md_read (data_md, algo);
@@ -486,6 +494,25 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
         }
     }
 
+  /* 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:
+
+        aes128-CBC
+        des-EDE3-CBC
+  */
+  err = ksba_cms_add_smime_capability (cms, "2.16.840.1.101.3.4.1.2", NULL, 0);
+  if (!err)
+    err = ksba_cms_add_smime_capability (cms, "1.2.840.113549.3.7", NULL, 0);
+  if (err)
+    {
+      log_error ("ksba_cms_add_smime_capability failed: %s\n",
+                 gpg_strerror (err));
+      goto leave;
+    }
+
+
+  /* Main building loop. */
   do 
     {
       err = ksba_cms_build (cms, &stopreason);
@@ -562,7 +589,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
                   goto leave;
                 }
             
-              rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval);
+              rc = gpgsm_create_cms_signature (ctrl, cl->cert,
+                                               md, algo, &sigval);
               if (rc)
                 {
                   gcry_md_close (md);
@@ -588,12 +616,15 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
                   gcry_md_close (md);
                   goto leave;
                 }
-              rc = asprintf (&buf, "%c %d %d 00 %s %s",
-                             detached? 'D':'S',
-                             GCRY_PK_RSA,  /* FIXME: get pk algo from cert */
-                             algo, 
-                             signed_at,
-                             fpr);
+              {
+                int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
+                rc = asprintf (&buf, "%c %d %d 00 %s %s",
+                               detached? 'D':'S',
+                               pkalgo, 
+                               algo, 
+                               signed_at,
+                               fpr);
+              }
               xfree (fpr);
               if (rc < 0)
                 {
@@ -622,6 +653,9 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
 
 
  leave:
+  if (rc)
+    log_error ("error creating signature: %s <%s>\n",
+               gpg_strerror (rc), gpg_strsource (rc) );
   if (release_signerlist)
     gpgsm_release_certlist (signerlist);
   ksba_cms_release (cms);