aboutsummaryrefslogtreecommitdiffstats
path: root/tools/card-keys.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-06-03 14:24:44 +0000
committerWerner Koch <[email protected]>2020-06-03 14:25:59 +0000
commit4f6e0e12cbd3444b9e6ea5e4b92ea5b3072a3e17 (patch)
tree276274d0eea567faf6ffd44da8d6040577478a57 /tools/card-keys.c
parentgpg: Improve generation of keys stored on card (brainpool,cv25519). (diff)
downloadgnupg-4f6e0e12cbd3444b9e6ea5e4b92ea5b3072a3e17.tar.gz
gnupg-4f6e0e12cbd3444b9e6ea5e4b92ea5b3072a3e17.zip
card: Improve openpgp key writing in "writecert".
* tools/card-keys.c (struct export_key_status_parm_s): New. (export_key_status_cb): New. (get_minimal_openpgp_key): New. * tools/gpg-card.c (cmd_writecert): Allow writing a keyblock directly from an existing gpg key. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'tools/card-keys.c')
-rw-r--r--tools/card-keys.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/tools/card-keys.c b/tools/card-keys.c
index 4706cb320..3027de9c7 100644
--- a/tools/card-keys.c
+++ b/tools/card-keys.c
@@ -557,3 +557,96 @@ test_get_matching_keys (const char *hexgrip)
release_keyblock (keyblock);
return 0;
}
+
+
+
+
+struct export_key_status_parm_s
+{
+ const char *fpr;
+ int found;
+ int count;
+};
+
+
+static void
+export_key_status_cb (void *opaque, const char *keyword, char *args)
+{
+ struct export_key_status_parm_s *parm = opaque;
+
+ if (!strcmp (keyword, "EXPORTED"))
+ {
+ parm->count++;
+ if (!ascii_strcasecmp (args, parm->fpr))
+ parm->found = 1;
+ }
+}
+
+
+/* Get a key by fingerprint from gpg's keyring. The binary key is
+ * returned as a new memory stream at R_KEY. */
+gpg_error_t
+get_minimal_openpgp_key (estream_t *r_key, const char *fingerprint)
+{
+ gpg_error_t err;
+ ccparray_t ccp;
+ const char **argv = NULL;
+ estream_t key = NULL;
+ struct export_key_status_parm_s parm = { NULL };
+
+ *r_key = NULL;
+
+ key = es_fopenmem (0, "w+b");
+ if (!key)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ ccparray_init (&ccp, 0);
+
+ ccparray_put (&ccp, "--no-options");
+ if (!opt.verbose)
+ ccparray_put (&ccp, "--quiet");
+ else if (opt.verbose > 1)
+ ccparray_put (&ccp, "--verbose");
+ ccparray_put (&ccp, "--batch");
+ ccparray_put (&ccp, "--status-fd=2");
+ ccparray_put (&ccp, "--always-trust");
+ ccparray_put (&ccp, "--no-armor");
+ ccparray_put (&ccp, "--export-options=export-minimal");
+ ccparray_put (&ccp, "--export");
+ ccparray_put (&ccp, "--");
+ ccparray_put (&ccp, fingerprint);
+
+ ccparray_put (&ccp, NULL);
+ argv = ccparray_get (&ccp, NULL);
+ if (!argv)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ parm.fpr = fingerprint;
+ err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
+ NULL, key,
+ export_key_status_cb, &parm);
+ if (!err && parm.count > 1)
+ err = gpg_error (GPG_ERR_TOO_MANY);
+ else if (!err && !parm.found)
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ if (err)
+ {
+ log_error ("export failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ es_rewind (key);
+ *r_key = key;
+ key = NULL;
+
+ leave:
+ es_fclose (key);
+ xfree (argv);
+ return err;
+}