Merge branch 'STABLE-BRANCH-2-2' into master
[gnupg.git] / g10 / misc.c
index 547944d..1e6df5f 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>
@@ -42,6 +42,7 @@
 #include <time.h>
 #include <process.h>
 #ifdef HAVE_WINSOCK2_H
+# define WIN32_LEAN_AND_MEAN 1
 # include <winsock2.h>
 #endif
 #include <windows.h>
 
 #include "gpg.h"
 #ifdef HAVE_W32_SYSTEM
-# include "status.h"
+# include "../common/status.h"
 #endif /*HAVE_W32_SYSTEM*/
-#include "util.h"
+#include "../common/util.h"
 #include "main.h"
 #include "photoid.h"
 #include "options.h"
 #include "call-agent.h"
-#include "i18n.h"
-#include "zb32.h"
+#include "../common/i18n.h"
+#include "../common/zb32.h"
 
-#include <assert.h>
+
+/* FIXME: Libgcrypt 1.9 will support EAX.  Until we kame this a
+ * requirement we hardwire the enum used for EAX.  */
+#define MY_GCRY_CIPHER_MODE_EAX 14
 
 
 #ifdef ENABLE_SELINUX_HACKS
@@ -358,6 +362,52 @@ print_digest_rejected_note (enum gcry_md_algos algo)
 }
 
 
+/* Print a message
+ *  "(reported error: %s)\n
+ * in verbose mode to further explain an error.  If the error code has
+ * the value IGNORE_EC no message is printed.  A message is also not
+ * printed if ERR is 0.  */
+void
+print_reported_error (gpg_error_t err, gpg_err_code_t ignore_ec)
+{
+  if (!opt.verbose)
+    return;
+
+  if (!gpg_err_code (err))
+    ;
+  else if (gpg_err_code (err) == ignore_ec)
+    ;
+  else if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
+    log_info (_("(reported error: %s)\n"),
+              gpg_strerror (err));
+  else
+    log_info (_("(reported error: %s <%s>)\n"),
+              gpg_strerror (err), gpg_strsource (err));
+
+}
+
+
+/* Print a message
+ *   "(further info: %s)\n
+ * in verbose mode to further explain an error.  That message is
+ * intended to help debug a problem and should not be translated.
+ */
+void
+print_further_info (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!opt.verbose)
+    return;
+
+  log_info (_("(further info: "));
+  va_start (arg_ptr, format);
+  log_logv (GPGRT_LOGLVL_CONT, format, arg_ptr);
+  va_end (arg_ptr);
+  log_printf (")\n");
+}
+
+
 /* Map OpenPGP algo numbers to those used by Libgcrypt.  We need to do
    this for algorithms we implemented in Libgcrypt after they become
    part of OpenPGP.  */
@@ -429,8 +479,8 @@ map_cipher_openpgp_to_gcry (cipher_algo_t algo)
 #else
     case CIPHER_ALGO_CAMELLIA256: return 0;
 #endif
+    default: return 0;
     }
-  return 0;
 }
 
 /* The inverse function of above.  */
@@ -465,7 +515,7 @@ map_pk_gcry_to_openpgp (enum gcry_pk_algos algo)
     {
     case GCRY_PK_ECDSA:  return PUBKEY_ALGO_ECDSA;
     case GCRY_PK_ECDH:   return PUBKEY_ALGO_ECDH;
-    default: return algo < 110 ? algo : 0;
+    default: return algo < 110 ? (pubkey_algo_t)algo : 0;
     }
 }
 
@@ -478,7 +528,7 @@ openpgp_cipher_blocklen (cipher_algo_t algo)
      block length.  This is so that the packet parsing code works even
      for unknown algorithms (for which we assume 8 due to tradition).
 
-     NOTE: If you change the the returned blocklen above 16, check
+     NOTE: If you change the returned blocklen above 16, check
      the callers because they may use a fixed size buffer of that
      size. */
   switch (algo)
@@ -521,7 +571,6 @@ openpgp_cipher_algo_name (cipher_algo_t algo)
 {
   switch (algo)
     {
-    case CIPHER_ALGO_NONE:        break;
     case CIPHER_ALGO_IDEA:        return "IDEA";
     case CIPHER_ALGO_3DES:       return "3DES";
     case CIPHER_ALGO_CAST5:      return "CAST5";
@@ -533,11 +582,86 @@ openpgp_cipher_algo_name (cipher_algo_t algo)
     case CIPHER_ALGO_CAMELLIA128: return "CAMELLIA128";
     case CIPHER_ALGO_CAMELLIA192: return "CAMELLIA192";
     case CIPHER_ALGO_CAMELLIA256: return "CAMELLIA256";
+    case CIPHER_ALGO_NONE:
+    default: return "?";
+    }
+}
+
+
+/* Return 0 if ALGO is supported.  Return an error if not. */
+gpg_error_t
+openpgp_aead_test_algo (aead_algo_t algo)
+{
+  /* FIXME: We currently have no easy way to test whether libgcrypt
+   * implements a mode.  The only way we can do this is to open a
+   * cipher context with that mode and close it immediately.  That is
+   * a bit costly.  So we look at the libgcrypt version and assume
+   * nothing has been patched out.  */
+  switch (algo)
+    {
+    case AEAD_ALGO_NONE:
+      break;
+
+    case AEAD_ALGO_EAX:
+#if GCRYPT_VERSION_NUMBER < 0x010900
+      break;
+#else
+      return 0;
+#endif
+
+    case AEAD_ALGO_OCB:
+      return 0;
     }
+
+  return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+}
+
+
+/* Map the OpenPGP AEAD algorithm with ID ALGO to a string
+ * representation of the algorithm name.  For unknown algorithm IDs
+ * this function returns "?".  */
+const char *
+openpgp_aead_algo_name (aead_algo_t algo)
+{
+  switch (algo)
+    {
+    case AEAD_ALGO_NONE:  break;
+    case AEAD_ALGO_EAX:   return "EAX";
+    case AEAD_ALGO_OCB:   return "OCB";
+    }
+
   return "?";
 }
 
 
+/* Return information for the AEAD algorithm ALGO.  The corresponding
+ * Libgcrypt ciphermode is stored at R_MODE and the required number of
+ * octets for the nonce at R_NONCELEN.  On error and error code is
+ * returned.  Note that the taglen is always 128 bits.  */
+gpg_error_t
+openpgp_aead_algo_info (aead_algo_t algo, enum gcry_cipher_modes *r_mode,
+                        unsigned int *r_noncelen)
+{
+  switch (algo)
+    {
+    case AEAD_ALGO_OCB:
+      *r_mode = GCRY_CIPHER_MODE_OCB;
+      *r_noncelen = 15;
+      break;
+
+    case AEAD_ALGO_EAX:
+      *r_mode = MY_GCRY_CIPHER_MODE_EAX;
+      *r_noncelen = 16;
+      break;
+
+    default:
+      log_error ("unsupported AEAD algo %d\n", algo);
+      return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+    }
+  return 0;
+}
+
+
 /* Return 0 if ALGO is a supported OpenPGP public key algorithm.  */
 int
 openpgp_pk_test_algo (pubkey_algo_t algo)
@@ -592,11 +716,14 @@ openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use)
       if (RFC2440)
         ga = GCRY_PK_ELG;
       break;
+
+    default:
+      break;
     }
   if (!ga)
     return gpg_error (GPG_ERR_PUBKEY_ALGO);
 
-  /* No check whether Libgcrypt has support for the algorithm.  */
+  /* Now check whether Libgcrypt has support for the algorithm.  */
   return gcry_pk_algo_info (ga, GCRYCTL_TEST_ALGO, NULL, &use_buf);
 }
 
@@ -655,8 +782,8 @@ openpgp_pk_algo_name (pubkey_algo_t algo)
     case PUBKEY_ALGO_ECDH:      return "ECDH";
     case PUBKEY_ALGO_ECDSA:     return "ECDSA";
     case PUBKEY_ALGO_EDDSA:     return "EDDSA";
+    default: return "?";
     }
-  return "?";
 }
 
 
@@ -700,8 +827,8 @@ map_md_openpgp_to_gcry (digest_algo_t algo)
 #else
     case DIGEST_ALGO_SHA512: return 0;
 #endif
+    default: return 0;
     }
-  return 0;
 }
 
 
@@ -1065,6 +1192,39 @@ string_to_cipher_algo (const char *string)
   return val;
 }
 
+
+/*
+ * Map an AEAD mode string to a an AEAD algorithm number as defined by
+ * rrc4880bis.  Also support the "An" syntax as used by the preference
+ * strings.
+ */
+aead_algo_t
+string_to_aead_algo (const char *string)
+{
+  int result;
+
+  if (!string)
+    result = 0;
+  if (!ascii_strcasecmp (string, "EAX"))
+    result = 1;
+  else if (!ascii_strcasecmp (string, "OCB"))
+    result = 2;
+  else if ((string[0]=='A' || string[0]=='a'))
+    {
+      char *endptr;
+
+      string++;
+      result = strtol (string, &endptr, 10);
+      if (!*string || *endptr || result < 1 || result > 2)
+        result = 0;
+    }
+  else
+    result = 0;
+
+  return result;
+}
+
+
 /*
  * Wrapper around gcry_md_map_name to provide a fallback using the
  * "Hn" syntax as used by the preference strings.
@@ -1181,6 +1341,18 @@ default_cipher_algo(void)
     return opt.s2k_cipher_algo;
 }
 
+
+aead_algo_t
+default_aead_algo(void)
+{
+  if(opt.def_aead_algo)
+    return opt.def_aead_algo;
+  else if(opt.personal_aead_prefs)
+    return opt.personal_aead_prefs[0].value;
+  else
+    return DEFAULT_AEAD_ALGO;
+}
+
 /* There is no default_digest_algo function, but see
    sign.c:hash_for() */
 
@@ -1195,23 +1367,6 @@ default_compress_algo(void)
     return DEFAULT_COMPRESS_ALGO;
 }
 
-const char *
-compliance_option_string(void)
-{
-  char *ver="???";
-
-  switch(opt.compliance)
-    {
-    case CO_GNUPG:   return "--gnupg";
-    case CO_RFC4880: return "--openpgp";
-    case CO_RFC2440: return "--rfc2440";
-    case CO_PGP6:    return "--pgp6";
-    case CO_PGP7:    return "--pgp7";
-    case CO_PGP8:    return "--pgp8";
-    }
-
-  return ver;
-}
 
 void
 compliance_failure(void)
@@ -1243,6 +1398,10 @@ compliance_failure(void)
     case CO_PGP8:
       ver="PGP 8.x";
       break;
+
+    case CO_DE_VS:
+      ver="DE-VS applications";
+      break;
     }
 
   log_info(_("this message may not be usable by %s\n"),ver);
@@ -1515,8 +1674,8 @@ pubkey_get_npkey (pubkey_algo_t algo)
     case PUBKEY_ALGO_ECDSA:     return 2;
     case PUBKEY_ALGO_ELGAMAL:   return 3;
     case PUBKEY_ALGO_EDDSA:     return 2;
+    default: return 0;
     }
-  return 0;
 }
 
 
@@ -1535,8 +1694,8 @@ pubkey_get_nskey (pubkey_algo_t algo)
     case PUBKEY_ALGO_ECDSA:     return 3;
     case PUBKEY_ALGO_ELGAMAL:   return 4;
     case PUBKEY_ALGO_EDDSA:     return 3;
+    default: return 0;
     }
-  return 0;
 }
 
 /* Temporary helper. */
@@ -1554,8 +1713,8 @@ pubkey_get_nsig (pubkey_algo_t algo)
     case PUBKEY_ALGO_ECDSA:     return 2;
     case PUBKEY_ALGO_ELGAMAL:   return 2;
     case PUBKEY_ALGO_EDDSA:     return 2;
+    default: return 0;
     }
-  return 0;
 }
 
 
@@ -1574,8 +1733,8 @@ pubkey_get_nenc (pubkey_algo_t algo)
     case PUBKEY_ALGO_ECDSA:     return 0;
     case PUBKEY_ALGO_ELGAMAL:   return 2;
     case PUBKEY_ALGO_EDDSA:     return 0;
+    default: return 0;
     }
-  return 0;
 }