1 /* genkey.c - Generate a keypair
2 * Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
34 store_key (gcry_sexp_t private, const char *passphrase, int force,
35 unsigned long s2k_count)
40 unsigned char grip[20];
42 if ( !gcry_pk_get_keygrip (private, grip) )
44 log_error ("can't calculate keygrip\n");
45 return gpg_error (GPG_ERR_GENERAL);
48 len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
50 buf = gcry_malloc_secure (len);
52 return out_of_core ();
53 len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
60 rc = agent_protect (buf, passphrase, &p, &len, s2k_count);
70 rc = agent_write_private_key (grip, buf, len, force);
76 /* Count the number of non-alpha characters in S. Control characters
77 and non-ascii characters are not considered. */
79 nonalpha_count (const char *s)
84 if (isascii (*s) && ( isdigit (*s) || ispunct (*s) ))
91 /* Check PW against a list of pattern. Return 0 if PW does not match
94 check_passphrase_pattern (ctrl_t ctrl, const char *pw)
97 const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
105 infp = gnupg_tmpfile ();
108 err = gpg_error_from_syserror ();
109 log_error (_("error creating temporary file: %s\n"), gpg_strerror (err));
110 return 1; /* Error - assume password should not be used. */
113 if (fwrite (pw, strlen (pw), 1, infp) != 1)
115 err = gpg_error_from_syserror ();
116 log_error (_("error writing to temporary file: %s\n"),
119 return 1; /* Error - assume password should not be used. */
121 fseek (infp, 0, SEEK_SET);
125 argv[i++] = "--null";
127 argv[i++] = opt.check_passphrase_pattern,
129 assert (i < sizeof argv);
131 if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid))
132 result = 1; /* Execute error - assume password should no be used. */
133 else if (gnupg_wait_process (pgmname, pid, 1, NULL))
134 result = 1; /* Helper returned an error - probably a match. */
136 result = 0; /* Success; i.e. no match. */
137 gnupg_release_process (pid);
139 /* Overwrite our temporary file. */
140 fseek (infp, 0, SEEK_SET);
142 for (i=((strlen (pw)+99)/100)*100; i > 0; i--)
151 take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn)
155 if (opt.enforce_passphrase_constraints)
157 err = agent_show_message (ctrl, desc, _("Enter new passphrase"));
159 err = gpg_error (GPG_ERR_CANCELED);
162 err = agent_get_confirmation (ctrl, desc,
163 anyway_btn, _("Enter new passphrase"), 0);
169 take_this_one_anyway (ctrl_t ctrl, const char *desc)
171 return take_this_one_anyway2 (ctrl, desc, _("Take this one anyway"));
175 /* Check whether the passphrase PW is suitable. Returns 0 if the
176 passphrase is suitable and true if it is not and the user should be
177 asked to provide a different one. If SILENT is set, no message are
180 check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
183 unsigned int minlen = opt.min_passphrase_len;
184 unsigned int minnonalpha = opt.min_passphrase_nonalpha;
189 if (utf8_charcount (pw) < minlen )
194 return gpg_error (GPG_ERR_INV_PASSPHRASE);
197 ( ngettext ("Warning: You have entered an insecure passphrase.%%0A"
198 "A passphrase should be at least %u character long.",
199 "Warning: You have entered an insecure passphrase.%%0A"
200 "A passphrase should be at least %u characters long.",
203 return gpg_error_from_syserror ();
204 err = take_this_one_anyway (ctrl, desc);
210 if (nonalpha_count (pw) < minnonalpha )
215 return gpg_error (GPG_ERR_INV_PASSPHRASE);
218 ( ngettext ("Warning: You have entered an insecure passphrase.%%0A"
219 "A passphrase should contain at least %u digit or%%0A"
220 "special character.",
221 "Warning: You have entered an insecure passphrase.%%0A"
222 "A passphrase should contain at least %u digits or%%0A"
223 "special characters.",
224 minnonalpha), minnonalpha );
226 return gpg_error_from_syserror ();
227 err = take_this_one_anyway (ctrl, desc);
233 /* If configured check the passphrase against a list of know words
234 and pattern. The actual test is done by an external program.
235 The warning message is generic to give the user no hint on how to
236 circumvent this list. */
237 if (*pw && opt.check_passphrase_pattern &&
238 check_passphrase_pattern (ctrl, pw))
241 /* */ _("Warning: You have entered an insecure passphrase.%%0A"
242 "A passphrase may not be a known term or match%%0A"
246 return gpg_error (GPG_ERR_INV_PASSPHRASE);
248 err = take_this_one_anyway (ctrl, desc);
253 /* The final check is to warn about an empty passphrase. */
256 const char *desc = (opt.enforce_passphrase_constraints?
257 _("You have not entered a passphrase!%0A"
258 "An empty passphrase is not allowed.") :
259 _("You have not entered a passphrase - "
260 "this is in general a bad idea!%0A"
261 "Please confirm that you do not want to "
262 "have any protection on your key."));
265 return gpg_error (GPG_ERR_INV_PASSPHRASE);
267 err = take_this_one_anyway2 (ctrl, desc,
268 _("Yes, protection is not needed"));
277 /* Callback function to compare the first entered PIN with the one
278 currently being entered. */
280 reenter_compare_cb (struct pin_entry_info_s *pi)
282 const char *pin1 = pi->check_cb_arg;
284 if (!strcmp (pin1, pi->pin))
290 /* Ask the user for a new passphrase using PROMPT. On success the
291 function returns 0 and store the passphrase at R_PASSPHRASE; if the
292 user opted not to use a passphrase NULL will be stored there. The
293 user needs to free the returned string. In case of an error and
294 error code is returned and NULL stored at R_PASSPHRASE. */
296 agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
300 const char *text1 = prompt;
301 const char *text2 = _("Please re-enter this passphrase");
302 const char *initial_errtext = NULL;
303 struct pin_entry_info_s *pi, *pi2;
305 *r_passphrase = NULL;
307 if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
311 unsigned char *buffer;
313 err = pinentry_loopback(ctrl, "NEW_PASSPHRASE", &buffer, &size, len);
319 *r_passphrase = buffer;
322 *r_passphrase = NULL;
327 pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
328 pi2 = pi + (sizeof *pi + 100);
329 pi->max_length = 100;
331 pi->with_qualitybar = 1;
332 pi2->max_length = 100;
334 pi2->check_cb = reenter_compare_cb;
335 pi2->check_cb_arg = pi->pin;
338 err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
339 initial_errtext = NULL;
342 if (check_passphrase_constraints (ctrl, pi->pin, 0))
344 pi->failed_tries = 0;
345 pi2->failed_tries = 0;
348 /* Unless the passphrase is empty, ask to confirm it. */
349 if (pi->pin && *pi->pin)
351 err = agent_askpin (ctrl, text2, NULL, NULL, pi2);
353 { /* The re-entered one did not match and the user did not
355 initial_errtext = _("does not match - try again");
361 if (!err && *pi->pin)
363 /* User wants a passphrase. */
364 *r_passphrase = xtrystrdup (pi->pin);
366 err = gpg_error_from_syserror ();
374 /* Generate a new keypair according to the parameters given in
375 KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
376 using the cache nonce. If NO_PROTECTION is true the key will not
377 be protected by a passphrase. */
379 agent_genkey (ctrl_t ctrl, const char *cache_nonce,
380 const char *keyparam, size_t keyparamlen, int no_protection,
381 int preset, membuf_t *outbuf)
383 gcry_sexp_t s_keyparam, s_key, s_private, s_public;
389 rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
392 log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
393 return gpg_error (GPG_ERR_INV_DATA);
396 /* Get the passphrase now, cause key generation may take a while. */
397 if (no_protection || !cache_nonce)
400 passphrase = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
402 if (passphrase || no_protection)
405 rc = agent_ask_new_passphrase (ctrl,
406 _("Please enter the passphrase to%0A"
407 "protect your new key"),
412 rc = gcry_pk_genkey (&s_key, s_keyparam );
413 gcry_sexp_release (s_keyparam);
416 log_error ("key generation failed: %s\n", gpg_strerror (rc));
421 /* break out the parts */
422 s_private = gcry_sexp_find_token (s_key, "private-key", 0);
425 log_error ("key generation failed: invalid return value\n");
426 gcry_sexp_release (s_key);
428 return gpg_error (GPG_ERR_INV_DATA);
430 s_public = gcry_sexp_find_token (s_key, "public-key", 0);
433 log_error ("key generation failed: invalid return value\n");
434 gcry_sexp_release (s_private);
435 gcry_sexp_release (s_key);
437 return gpg_error (GPG_ERR_INV_DATA);
439 gcry_sexp_release (s_key); s_key = NULL;
441 /* store the secret key */
443 log_debug ("storing private key\n");
444 rc = store_key (s_private, passphrase, 0, ctrl->s2k_count);
450 gcry_create_nonce (tmpbuf, 12);
451 cache_nonce = bin2hex (tmpbuf, 12, NULL);
455 && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
456 passphrase, ctrl->cache_ttl_opt_preset))
457 agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
458 if (preset && !no_protection)
460 unsigned char grip[20];
462 if (gcry_pk_get_keygrip (s_private, grip))
464 bin2hex(grip, 20, hexgrip);
465 rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
466 ctrl->cache_ttl_opt_preset);
472 gcry_sexp_release (s_private);
475 gcry_sexp_release (s_public);
479 /* return the public key */
481 log_debug ("returning public key\n");
482 len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
484 buf = xtrymalloc (len);
487 gpg_error_t tmperr = out_of_core ();
488 gcry_sexp_release (s_private);
489 gcry_sexp_release (s_public);
492 len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
494 put_membuf (outbuf, buf, len);
495 gcry_sexp_release (s_public);
503 /* Apply a new passphrase to the key S_SKEY and store it. If
504 PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
505 passphrase. If PASSPHRASE_ADDR is not NULL store a newly entered
506 passphrase at that address. */
508 agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
509 char **passphrase_addr)
513 if (passphrase_addr && *passphrase_addr)
515 /* Take an empty string as request not to protect the key. */
516 err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1,
525 xfree (*passphrase_addr);
526 *passphrase_addr = NULL;
528 err = agent_ask_new_passphrase (ctrl,
529 _("Please enter the new passphrase"),
532 err = store_key (s_skey, pass, 1, ctrl->s2k_count);
533 if (!err && passphrase_addr)
534 *passphrase_addr = pass;