gpg: New option --key-origin.
[gnupg.git] / g10 / encrypt.c
index 57d24be..4b21a61 100644 (file)
@@ -16,7 +16,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 "trustdb.h"
-#include "i18n.h"
-#include "status.h"
+#include "../common/i18n.h"
+#include "../common/status.h"
 #include "pkglue.h"
+#include "../common/compliance.h"
 
 
 static int encrypt_simple( const char *filename, int mode, int use_seskey );
-static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out );
+static int write_pubkey_enc_from_list (ctrl_t ctrl,
+                                       PK_LIST pk_list, DEK *dek, iobuf_t out);
 
 /****************
  * Encrypt FILENAME with only the symmetric cipher.  Take input from
@@ -221,8 +223,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
       s2k = xmalloc_clear( sizeof *s2k );
       s2k->mode = opt.s2k_mode;
       s2k->hash_algo = S2K_DIGEST_ALGO;
-      cfx.dek = passphrase_to_dek (NULL, 0,
-                                   default_cipher_algo(), s2k, 4,
+      cfx.dek = passphrase_to_dek (default_cipher_algo (), s2k, 1, 0,
                                    NULL, &canceled);
       if ( !cfx.dek || !cfx.dek->keylen )
         {
@@ -320,7 +321,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
            && !overflow && opt.verbose)
         log_info(_("WARNING: '%s' is an empty file\n"), filename );
       /* We can't encode the length of very large files because
-         OpenPGP uses only 32 bit for file sizes.  So if the the
+         OpenPGP uses only 32 bit for file sizes.  So if the
          size of a file is larger than 2^32 minus some bytes for
          packet headers, we switch to partial length encoding. */
       if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
@@ -335,7 +336,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
     {
       /* Note that PT has been initialized above in !no_literal mode.  */
       pt->timestamp = make_timestamp();
-      pt->mode = opt.textmode? 't' : 'b';
+      pt->mode = opt.mimemode? 'm' : opt.textmode? 't' : 'b';
       pt->len = filesize;
       pt->new_ctb = !pt->len;
       pt->buf = inp;
@@ -395,7 +396,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
     }
   if (pt)
     pt->buf = NULL;
-  free_packet (&pkt);
+  free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (s2k);
   release_armor_context (afx);
@@ -413,8 +414,8 @@ setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek)
   (*symkey_s2k)->mode = opt.s2k_mode;
   (*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
 
-  *symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_algo,
-                               *symkey_s2k, 4, NULL, &canceled);
+  *symkey_dek = passphrase_to_dek (opt.s2k_cipher_algo,
+                                   *symkey_s2k, 1, 0, NULL, &canceled);
   if(!*symkey_dek || !(*symkey_dek)->keylen)
     {
       xfree(*symkey_dek);
@@ -462,7 +463,7 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
  * The caller may provide a checked list of public keys in
  * PROVIDED_PKS; if not the function builds a list of keys on its own.
  *
- * Note that FILEFD is currently only used by cmd_encrypt in the the
+ * Note that FILEFD is currently only used by cmd_encrypt in the
  * not yet finished server.c.
  */
 int
@@ -485,6 +486,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
   progress_filter_context_t *pfx;
   PK_LIST pk_list;
   int do_compress;
+  int compliant;
 
   if (filefd != -1 && filename)
     return gpg_error (GPG_ERR_INV_ARG);  /* Both given.  */
@@ -612,6 +614,53 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
       cfx.dek->algo = opt.def_cipher_algo;
     }
 
+  /* Check compliance.  */
+  if (! gnupg_cipher_is_allowed (opt.compliance, 1, cfx.dek->algo,
+                                 GCRY_CIPHER_MODE_CFB))
+    {
+      log_error (_("you may not use cipher algorithm '%s'"
+                  " while in %s mode\n"),
+                openpgp_cipher_algo_name (cfx.dek->algo),
+                gnupg_compliance_option_string (opt.compliance));
+      rc = gpg_error (GPG_ERR_CIPHER_ALGO);
+      goto leave;
+    }
+
+  compliant = gnupg_cipher_is_compliant (CO_DE_VS, cfx.dek->algo,
+                                         GCRY_CIPHER_MODE_CFB);
+
+  {
+    pk_list_t pkr;
+
+    for (pkr = pk_list; pkr; pkr = pkr->next)
+      {
+        PKT_public_key *pk = pkr->pk;
+        unsigned int nbits = nbits_from_pk (pk);
+
+        if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_ENCRYPTION,
+                                   pk->pubkey_algo, pk->pkey, nbits, NULL))
+          {
+            log_error (_("key %s not suitable for encryption"
+                         " while in %s mode\n"),
+                       keystr_from_pk (pk),
+                       gnupg_compliance_option_string (opt.compliance));
+            rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
+            goto leave;
+          }
+
+        if (compliant
+            && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
+                                       nbits, NULL))
+          compliant = 0;
+      }
+
+  }
+
+  if (compliant)
+    write_status_strings (STATUS_ENCRYPTION_COMPLIANCE_MODE,
+                          gnupg_status_compliance_flag (CO_DE_VS),
+                          NULL);
+
   cfx.dek->use_mdc = use_mdc (pk_list,cfx.dek->algo);
 
   /* Only do the is-file-already-compressed check if we are using a
@@ -635,7 +684,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
   if (DBG_CRYPTO)
     log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen );
 
-  rc = write_pubkey_enc_from_list (pk_list, cfx.dek, out);
+  rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out);
   if (rc)
     goto leave;
 
@@ -660,7 +709,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
            && !overflow && opt.verbose)
         log_info(_("WARNING: '%s' is an empty file\n"), filename );
       /* We can't encode the length of very large files because
-         OpenPGP uses only 32 bit for file sizes.  So if the the size
+         OpenPGP uses only 32 bit for file sizes.  So if the size
          of a file is larger than 2^32 minus some bytes for packet
          headers, we switch to partial length encoding. */
       if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
@@ -674,7 +723,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
   if (!opt.no_literal)
     {
       pt->timestamp = make_timestamp();
-      pt->mode = opt.textmode ? 't' : 'b';
+      pt->mode = opt.mimemode? 'm' : opt.textmode ? 't' : 'b';
       pt->len = filesize;
       pt->new_ctb = !pt->len;
       pt->buf = inp;
@@ -756,7 +805,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
     }
   if (pt)
     pt->buf = NULL;
-  free_packet (&pkt);
+  free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (symkey_dek);
   xfree (symkey_s2k);
@@ -829,7 +878,8 @@ encrypt_filter (void *opaque, int control,
           if (DBG_CRYPTO)
             log_printhex ("DEK is: ", efx->cfx.dek->key, efx->cfx.dek->keylen);
 
-          rc = write_pubkey_enc_from_list (efx->pk_list, efx->cfx.dek, a);
+          rc = write_pubkey_enc_from_list (efx->ctrl,
+                                           efx->pk_list, efx->cfx.dek, a);
           if (rc)
             return rc;
 
@@ -865,7 +915,8 @@ encrypt_filter (void *opaque, int control,
  * Write a pubkey-enc packet for the public key PK to OUT.
  */
 int
-write_pubkey_enc (PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out)
+write_pubkey_enc (ctrl_t ctrl,
+                  PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out)
 {
   PACKET pkt;
   PKT_pubkey_enc *enc;
@@ -900,7 +951,7 @@ write_pubkey_enc (PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out)
     {
       if ( opt.verbose )
         {
-          char *ustr = get_user_id_string_native (enc->keyid);
+          char *ustr = get_user_id_string_native (ctrl, enc->keyid);
           log_info (_("%s/%s encrypted for: \"%s\"\n"),
                     openpgp_pk_algo_name (enc->pubkey_algo),
                     openpgp_cipher_algo_name (dek->algo),
@@ -925,12 +976,13 @@ write_pubkey_enc (PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out)
  * Write pubkey-enc packets from the list of PKs to OUT.
  */
 static int
-write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
+write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out)
 {
   if (opt.throw_keyids && (PGP6 || PGP7 || PGP8))
     {
       log_info(_("you may not use %s while in %s mode\n"),
-               "--throw-keyids",compliance_option_string());
+               "--throw-keyids",
+               gnupg_compliance_option_string (opt.compliance));
       compliance_failure();
     }
 
@@ -938,7 +990,7 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
     {
       PKT_public_key *pk = pk_list->pk;
       int throw_keyid = (opt.throw_keyids || (pk_list->flags&1));
-      int rc = write_pubkey_enc (pk, throw_keyid, dek, out);
+      int rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out);
       if (rc)
         return rc;
     }