diff options
author | Werner Koch <wk@gnupg.org> | 2017-10-17 21:10:19 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2017-10-17 21:10:19 +0200 |
commit | 825abec0e7f38667a34dce3025fc2f3a05001dde (patch) | |
tree | 8508d92f6b68271377353c15756cec57f03fc694 /sm | |
parent | sm: Fix colon listing of fields > 12 in crt records. (diff) | |
download | gnupg2-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.c | 64 | ||||
-rw-r--r-- | sm/gpgsm.c | 6 | ||||
-rw-r--r-- | sm/gpgsm.h | 3 | ||||
-rw-r--r-- | sm/keylist.c | 51 |
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; |