gpg: New option --force-aead
authorWerner Koch <wk@gnupg.org>
Wed, 10 Jan 2018 16:07:11 +0000 (17:07 +0100)
committerWerner Koch <wk@gnupg.org>
Wed, 10 Jan 2018 16:07:11 +0000 (17:07 +0100)
* g10/dek.h (DEK): Turn fields use_mdc, algo_printed and symmetric
into single bit vars.  Make sure they are always set to 1 or 0.
(DEK): New field use_aead.
* g10/options.h (struct opt): New field force_aead.
* g10/pkclist.c (select_aead_from_pklist): New.
* g10/gpg.c (oForceAEAD): New const.
(opts): New options "--force-aead".
(main): Set new option.
* g10/encrypt.c (use_aead): New.
(encrypt_simple): Implement new flags DEK.use_aead.
(encrypt_crypt): Ditto.
(encrypt_filter): Ditto.
* g10/sign.c (sign_symencrypt_file): Ditto.
--

This patch should be enough to detect whether AEAD can be used.
Not tested.

Signed-off-by: Werner Koch <wk@gnupg.org>
g10/dek.h
g10/encrypt.c
g10/gpg.c
g10/keydb.h
g10/main.h
g10/options.h
g10/pkclist.c
g10/sign.c

index 666810c..64e98fc 100644 (file)
--- a/g10/dek.h
+++ b/g10/dek.h
@@ -1,5 +1,5 @@
 /* dek.h - The data encryption key structure.
- * Copyright (C) 2014 Werner Koch
+ * Copyright (C) 2014, 2017 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -26,14 +26,25 @@ typedef struct
   int algo;
   /* The length of the key (in bytes).  */
   int keylen;
+
   /* Whether we've already printed information about this key.  This
-     is currently only used in decrypt_data() and only if we are in
-     verbose mode.  */
-  int algo_info_printed;
-  int use_mdc;
+   * is currently only used in decrypt_data() and only if we are in
+   * verbose mode.  */
+  int algo_info_printed : 1;
+
+  /* AEAD shall be used.  */
+  int use_aead : 1;
+
+  /* MDC shall be used.  */
+  int use_mdc : 1;
+
   /* This key was read from a SK-ESK packet (see proc_symkey_enc).  */
-  int symmetric;
-  byte key[32]; /* This is the largest used keylen (256 bit). */
+  int symmetric : 1;
+
+  /* This is the largest used keylen (256 bit). */
+  byte key[32];
+
+  /* The cacheid for the S2K. */
   char s2k_cacheid[1+16+1];
 } DEK;
 
index 263226a..2951a45 100644 (file)
@@ -109,6 +109,47 @@ encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey)
 }
 
 
+/* Return true if we shall use AEAD mode.  */
+int
+use_aead (pk_list_t pk_list, int algo)
+{
+  int can_use;
+
+  if (!opt.flags.rfc4880bis)
+    {
+      if (opt.force_aead)
+        log_info ("Warning: Option %s currently requires option '%s'\n",
+                  "--force-aead", "--rfc4880bis");
+      return 0;
+    }
+
+  can_use = openpgp_cipher_get_algo_blklen (algo) != 16;
+
+  /* With --force-mdc we clearly do not want AEAD.  */
+  if (opt.force_mdc)
+    return 0;
+
+  /* However with --force-aead we want AEAD.  */
+  if (opt.force_aead)
+    {
+      if (!can_use)
+        log_info ("Warning: request to use AEAD ignored for cipher '%s'\n",
+                  openpgp_cipher_algo_name (algo));
+      return 1;
+    }
+
+  /* AEAD does noly work with 128 bit cipher blocklength.  */
+  if (!can_use)
+    return 0;
+
+  /* If all keys support AEAD we can use it.  */
+  if (select_aead_from_pklist (pk_list))
+    return 1;
+
+  return 0; /* No AEAD. */
+}
+
+
 /* We try very hard to use a MDC */
 int
 use_mdc (pk_list_t pk_list,int algo)
@@ -265,10 +306,15 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
         log_info(_("using cipher %s\n"),
                  openpgp_cipher_algo_name (cfx.dek->algo));
 
-      cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
+      if (use_aead (NULL, cfx.dek->algo))
+        cfx.dek->use_aead = 1;
+      else
+        cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
     }
 
-  if (do_compress && cfx.dek && cfx.dek->use_mdc
+  if (do_compress
+      && cfx.dek
+      && (cfx.dek->use_mdc || cfx.dek->use_aead)
       && is_file_compressed(filename, &rc))
     {
       if (opt.verbose)
@@ -368,7 +414,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
   /* Register the compress filter. */
   if ( do_compress )
     {
-      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());
     }
@@ -676,14 +722,18 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
                           gnupg_status_compliance_flag (CO_DE_VS),
                           NULL);
 
-  cfx.dek->use_mdc = use_mdc (pk_list,cfx.dek->algo);
+  if (use_aead (pk_list, cfx.dek->algo))
+    cfx.dek->use_aead = 1;
+  else
+    cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo);
 
   /* Only do the is-file-already-compressed check if we are using a
-     MDC.  This forces compressed files to be re-compressed if we do
-     not have a MDC to give some protection against chosen ciphertext
-     attacks. */
-
-  if (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2))
+   * MDC or AEAD.  This forces compressed files to be re-compressed if
+   * we do not have a MDC to give some protection against chosen
+   * ciphertext attacks. */
+  if (do_compress
+      && (cfx.dek->use_mdc || cfx.dek->use_aead)
+      && is_file_compressed (filename, &rc2))
     {
       if (opt.verbose)
         log_info(_("'%s' already compressed\n"), filename);
@@ -777,7 +827,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
       /* Algo 0 means no compression. */
       if (compr_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,compr_algo);
         }
@@ -887,7 +937,10 @@ encrypt_filter (void *opaque, int control,
              efx->cfx.dek->algo = opt.def_cipher_algo;
            }
 
-          efx->cfx.dek->use_mdc = use_mdc (efx->pk_list,efx->cfx.dek->algo);
+          if (use_aead (efx->pk_list, efx->cfx.dek->algo))
+            efx->cfx.dek->use_aead = 1;
+          else
+            efx->cfx.dek->use_mdc = !!use_mdc (efx->pk_list,efx->cfx.dek->algo);
 
           make_session_key ( efx->cfx.dek );
           if (DBG_CRYPTO)
index fadd2f0..a643388 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -304,6 +304,7 @@ enum cmd_and_opt_values
     oNoForceMDC,
     oDisableMDC,
     oNoDisableMDC,
+    oForceAEAD,
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
@@ -605,6 +606,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oDisableMDC, "disable-mdc", "@"),
   ARGPARSE_s_n (oNoDisableMDC, "no-disable-mdc", "@"),
 
+  ARGPARSE_s_n (oForceAEAD, "force-aead", "@"),
+
   ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"),
 
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
@@ -2977,6 +2980,8 @@ main (int argc, char **argv)
          case oDisableMDC: opt.disable_mdc = 1; break;
          case oNoDisableMDC: opt.disable_mdc = 0; break;
 
+         case oForceAEAD: opt.force_aead = 1; break;
+
           case oDisableSignerUID: opt.flags.disable_signer_uid = 1; break;
 
          case oS2KMode:   opt.s2k_mode = pargs.r.ret_int; break;
index 7393768..9f6064b 100644 (file)
@@ -232,6 +232,7 @@ int  algo_available( preftype_t preftype, int algo,
 int  select_algo_from_prefs( PK_LIST pk_list, int preftype,
                             int request, const union pref_hint *hint);
 int  select_mdc_from_pklist (PK_LIST pk_list);
+int  select_aead_from_pklist (pk_list_t pk_list);
 void warn_missing_mdc_from_pklist (PK_LIST pk_list);
 void warn_missing_aes_from_pklist (PK_LIST pk_list);
 
index 6abc598..393a1b0 100644 (file)
@@ -233,6 +233,7 @@ void display_online_help( const char *keyword );
 /*-- encode.c --*/
 int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
 void encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey);
+int use_aead (pk_list_t pk_list, int algo);
 int use_mdc (pk_list_t pk_list,int algo);
 int encrypt_symmetric (const char *filename );
 int encrypt_store (const char *filename );
index 6ad1037..36bea69 100644 (file)
@@ -95,6 +95,7 @@ struct
   int def_aead_algo;
   int force_mdc;
   int disable_mdc;
+  int force_aead;
   int def_digest_algo;
   int cert_digest_algo;
   int compress_algo;
index a759672..b85efa4 100644 (file)
@@ -1651,6 +1651,31 @@ select_mdc_from_pklist (PK_LIST pk_list)
 }
 
 
+/* Select the AEAD flag from the pk_list.  We can only use AEAD if all
+ * recipients support this feature.  Returns true if AEAD can be used.  */
+int
+select_aead_from_pklist (PK_LIST pk_list)
+{
+  pk_list_t pkr;
+  int aead;
+
+  if (!pk_list)
+    return 0;
+
+  for (pkr = pk_list; pkr; pkr = pkr->next)
+    {
+      if (pkr->pk->user_id) /* selected by user ID */
+        aead = pkr->pk->user_id->flags.aead;
+      else
+        aead = pkr->pk->flags.aead;
+      if (!aead)
+        return 0;  /* At least one recipient does not support it. */
+    }
+
+  return 1; /* Can be used. */
+}
+
+
 /* Print a warning for all keys in PK_LIST missing the MDC feature. */
 void
 warn_missing_mdc_from_pklist (PK_LIST pk_list)
index 4cf0cd3..f8a1241 100644 (file)
@@ -1337,7 +1337,10 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
         goto leave;
     }
 
-    cfx.dek->use_mdc = use_mdc (NULL, cfx.dek->algo);
+    if (use_aead (NULL, cfx.dek->algo))
+      cfx.dek->use_aead = 1;
+    else
+      cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
 
     /* now create the outfile */
     rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out);
@@ -1381,7 +1384,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
     /* 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() );
       }