gpg: Delete secret key after "keytocard".

* g10/card-util.c (card_store_subkey): Add arg processed_keys.
* g10/keyedit.c (keyedit_menu): Delete secret key.
--

This used to work using the gpg-agent: learn we called at "save" time.
However, the recent change inhibited the creation of a shadow key by
learn if a regular key still exists.  Now we do an explicit delete key
at save time.  This syncs the behaviour with the description of the
man page.

GnuPG-bug-id: 6378
This commit is contained in:
Werner Koch 2023-03-15 09:36:36 +01:00
parent 2e065b4bd2
commit 5118beeec1
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 48 additions and 9 deletions

View File

@ -1781,12 +1781,13 @@ card_generate_subkey (ctrl_t ctrl, kbnode_t pub_keyblock)
} }
/* Store the key at NODE into the smartcard and modify NODE to /* Store the key at NODE into the smartcard and modify NODE to carry
carry the serialno stuff instead of the actual secret key the serialno stuff instead of the actual secret key parameters.
parameters. USE is the usage for that key; 0 means any USE is the usage for that key; 0 means any usage. If
usage. */ PROCESSED_KEYS is not NULL it is a poiter to an strlist which will
be filled with the keygrips of successfully stored keys. */
int int
card_store_subkey (KBNODE node, int use) card_store_subkey (KBNODE node, int use, strlist_t *processed_keys)
{ {
struct agent_card_info_s info; struct agent_card_info_s info;
int okay = 0; int okay = 0;
@ -1875,7 +1876,11 @@ card_store_subkey (KBNODE node, int use)
if (rc) if (rc)
log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc)); log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
else else
okay = 1; {
okay = 1;
if (processed_keys)
add_to_strlist (processed_keys, hexgrip);
}
xfree (hexgrip); xfree (hexgrip);
leave: leave:

View File

@ -1424,6 +1424,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
int sec_shadowing = 0; int sec_shadowing = 0;
int run_subkey_warnings = 0; int run_subkey_warnings = 0;
int have_commands = !!commands; int have_commands = !!commands;
strlist_t delseckey_list = NULL;
int delseckey_list_warn = 0;
if (opt.command_fd != -1) if (opt.command_fd != -1)
; ;
@ -1500,6 +1502,14 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
subkey_expire_warning (keyblock); subkey_expire_warning (keyblock);
} }
if (delseckey_list_warn)
{
delseckey_list_warn = 0;
tty_printf
(_("Note: the local copy of the secret key"
" will only be deleted with \"save\".\n"));
}
do do
{ {
xfree (answer); xfree (answer);
@ -1872,10 +1882,12 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
if (node) if (node)
{ {
PKT_public_key *xxpk = node->pkt->pkt.public_key; PKT_public_key *xxpk = node->pkt->pkt.public_key;
if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0)) if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0,
&delseckey_list))
{ {
redisplay = 1; redisplay = 1;
sec_shadowing = 1; sec_shadowing = 1;
delseckey_list_warn = 1;
} }
} }
} }
@ -1952,7 +1964,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
pkt->pkttype = PKT_PUBLIC_KEY; pkt->pkttype = PKT_PUBLIC_KEY;
/* Ask gpg-agent to store the secret key to card. */ /* Ask gpg-agent to store the secret key to card. */
if (card_store_subkey (node, 0)) if (card_store_subkey (node, 0, NULL))
{ {
redisplay = 1; redisplay = 1;
sec_shadowing = 1; sec_shadowing = 1;
@ -2262,6 +2274,27 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
} }
} }
if (delseckey_list)
{
strlist_t sl;
for (err = 0, sl = delseckey_list; sl; sl = sl->next)
{
if (*sl->d)
{
err = agent_delete_key (ctrl, sl->d, NULL, 1/*force*/);
if (err)
break;
*sl->d = 0; /* Mark deleted. */
}
}
if (err)
{
log_error (_("deleting copy of secret key failed: %s\n"),
gpg_strerror (err));
break; /* the "save". */
}
}
if (sec_shadowing) if (sec_shadowing)
{ {
err = agent_scd_learn (NULL, 1); err = agent_scd_learn (NULL, 1);
@ -2291,6 +2324,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
} /* End of the main command loop. */ } /* End of the main command loop. */
leave: leave:
free_strlist (delseckey_list);
release_kbnode (keyblock); release_kbnode (keyblock);
keydb_release (kdbhd); keydb_release (kdbhd);
xfree (answer); xfree (answer);

View File

@ -516,7 +516,7 @@ void change_pin (int no, int allow_admin);
void card_status (ctrl_t ctrl, estream_t fp, const char *serialno); void card_status (ctrl_t ctrl, estream_t fp, const char *serialno);
void card_edit (ctrl_t ctrl, strlist_t commands); void card_edit (ctrl_t ctrl, strlist_t commands);
gpg_error_t card_generate_subkey (ctrl_t ctrl, kbnode_t pub_keyblock); gpg_error_t card_generate_subkey (ctrl_t ctrl, kbnode_t pub_keyblock);
int card_store_subkey (KBNODE node, int use); int card_store_subkey (KBNODE node, int use, strlist_t *processed_keys);
#endif #endif
/*-- migrate.c --*/ /*-- migrate.c --*/