1 /* genkey.c - Generate a keypair
2 * Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
3 * Copyright (C) 2015 g10 Code GmbH.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
35 store_key (gcry_sexp_t private, const char *passphrase, int force,
36 unsigned long s2k_count)
41 unsigned char grip[20];
43 if ( !gcry_pk_get_keygrip (private, grip) )
45 log_error ("can't calculate keygrip\n");
46 return gpg_error (GPG_ERR_GENERAL);
49 len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
51 buf = gcry_malloc_secure (len);
53 return out_of_core ();
54 len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
61 rc = agent_protect (buf, passphrase, &p, &len, s2k_count, -1);
71 rc = agent_write_private_key (grip, buf, len, force);
77 /* Count the number of non-alpha characters in S. Control characters
78 and non-ascii characters are not considered. */
80 nonalpha_count (const char *s)
85 if (isascii (*s) && ( isdigit (*s) || ispunct (*s) ))
92 /* Check PW against a list of pattern. Return 0 if PW does not match
95 check_passphrase_pattern (ctrl_t ctrl, const char *pw)
98 const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
100 const char *argv[10];
106 infp = gnupg_tmpfile ();
109 err = gpg_error_from_syserror ();
110 log_error (_("error creating temporary file: %s\n"), gpg_strerror (err));
111 return 1; /* Error - assume password should not be used. */
114 if (fwrite (pw, strlen (pw), 1, infp) != 1)
116 err = gpg_error_from_syserror ();
117 log_error (_("error writing to temporary file: %s\n"),
120 return 1; /* Error - assume password should not be used. */
122 fseek (infp, 0, SEEK_SET);
126 argv[i++] = "--null";
128 argv[i++] = opt.check_passphrase_pattern,
130 assert (i < sizeof argv);
132 if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid))
133 result = 1; /* Execute error - assume password should no be used. */
134 else if (gnupg_wait_process (pgmname, pid, 1, NULL))
135 result = 1; /* Helper returned an error - probably a match. */
137 result = 0; /* Success; i.e. no match. */
138 gnupg_release_process (pid);
140 /* Overwrite our temporary file. */
141 fseek (infp, 0, SEEK_SET);
143 for (i=((strlen (pw)+99)/100)*100; i > 0; i--)
152 take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn)
156 if (opt.enforce_passphrase_constraints)
158 err = agent_show_message (ctrl, desc, L_("Enter new passphrase"));
160 err = gpg_error (GPG_ERR_CANCELED);
163 err = agent_get_confirmation (ctrl, desc,
164 anyway_btn, L_("Enter new passphrase"), 0);
170 take_this_one_anyway (ctrl_t ctrl, const char *desc)
172 return take_this_one_anyway2 (ctrl, desc, L_("Take this one anyway"));
176 /* Check whether the passphrase PW is suitable. Returns 0 if the
177 passphrase is suitable and true if it is not and the user should be
178 asked to provide a different one. If FAILED_CONSTRAINT is set, a
179 message describing the problem is returned in
180 *FAILED_CONSTRAINT. */
182 check_passphrase_constraints (ctrl_t ctrl, const char *pw,
183 char **failed_constraint)
186 unsigned int minlen = opt.min_passphrase_len;
187 unsigned int minnonalpha = opt.min_passphrase_nonalpha;
192 if (ctrl && ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
198 /* The first check is to warn about an empty passphrase. */
201 const char *desc = (opt.enforce_passphrase_constraints?
202 L_("You have not entered a passphrase!%0A"
203 "An empty passphrase is not allowed.") :
204 L_("You have not entered a passphrase - "
205 "this is in general a bad idea!%0A"
206 "Please confirm that you do not want to "
207 "have any protection on your key."));
210 if (failed_constraint)
212 if (opt.enforce_passphrase_constraints)
213 *failed_constraint = xstrdup (desc);
215 err = take_this_one_anyway2 (ctrl, desc,
216 L_("Yes, protection is not needed"));
222 /* Now check the constraints and collect the error messages unless
223 in in silent mode which returns immediately. */
224 if (utf8_charcount (pw, -1) < minlen )
226 if (!failed_constraint)
228 err = gpg_error (GPG_ERR_INV_PASSPHRASE);
233 ( ngettext ("A passphrase should be at least %u character long.",
234 "A passphrase should be at least %u characters long.",
238 err = gpg_error_from_syserror ();
243 if (nonalpha_count (pw) < minnonalpha )
245 if (!failed_constraint)
247 err = gpg_error (GPG_ERR_INV_PASSPHRASE);
252 ( ngettext ("A passphrase should contain at least %u digit or%%0A"
253 "special character.",
254 "A passphrase should contain at least %u digits or%%0A"
255 "special characters.",
256 minnonalpha), minnonalpha );
259 err = gpg_error_from_syserror ();
264 /* If configured check the passphrase against a list of known words
265 and pattern. The actual test is done by an external program.
266 The warning message is generic to give the user no hint on how to
267 circumvent this list. */
268 if (*pw && opt.check_passphrase_pattern &&
269 check_passphrase_pattern (ctrl, pw))
271 if (!failed_constraint)
273 err = gpg_error (GPG_ERR_INV_PASSPHRASE);
278 (L_("A passphrase may not be a known term or match%%0A"
279 "certain pattern."));
282 err = gpg_error_from_syserror ();
287 if (failed_constraint && (msg1 || msg2 || msg3))
293 (L_("Warning: You have entered an insecure passphrase."),
295 msg1? msg1 : "", msg1? "%0A" : "",
296 msg2? msg2 : "", msg2? "%0A" : "",
297 msg3? msg3 : "", msg3? "%0A" : "",
301 err = gpg_error_from_syserror ();
304 /* Strip a trailing "%0A". */
306 if (n > 3 && !strcmp (msg + n - 3, "%0A"))
310 if (opt.enforce_passphrase_constraints)
311 *failed_constraint = msg;
314 err = take_this_one_anyway (ctrl, msg);
327 /* Callback function to compare the first entered PIN with the one
328 currently being entered. */
330 reenter_compare_cb (struct pin_entry_info_s *pi)
332 const char *pin1 = pi->check_cb_arg;
334 if (!strcmp (pin1, pi->pin))
336 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
340 /* Ask the user for a new passphrase using PROMPT. On success the
341 function returns 0 and store the passphrase at R_PASSPHRASE; if the
342 user opted not to use a passphrase NULL will be stored there. The
343 user needs to free the returned string. In case of an error and
344 error code is returned and NULL stored at R_PASSPHRASE. */
346 agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
350 const char *text1 = prompt;
351 const char *text2 = L_("Please re-enter this passphrase");
352 char *initial_errtext = NULL;
353 struct pin_entry_info_s *pi, *pi2;
355 *r_passphrase = NULL;
357 if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
361 unsigned char *buffer;
363 err = pinentry_loopback(ctrl, "NEW_PASSPHRASE", &buffer, &size, len);
369 *r_passphrase = buffer;
372 *r_passphrase = NULL;
377 pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
379 return gpg_error_from_syserror ();
380 pi2 = gcry_calloc_secure (1, sizeof (*pi2) + MAX_PASSPHRASE_LEN + 1);
383 err = gpg_error_from_syserror ();
387 pi->max_length = MAX_PASSPHRASE_LEN + 1;
389 pi->with_qualitybar = 1;
391 pi2->max_length = MAX_PASSPHRASE_LEN + 1;
393 pi2->check_cb = reenter_compare_cb;
394 pi2->check_cb_arg = pi->pin;
397 err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi, NULL, 0);
398 xfree (initial_errtext);
399 initial_errtext = NULL;
402 if (check_passphrase_constraints (ctrl, pi->pin, &initial_errtext))
404 pi->failed_tries = 0;
405 pi2->failed_tries = 0;
408 /* Unless the passphrase is empty or the pinentry told us that
409 it already did the repetition check, ask to confirm it. */
410 if (*pi->pin && !pi->repeat_okay)
412 err = agent_askpin (ctrl, text2, NULL, NULL, pi2, NULL, 0);
413 if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
414 { /* The re-entered one did not match and the user did not
416 initial_errtext = xtrystrdup (L_("does not match - try again"));
419 err = gpg_error_from_syserror ();
424 if (!err && *pi->pin)
426 /* User wants a passphrase. */
427 *r_passphrase = xtrystrdup (pi->pin);
429 err = gpg_error_from_syserror ();
432 xfree (initial_errtext);
440 /* Generate a new keypair according to the parameters given in
441 KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
442 using the cache nonce. If NO_PROTECTION is true the key will not
443 be protected by a passphrase. If OVERRIDE_PASSPHRASE is true that
444 passphrase will be used for the new key. */
446 agent_genkey (ctrl_t ctrl, const char *cache_nonce,
447 const char *keyparam, size_t keyparamlen, int no_protection,
448 const char *override_passphrase, int preset, membuf_t *outbuf)
450 gcry_sexp_t s_keyparam, s_key, s_private, s_public;
451 char *passphrase_buffer = NULL;
452 const char *passphrase;
457 rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
460 log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
461 return gpg_error (GPG_ERR_INV_DATA);
464 /* Get the passphrase now, cause key generation may take a while. */
465 if (override_passphrase)
466 passphrase = override_passphrase;
467 else if (no_protection || !cache_nonce)
471 passphrase_buffer = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
472 passphrase = passphrase_buffer;
475 if (passphrase || no_protection)
479 rc = agent_ask_new_passphrase (ctrl,
480 L_("Please enter the passphrase to%0A"
481 "protect your new key"),
485 passphrase = passphrase_buffer;
488 rc = gcry_pk_genkey (&s_key, s_keyparam );
489 gcry_sexp_release (s_keyparam);
492 log_error ("key generation failed: %s\n", gpg_strerror (rc));
493 xfree (passphrase_buffer);
497 /* break out the parts */
498 s_private = gcry_sexp_find_token (s_key, "private-key", 0);
501 log_error ("key generation failed: invalid return value\n");
502 gcry_sexp_release (s_key);
503 xfree (passphrase_buffer);
504 return gpg_error (GPG_ERR_INV_DATA);
506 s_public = gcry_sexp_find_token (s_key, "public-key", 0);
509 log_error ("key generation failed: invalid return value\n");
510 gcry_sexp_release (s_private);
511 gcry_sexp_release (s_key);
512 xfree (passphrase_buffer);
513 return gpg_error (GPG_ERR_INV_DATA);
515 gcry_sexp_release (s_key); s_key = NULL;
517 /* store the secret key */
519 log_debug ("storing private key\n");
520 rc = store_key (s_private, passphrase, 0, ctrl->s2k_count);
526 gcry_create_nonce (tmpbuf, 12);
527 cache_nonce = bin2hex (tmpbuf, 12, NULL);
531 && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
532 passphrase, ctrl->cache_ttl_opt_preset))
533 agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
534 if (preset && !no_protection)
536 unsigned char grip[20];
538 if (gcry_pk_get_keygrip (s_private, grip))
540 bin2hex(grip, 20, hexgrip);
541 rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
542 ctrl->cache_ttl_opt_preset);
546 xfree (passphrase_buffer);
547 passphrase_buffer = NULL;
549 gcry_sexp_release (s_private);
552 gcry_sexp_release (s_public);
556 /* return the public key */
558 log_debug ("returning public key\n");
559 len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
561 buf = xtrymalloc (len);
564 gpg_error_t tmperr = out_of_core ();
565 gcry_sexp_release (s_private);
566 gcry_sexp_release (s_public);
569 len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
571 put_membuf (outbuf, buf, len);
572 gcry_sexp_release (s_public);
580 /* Apply a new passphrase to the key S_SKEY and store it. If
581 PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
582 passphrase. If PASSPHRASE_ADDR is not NULL store a newly entered
583 passphrase at that address. */
585 agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
586 char **passphrase_addr)
590 if (passphrase_addr && *passphrase_addr)
592 /* Take an empty string as request not to protect the key. */
593 err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1,
602 xfree (*passphrase_addr);
603 *passphrase_addr = NULL;
605 err = agent_ask_new_passphrase (ctrl,
606 L_("Please enter the new passphrase"),
609 err = store_key (s_skey, pass, 1, ctrl->s2k_count);
610 if (!err && passphrase_addr)
611 *passphrase_addr = pass;