diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/agent.h | 3 | ||||
-rw-r--r-- | agent/command.c | 46 | ||||
-rw-r--r-- | agent/genkey.c | 43 |
3 files changed, 69 insertions, 23 deletions
diff --git a/agent/agent.h b/agent/agent.h index c7c65afa7..4be592526 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -396,7 +396,8 @@ gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt, char **r_passphrase); int agent_genkey (ctrl_t ctrl, const char *cache_nonce, const char *keyparam, size_t keyparmlen, - int no_protection, int preset, membuf_t *outbuf); + int no_protection, const char *override_passphrase, + int preset, membuf_t *outbuf); gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey, char **passphrase_addr); diff --git a/agent/command.c b/agent/command.c index da7e50857..d5644cbac 100644 --- a/agent/command.c +++ b/agent/command.c @@ -914,22 +914,23 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) static const char hlp_genkey[] = - "GENKEY [--no-protection] [--preset] [<cache_nonce>]\n" + "GENKEY [--no-protection] [--preset] [--inq-passwd] [<cache_nonce>]\n" "\n" "Generate a new key, store the secret part and return the public\n" "part. Here is an example transaction:\n" "\n" " C: GENKEY\n" " S: INQUIRE KEYPARAM\n" - " C: D (genkey (rsa (nbits 1024)))\n" + " C: D (genkey (rsa (nbits 2048)))\n" " C: END\n" " S: D (public-key\n" " S: D (rsa (n 326487324683264) (e 10001)))\n" " S: OK key created\n" "\n" "When the --preset option is used the passphrase for the generated\n" - "key will be added to the cache.\n" - "\n"; + "key will be added to the cache. When --inq-passwd is used an inquire\n" + "with the keyword NEWPASSWD is used to request the passphrase for the\n" + "new key.\n"; static gpg_error_t cmd_genkey (assuan_context_t ctx, char *line) { @@ -938,16 +939,20 @@ cmd_genkey (assuan_context_t ctx, char *line) int no_protection; unsigned char *value; size_t valuelen; + unsigned char *newpasswd = NULL; membuf_t outbuf; char *cache_nonce = NULL; int opt_preset; + int opt_inq_passwd; + size_t n; char *p; if (ctrl->restricted) return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); - opt_preset = has_option (line, "--preset"); no_protection = has_option (line, "--no-protection"); + opt_preset = has_option (line, "--preset"); + opt_inq_passwd = has_option (line, "--inq-passwd"); line = skip_options (line); p = line; @@ -966,8 +971,37 @@ cmd_genkey (assuan_context_t ctx, char *line) init_membuf (&outbuf, 512); + /* If requested, ask for the password to be used for the key. If + this is not used the regular Pinentry mechanism is used. */ + if (opt_inq_passwd && !no_protection) + { + /* (N is used as a dummy) */ + assuan_begin_confidential (ctx); + rc = assuan_inquire (ctx, "NEWPASSWD", &newpasswd, &n, 256); + assuan_end_confidential (ctx); + if (rc) + goto leave; + if (!*newpasswd) + { + /* Empty password given - switch to no-protection mode. */ + xfree (newpasswd); + newpasswd = NULL; + no_protection = 1; + } + + } + rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection, - opt_preset, &outbuf); + newpasswd, opt_preset, &outbuf); + + leave: + if (newpasswd) + { + /* Assuan_inquire does not allow us to read into secure memory + thus we need to wipe it ourself. */ + wipememory (newpasswd, strlen (newpasswd)); + xfree (newpasswd); + } xfree (value); if (rc) clear_outbuf (&outbuf); diff --git a/agent/genkey.c b/agent/genkey.c index 91917f77b..d7b6007bf 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -410,14 +410,16 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt, /* Generate a new keypair according to the parameters given in KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase using the cache nonce. If NO_PROTECTION is true the key will not - be protected by a passphrase. */ + be protected by a passphrase. If OVERRIDE_PASSPHRASE is true that + passphrase will be used for the new key. */ int agent_genkey (ctrl_t ctrl, const char *cache_nonce, const char *keyparam, size_t keyparamlen, int no_protection, - int preset, membuf_t *outbuf) + const char *override_passphrase, int preset, membuf_t *outbuf) { gcry_sexp_t s_keyparam, s_key, s_private, s_public; - char *passphrase; + char *passphrase_buffer = NULL; + const char *passphrase; int rc; size_t len; char *buf; @@ -430,27 +432,35 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, } /* Get the passphrase now, cause key generation may take a while. */ - if (no_protection || !cache_nonce) + if (override_passphrase) + passphrase = override_passphrase; + else if (no_protection || !cache_nonce) passphrase = NULL; else - passphrase = agent_get_cache (cache_nonce, CACHE_MODE_NONCE); + { + passphrase_buffer = agent_get_cache (cache_nonce, CACHE_MODE_NONCE); + passphrase = passphrase_buffer; + } if (passphrase || no_protection) - rc = 0; + ; else - rc = agent_ask_new_passphrase (ctrl, - _("Please enter the passphrase to%0A" - "protect your new key"), - &passphrase); - if (rc) - return rc; + { + rc = agent_ask_new_passphrase (ctrl, + _("Please enter the passphrase to%0A" + "protect your new key"), + &passphrase_buffer); + if (rc) + return rc; + passphrase = passphrase_buffer; + } rc = gcry_pk_genkey (&s_key, s_keyparam ); gcry_sexp_release (s_keyparam); if (rc) { log_error ("key generation failed: %s\n", gpg_strerror (rc)); - xfree (passphrase); + xfree (passphrase_buffer); return rc; } @@ -460,7 +470,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, { log_error ("key generation failed: invalid return value\n"); gcry_sexp_release (s_key); - xfree (passphrase); + xfree (passphrase_buffer); return gpg_error (GPG_ERR_INV_DATA); } s_public = gcry_sexp_find_token (s_key, "public-key", 0); @@ -469,7 +479,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, log_error ("key generation failed: invalid return value\n"); gcry_sexp_release (s_private); gcry_sexp_release (s_key); - xfree (passphrase); + xfree (passphrase_buffer); return gpg_error (GPG_ERR_INV_DATA); } gcry_sexp_release (s_key); s_key = NULL; @@ -503,7 +513,8 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, } } } - xfree (passphrase); + xfree (passphrase_buffer); + passphrase_buffer = NULL; passphrase = NULL; gcry_sexp_release (s_private); if (rc) |