diff options
-rw-r--r-- | agent/agent.h | 7 | ||||
-rw-r--r-- | agent/command-ssh.c | 4 | ||||
-rw-r--r-- | agent/command.c | 12 | ||||
-rw-r--r-- | agent/cvt-openpgp.c | 4 | ||||
-rw-r--r-- | agent/findkey.c | 23 | ||||
-rw-r--r-- | agent/genkey.c | 2 | ||||
-rw-r--r-- | agent/learncard.c | 9 | ||||
-rw-r--r-- | agent/protect-tool.c | 4 | ||||
-rw-r--r-- | g10/call-agent.c | 6 | ||||
-rw-r--r-- | g10/keygen.c | 7 |
10 files changed, 51 insertions, 27 deletions
diff --git a/agent/agent.h b/agent/agent.h index e72a75068..d32b89215 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -422,7 +422,8 @@ void start_command_handler_ssh (ctrl_t, gnupg_fd_t); gpg_error_t agent_modify_description (const char *in, const char *comment, const gcry_sexp_t key, char **result); int agent_write_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force, + const void *buffer, size_t length, + int force, int reallyforce, const char *serialno, const char *keyref, const char *dispserialno, time_t timestamp); gpg_error_t agent_key_from_file (ctrl_t ctrl, @@ -548,6 +549,7 @@ gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo, gpg_error_t agent_write_shadow_key (const unsigned char *grip, const char *serialno, const char *keyid, const unsigned char *pkbuf, int force, + int reallyforce, const char *dispserialno); @@ -628,7 +630,8 @@ void agent_card_killscd (void); /*-- learncard.c --*/ -int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force); +int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, + int force, int reallyforce); /*-- cvt-openpgp.c --*/ diff --git a/agent/command-ssh.c b/agent/command-ssh.c index f5ad977e2..bd1a41863 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2499,7 +2499,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) /* (Shadow)-key is not available in our key storage. */ agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno); - err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0, + err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0, 0, dispserialno); xfree (dispserialno); if (err) @@ -3159,7 +3159,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec, /* Store this key to our key storage. We do not store a creation * timestamp because we simply do not know. */ - err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, + err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, 0, NULL, NULL, NULL, 0); if (err) goto out; diff --git a/agent/command.c b/agent/command.c index 4a4d6e81a..2e1d820ba 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1042,7 +1042,7 @@ cmd_readkey (assuan_context_t ctx, char *line) /* Shadow-key is or is not available in our key storage. In * any case we need to check whether we need to update with * a new display-s/n or whatever. */ - rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0, + rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0, 0, dispserialno); if (rc) goto leave; @@ -1855,16 +1855,18 @@ cmd_learn (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); gpg_error_t err; - int send, sendinfo, force; + int send, sendinfo, force, reallyforce; send = has_option (line, "--send"); sendinfo = send? 1 : has_option (line, "--sendinfo"); force = has_option (line, "--force"); + reallyforce = has_option (line, "--reallyforce"); if (ctrl->restricted) return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); - err = agent_handle_learn (ctrl, send, sendinfo? ctx : NULL, force); + err = agent_handle_learn (ctrl, send, sendinfo? ctx : NULL, + force, reallyforce); return leave_cmd (ctx, err); } @@ -2427,11 +2429,11 @@ cmd_import_key (assuan_context_t ctx, char *line) err = agent_protect (key, passphrase, &finalkey, &finalkeylen, ctrl->s2k_count); if (!err) - err = agent_write_private_key (grip, finalkey, finalkeylen, force, + err = agent_write_private_key (grip, finalkey, finalkeylen, force, 0, NULL, NULL, NULL, opt_timestamp); } else - err = agent_write_private_key (grip, key, realkeylen, force, + err = agent_write_private_key (grip, key, realkeylen, force, 0, NULL, NULL, NULL, opt_timestamp); leave: diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index c9b70a591..fe515068c 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -1070,7 +1070,7 @@ convert_from_openpgp_native (ctrl_t ctrl, &protectedkey, &protectedkeylen, ctrl->s2k_count)) agent_write_private_key (grip, protectedkey, protectedkeylen, - 1/*force*/, NULL, NULL, NULL, 0); + 1/*force*/, 0, NULL, NULL, NULL, 0); xfree (protectedkey); } else @@ -1079,7 +1079,7 @@ convert_from_openpgp_native (ctrl_t ctrl, agent_write_private_key (grip, *r_key, gcry_sexp_canon_len (*r_key, 0, NULL,NULL), - 1/*force*/, NULL, NULL, NULL, 0); + 1/*force*/, 0, NULL, NULL, NULL, 0); } } diff --git a/agent/findkey.c b/agent/findkey.c index 31868324c..a5055bcc4 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -82,7 +82,8 @@ fname_from_keygrip (const unsigned char *grip, int for_new) * recorded as creation date. */ int agent_write_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force, + const void *buffer, size_t length, + int force, int reallyforce, const char *serialno, const char *keyref, const char *dispserialno, time_t timestamp) @@ -165,10 +166,13 @@ agent_write_private_key (const unsigned char *grip, /* Check that we do not update a regular key with a shadow key. */ if (is_regular && gpg_err_code (is_shadowed_key (key)) == GPG_ERR_TRUE) { - log_info ("updating regular key file '%s'" - " by a shadow key inhibited\n", oldfname); - err = 0; /* Simply ignore the error. */ - goto leave; + if (!reallyforce) + { + log_info ("updating regular key file '%s'" + " by a shadow key inhibited\n", oldfname); + err = 0; /* Simply ignore the error. */ + goto leave; + } } /* Check that we update a regular key only in force mode. */ if (is_regular && !force) @@ -1704,12 +1708,13 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text, * Shadow key is created by an S-expression public key in PKBUF and * card's SERIALNO and the IDSTRING. With FORCE passed as true an * existing key with the given GRIP will get overwritten. If - * DISPSERIALNO is not NULL the human readable s/n will also be - * recorded in the key file. */ + * REALLYFORCE is also true, even a private key will be overwritten by + * a shadown key. If DISPSERIALNO is not NULL the human readable s/n + * will also be recorded in the key file. */ gpg_error_t agent_write_shadow_key (const unsigned char *grip, const char *serialno, const char *keyid, - const unsigned char *pkbuf, int force, + const unsigned char *pkbuf, int force, int reallyforce, const char *dispserialno) { gpg_error_t err; @@ -1737,7 +1742,7 @@ agent_write_shadow_key (const unsigned char *grip, } len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); - err = agent_write_private_key (grip, shdkey, len, force, + err = agent_write_private_key (grip, shdkey, len, force, reallyforce, serialno, keyid, dispserialno, 0); xfree (shdkey); if (err) diff --git a/agent/genkey.c b/agent/genkey.c index 291862f2f..d080bac57 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -69,7 +69,7 @@ store_key (gcry_sexp_t private, const char *passphrase, int force, buf = p; } - rc = agent_write_private_key (grip, buf, len, force, + rc = agent_write_private_key (grip, buf, len, force, 0, NULL, NULL, NULL, timestamp); xfree (buf); return rc; diff --git a/agent/learncard.c b/agent/learncard.c index 0df9b69c1..f007b6da6 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -297,9 +297,12 @@ send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context) } /* Perform the learn operation. If ASSUAN_CONTEXT is not NULL and - SEND is true all new certificates are send back via Assuan. */ + SEND is true all new certificates are send back via Assuan. If + REALLYFORCE is true a private key will be overwritten by a stub + key. */ int -agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force) +agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, + int force, int reallyforce) { int rc; struct kpinfo_cb_parm_s parm; @@ -414,7 +417,7 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force) agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno); rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, - force, dispserialno); + force, reallyforce, dispserialno); xfree (dispserialno); } xfree (pubkey); diff --git a/agent/protect-tool.c b/agent/protect-tool.c index c0c8cbd04..35ed9932f 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -807,13 +807,15 @@ agent_askpin (ctrl_t ctrl, * to stdout. */ int agent_write_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force, + const void *buffer, size_t length, + int force, int reallyforce, const char *serialno, const char *keyref, const char *dispserialno, time_t timestamp) { char hexgrip[40+4+1]; char *p; + (void)reallyforce; (void)force; (void)timestamp; (void)serialno; diff --git a/g10/call-agent.c b/g10/call-agent.c index 20235d2ad..486b7d95f 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -745,6 +745,11 @@ learn_status_cb (void *opaque, const char *line) * card-util.c * keyedit_menu * card_store_key_with_backup (Woth force to remove secret key data) + * + * If force has the value 2 the --reallyforce option is also used. + * This is to make sure the sshadow key overwrites the private key. + * Note that this option is gnupg 2.2 specific because since 2.4.4 an + * ephemeral private key store is used instead. */ int agent_scd_learn (struct agent_card_info_s *info, int force) @@ -764,6 +769,7 @@ agent_scd_learn (struct agent_card_info_s *info, int force) parm.ctx = agent_ctx; rc = assuan_transact (agent_ctx, + force == 2? "LEARN --sendinfo --force --reallyforce" : force ? "LEARN --sendinfo --force" : "LEARN --sendinfo", dummy_data_cb, NULL, default_inq_cb, &parm, learn_status_cb, info); diff --git a/g10/keygen.c b/g10/keygen.c index 08e546954..c8487be0a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -5201,8 +5201,11 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk, if (err) log_error ("writing card key to backup file: %s\n", gpg_strerror (err)); else - /* Remove secret key data in agent side. */ - agent_scd_learn (NULL, 1); + { + /* Remove secret key data in agent side. We use force 2 here to + * allow overwriting of the temporary private key. */ + agent_scd_learn (NULL, 2); + } leave: xfree (ecdh_param_str); |