e01a7bcb672b508d8b164f30e5c185fe2c44979b
[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"), strerror (errno));
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                  strerror (errno));
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;
183   unsigned int minlen = opt.min_passphrase_len;
184   unsigned int minnonalpha = opt.min_passphrase_nonalpha;
185
186   if (!pw)
187     pw = "";
188
189   if (utf8_charcount (pw) < minlen )
190     {
191       char *desc;
192
193       if (silent)
194         return gpg_error (GPG_ERR_INV_PASSPHRASE);
195
196       desc = xtryasprintf
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.",
201                     minlen), minlen );
202       if (!desc)
203         return gpg_error_from_syserror ();
204       err = take_this_one_anyway (ctrl, desc);
205       xfree (desc);
206       if (err)
207         return err;
208     }
209
210   if (nonalpha_count (pw) < minnonalpha )
211     {
212       char *desc;
213
214       if (silent)
215         return gpg_error (GPG_ERR_INV_PASSPHRASE);
216
217       desc = xtryasprintf
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 );
225       if (!desc)
226         return gpg_error_from_syserror ();
227       err = take_this_one_anyway (ctrl, desc);
228       xfree (desc);
229       if (err)
230         return err;
231     }
232
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))
239     {
240       const char *desc =
241         /* */     _("Warning: You have entered an insecure passphrase.%%0A"
242                     "A passphrase may not be a known term or match%%0A"
243                     "certain pattern.");
244
245       if (silent)
246         return gpg_error (GPG_ERR_INV_PASSPHRASE);
247
248       err = take_this_one_anyway (ctrl, desc);
249       if (err)
250         return err;
251     }
252
253   /* The final check is to warn about an empty passphrase. */
254   if (!*pw)
255     {
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."));
263
264       if (silent)
265         return gpg_error (GPG_ERR_INV_PASSPHRASE);
266
267       err = take_this_one_anyway2 (ctrl, desc,
268                                    _("Yes, protection is not needed"));
269       if (err)
270         return err;
271     }
272
273   return 0;
274 }
275
276
277 /* Callback function to compare the first entered PIN with the one
278    currently being entered. */
279 static int
280 reenter_compare_cb (struct pin_entry_info_s *pi)
281 {
282   const char *pin1 = pi->check_cb_arg;
283
284   if (!strcmp (pin1, pi->pin))
285     return 0; /* okay */
286   return -1;
287 }
288
289
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.  */
295 gpg_error_t
296 agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
297                           char **r_passphrase)
298 {
299   gpg_error_t err;
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;
304
305   *r_passphrase = NULL;
306
307   pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
308   pi2 = pi + (sizeof *pi + 100);
309   pi->max_length = 100;
310   pi->max_tries = 3;
311   pi->with_qualitybar = 1;
312   pi2->max_length = 100;
313   pi2->max_tries = 3;
314   pi2->check_cb = reenter_compare_cb;
315   pi2->check_cb_arg = pi->pin;
316
317  next_try:
318   err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
319   initial_errtext = NULL;
320   if (!err)
321     {
322       if (check_passphrase_constraints (ctrl, pi->pin, 0))
323         {
324           pi->failed_tries = 0;
325           pi2->failed_tries = 0;
326           goto next_try;
327         }
328       /* Unless the passphrase is empty, ask to confirm it.  */
329       if (pi->pin && *pi->pin)
330         {
331           err = agent_askpin (ctrl, text2, NULL, NULL, pi2);
332           if (err == -1)
333             { /* The re-entered one did not match and the user did not
334                  hit cancel. */
335               initial_errtext = _("does not match - try again");
336               goto next_try;
337             }
338         }
339     }
340
341   if (!err && *pi->pin)
342     {
343       /* User wants a passphrase. */
344       *r_passphrase = xtrystrdup (pi->pin);
345       if (!*r_passphrase)
346         err = gpg_error_from_syserror ();
347     }
348   xfree (pi);
349   return err;
350 }
351
352
353
354 /* Generate a new keypair according to the parameters given in
355    KEYPARAM.  If CACHE_NONCE is given first try to lookup a passphrase
356    using the cache nonce.  If NO_PROTECTION is true the key will not
357    be protected by a passphrase.  */
358 int
359 agent_genkey (ctrl_t ctrl, const char *cache_nonce,
360               const char *keyparam, size_t keyparamlen, int no_protection,
361               int preset, membuf_t *outbuf)
362 {
363   gcry_sexp_t s_keyparam, s_key, s_private, s_public;
364   char *passphrase;
365   int rc;
366   size_t len;
367   char *buf;
368
369   rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
370   if (rc)
371     {
372       log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
373       return gpg_error (GPG_ERR_INV_DATA);
374     }
375
376   /* Get the passphrase now, cause key generation may take a while. */
377   if (no_protection || !cache_nonce)
378     passphrase = NULL;
379   else
380     passphrase = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
381
382   if (passphrase || no_protection)
383     rc = 0;
384   else
385     rc = agent_ask_new_passphrase (ctrl,
386                                    _("Please enter the passphrase to%0A"
387                                      "to protect your new key"),
388                                    &passphrase);
389   if (rc)
390     return rc;
391
392   rc = gcry_pk_genkey (&s_key, s_keyparam );
393   gcry_sexp_release (s_keyparam);
394   if (rc)
395     {
396       log_error ("key generation failed: %s\n", gpg_strerror (rc));
397       xfree (passphrase);
398       return rc;
399     }
400
401   /* break out the parts */
402   s_private = gcry_sexp_find_token (s_key, "private-key", 0);
403   if (!s_private)
404     {
405       log_error ("key generation failed: invalid return value\n");
406       gcry_sexp_release (s_key);
407       xfree (passphrase);
408       return gpg_error (GPG_ERR_INV_DATA);
409     }
410   s_public = gcry_sexp_find_token (s_key, "public-key", 0);
411   if (!s_public)
412     {
413       log_error ("key generation failed: invalid return value\n");
414       gcry_sexp_release (s_private);
415       gcry_sexp_release (s_key);
416       xfree (passphrase);
417       return gpg_error (GPG_ERR_INV_DATA);
418     }
419   gcry_sexp_release (s_key); s_key = NULL;
420
421   /* store the secret key */
422   if (DBG_CRYPTO)
423     log_debug ("storing private key\n");
424   rc = store_key (s_private, passphrase, 0, ctrl->s2k_count);
425   if (!rc)
426     {
427       if (!cache_nonce)
428         {
429           char tmpbuf[12];
430           gcry_create_nonce (tmpbuf, 12);
431           cache_nonce = bin2hex (tmpbuf, 12, NULL);
432         }
433       if (cache_nonce
434           && !no_protection
435           && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
436                                passphrase, ctrl->cache_ttl_opt_preset))
437         agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
438       if (preset && !no_protection)
439         {
440           unsigned char grip[20];
441           char hexgrip[40+1];
442           if (gcry_pk_get_keygrip (s_private, grip))
443             {
444               bin2hex(grip, 20, hexgrip);
445               rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
446                                     ctrl->cache_ttl_opt_preset);
447             }
448         }
449     }
450   xfree (passphrase);
451   passphrase = NULL;
452   gcry_sexp_release (s_private);
453   if (rc)
454     {
455       gcry_sexp_release (s_public);
456       return rc;
457     }
458
459   /* return the public key */
460   if (DBG_CRYPTO)
461     log_debug ("returning public key\n");
462   len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
463   assert (len);
464   buf = xtrymalloc (len);
465   if (!buf)
466     {
467       gpg_error_t tmperr = out_of_core ();
468       gcry_sexp_release (s_private);
469       gcry_sexp_release (s_public);
470       return tmperr;
471     }
472   len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
473   assert (len);
474   put_membuf (outbuf, buf, len);
475   gcry_sexp_release (s_public);
476   xfree (buf);
477
478   return 0;
479 }
480
481
482 \f
483 /* Apply a new passphrase to the key S_SKEY and store it.  If
484    PASSPHRASE_ADDR and *PASSPHRASE_ADDR are not NULL, use that
485    passphrase.  If PASSPHRASE_ADDR is not NULL store a newly entered
486    passphrase at that address. */
487 gpg_error_t
488 agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
489                          char **passphrase_addr)
490 {
491   gpg_error_t err;
492
493   if (passphrase_addr && *passphrase_addr)
494     {
495       /* Take an empty string as request not to protect the key.  */
496       err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1,
497               ctrl->s2k_count);
498     }
499   else
500     {
501       char *pass = NULL;
502
503       if (passphrase_addr)
504         {
505           xfree (*passphrase_addr);
506           *passphrase_addr = NULL;
507         }
508       err = agent_ask_new_passphrase (ctrl,
509                                       _("Please enter the new passphrase"),
510                                       &pass);
511       if (!err)
512         err = store_key (s_skey, pass, 1, ctrl->s2k_count);
513       if (!err && passphrase_addr)
514         *passphrase_addr = pass;
515       else
516         xfree (pass);
517     }
518
519   return err;
520 }