diff options
author | Werner Koch <[email protected]> | 2020-02-09 20:20:48 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2020-02-09 20:26:35 +0000 |
commit | 3a1fa13eedb969b561bae18cd3d7c2fb0b63d6ab (patch) | |
tree | 704e4441d3a713a82dd587e94c6874cd1615f87e /common/openpgp-oid.c | |
parent | common: Add OpenPGP<->Gcrypt pubkey id mapping functions. (diff) | |
download | gnupg-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.c | 121 |
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. */ +} |