Pass DBUS_SESSION_BUS_ADDRESS for gnome3
[gnupg.git] / common / openpgp-oid.c
index 222c5a0..7a75801 100644 (file)
@@ -1,14 +1,25 @@
 /* openpgp-oids.c - OID helper for OpenPGP
  * Copyright (C) 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
  *
- * GnuPG is distributed in the hope that it will be useful,
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
 #include "util.h"
 
 
+/* A table with all our supported OpenPGP curves.  */
+static struct {
+  const char *name;   /* Standard name.  */
+  const char *oidstr; /* IETF formatted OID.  */
+  unsigned int nbits; /* Nominal bit length of the curve.  */
+  const char *alias;  /* NULL or alternative name of the curve.  */
+} oidtable[] = {
+
+  { "Ed25519",         "1.3.6.1.4.1.11591.15.1", 255, "ed25519" },
+
+  { "NIST P-256",      "1.2.840.10045.3.1.7",    256, "nistp256" },
+  { "NIST P-384",      "1.3.132.0.34",           384, "nistp384" },
+  { "NIST P-521",      "1.3.132.0.35",           521, "nistp521" },
+
+  { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7",   256 },
+  { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11",  384 },
+  { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13",  512 },
+
+  { "secp256k1",       "1.3.132.0.10",           256 },
+
+  { NULL, NULL, 0}
+};
+
+
+/* The OID for Curve Ed25519 in OpenPGP format.  */
+static const char oid_ed25519[] =
+  { 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
+
+
 /* Helper for openpgp_oid_from_str.  */
 static size_t
 make_flagged_int (unsigned long value, char *buf, size_t buflen)
@@ -145,20 +185,23 @@ openpgp_oid_to_str (gcry_mpi_t a)
 {
   const unsigned char *buf;
   size_t length;
+  unsigned int lengthi;
   char *string, *p;
   int n = 0;
   unsigned long val, valmask;
 
   valmask = (unsigned long)0xfe << (8 * (sizeof (valmask) - 1));
 
-  if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+  if (!a
+      || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
+      || !(buf = gcry_mpi_get_opaque (a, &lengthi)))
     {
       gpg_err_set_errno (EINVAL);
       return NULL;
     }
 
-  buf = gcry_mpi_get_opaque (a, &length);
-  length = (length+7)/8;
+  buf = gcry_mpi_get_opaque (a, &lengthi);
+  length = (lengthi+7)/8;
 
   /* The first bytes gives the length; check consistency.  */
   if (!length || buf[0] != length -1)
@@ -176,7 +219,7 @@ openpgp_oid_to_str (gcry_mpi_t a)
   string = p = xtrymalloc (length*(1+3)+2+1);
   if (!string)
     return NULL;
-  if (!buf || !length)
+  if (!length)
     {
       *p = 0;
       return string;
@@ -195,6 +238,8 @@ openpgp_oid_to_str (gcry_mpi_t a)
         val <<= 7;
         val |= buf[n] & 0x7f;
       }
+    if (val < 80)
+      goto badoid;
     val -= 80;
     sprintf (p, "2.%lu", val);
     p += strlen (p);
@@ -225,3 +270,120 @@ openpgp_oid_to_str (gcry_mpi_t a)
   xfree (string);
   return xtrystrdup ("1.3.6.1.4.1.11591.2.12242973");
 }
+
+
+
+/* Return true if A represents the OID for Ed25519.  */
+int
+openpgp_oid_is_ed25519 (gcry_mpi_t a)
+{
+  const unsigned char *buf;
+  unsigned int nbits;
+  size_t n;
+
+  if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+    return 0;
+
+  buf = gcry_mpi_get_opaque (a, &nbits);
+  n = (nbits+7)/8;
+  return (n == DIM (oid_ed25519)
+          && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
+}
+
+
+
+/* Map the Libgcrypt ECC curve NAME to an OID.  If R_NBITS is not NULL
+   store the bit size of the curve there.  Returns NULL for unknown
+   curve names.  */
+const char *
+openpgp_curve_to_oid (const char *name, unsigned int *r_nbits)
+{
+  int i;
+  unsigned int nbits = 0;
+  const char *oidstr = NULL;
+
+  if (name)
+    {
+      for (i=0; oidtable[i].name; i++)
+        if (!strcmp (oidtable[i].name, name)
+            || (oidtable[i].alias && !strcmp (oidtable[i].alias, name)))
+          {
+            oidstr = oidtable[i].oidstr;
+            nbits  = oidtable[i].nbits;
+            break;
+          }
+      if (!oidtable[i].name)
+        {
+          /* If not found assume the input is already an OID and check
+             whether we support it.  */
+          for (i=0; oidtable[i].name; i++)
+            if (!strcmp (name, oidtable[i].oidstr))
+              {
+                oidstr = oidtable[i].oidstr;
+                nbits  = oidtable[i].nbits;
+                break;
+              }
+        }
+    }
+
+  if (r_nbits)
+    *r_nbits = nbits;
+  return oidstr;
+}
+
+
+/* Map an OpenPGP OID to the Libgcrypt curve NAME.  Returns "?" for
+   unknown curve names.  We prefer an alias name here which is more
+   suitable for printing.  */
+const char *
+openpgp_oid_to_curve (const char *oidstr)
+{
+  int i;
+
+  if (!oidstr)
+    return "";
+
+  for (i=0; oidtable[i].name; i++)
+    if (!strcmp (oidtable[i].oidstr, oidstr))
+      return oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
+
+  return "?";
+}
+
+
+/* Return true if the curve with NAME is supported.  */
+static int
+curve_supported_p (const char *name)
+{
+  int result = 0;
+  gcry_sexp_t keyparms;
+
+  if (!gcry_sexp_build (&keyparms, NULL, "(public-key(ecc(curve %s)))", name))
+    {
+      result = !!gcry_pk_get_curve (keyparms, 0, NULL);
+      gcry_sexp_release (keyparms);
+    }
+  return result;
+}
+
+
+/* Enumerate available and supported OpenPGP curves.  The caller needs
+   to set the integer variable at ITERP to zero and keep on calling
+   this fucntion until NULL is returned.  */
+const char *
+openpgp_enum_curves (int *iterp)
+{
+  int idx = *iterp;
+
+  while (idx >= 0 && idx < DIM (oidtable) && oidtable[idx].name)
+    {
+      if (curve_supported_p (oidtable[idx].name))
+        {
+          *iterp = idx + 1;
+          return oidtable[idx].alias? oidtable[idx].alias : oidtable[idx].name;
+        }
+      idx++;
+    }
+  *iterp = idx;
+  return NULL;
+}