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