summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-03-20 10:09:40 +0100
committerWerner Koch <wk@gnupg.org>2017-03-20 10:09:40 +0100
commitfe0b37e123ded51cc5f4cb5e3547fdfbce37a43e (patch)
treef2d6fd82b6f04fce658d397b6961374a8b09f514
parentgpg: Remove unused stuff. (diff)
downloadgnupg2-fe0b37e123ded51cc5f4cb5e3547fdfbce37a43e.tar.xz
gnupg2-fe0b37e123ded51cc5f4cb5e3547fdfbce37a43e.zip
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>
-rw-r--r--doc/DETAILS9
-rw-r--r--g10/keylist.c73
-rw-r--r--g10/main.h3
-rw-r--r--g10/misc.c90
-rw-r--r--sm/keylist.c18
5 files changed, 168 insertions, 25 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index 8c1187287..cfe70e1df 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -218,6 +218,15 @@ described here.
For pub, sub, sec, and ssb records this field is used for the ECC
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
*** PKD - Public key data
diff --git a/g10/keylist.c b/g10/keylist.c
index 32cf1e845..b8f32be56 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -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
record (i.e. requested via --list-secret-key). If HAS_SECRET a
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;
char *serialno = NULL;
int stubkey;
+ unsigned int keylength;
+ char *curve = NULL;
+ const char *curvename = NULL;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@@ -1239,14 +1265,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
else
ownertrust_print = 0;
+ keylength = nbits_from_pk (pk);
+
es_fputs (secret? "sec:":"pub:", es_stdout);
if (trustletter_print)
es_putc (trustletter_print, es_stdout);
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
- nbits_from_pk (pk),
- pk->pubkey_algo,
- (ulong) keyid[0], (ulong) keyid[1],
- colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
+ keylength,
+ pk->pubkey_algo,
+ (ulong) keyid[0], (ulong) keyid[1],
+ colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
if (ownertrust_print)
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_ECDH)
{
- char *curve = openpgp_oid_to_str (pk->pkey[0]);
- const char *name = openpgp_oid_to_curve (curve, 0);
- if (!name)
- name = curve;
- es_fputs (name, es_stdout);
- xfree (curve);
+ curve = openpgp_oid_to_str (pk->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. */
+ print_compliance_flags (pk, keylength, curvename);
es_putc (':', es_stdout); /* End of field 18. */
es_putc ('\n', es_stdout);
@@ -1380,13 +1408,13 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
if (trustletter)
es_fprintf (es_stdout, "%c", trustletter);
}
+ keylength = nbits_from_pk (pk2);
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
- nbits_from_pk (pk2),
- pk2->pubkey_algo,
- (ulong) keyid2[0], (ulong) keyid2[1],
- colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate)
- /* fixme: add LID and ownertrust here */
- );
+ keylength,
+ pk2->pubkey_algo,
+ (ulong) keyid2[0], (ulong) keyid2[1],
+ colon_datestr_from_pk (pk2),
+ colon_strtime (pk2->expiredate));
print_capabilities (pk2, NULL);
es_putc (':', es_stdout); /* End of field 13. */
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_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);
+ 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. */
+ print_compliance_flags (pk2, keylength, curvename);
+ es_putc (':', es_stdout); /* End of field 18. */
es_putc ('\n', es_stdout);
print_fingerprint (NULL, pk2, 0);
if (hexgrip)
@@ -1540,6 +1570,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
}
}
+ xfree (curve);
xfree (hexgrip_buffer);
xfree (serialno);
}
diff --git a/g10/main.h b/g10/main.h
index f58f04162..c9c345418 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -125,6 +125,9 @@ int openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use);
int openpgp_pk_algo_usage ( int 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);
int openpgp_md_test_algo (digest_algo_t algo);
const char *openpgp_md_algo_name (int algo);
diff --git a/g10/misc.c b/g10/misc.c
index c69f9948b..0ecdb0478 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -640,7 +640,7 @@ openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use)
if (!ga)
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);
}
@@ -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. */
/* FIXME: We do not yes use it everywhere. */
enum gcry_md_algos
diff --git a/sm/keylist.c b/sm/keylist.c
index d27d4f441..1b1a261fd 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -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 */
@@ -496,6 +504,8 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
print_capabilities (cert, fp);
/* Field 13, not used: */
es_putc (':', fp);
+ /* Field 14, not used: */
+ es_putc (':', fp);
if (have_secret || ctrl->with_secret)
{
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)
&& (cardsn || ctrl->with_secret))
{
- /* Field 14, not used: */
- es_putc (':', fp);
/* Field 15: Token serial number or secret key indicator. */
if (cardsn)
es_fputs (cardsn, fp);
else if (ctrl->with_secret)
es_putc ('+', fp);
- es_putc (':', fp);
}
xfree (cardsn);
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);
/* FPR record */