1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-03 22:48:03 +02:00

gpg: Add new field no 18 to the colon listing.

* g10/misc.c (gnupg_pk_is_compliant): New.
* g10/keylist.c (print_compliance_flags): New.
(list_keyblock_colon): Call it here.
* sm/keylist.c (print_compliance_flags): New.
(list_cert_colon): Call it here.
--

This patch is to convey information about DE_VS compliant keys to the
caller.  The double digit value is used so that parsers do the right
thing and don't just look for a single digit.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-03-20 10:09:40 +01:00
parent e2c63a13e2
commit fe0b37e123
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
5 changed files with 168 additions and 25 deletions

View File

@ -218,6 +218,15 @@ described here.
For pub, sub, sec, and ssb records this field is used for the ECC For pub, sub, sec, and ssb records this field is used for the ECC
curve name. curve name.
*** Field 18 - Compliance flags
Space separated list of asserted compliance modes for this key.
Valid values are:
- 8 :: The key is compliant with RFC4880bis
- 23 :: The key is compliant with compliance mode "de-vs".
** Special fields ** Special fields
*** PKD - Public key data *** PKD - Public key data

View File

@ -1170,6 +1170,29 @@ print_revokers (estream_t fp, PKT_public_key * pk)
} }
/* Print the compliance flags to field 18. PK is the public key.
* KEYLENGTH is the length of the key in bits and CURVENAME is either
* NULL or the name of the curve. The latter two args are here
* merely because the caller has already computed them. */
static void
print_compliance_flags (PKT_public_key *pk,
unsigned int keylength, const char *curvename)
{
int any = 0;
if (pk->version == 5)
{
es_fputs ("8", es_stdout);
any++;
}
if (gnupg_pk_is_compliant (CO_DE_VS, pk, keylength, curvename))
{
es_fputs (any? " 23":"23", es_stdout);
any++;
}
}
/* List a key in colon mode. If SECRET is true this is a secret key /* List a key in colon mode. If SECRET is true this is a secret key
record (i.e. requested via --list-secret-key). If HAS_SECRET a record (i.e. requested via --list-secret-key). If HAS_SECRET a
secret key is available even if SECRET is not set. */ secret key is available even if SECRET is not set. */
@ -1191,6 +1214,9 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
const char *hexgrip = NULL; const char *hexgrip = NULL;
char *serialno = NULL; char *serialno = NULL;
int stubkey; int stubkey;
unsigned int keylength;
char *curve = NULL;
const char *curvename = NULL;
/* Get the keyid from the keyblock. */ /* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY); node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@ -1239,14 +1265,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
else else
ownertrust_print = 0; ownertrust_print = 0;
keylength = nbits_from_pk (pk);
es_fputs (secret? "sec:":"pub:", es_stdout); es_fputs (secret? "sec:":"pub:", es_stdout);
if (trustletter_print) if (trustletter_print)
es_putc (trustletter_print, es_stdout); es_putc (trustletter_print, es_stdout);
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::", es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
nbits_from_pk (pk), keylength,
pk->pubkey_algo, pk->pubkey_algo,
(ulong) keyid[0], (ulong) keyid[1], (ulong) keyid[0], (ulong) keyid[1],
colon_datestr_from_pk (pk), colon_strtime (pk->expiredate)); colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
if (ownertrust_print) if (ownertrust_print)
es_putc (ownertrust_print, es_stdout); es_putc (ownertrust_print, es_stdout);
@ -1272,14 +1300,14 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH) || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{ {
char *curve = openpgp_oid_to_str (pk->pkey[0]); curve = openpgp_oid_to_str (pk->pkey[0]);
const char *name = openpgp_oid_to_curve (curve, 0); curvename = openpgp_oid_to_curve (curve, 0);
if (!name) if (!curvename)
name = curve; curvename = curve;
es_fputs (name, es_stdout); es_fputs (curvename, es_stdout);
xfree (curve);
} }
es_putc (':', es_stdout); /* End of field 17. */ es_putc (':', es_stdout); /* End of field 17. */
print_compliance_flags (pk, keylength, curvename);
es_putc (':', es_stdout); /* End of field 18. */ es_putc (':', es_stdout); /* End of field 18. */
es_putc ('\n', es_stdout); es_putc ('\n', es_stdout);
@ -1380,13 +1408,13 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
if (trustletter) if (trustletter)
es_fprintf (es_stdout, "%c", trustletter); es_fprintf (es_stdout, "%c", trustletter);
} }
keylength = nbits_from_pk (pk2);
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::", es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
nbits_from_pk (pk2), keylength,
pk2->pubkey_algo, pk2->pubkey_algo,
(ulong) keyid2[0], (ulong) keyid2[1], (ulong) keyid2[0], (ulong) keyid2[1],
colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate) colon_datestr_from_pk (pk2),
/* fixme: add LID and ownertrust here */ colon_strtime (pk2->expiredate));
);
print_capabilities (pk2, NULL); print_capabilities (pk2, NULL);
es_putc (':', es_stdout); /* End of field 13. */ es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */ es_putc (':', es_stdout); /* End of field 14. */
@ -1405,14 +1433,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
|| pk2->pubkey_algo == PUBKEY_ALGO_EDDSA || pk2->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk2->pubkey_algo == PUBKEY_ALGO_ECDH) || pk2->pubkey_algo == PUBKEY_ALGO_ECDH)
{ {
char *curve = openpgp_oid_to_str (pk2->pkey[0]);
const char *name = openpgp_oid_to_curve (curve, 0);
if (!name)
name = curve;
es_fputs (name, es_stdout);
xfree (curve); xfree (curve);
curve = openpgp_oid_to_str (pk2->pkey[0]);
curvename = openpgp_oid_to_curve (curve, 0);
if (!curvename)
curvename = curve;
es_fputs (curvename, es_stdout);
} }
es_putc (':', es_stdout); /* End of field 17. */ es_putc (':', es_stdout); /* End of field 17. */
print_compliance_flags (pk2, keylength, curvename);
es_putc (':', es_stdout); /* End of field 18. */
es_putc ('\n', es_stdout); es_putc ('\n', es_stdout);
print_fingerprint (NULL, pk2, 0); print_fingerprint (NULL, pk2, 0);
if (hexgrip) if (hexgrip)
@ -1540,6 +1570,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
} }
} }
xfree (curve);
xfree (hexgrip_buffer); xfree (hexgrip_buffer);
xfree (serialno); xfree (serialno);
} }

View File

@ -125,6 +125,9 @@ int openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use);
int openpgp_pk_algo_usage ( int algo ); int openpgp_pk_algo_usage ( int algo );
const char *openpgp_pk_algo_name (pubkey_algo_t algo); const char *openpgp_pk_algo_name (pubkey_algo_t algo);
int gnupg_pk_is_compliant (int compliance, PKT_public_key *pk,
unsigned int keylength, const char *curvename);
enum gcry_md_algos map_md_openpgp_to_gcry (digest_algo_t algo); enum gcry_md_algos map_md_openpgp_to_gcry (digest_algo_t algo);
int openpgp_md_test_algo (digest_algo_t algo); int openpgp_md_test_algo (digest_algo_t algo);
const char *openpgp_md_algo_name (int algo); const char *openpgp_md_algo_name (int algo);

View File

@ -640,7 +640,7 @@ openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use)
if (!ga) if (!ga)
return gpg_error (GPG_ERR_PUBKEY_ALGO); 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); return gcry_pk_algo_info (ga, GCRYCTL_TEST_ALGO, NULL, &use_buf);
} }
@ -704,6 +704,94 @@ openpgp_pk_algo_name (pubkey_algo_t algo)
} }
/* Return true if PK is compliant to the give COMPLIANCE mode. If
* KEYLENGTH and CURVENAME are not 0/NULL the are assumed to be the
* already computed values from PK. */
int
gnupg_pk_is_compliant (int compliance, PKT_public_key *pk,
unsigned int keylength, const char *curvename)
{
enum { is_rsa, is_pgp5, is_elg_sign, is_ecc } algotype;
int result;
switch (pk->pubkey_algo)
{
case PUBKEY_ALGO_RSA:
case PUBKEY_ALGO_RSA_E:
case PUBKEY_ALGO_RSA_S:
algotype = is_rsa;
break;
case PUBKEY_ALGO_ELGAMAL_E:
case PUBKEY_ALGO_DSA:
algotype = is_pgp5;
break;
case PUBKEY_ALGO_ECDH:
case PUBKEY_ALGO_ECDSA:
case PUBKEY_ALGO_EDDSA:
algotype = is_ecc;
break;
case PUBKEY_ALGO_ELGAMAL:
algotype = is_elg_sign;
break;
default: /* Unknown. */
return 0;
}
if (compliance == CO_DE_VS)
{
char *curve = NULL;
switch (algotype)
{
case is_pgp5:
result = 0;
break;
case is_rsa:
if (!keylength)
keylength = nbits_from_pk (pk);
result = (keylength >= 2048);
break;
case is_ecc:
if (!curvename)
{
curve = openpgp_oid_to_str (pk->pkey[0]);
curvename = openpgp_oid_to_curve (curve, 0);
if (!curvename)
curvename = curve;
}
result = (curvename
&& pk->pubkey_algo != PUBKEY_ALGO_EDDSA
&& (!strcmp (curvename, "brainpoolP256r1")
|| !strcmp (curvename, "brainpoolP384r1")
|| !strcmp (curvename, "brainpoolP512r1")));
break;
default:
result = 0;
}
xfree (curve);
}
else if (algotype == is_elg_sign)
{
/* An Elgamal signing key is only RFC-2440 compliant. */
result = (compliance == RFC2440);
}
else
{
result = 1; /* Assume compliance. */
}
return result;
}
/* Explicit mapping of OpenPGP digest algos to Libgcrypt. */ /* Explicit mapping of OpenPGP digest algos to Libgcrypt. */
/* FIXME: We do not yes use it everywhere. */ /* FIXME: We do not yes use it everywhere. */
enum gcry_md_algos enum gcry_md_algos

View File

@ -346,6 +346,14 @@ email_kludge (const char *name)
} }
/* Print the compliance flags to field 18. ALGO is the gcrypt algo
* number. NBITS is the length of the key in bits. */
static void
print_compliance_flags (int algo, unsigned int nbits, estream_t fp)
{
if (algo == GCRY_PK_RSA && nbits >= 2048)
es_fputs ("23", fp);
}
/* List one certificate in colon mode */ /* List one certificate in colon mode */
@ -496,6 +504,8 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
print_capabilities (cert, fp); print_capabilities (cert, fp);
/* Field 13, not used: */ /* Field 13, not used: */
es_putc (':', fp); es_putc (':', fp);
/* Field 14, not used: */
es_putc (':', fp);
if (have_secret || ctrl->with_secret) if (have_secret || ctrl->with_secret)
{ {
char *cardsn; char *cardsn;
@ -504,18 +514,20 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn)
&& (cardsn || ctrl->with_secret)) && (cardsn || ctrl->with_secret))
{ {
/* Field 14, not used: */
es_putc (':', fp);
/* Field 15: Token serial number or secret key indicator. */ /* Field 15: Token serial number or secret key indicator. */
if (cardsn) if (cardsn)
es_fputs (cardsn, fp); es_fputs (cardsn, fp);
else if (ctrl->with_secret) else if (ctrl->with_secret)
es_putc ('+', fp); es_putc ('+', fp);
es_putc (':', fp);
} }
xfree (cardsn); xfree (cardsn);
xfree (p); xfree (p);
} }
es_putc (':', fp); /* End of field 15. */
es_putc (':', fp); /* End of field 16. */
es_putc (':', fp); /* End of field 17. */
print_compliance_flags (algo, nbits, fp);
es_putc (':', fp); /* End of field 18. */
es_putc ('\n', fp); es_putc ('\n', fp);
/* FPR record */ /* FPR record */