mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
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. (openpgp_oid_or_name_to_curve): 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 <wk@gnupg.org> (cherry picked from commit 3a1fa13eedb969b561bae18cd3d7c2fb0b63d6ab) (cherry picked from commit 332a72f7340895e7db1e9c5f89046f722bb7465b)
This commit is contained in:
parent
398cec3ac7
commit
2e39fed109
@ -71,6 +71,21 @@ static const char oid_ed25519[] =
|
|||||||
static const char oid_cv25519[] =
|
static const char oid_cv25519[] =
|
||||||
{ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
|
{ 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. */
|
/* Helper for openpgp_oid_from_str. */
|
||||||
static size_t
|
static size_t
|
||||||
@ -383,9 +398,9 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Map an OpenPGP OID to the Libgcrypt curve NAME. Returns NULL for
|
/* Map an OpenPGP OID to the Libgcrypt curve name. Returns NULL for
|
||||||
unknown curve names. Unless CANON is set we prefer an alias name
|
* unknown curve names. Unless CANON is set we prefer an alias name
|
||||||
here which is more suitable for printing. */
|
* here which is more suitable for printing. */
|
||||||
const char *
|
const char *
|
||||||
openpgp_oid_to_curve (const char *oidstr, int canon)
|
openpgp_oid_to_curve (const char *oidstr, int canon)
|
||||||
{
|
{
|
||||||
@ -402,6 +417,27 @@ openpgp_oid_to_curve (const char *oidstr, int canon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Map an OpenPGP OID, name or alias to the Libgcrypt curve name.
|
||||||
|
* Returns NULL for unknown curve names. Unless CANON is set we
|
||||||
|
* prefer an alias name here which is more suitable for printing. */
|
||||||
|
const char *
|
||||||
|
openpgp_oid_or_name_to_curve (const char *oidname, int canon)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!oidname)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i=0; oidtable[i].name; i++)
|
||||||
|
if (!strcmp (oidtable[i].oidstr, oidname)
|
||||||
|
|| !strcmp (oidtable[i].name, oidname)
|
||||||
|
|| (oidtable[i].alias &&!strcmp (oidtable[i].alias, oidname)))
|
||||||
|
return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return true if the curve with NAME is supported. */
|
/* Return true if the curve with NAME is supported. */
|
||||||
static int
|
static int
|
||||||
curve_supported_p (const char *name)
|
curve_supported_p (const char *name)
|
||||||
@ -470,3 +506,126 @@ openpgp_is_curve_supported (const char *name, int *r_algo,
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Map an OpenPGP public key algorithm number to the one used by
|
||||||
|
* Libgcrypt. Returns 0 for unknown gcry algorithm. */
|
||||||
|
enum gcry_pk_algos
|
||||||
|
map_openpgp_pk_to_gcry (pubkey_algo_t algo)
|
||||||
|
{
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case PUBKEY_ALGO_EDDSA: return GCRY_PK_EDDSA;
|
||||||
|
case PUBKEY_ALGO_ECDSA: return GCRY_PK_ECDSA;
|
||||||
|
case PUBKEY_ALGO_ECDH: return GCRY_PK_ECDH;
|
||||||
|
default: return algo < 110 ? (enum gcry_pk_algos)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;
|
||||||
|
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_ECC:
|
||||||
|
case GCRY_PK_ECDH:
|
||||||
|
case GCRY_PK_ECDSA:
|
||||||
|
case GCRY_PK_EDDSA: prefix = ""; break;
|
||||||
|
default: prefix = NULL; 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_or_name_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. */
|
||||||
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#define pass() do { ; } while(0)
|
#define pass() do { ; } while(0)
|
||||||
#define fail(a,e) \
|
#define fail(a,e) \
|
||||||
do { fprintf (stderr, "%s:%d: test %d failed (%s)\n", \
|
do { fprintf (stderr, "%s:%d: test %d failed (%s)\n", \
|
||||||
__FILE__,__LINE__, (a), gpg_strerror (e)); \
|
__func__, __LINE__, (a), gpg_strerror (e)); \
|
||||||
exit (1); \
|
exit (1); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@ -226,6 +226,74 @@ test_openpgp_enum_curves (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_get_keyalgo_string (void)
|
||||||
|
{
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
int algo;
|
||||||
|
unsigned int nbits;
|
||||||
|
const char *curve;
|
||||||
|
const char *name;
|
||||||
|
} samples[] =
|
||||||
|
{
|
||||||
|
{ GCRY_PK_RSA, 1024, NULL, "rsa1024" },
|
||||||
|
{ GCRY_PK_RSA, 1536, NULL, "rsa1536" },
|
||||||
|
{ GCRY_PK_RSA, 768, NULL, "rsa768" },
|
||||||
|
{ GCRY_PK_DSA, 3072, NULL, "dsa3072" },
|
||||||
|
{ GCRY_PK_DSA, 1024, NULL, "dsa1024" },
|
||||||
|
{ GCRY_PK_ELG, 2048, NULL, "elg2048" },
|
||||||
|
{ GCRY_PK_ELG, 0, NULL, "unknown_20" },
|
||||||
|
{ 47114711, 1000, NULL, "unknown_47114711" },
|
||||||
|
/* Note that we don't care about the actual ECC algorithm. */
|
||||||
|
{ GCRY_PK_EDDSA, 0, "1.3.6.1.4.1.11591.15.1", "ed25519" },
|
||||||
|
{ GCRY_PK_ECDSA, 0, "1.3.6.1.4.1.11591.15.1", "ed25519" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.6.1.4.1.11591.15.1", "ed25519" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.6.1.4.1.3029.1.5.1", "cv25519" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.36.3.3.2.8.1.1.7", "brainpoolP256r1" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.36.3.3.2.8.1.1.11", "brainpoolP384r1" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.36.3.3.2.8.1.1.13", "brainpoolP512r1" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.132.0.10", "secp256k1" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.2.840.10045.3.1.7", "nistp256" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.132.0.34", "nistp384" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.132.0.35", "nistp521" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.2.3.4.5.6", "E_1.2.3.4.5.6" },
|
||||||
|
{ GCRY_PK_ECDH, 0, BADOID, "E_1.3.6.1.4.1.11591.2.12242973" },
|
||||||
|
|
||||||
|
/* Some again to test existing lookups. */
|
||||||
|
{ GCRY_PK_RSA, 768, NULL, "rsa768" },
|
||||||
|
{ GCRY_PK_DSA, 3072, NULL, "dsa3072" },
|
||||||
|
{ GCRY_PK_DSA, 1024, NULL, "dsa1024" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.6.1.4.1.11591.15.1", "ed25519" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.6.1.4.1.3029.1.5.1", "cv25519" },
|
||||||
|
{ GCRY_PK_ECDH, 0, "1.3.36.3.3.2.8.1.1.7", "brainpoolP256r1" },
|
||||||
|
{ 47114711, 1000, NULL, "unknown_47114711" }
|
||||||
|
};
|
||||||
|
int idx;
|
||||||
|
const char *name;
|
||||||
|
int oops = 0;
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
/* We do several passes becuase that is how the function is
|
||||||
|
* called. */
|
||||||
|
for (pass=0; pass < 3; pass++)
|
||||||
|
for (idx=0; idx < DIM (samples); idx++)
|
||||||
|
{
|
||||||
|
name = get_keyalgo_string (samples[idx].algo,
|
||||||
|
samples[idx].nbits,
|
||||||
|
samples[idx].curve);
|
||||||
|
if (strcmp (samples[idx].name, name))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s:test %d.%d: want '%s' got '%s'\n",
|
||||||
|
__func__, pass, idx, samples[idx].name, name);
|
||||||
|
oops = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oops)
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -241,6 +309,7 @@ main (int argc, char **argv)
|
|||||||
test_openpgp_oid_to_str ();
|
test_openpgp_oid_to_str ();
|
||||||
test_openpgp_oid_is_ed25519 ();
|
test_openpgp_oid_is_ed25519 ();
|
||||||
test_openpgp_enum_curves ();
|
test_openpgp_enum_curves ();
|
||||||
|
test_get_keyalgo_string ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -248,9 +248,12 @@ int openpgp_oid_is_cv25519 (gcry_mpi_t a);
|
|||||||
const char *openpgp_curve_to_oid (const char *name,
|
const char *openpgp_curve_to_oid (const char *name,
|
||||||
unsigned int *r_nbits, int *r_algo);
|
unsigned int *r_nbits, int *r_algo);
|
||||||
const char *openpgp_oid_to_curve (const char *oid, int canon);
|
const char *openpgp_oid_to_curve (const char *oid, int canon);
|
||||||
|
const char *openpgp_oid_or_name_to_curve (const char *oidname, int canon);
|
||||||
const char *openpgp_enum_curves (int *idxp);
|
const char *openpgp_enum_curves (int *idxp);
|
||||||
const char *openpgp_is_curve_supported (const char *name,
|
const char *openpgp_is_curve_supported (const char *name,
|
||||||
int *r_algo, unsigned int *r_nbits);
|
int *r_algo, unsigned int *r_nbits);
|
||||||
|
const char *get_keyalgo_string (enum gcry_pk_algos algo,
|
||||||
|
unsigned int nbits, const char *curve);
|
||||||
|
|
||||||
|
|
||||||
/*-- homedir.c --*/
|
/*-- homedir.c --*/
|
||||||
|
@ -88,7 +88,10 @@ pubkey_letter( int algo )
|
|||||||
"256E" - ECDSA using a curve with 256 bit
|
"256E" - ECDSA using a curve with 256 bit
|
||||||
|
|
||||||
The macro PUBKEY_STRING_SIZE may be used to allocate a buffer with
|
The macro PUBKEY_STRING_SIZE may be used to allocate a buffer with
|
||||||
a suitable size.*/
|
a suitable size. Note that a more general version of this function
|
||||||
|
exists as get_keyalgo_string. However, that has no special
|
||||||
|
treatment for the old and unsupported Elgamal which we here print as
|
||||||
|
xxxNNNN. */
|
||||||
char *
|
char *
|
||||||
pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
|
pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user