summaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-10-17 21:10:19 +0200
committerWerner Koch <wk@gnupg.org>2017-10-17 21:10:19 +0200
commit825abec0e7f38667a34dce3025fc2f3a05001dde (patch)
tree8508d92f6b68271377353c15756cec57f03fc694 /sm
parentsm: Fix colon listing of fields > 12 in crt records. (diff)
downloadgnupg2-825abec0e7f38667a34dce3025fc2f3a05001dde.tar.xz
gnupg2-825abec0e7f38667a34dce3025fc2f3a05001dde.zip
gpg,sm: New option --with-key-screening.
* common/pkscreening.c: New. * common/pkscreening.h: New. * common/Makefile.am (common_sources): Add them. * g10/gpg.c (opts): New option --with-key-screening. * g10/options.h (struct opt): New field with_key_screening. * g10/keylist.c: Include pkscreening.h. (print_pk_screening): New. (list_keyblock_print): Call it. (print_compliance_flags): Call it. * sm/gpgsm.c (opts): New option --with-key-screening. * sm/gpgsm.h (scruct opt): New field with_key_screening. * sm/keylist.c: Include pkscreening.h. (print_pk_screening): New. (print_compliance_flags): Call it. Add new arg cert. (list_cert_colon): Pass arg cert (list_cert_std): Call print_pk_screening. * sm/fingerprint.c (gpgsm_get_rsa_modulus): New. -- This new option can be used to detect ROCA affected keys. To scan an entire keyring and print the affected fingerprints use this: gpg -k --with-key-screening --with-colons | gawk -F: \ '$1~/pub|sub|sec|ssb|crt/ && $18~/\<6001\>/ {found=1;next}; $1=="fpr" && found {print $10}; {found=0}' The same works for gpgsm. Note that we need gawk due to the "\<" in the r.e. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'sm')
-rw-r--r--sm/fingerprint.c64
-rw-r--r--sm/gpgsm.c6
-rw-r--r--sm/gpgsm.h3
-rw-r--r--sm/keylist.c51
4 files changed, 121 insertions, 3 deletions
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
index fbcec5883..59688f3a4 100644
--- a/sm/fingerprint.c
+++ b/sm/fingerprint.c
@@ -277,6 +277,70 @@ gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
}
+/* If KEY is an RSA key, return its modulus. For non-RSA keys or on
+ * error return NULL. */
+gcry_mpi_t
+gpgsm_get_rsa_modulus (ksba_cert_t cert)
+{
+ gpg_error_t err;
+ gcry_sexp_t key;
+ gcry_sexp_t list = NULL;
+ gcry_sexp_t l2 = NULL;
+ char *name = NULL;
+ gcry_mpi_t modulus = NULL;
+
+ {
+ ksba_sexp_t ckey;
+ size_t n;
+
+ ckey = ksba_cert_get_public_key (cert);
+ if (!ckey)
+ return NULL;
+ n = gcry_sexp_canon_len (ckey, 0, NULL, NULL);
+ if (!n)
+ {
+ xfree (ckey);
+ return NULL;
+ }
+ err = gcry_sexp_sscan (&key, NULL, (char *)ckey, n);
+ xfree (ckey);
+ if (err)
+ return NULL;
+ }
+
+ list = gcry_sexp_find_token (key, "public-key", 0);
+ if (!list)
+ list = gcry_sexp_find_token (key, "private-key", 0);
+ if (!list)
+ list = gcry_sexp_find_token (key, "protected-private-key", 0);
+ if (!list)
+ list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
+
+ gcry_sexp_release (key);
+ if (!list)
+ return NULL; /* No suitable key. */
+
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ l2 = NULL;
+
+ name = gcry_sexp_nth_string (list, 0);
+ if (!name)
+ ;
+ else if (gcry_pk_map_name (name) == GCRY_PK_RSA)
+ {
+ l2 = gcry_sexp_find_token (list, "n", 1);
+ if (l2)
+ modulus = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+ }
+
+ gcry_free (name);
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+ return modulus;
+}
+
/* For certain purposes we need a certificate id which has an upper
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index fa37f63be..bd701ab7f 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -155,6 +155,7 @@ enum cmd_and_opt_values {
oWithMD5Fingerprint,
oWithKeygrip,
oWithSecret,
+ oWithKeyScreening,
oAnswerYes,
oAnswerNo,
oKeyring,
@@ -391,6 +392,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"),
ARGPARSE_s_n (oWithSecret, "with-secret", "@"),
+ ARGPARSE_s_n (oWithKeyScreening,"with-key-screening", "@"),
ARGPARSE_s_s (oDisableCipherAlgo, "disable-cipher-algo", "@"),
ARGPARSE_s_s (oDisablePubkeyAlgo, "disable-pubkey-algo", "@"),
ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
@@ -1289,6 +1291,10 @@ main ( int argc, char **argv)
opt.with_keygrip = 1;
break;
+ case oWithKeyScreening:
+ opt.with_key_screening = 1;
+ break;
+
case oOptions:
/* config files may not be nested (silently ignore them) */
if (!configfp)
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 8c1f520de..0421b97bb 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -85,6 +85,8 @@ struct
int with_keygrip; /* Option --with-keygrip active. */
+ int with_key_screening; /* Option --with-key-screening active. */
+
int pinentry_mode;
int armor; /* force base64 armoring (see also ctrl.with_base64) */
@@ -258,6 +260,7 @@ unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert,
unsigned char *gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array);
char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert);
int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits);
+gcry_mpi_t gpgsm_get_rsa_modulus (ksba_cert_t cert);
char *gpgsm_get_certid (ksba_cert_t cert);
diff --git a/sm/keylist.c b/sm/keylist.c
index 9997da812..ea2a22093 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -37,6 +37,7 @@
#include "../common/i18n.h"
#include "../common/tlv.h"
#include "../common/compliance.h"
+#include "../common/pkscreening.h"
struct list_external_parm_s
{
@@ -238,6 +239,38 @@ print_key_data (ksba_cert_t cert, estream_t fp)
#endif
}
+
+/* Various public key screenings. (Right now just ROCA). With
+ * COLON_MODE set the output is formatted for use in the compliance
+ * field of a colon listing. */
+static void
+print_pk_screening (ksba_cert_t cert, int colon_mode, estream_t fp)
+{
+ gpg_error_t err;
+ gcry_mpi_t modulus;
+
+ modulus = gpgsm_get_rsa_modulus (cert);
+ if (modulus)
+ {
+ err = screen_key_for_roca (modulus);
+ if (!err)
+ ;
+ else if (gpg_err_code (err) == GPG_ERR_TRUE)
+ {
+ if (colon_mode)
+ es_fprintf (fp, colon_mode > 1? " %d":"%d", 6001);
+ else
+ es_fprintf (fp, " screening: ROCA vulnerability detected\n");
+ }
+ else if (!colon_mode)
+ es_fprintf (fp, " screening: [ROCA check failed: %s]\n",
+ gpg_strerror (err));
+ gcry_mpi_release (modulus);
+ }
+
+}
+
+
static void
print_capabilities (ksba_cert_t cert, estream_t fp)
{
@@ -348,10 +381,19 @@ 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)
+print_compliance_flags (ksba_cert_t cert, int algo, unsigned int nbits,
+ estream_t fp)
{
+ int any = 0;
+
if (gnupg_pk_is_compliant (CO_DE_VS, algo, NULL, nbits, NULL))
- es_fputs (gnupg_status_compliance_flag (CO_DE_VS), fp);
+ {
+ es_fputs (gnupg_status_compliance_flag (CO_DE_VS), fp);
+ any++;
+ }
+
+ if (opt.with_key_screening)
+ print_pk_screening (cert, 1+any, fp);
}
@@ -526,7 +568,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
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);
+ print_compliance_flags (cert, algo, nbits, fp);
es_putc (':', fp); /* End of field 18. */
es_putc ('\n', fp);
@@ -1253,6 +1295,9 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
}
}
+ if (opt.with_key_screening)
+ print_pk_screening (cert, 0, fp);
+
if (have_secret)
{
char *cardsn;