aboutsummaryrefslogtreecommitdiffstats
path: root/common/openpgp-oid.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-02-09 20:20:48 +0000
committerWerner Koch <[email protected]>2020-02-09 20:26:35 +0000
commit3a1fa13eedb969b561bae18cd3d7c2fb0b63d6ab (patch)
tree704e4441d3a713a82dd587e94c6874cd1615f87e /common/openpgp-oid.c
parentcommon: Add OpenPGP<->Gcrypt pubkey id mapping functions. (diff)
downloadgnupg-3a1fa13eedb969b561bae18cd3d7c2fb0b63d6ab.tar.gz
gnupg-3a1fa13eedb969b561bae18cd3d7c2fb0b63d6ab.zip
common: New function get_keyalgo_string.
* common/openpgp-oid.c (struct keyalgo_string_s): New. (keyalgo_strings): New. (keyalgo_strings_size, keyalgo_strings_used): New. (get_keyalgo_string): New. -- This function is intended as a more general version of gpg's pubkey_string function. It has the advantage to avoid mallocs and uses static table of algorithm strings instead. There should be only a few dozen of such strings (if at all) and thus all those allocations we do internally in gpg's pubkey_string and the static buffers all over the place are not too nice. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'common/openpgp-oid.c')
-rw-r--r--common/openpgp-oid.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c
index 802d71162..b539f8588 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -71,6 +71,21 @@ static const char oid_ed25519[] =
static const char oid_cv25519[] =
{ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
+/* A table to store keyalgo strings like "rsa2048 or "ed25519" so that
+ * we do not need to allocate them. This is currently a simple array
+ * but may eventually be changed to a fast data structure. Noet that
+ * unknown algorithms are stored with (NBITS,CURVE) set to (0,NULL). */
+struct keyalgo_string_s
+{
+ enum gcry_pk_algos algo; /* Mandatory. */
+ unsigned int nbits; /* Size for classical algos. */
+ char *curve; /* Curvename (OID) or NULL. */
+ char *name; /* Allocated name. */
+};
+static struct keyalgo_string_s *keyalgo_strings; /* The table. */
+static size_t keyalgo_strings_size; /* Allocated size. */
+static size_t keyalgo_strings_used; /* Used size. */
+
/* Helper for openpgp_oid_from_str. */
static size_t
@@ -492,3 +507,109 @@ map_openpgp_pk_to_gcry (pubkey_algo_t algo)
default: return algo < 110 ? algo : 0;
}
}
+
+
+/* Return a string describing the public key algorithm and the
+ * keysize. For elliptic curves the function prints the name of the
+ * curve because the keysize is a property of the curve. ALGO is the
+ * Gcrypt algorithmj number, curve is either NULL or give the PID of
+ * the curve, NBITS is either 0 or the size of the algorithms for RSA
+ * etc. The returned string is taken from permanent table. Examples
+ * for the output are:
+ *
+ * "rsa3072" - RSA with 3072 bit
+ * "elg1024" - Elgamal with 1024 bit
+ * "ed25519" - ECC using the curve Ed25519.
+ * "E_1.2.3.4" - ECC using the unsupported curve with OID "1.2.3.4".
+ * "E_1.3.6.1.4.1.11591.2.12242973" - ECC with a bogus OID.
+ * "unknown_N" - Unknown OpenPGP algorithm N.
+ * If N is > 110 this is a gcrypt algo.
+ */
+const char *
+get_keyalgo_string (enum gcry_pk_algos algo,
+ unsigned int nbits, const char *curve)
+{
+ const char *prefix = NULL;
+ int i;
+ char *name, *curvebuf;
+
+ switch (algo)
+ {
+ case GCRY_PK_RSA: prefix = "rsa"; break;
+ case GCRY_PK_ELG: prefix = "elg"; break;
+ case GCRY_PK_DSA: prefix = "dsa"; break;
+ case GCRY_PK_ECDH:
+ case GCRY_PK_ECDSA:
+ case GCRY_PK_EDDSA: prefix = ""; break;
+ }
+
+ if (prefix && *prefix && nbits)
+ {
+ for (i=0; i < keyalgo_strings_used; i++)
+ {
+ if (keyalgo_strings[i].algo == algo
+ && keyalgo_strings[i].nbits
+ && keyalgo_strings[i].nbits == nbits)
+ return keyalgo_strings[i].name;
+ }
+ /* Not yet in the table - add it. */
+ name = xasprintf ("%s%u", prefix, nbits);
+ nbits = nbits? nbits : 1; /* No nbits - oops - use 1 instead. */
+ curvebuf = NULL;
+ }
+ else if (prefix && !*prefix)
+ {
+ const char *curvename;
+
+ for (i=0; i < keyalgo_strings_used; i++)
+ {
+ if (keyalgo_strings[i].algo == algo
+ && keyalgo_strings[i].curve
+ && !strcmp (keyalgo_strings[i].curve, curve))
+ return keyalgo_strings[i].name;
+ }
+
+ /* Not yet in the table - add it. */
+ curvename = openpgp_oid_to_curve (curve, 0);
+ if (curvename)
+ name = xasprintf ("%s", curvename);
+ else if (curve)
+ name = xasprintf ("E_%s", curve);
+ else
+ name = xasprintf ("E_error");
+ nbits = 0;
+ curvebuf = xstrdup (curve);
+ }
+ else
+ {
+ for (i=0; i < keyalgo_strings_used; i++)
+ {
+ if (keyalgo_strings[i].algo == algo
+ && !keyalgo_strings[i].nbits
+ && !keyalgo_strings[i].curve)
+ return keyalgo_strings[i].name;
+ }
+ /* Not yet in the table - add it. */
+ name = xasprintf ("unknown_%u", (unsigned int)algo);
+ nbits = 0;
+ curvebuf = NULL;
+ }
+
+ /* Store a new entry. This is a loop because of a possible nPth
+ * thread switch during xrealloc. */
+ while (keyalgo_strings_used >= keyalgo_strings_size)
+ {
+ keyalgo_strings_size += 10;
+ if (keyalgo_strings_size > 1024*1024)
+ log_fatal ("%s: table getting too large - possible DoS\n", __func__);
+ keyalgo_strings = xrealloc (keyalgo_strings, (keyalgo_strings_size
+ * sizeof *keyalgo_strings));
+ }
+ keyalgo_strings[keyalgo_strings_used].algo = algo;
+ keyalgo_strings[keyalgo_strings_used].nbits = nbits;
+ keyalgo_strings[keyalgo_strings_used].curve = curvebuf;
+ keyalgo_strings[keyalgo_strings_used].name = name;
+ keyalgo_strings_used++;
+
+ return name; /* Note that this is in the table. */
+}