agent: Support pinentries with integrated repeat passphrase feature.
[gnupg.git] / agent / genkey.c
1 /* genkey.c - Generate a keypair
2  * Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <assert.h>
27
28 #include "agent.h"
29 #include "i18n.h"
30 #include "exechelp.h"
31 #include "sysutils.h"
32
33 static int
34 store_key (gcry_sexp_t private, const char *passphrase, int force,
35         unsigned long s2k_count)
36 {
37   int rc;
38   unsigned char *buf;
39   size_t len;
40   unsigned char grip[20];
41
42   if ( !gcry_pk_get_keygrip (private, grip) )
43     {
44       log_error ("can't calculate keygrip\n");
45       return gpg_error (GPG_ERR_GENERAL);
46     }
47
48   len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
49   assert (len);
50   buf = gcry_malloc_secure (len);
51   if (!buf)
52       return out_of_core ();
53   len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
54   assert (len);
55
56   if (passphrase)
57     {
58       unsigned char *p;
59
60       rc = agent_protect (buf, passphrase, &p, &len, s2k_count);
61       if (rc)
62         {
63           xfree (buf);
64           return rc;
65         }
66       xfree (buf);
67       buf = p;
68     }
69
70   rc = agent_write_private_key (grip, buf, len, force);
71   xfree (buf);
72   return rc;
73 }
74
75
76 /* Count the number of non-alpha characters in S.  Control characters
77    and non-ascii characters are not considered.  */
78 static size_t
79 nonalpha_count (const char *s)
80 {
81   size_t n;
82
83   for (n=0; *s; s++)
84     if (isascii (*s) && ( isdigit (*s) || ispunct (*s) ))
85       n++;
86
87   return n;
88 }
89
90
91 /* Check PW against a list of pattern.  Return 0 if PW does not match
92    these pattern.  */
93 static int
94 check_passphrase_pattern (ctrl_t ctrl, const char *pw)
95 {
96   gpg_error_t err = 0;
97   const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
98   FILE *infp;
99   const char *argv[10];
100   pid_t pid;
101   int result, i;
102
103   (void)ctrl;
104
105   infp = gnupg_tmpfile ();
106   if (!infp)
107     {
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.  */
111     }
112
113   if (fwrite (pw, strlen (pw), 1, infp) != 1)
114     {
115       err = gpg_error_from_syserror ();
116       log_error (_("error writing to temporary file: %s\n"),
117                  gpg_strerror (err));
118       fclose (infp);
119       return 1; /* Error - assume password should not be used.  */
120     }
121   fseek (infp, 0, SEEK_SET);
122   clearerr (infp);
123
124   i = 0;
125   argv[i++] = "--null";
126   argv[i++] = "--",
127   argv[i++] = opt.check_passphrase_pattern,
128   argv[i] = NULL;
129   assert (i < sizeof argv);
130
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.  */
135   else
136     result = 0; /* Success; i.e. no match.  */
137   gnupg_release_process (pid);
138
139   /* Overwrite our temporary file. */
140   fseek (infp, 0, SEEK_SET);
141   clearerr (infp);
142   for (i=((strlen (pw)+99)/100)*100; i > 0; i--)
143     putc ('\xff', infp);
144   fflush (infp);
145   fclose (infp);
146   return result;
147 }
148
149
150 static int
151 take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn)
152 {
153   gpg_error_t err;
154
155   if (opt.enforce_passphrase_constraints)
156     {
157       err = agent_show_message (ctrl, desc, _("Enter new passphrase"));
158       if (!err)
159         err = gpg_error (GPG_ERR_CANCELED);
160     }
161   else
162     err = agent_get_confirmation (ctrl, desc,
163                                   anyway_btn, _("Enter new passphrase"), 0);
164   return err;
165 }
166
167
168 static int
169 take_this_one_anyway (ctrl_t ctrl, const char *desc)
170 {
171   return take_this_one_anyway2 (ctrl, desc, _("Take this one anyway"));
172 }
173
174
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
178    displayed.  */
179 int
180 check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent)
181 {
182   gpg_error_t err = 0;
183   unsigned int minlen = opt.min_passphrase_len;
184   unsigned int minnonalpha = opt.min_passphrase_nonalpha;
185   char *msg1 = NULL;
186   char *msg2 = NULL;
187   char *msg3 = NULL;
188
189   if (!pw)
190     pw = "";
191
192   /* The first check is to warn about an empty passphrase. */
193   if (!*pw)
194     {
195       const char *desc = (opt.enforce_passphrase_constraints?
196                           _("You have not entered a passphrase!%0A"
197                             "An empty passphrase is not allowed.") :
198                           _("You have not entered a passphrase - "
199                             "this is in general a bad idea!%0A"
200                             "Please confirm that you do not want to "
201                             "have any protection on your key."));
202
203       if (silent)
204         return gpg_error (GPG_ERR_INV_PASSPHRASE);
205
206       err = take_this_one_anyway2 (ctrl, desc,
207                                    _("Yes, protection is not needed"));
208       goto leave;
209     }
210
211   /* Now check the constraints and collect the error messages unless
212      in in silent mode which returns immediately.  */
213   if (utf8_charcount (pw) < minlen )
214     {
215       if (silent)
216         {
217           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
218           goto leave;
219         }
220
221       msg1 = xtryasprintf
222         ( ngettext ("A passphrase should be at least %u character long.",
223                     "A passphrase should be at least %u characters long.",
224                     minlen), minlen );
225       if (!msg1)
226         {
227           err = gpg_error_from_syserror ();
228           goto leave;
229         }
230     }
231
232   if (nonalpha_count (pw) < minnonalpha )
233     {
234       if (silent)
235         {
236           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
237           goto leave;
238         }
239
240       msg2 = xtryasprintf
241         ( ngettext ("A passphrase should contain at least %u digit or%%0A"
242                     "special character.",
243                     "A passphrase should contain at least %u digits or%%0A"
244                     "special characters.",
245                     minnonalpha), minnonalpha );
246       if (!msg2)
247         {
248           err = gpg_error_from_syserror ();
249           goto leave;
250         }
251     }
252
253   /* If configured check the passphrase against a list of known words
254      and pattern.  The actual test is done by an external program.
255      The warning message is generic to give the user no hint on how to
256      circumvent this list.  */
257   if (*pw && opt.check_passphrase_pattern &&
258       check_passphrase_pattern (ctrl, pw))
259     {
260       if (silent)
261         {
262           err = gpg_error (GPG_ERR_INV_PASSPHRASE);
263           goto leave;
264         }
265
266       msg3 = xtryasprintf
267         (_("A passphrase may not be a known term or match%%0A"
268            "certain pattern."));
269       if (!msg3)
270         {
271           err = gpg_error_from_syserror ();
272           goto leave;
273         }
274     }
275
276   if (msg1 || msg2 || msg3)
277     {
278       char *msg;
279       size_t n;
280
281       msg = strconcat
282         (_("Warning: You have entered an insecure passphrase."),
283          "%0A%0A",
284          msg1? msg1 : "", msg1? "%0A" : "",
285          msg2? msg2 : "", msg2? "%0A" : "",
286          msg3? msg3 : "", msg3? "%0A" : "",
287          NULL);
288       if (!msg)
289         {
290           err = gpg_error_from_syserror ();
291           goto leave;
292         }
293       /* Strip a trailing "%0A".  */
294       n = strlen (msg);
295       if (n > 3 && !strcmp (msg + n - 3, "%0A"))
296         msg[n-3] = 0;
297
298       /* Show error messages.  */
299       err = take_this_one_anyway (ctrl, msg);
300       xfree (msg);
301     }
302
303  leave:
304   xfree (msg1);
305   xfree (msg2);
306   xfree (msg3);
307   return err;
308 }
309
310
311 /* Callback function to compare the first entered PIN with the one
312    currently being entered. */
313 static int
314 reenter_compare_cb (struct pin_entry_info_s *pi)
315 {
316   const char *pin1 = pi->check_cb_arg;
317
318   if (!strcmp (pin1, pi->pin))
319     return 0; /* okay */
320   return -1;
321 }
322
323
324 /* Ask the user for a new passphrase using PROMPT.  On success the
325    function returns 0 and store the passphrase at R_PASSPHRASE; if the
326    user opted not to use a passphrase NULL will be stored there.  The
327    user needs to free the returned string.  In case of an error and
328    error code is returned and NULL stored at R_PASSPHRASE.  */
329 gpg_error_t
330 agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
331                           char **r_passphrase)
332 {
333   gpg_error_t err;
334   const char *text1 = prompt;
335   const char *text2 = _("Please re-enter this passphrase");
336   const char *initial_errtext = NULL;
337   struct pin_entry_info_s *pi, *pi2;
338
339   *r_passphrase = NULL;
340
341   if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
342     {
343         size_t size;
344         size_t len = 100;
345         unsigned char *buffer;
346
347         err = pinentry_loopback(ctrl, "NEW_PASSPHRASE", &buffer, &size, len);
348         if (!err)
349           {
350             if (size)
351               {
352                 buffer[size] = 0;
353                 *r_passphrase = buffer;
354               }
355             else
356                 *r_passphrase = NULL;
357           }
358         return err;
359     }
360
361   pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
362   pi2 = pi + (sizeof *pi + 100);
363   pi->max_length = 100;
364   pi->max_tries = 3;
365   pi->with_qualitybar = 1;
366   pi->with_repeat = 1;
367   pi2->max_length = 100;
368   pi2->max_tries = 3;
369   pi2->check_cb = reenter_compare_cb;
370   pi2->check_cb_arg = pi->pin;
371
372  next_try:
373   err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
374   initial_errtext = NULL;
375   if (!err)
376     {
377       if (check_passphrase_constraints (ctrl, pi->pin, 0))
378         {
379           pi->failed_tries = 0;
380           pi2->failed_tries = 0;
381           goto next_try;
382         }
383       /* Unless the passphrase is empty or the pinentry told us that
384          it already did the repetition check, ask to confirm it.  */
385       if (pi->pin && *pi->pin && !pi->repeat_okay)
386         {
387           err = agent_askpin (ctrl, text2, NULL, NULL, pi2);
388           if (err == -1)
389             { /* The re-entered one did not match and the user did not
390                  hit cancel. */
391               initial_errtext = _("does not match - try again");
392               goto next_try;
393             }
394         }
395     }
396
397   if (!err && *pi->pin)
398     {
399       /* User wants a passphrase. */
400       *r_passphrase = xtrystrdup (pi->pin);
401       if (!*r_passphrase)
402         err = gpg_error_from_syserror ();
403     }
404   xfree (pi);
405   return err;
406 }
407
408
409
410 /* Generate a new keypair according to the parameters given in
411    KEYPARAM.  If CACHE_NONCE is given first try to lookup a passphrase
412    using the cache nonce.  If NO_PROTECTION is true the key will not
413    be protected by a passphrase.  */
414 int
415 agent_genkey (ctrl_t ctrl, const char *cache_nonce,
416               const char *keyparam, size_t keyparamlen, int no_protection,
417               int preset, membuf_t *outbuf)
418 {
419   gcry_sexp_t s_keyparam, s_key, s_private, s_public;
420   char *passphrase;
421   int rc;
422   size_t len;
423   char *buf;
424
425   rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
426   if (rc)
427     {
428       log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
429       return gpg_error (GPG_ERR_INV_DATA);
430     }
431
432   /* Get the passphrase now, cause key generation may take a while. */
433   if (no_protection || !cache_nonce)
434     passphrase = NULL;
435   else
436     passphrase = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
437
438   if (passphrase || no_protection)
439     rc = 0;
440   else
441     rc = agent_ask_new_passphrase (ctrl,
442                                    _("Please enter the passphrase to%0A"
443                                      "protect your new key"),
444                                    &passphrase);
445   if (rc)
446     return rc;
447
448   rc = gcry_pk_genkey (&s_key, s_keyparam );
449   gcry_sexp_release (s_keyparam);
450   if (rc)
451     {
452       log_error ("key generation failed: %s\n", gpg_strerror (rc));
453       xfree (passphrase);
454       return rc;
455     }
456
457   /* break out the parts */
458   s_private = gcry_sexp_find_token (s_key, "private-key", 0);
459   if (!s_private)
460     {
461       log_error ("key generation failed: invalid return value\n");
462       gcry_sexp_release (s_key);
463       xfree (passphrase);
464       return gpg_error (GPG_ERR_INV_DATA);
465     }
466   s_public = gcry_sexp_find_token (s_key, "public-key", 0);
467   if (!s_public)
468     {
469       log_error ("key generation failed: invalid return value\n");
470       gcry_sexp_release (s_private);
471       gcry_sexp_release (s_key);
472       xfree (passphrase);
473       return gpg_error (GPG_ERR_INV_DATA);
474     }
475   gcry_sexp_release (s_key); s_key = NULL;
476
477   /* store the secret key */
478   if (DBG_CRYPTO)
479     log_debug ("storing private key\n");
480   rc = store_key (s_private, passphrase, 0, ctrl->s2k_count);
481   if (!rc)
482     {
483       if (!cache_nonce)
484         {
485           char tmpbuf[12];
486           gcry_create_nonce (tmpbuf, 12);
487           cache_nonce = bin2hex (tmpbuf, 12, NULL);
488         }
489       if (cache_nonce
490           && !no_protection
491           && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
492                                passphrase, ctrl->cache_ttl_opt_preset))
493         agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
494       if (preset && !no_protection)
495         {
496           unsigned char grip[20];
497           char hexgrip[40+1];
498           if (gcry_pk_get_keygrip (s_private, grip))
499             {
500               bin2hex(grip, 20, hexgrip);
501               rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
502                                     ctrl->cache_ttl_opt_preset);
503             }
504         }
505     }
506   xfree (passphrase);
507   passphrase = NULL;
508   gcry_sexp_release (s_private);
509   if (rc)
510     {
511       gcry_sexp_release (s_public);
512       return rc;
513     }
514
515   /* return the public key */
516   if (DBG_CRYPTO)
517     log_debug ("returning public key\n");
518   len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
519   assert (len);
520   buf = xtrymalloc (len);
521   if (!buf)
522     {
523       gpg_error_t tmperr = out_of_core ();
524       gcry_sexp_release (s_private);
525       gcry_sexp_release (s_public);
526       return tmperr;
527     }
528   len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
529   assert (len);
530   put_membuf (outbuf, buf, len);
531   gcry_sexp_release (s_public);
532   xfree (buf);
533
534   return 0;
535 }
536
537
538 \f
539 /* Apply a new passphrase to the key S_SKEY and store it.  If
540    PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
541    passphrase.  If PASSPHRASE_ADDR is not NULL store a newly entered
542    passphrase at that address. */
543 gpg_error_t
544 agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
545                          char **passphrase_addr)
546 {
547   gpg_error_t err;
548
549   if (passphrase_addr && *passphrase_addr)
550     {
551       /* Take an empty string as request not to protect the key.  */
552       err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1,
553               ctrl->s2k_count);
554     }
555   else
556     {
557       char *pass = NULL;
558
559       if (passphrase_addr)
560         {
561           xfree (*passphrase_addr);
562           *passphrase_addr = NULL;
563         }
564       err = agent_ask_new_passphrase (ctrl,
565                                       _("Please enter the new passphrase"),
566                                       &pass);
567       if (!err)
568         err = store_key (s_skey, pass, 1, ctrl->s2k_count);
569       if (!err && passphrase_addr)
570         *passphrase_addr = pass;
571       else
572         xfree (pass);
573     }
574
575   return err;
576 }