gpg: Remove unused arg from a function.
[gnupg.git] / g10 / sign.c
index 6a7a87e..581a08f 100644 (file)
@@ -15,7 +15,7 @@
  * 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, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "status.h"
-#include "iobuf.h"
+#include "../common/status.h"
+#include "../common/iobuf.h"
 #include "keydb.h"
-#include "util.h"
+#include "../common/util.h"
 #include "main.h"
 #include "filter.h"
-#include "ttyio.h"
+#include "../common/ttyio.h"
 #include "trustdb.h"
-#include "status.h"
-#include "i18n.h"
+#include "../common/status.h"
+#include "../common/i18n.h"
 #include "pkglue.h"
-#include "sysutils.h"
+#include "../common/sysutils.h"
 #include "call-agent.h"
-#include "mbox-util.h"
+#include "../common/mbox-util.h"
+#include "../common/compliance.h"
 
 #ifdef HAVE_DOSISH_SYSTEM
 #define LF "\r\n"
@@ -158,6 +159,21 @@ mk_notation_policy_etc (PKT_signature *sig,
           build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, mbox, strlen (mbox));
           xfree (mbox);
         }
+      else if (opt.sender_list)
+        {
+          /* If a list of --sender was given we scan that list and use
+           * the first one matching a user id of the current key.  */
+
+          /* FIXME: We need to get the list of user ids for the PKSK
+           * packet.  That requires either a function to look it up
+           * again or we need to extend the key packet struct to link
+           * to the primary key which in turn could link to the user
+           * ids.  Too much of a change right now.  Let's take just
+           * one from the supplied list and hope that the caller
+           * passed a matching one.  */
+          build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID,
+                            opt.sender_list->d, strlen (opt.sender_list->d));
+        }
     }
 }
 
@@ -236,9 +252,9 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
 
 
 /* Perform the sign operation.  If CACHE_NONCE is given the agent is
-   advised to use that cached passphrase fro the key.  */
+   advised to use that cached passphrase for the key.  */
 static int
-do_sign (PKT_public_key *pksk, PKT_signature *sig,
+do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
         gcry_md_hd_t md, int mdalgo, const char *cache_nonce)
 {
   gpg_error_t err;
@@ -262,12 +278,44 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
   if (!mdalgo)
     mdalgo = gcry_md_get_algo (md);
 
+  /* Check compliance.  */
+  if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
+    {
+      log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+                gcry_md_algo_name (mdalgo),
+                gnupg_compliance_option_string (opt.compliance));
+      err = gpg_error (GPG_ERR_DIGEST_ALGO);
+      goto leave;
+    }
+
+  if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pksk->pubkey_algo,
+                             pksk->pkey, nbits_from_pk (pksk), NULL))
+    {
+      log_error (_("key %s may not be used for signing in %s mode\n"),
+                 keystr_from_pk (pksk),
+                 gnupg_compliance_option_string (opt.compliance));
+      err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+      goto leave;
+    }
+
+  if (!gnupg_rng_is_compliant (opt.compliance))
+    {
+      err = gpg_error (GPG_ERR_FORBIDDEN);
+      log_error (_("%s is not compliant with %s mode\n"),
+                 "RNG",
+                 gnupg_compliance_option_string (opt.compliance));
+      write_status_error ("random-compliance", err);
+      goto leave;
+    }
+
   print_digest_algo_note (mdalgo);
   dp = gcry_md_read  (md, mdalgo);
   sig->digest_algo = mdalgo;
   sig->digest_start[0] = dp[0];
   sig->digest_start[1] = dp[1];
+  mpi_release (sig->data[0]);
   sig->data[0] = NULL;
+  mpi_release (sig->data[1]);
   sig->data[1] = NULL;
 
 
@@ -277,7 +325,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
       char *desc;
       gcry_sexp_t s_sigval;
 
-      desc = gpg_format_keydesc (pksk, FORMAT_KEYDESC_NORMAL, 1);
+      desc = gpg_format_keydesc (ctrl, pksk, FORMAT_KEYDESC_NORMAL, 1);
       err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc,
                           pksk->keyid, pksk->main_keyid, pksk->pubkey_algo,
                           dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
@@ -304,13 +352,14 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
     }
   xfree (hexgrip);
 
+ leave:
   if (err)
     log_error (_("signing failed: %s\n"), gpg_strerror (err));
   else
     {
       if (opt.verbose)
         {
-          char *ustr = get_user_id_string_native (sig->keyid);
+          char *ustr = get_user_id_string_native (ctrl, sig->keyid);
           log_info (_("%s/%s signature from: \"%s\"\n"),
                     openpgp_pk_algo_name (pksk->pubkey_algo),
                     openpgp_md_algo_name (sig->digest_algo),
@@ -322,14 +371,15 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
 }
 
 
-int
-complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md,
+static int
+complete_sig (ctrl_t ctrl,
+              PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md,
               const char *cache_nonce)
 {
   int rc;
 
   /* if (!(rc = check_secret_key (pksk, 0))) */
-  rc = do_sign (pksk, sig, md, 0, cache_nonce);
+  rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce);
   return rc;
 }
 
@@ -558,7 +608,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass )
         pkt.pkttype = PKT_ONEPASS_SIG;
         pkt.pkt.onepass_sig = ops;
         rc = build_packet (out, &pkt);
-        free_packet (&pkt);
+        free_packet (&pkt, NULL);
         if (rc) {
             log_error ("build onepass_sig packet failed: %s\n",
                        gpg_strerror (rc));
@@ -628,7 +678,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
             log_error ("build_packet(PLAINTEXT) failed: %s\n",
                        gpg_strerror (rc) );
         pt->buf = NULL;
-        free_packet (&pkt);
+        free_packet (&pkt, NULL);
     }
     else {
         byte copy_buffer[4096];
@@ -652,7 +702,8 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
  * hash which will not be changes here.
  */
 static int
-write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
+write_signature_packets (ctrl_t ctrl,
+                         SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
                          int sigclass, u32 timestamp, u32 duration,
                         int status_letter, const char *cache_nonce)
 {
@@ -669,7 +720,10 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
       pk = sk_rover->pk;
 
       /* Build the signature packet.  */
-      sig = xmalloc_clear (sizeof *sig);
+      sig = xtrycalloc (1, sizeof *sig);
+      if (!sig)
+        return gpg_error_from_syserror ();
+
       if (duration || opt.sig_policy_url
           || opt.sig_notations || opt.sig_keyserver_url)
         sig->version = 4;
@@ -699,7 +753,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
       hash_sigversion_to_magic (md, sig);
       gcry_md_final (md);
 
-      rc = do_sign (pk, sig, md, hash_for (pk), cache_nonce);
+      rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce);
       gcry_md_close (md);
       if (!rc)
         {
@@ -712,10 +766,14 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
           rc = build_packet (out, &pkt);
           if (!rc && is_status_enabled())
             print_status_sig_created (pk, sig, status_letter);
-          free_packet (&pkt);
+          free_packet (&pkt, NULL);
           if (rc)
-            log_error ("build signature packet failed: %s\n", gpg_strerror (rc));
+            log_error ("build signature packet failed: %s\n",
+                       gpg_strerror (rc));
        }
+      else
+        free_seckey_enc (sig);
+
       if (rc)
         return rc;
     }
@@ -761,6 +819,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
     memset( &zfx, 0, sizeof zfx);
     memset( &mfx, 0, sizeof mfx);
     memset( &efx, 0, sizeof efx);
+    efx.ctrl = ctrl;
     init_packet( &pkt );
 
     if( filenames ) {
@@ -1042,7 +1101,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
        goto leave;
 
     /* write the signatures */
-    rc = write_signature_packets (sk_list, out, mfx.md,
+    rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
                                   opt.textmode && !outfile? 0x01 : 0x00,
                                  0, duration, detached ? 'D':'S', NULL);
     if( rc )
@@ -1185,8 +1244,8 @@ clearsign_file (ctrl_t ctrl,
     push_armor_filter (afx, out);
 
     /* Write the signatures.  */
-    rc = write_signature_packets (sk_list, out, textmd, 0x01, 0, duration, 'C',
-                                  NULL);
+    rc = write_signature_packets (ctrl, sk_list, out, textmd, 0x01, 0,
+                                  duration, 'C', NULL);
     if( rc )
         goto leave;
 
@@ -1267,10 +1326,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
     s2k->hash_algo = S2K_DIGEST_ALGO;
 
     algo = default_cipher_algo();
-    if (!opt.quiet || !opt.batch)
-        log_info (_("%s encryption will be used\n"),
-                  openpgp_cipher_algo_name (algo) );
-    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
+    cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled);
 
     if (!cfx.dek || !cfx.dek->keylen) {
         rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
@@ -1278,7 +1334,15 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
         goto leave;
     }
 
-    cfx.dek->use_mdc = use_mdc (NULL, cfx.dek->algo);
+    cfx.dek->use_aead = use_aead (NULL, cfx.dek->algo);
+    if (!cfx.dek->use_aead)
+      cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
+
+    if (!opt.quiet || !opt.batch)
+        log_info (_("%s.%s encryption will be used\n"),
+                  openpgp_cipher_algo_name (algo),
+                  cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead)
+                  /**/             : "CFB");
 
     /* now create the outfile */
     rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out);
@@ -1317,12 +1381,15 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
     }
 
     /* Push the encryption filter */
-    iobuf_push_filter( out, cipher_filter, &cfx );
+    iobuf_push_filter (out,
+                       cfx.dek->use_aead? cipher_filter_aead
+                       /**/             : cipher_filter_cfb,
+                       &cfx);
 
     /* Push the compress filter */
     if (default_compress_algo())
       {
-        if (cfx.dek && cfx.dek->use_mdc)
+        if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead))
           zfx.new_ctb = 1;
         push_compress_filter (out, &zfx,default_compress_algo() );
       }
@@ -1345,7 +1412,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
 
     /* Write the signatures */
     /*(current filters: zip - encrypt - armor)*/
-    rc = write_signature_packets (sk_list, out, mfx.md,
+    rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
                                  opt.textmode? 0x01 : 0x00,
                                  0, duration, 'S', NULL);
     if( rc )
@@ -1371,16 +1438,33 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
 
 
 /****************
- * Create a signature packet for the given public key certificate and
- * the user id and return it in ret_sig. User signature class SIGCLASS
- * user-id is not used (and may be NULL if sigclass is 0x20) If
- * DIGEST_ALGO is 0 the function selects an appropriate one.
- * SIGVERSION gives the minimal required signature packet version;
- * this is needed so that special properties like local sign are not
- * applied (actually: dropped) when a v3 key is used.  TIMESTAMP is
- * the timestamp to use for the signature. 0 means "now" */
+ * Create a v4 signature in *RET_SIG.
+ *
+ * PK is the primary key to sign (required for all sigs)
+ * UID is the user id to sign (required for 0x10..0x13, 0x30)
+ * SUBPK is subkey to sign (required for 0x18, 0x19, 0x28)
+ *
+ * PKSK is the signing key
+ *
+ * SIGCLASS is the type of signature to create.
+ *
+ * DIGEST_ALGO is the digest algorithm.  If it is 0 the function
+ * selects an appropriate one.
+ *
+ * TIMESTAMP is the timestamp to use for the signature. 0 means "now"
+ *
+ * DURATION is the amount of time (in seconds) until the signature
+ * expires.
+ *
+ * This function creates the following subpackets: issuer, created,
+ * and expire (if duration is not 0).  Additional subpackets can be
+ * added using MKSUBPKT, which is called after these subpackets are
+ * added and before the signature is generated.  OPAQUE is passed to
+ * MKSUBPKT.
+ */
 int
-make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
+make_keysig_packet (ctrl_t ctrl,
+                    PKT_signature **ret_sig, PKT_public_key *pk,
                    PKT_user_id *uid, PKT_public_key *subpk,
                    PKT_public_key *pksk,
                    int sigclass, int digest_algo,
@@ -1473,7 +1557,7 @@ make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
         hash_sigversion_to_magic (md, sig);
        gcry_md_final (md);
 
-       rc = complete_sig (sig, pksk, md, cache_nonce);
+       rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
     }
 
     gcry_md_close (md);
@@ -1495,7 +1579,8 @@ make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
  * TODO: Merge this with make_keysig_packet.
  */
 gpg_error_t
-update_keysig_packet( PKT_signature **ret_sig,
+update_keysig_packet (ctrl_t ctrl,
+                      PKT_signature **ret_sig,
                       PKT_signature *orig_sig,
                       PKT_public_key *pk,
                       PKT_user_id *uid,
@@ -1572,7 +1657,7 @@ update_keysig_packet( PKT_signature **ret_sig,
         hash_sigversion_to_magic (md, sig);
        gcry_md_final (md);
 
-       rc = complete_sig (sig, pksk, md, NULL);
+       rc = complete_sig (ctrl, sig, pksk, md, NULL);
     }
 
  leave: