diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c index 7add56daf..0d6dabf1b 100644 --- a/tools/card-call-scd.c +++ b/tools/card-call-scd.c @@ -1298,6 +1298,45 @@ scd_readcert (const char *certidstr, void **r_buf, size_t *r_buflen) } + +/* Send a READKEY command to the SCdaemon. On success a new + * s-expression is stored at R_RESULT. */ +gpg_error_t +scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result) +{ + gpg_error_t err; + char line[ASSUAN_LINELENGTH]; + membuf_t data; + unsigned char *buf; + size_t len, buflen; + + *r_result = NULL; + err = start_agent (0); + if (err) + return err; + + init_membuf (&data, 1024); + snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr); + err = assuan_transact (agent_ctx, line, + put_membuf_cb, &data, + NULL, NULL, + NULL, NULL); + if (err) + { + xfree (get_membuf (&data, &len)); + return err; + } + buf = get_membuf (&data, &buflen); + if (!buf) + return gpg_error_from_syserror (); + + err = gcry_sexp_new (r_result, buf, buflen, 0); + xfree (buf); + + return err; +} + + /* Callback function for card_cardlist. */ static gpg_error_t diff --git a/tools/card-tool-misc.c b/tools/card-tool-misc.c index 06fcb6705..5e0461cb8 100644 --- a/tools/card-tool-misc.c +++ b/tools/card-tool-misc.c @@ -77,3 +77,61 @@ hex_to_buffer (const char *string, size_t *r_length) *r_length = n; return buffer; } + + + +/* Given the public key S_PKEY, return a new buffer with a descriptive + * string for its algorithm. This function always returns a string. */ +char * +pubkey_algo_string (gcry_sexp_t s_pkey) +{ + const char *prefix; + gcry_sexp_t l1; + char *algoname; + int algo; + char *result; + + l1 = gcry_sexp_find_token (s_pkey, "public-key", 0); + if (!l1) + return xstrdup ("E_no_key"); + { + gcry_sexp_t l_tmp = gcry_sexp_cadr (l1); + gcry_sexp_release (l1); + l1 = l_tmp; + } + algoname = gcry_sexp_nth_string (l1, 0); + gcry_sexp_release (l1); + if (!algoname) + return xstrdup ("E_no_algo"); + + algo = gcry_pk_map_name (algoname); + 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: prefix = ""; break; + default: prefix = NULL; break; + } + + if (prefix && *prefix) + result = xasprintf ("%s%u", prefix, gcry_pk_get_nbits (s_pkey)); + else if (prefix) + { + const char *curve = gcry_pk_get_curve (s_pkey, 0, NULL); + const char *name = openpgp_oid_to_curve + (openpgp_curve_to_oid (curve, NULL), 0); + + if (name) + result = xstrdup (name); + else if (curve) + result = xasprintf ("X_%s", curve); + else + result = xstrdup ("E_unknown"); + } + else + result = xasprintf ("X_algo_%d", algo); + + xfree (algoname); + return result; +} diff --git a/tools/card-tool.h b/tools/card-tool.h index 2707b3e8f..c121e88ef 100644 --- a/tools/card-tool.h +++ b/tools/card-tool.h @@ -192,6 +192,7 @@ gpg_error_t test_get_matching_keys (const char *hexgrip); /*-- card-tool-misc.c --*/ key_info_t find_kinfo (card_info_t info, const char *keyref); void *hex_to_buffer (const char *string, size_t *r_length); +char *pubkey_algo_string (gcry_sexp_t s_pkey); /*-- card-call-scd.c --*/ @@ -211,6 +212,7 @@ gpg_error_t scd_genkey (int keyno, int force, u32 *createtime); gpg_error_t scd_serialno (char **r_serialno, const char *demand); gpg_error_t scd_readcert (const char *certidstr, void **r_buf, size_t *r_buflen); +gpg_error_t scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result); gpg_error_t scd_cardlist (strlist_t *result); gpg_error_t scd_change_pin (const char *pinref, int reset_mode); gpg_error_t scd_checkpin (const char *serialno); diff --git a/tools/gpg-card-tool.c b/tools/gpg-card-tool.c index 0dbf2b224..71ce13f1b 100644 --- a/tools/gpg-card-tool.c +++ b/tools/gpg-card-tool.c @@ -620,6 +620,7 @@ list_one_kinfo (key_info_t firstkinfo, key_info_t kinfo, estream_t fp) userid_t uid; key_info_t ki; const char *s; + gcry_sexp_t s_pkey; if (firstkinfo && kinfo) { @@ -630,6 +631,14 @@ list_one_kinfo (key_info_t firstkinfo, key_info_t kinfo, estream_t fp) goto leave; } print_keygrip (fp, kinfo->grip); + if (!scd_readkey (kinfo->keyref, &s_pkey)) + { + char *tmp = pubkey_algo_string (s_pkey); + tty_fprintf (fp, " algorithm ..: %s\n", tmp); + xfree (tmp); + gcry_sexp_release (s_pkey); + s_pkey = NULL; + } if (kinfo->fprlen && kinfo->created) {