aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/DETAILS1
-rw-r--r--g10/call-agent.c38
-rw-r--r--g10/call-agent.h4
-rw-r--r--g10/delkey.c47
-rw-r--r--g10/getkey.c32
-rw-r--r--g10/keydb.h3
-rw-r--r--g10/passphrase.c2
7 files changed, 121 insertions, 6 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index 3f9e747d5..03c200e71 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -818,6 +818,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
- 1 :: No such key
- 2 :: Must delete secret key first
- 3 :: Ambigious specification
+ - 4 :: Key is stored on a smartcard.
*** PROGRESS <what> <char> <cur> <total>
Used by the primegen and Public key functions to indicate
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 4ce6a06ab..5ad0983b9 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -2127,6 +2127,44 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
+ is not NULL, display DESC instead of the default description
+ message. */
+gpg_error_t
+agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
+{
+ gpg_error_t err;
+ char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
+
+ err = start_agent (ctrl, 0);
+ if (err)
+ return err;
+
+ if (!hexkeygrip || strlen (hexkeygrip) != 40)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (desc)
+ {
+ snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+ err = assuan_transact (agent_ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (err)
+ return err;
+ }
+
+ snprintf (line, DIM(line)-1, "DELETE_KEY %s", hexkeygrip);
+ err = assuan_transact (agent_ctx, line, NULL, NULL,
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
+ return err;
+}
+
+
+
/* Ask the agent to change the passphrase of the key identified by
HEXKEYGRIP. If DESC is not NULL, display DESC instead of the
default description message. If CACHE_NONCE_ADDR is not NULL the
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 2b944d21b..1deb8548a 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -185,6 +185,10 @@ gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip,
const char *desc, char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen);
+/* Delete a key from the agent. */
+gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip,
+ const char *desc);
+
/* Change the passphrase of a key. */
gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
char **cache_nonce_addr, char **passwd_nonce_addr);
diff --git a/g10/delkey.c b/g10/delkey.c
index 2e4477be9..3de705dfa 100644
--- a/g10/delkey.c
+++ b/g10/delkey.c
@@ -40,6 +40,7 @@
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
+#include "call-agent.h"
/****************
@@ -52,7 +53,7 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
{
gpg_error_t err;
kbnode_t keyblock = NULL;
- kbnode_t node;
+ kbnode_t node, kbctx;
KEYDB_HANDLE hd;
PKT_public_key *pk = NULL;
u32 keyid[2];
@@ -156,9 +157,47 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
{
if (secret)
{
- log_error (_("deleting secret key not implemented\n"));
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /* FIXME */
- goto leave;
+ char *prompt;
+ gpg_error_t firsterr = 0;
+ char *hexgrip;
+
+ setup_main_keyids (keyblock);
+ for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+ {
+ if (!(node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+ continue;
+
+ if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
+ continue; /* No secret key for that public (sub)key. */
+
+ prompt = gpg_format_keydesc (node->pkt->pkt.public_key,
+ FORMAT_KEYDESC_DELKEY, 1);
+ err = hexkeygrip_from_pk (node->pkt->pkt.public_key, &hexgrip);
+ if (!err)
+ err = agent_delete_key (NULL, hexgrip, prompt);
+ xfree (prompt);
+ xfree (hexgrip);
+ if (err)
+ {
+ if (gpg_err_code (err) == GPG_ERR_KEY_ON_CARD)
+ write_status_text (STATUS_DELETE_PROBLEM, "1");
+ log_error (_("deleting secret %s failed: %s\n"),
+ (node->pkt->pkttype == PKT_PUBLIC_KEY
+ ? _("key"):_("subkey")),
+ gpg_strerror (err));
+ if (!firsterr)
+ firsterr = err;
+ if (gpg_err_code (err) == GPG_ERR_CANCELED
+ || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+ break;
+ }
+
+ }
+
+ err = firsterr;
+ if (firsterr)
+ goto leave;
}
else
{
diff --git a/g10/getkey.c b/g10/getkey.c
index 777f3833f..458672a09 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1237,6 +1237,38 @@ getkey_end (getkey_ctx_t ctx)
************* Merging stuff ********************
************************************************/
+/* Set the mainkey_id fields for all keys in KEYBLOCK. This is
+ usually done by merge_selfsigs but at some places we only need the
+ main_kid but the the full merging. The function also guarantees
+ that all pk->keyids are computed. */
+void
+setup_main_keyids (kbnode_t keyblock)
+{
+ u32 kid[2], mainkid[2];
+ kbnode_t kbctx, node;
+ PKT_public_key *pk;
+
+ if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
+ BUG ();
+ pk = keyblock->pkt->pkt.public_key;
+
+ keyid_from_pk (pk, mainkid);
+ for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+ {
+ if (!(node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+ continue;
+ pk = node->pkt->pkt.public_key;
+ keyid_from_pk (pk, kid); /* Make sure pk->keyid is set. */
+ if (!pk->main_keyid[0] && !pk->main_keyid[1])
+ {
+ pk->main_keyid[0] = mainkid[0];
+ pk->main_keyid[1] = mainkid[1];
+ }
+ }
+}
+
+
/* Merge all self-signatures with the keys. */
void
merge_keys_and_selfsig (KBNODE keyblock)
diff --git a/g10/keydb.h b/g10/keydb.h
index 492cde37f..b21d9550d 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -201,7 +201,7 @@ void emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo);
#define FORMAT_KEYDESC_NORMAL 0
#define FORMAT_KEYDESC_IMPORT 1
#define FORMAT_KEYDESC_EXPORT 2
-
+#define FORMAT_KEYDESC_DELKEY 3
char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);
@@ -248,6 +248,7 @@ void getkey_end (getkey_ctx_t ctx);
gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk);
+void setup_main_keyids (kbnode_t keyblock);
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_user_id_string_native( u32 *keyid );
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 7c1d6aa08..280d8a9b5 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -702,7 +702,7 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
(int)uidlen, uid,
nbits_from_pk (pk), algo_name,
keystr (pk->keyid), timestr,
- maink?maink:"", trailer );
+ maink?maink:"", trailer);
xfree (maink);
xfree (uid);