1510a908150b8e41261242213839db7101eba5d1
[gnupg.git] / agent / findkey.c
1 /* findkey.c - locate the secret key
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005 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 2 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, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <fcntl.h>
29 #include <assert.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <assert.h>
33 #include <pth.h> /* (we use pth_sleep) */
34
35 #include "agent.h"
36
37 /* Helper to pass data to the check callback of the unprotect function. */
38 struct try_unprotect_arg_s {
39   const unsigned char *protected_key;
40   unsigned char *unprotected_key;
41 };
42
43
44 /* Write an S-expression formatted key to our key storage.  With FORCE
45    pased as true an existing key with the given GRIP will get
46    overwritten.  */
47 int
48 agent_write_private_key (const unsigned char *grip,
49                          const void *buffer, size_t length, int force)
50 {
51   int i;
52   char *fname;
53   FILE *fp;
54   char hexgrip[40+4+1];
55   int fd;
56   
57   for (i=0; i < 20; i++)
58     sprintf (hexgrip+2*i, "%02X", grip[i]);
59   strcpy (hexgrip+40, ".key");
60
61   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
62
63   if (!force && !access (fname, F_OK))
64     {
65       log_error ("secret key file `%s' already exists\n", fname);
66       xfree (fname);
67       return gpg_error (GPG_ERR_GENERAL);
68     }
69
70   /* In FORCE mode we would like to create FNAME but only if it does
71      not already exist.  We cannot make this guarantee just using
72      POSIX (GNU provides the "x" opentype for fopen, however, this is
73      not portable).  Thus, we use the more flexible open function and
74      then use fdopen to obtain a stream. */
75   fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY)
76                          : (O_CREAT | O_EXCL | O_WRONLY),
77              S_IRUSR | S_IWUSR 
78 #ifndef HAVE_W32_SYSTEM
79                  | S_IRGRP 
80 #endif
81                  );
82   if (fd < 0)
83     fp = NULL;
84   else
85     {
86       fp = fdopen (fd, "wb");
87       if (!fp)
88         { 
89           int save_e = errno;
90           close (fd);
91           errno = save_e;
92         }
93     }
94
95   if (!fp) 
96     { 
97       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
98       log_error ("can't create `%s': %s\n", fname, strerror (errno));
99       xfree (fname);
100       return tmperr;
101     }
102
103   if (fwrite (buffer, length, 1, fp) != 1)
104     {
105       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
106       log_error ("error writing `%s': %s\n", fname, strerror (errno));
107       fclose (fp);
108       remove (fname);
109       xfree (fname);
110       return tmperr;
111     }
112   if ( fclose (fp) )
113     {
114       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
115       log_error ("error closing `%s': %s\n", fname, strerror (errno));
116       remove (fname);
117       xfree (fname);
118       return tmperr;
119     }
120   bump_key_eventcounter ();
121   xfree (fname);
122   return 0;
123 }
124
125
126 /* Callback function to try the unprotection from the passpharse query
127    code. */
128 static int
129 try_unprotect_cb (struct pin_entry_info_s *pi)
130 {
131   struct try_unprotect_arg_s *arg = pi->check_cb_arg;
132   size_t dummy;
133
134   assert (!arg->unprotected_key);
135   return agent_unprotect (arg->protected_key, pi->pin,
136                           &arg->unprotected_key, &dummy);
137 }
138
139
140 /* Modify a Key description, replacing certain special format
141    characters.  List of currently supported replacements:
142
143    %% - Replaced by a single %
144    %c - Replaced by the content of COMMENT.
145
146    The functions returns 0 on success or an error code.  On success a
147    newly allocated string is stored at the address of RESULT.
148  */
149 static gpg_error_t
150 modify_description (const char *in, const char *comment, char **result)
151 {
152   size_t comment_length;
153   size_t in_len;
154   size_t out_len;
155   char *out;
156   size_t i;
157   int special, pass;
158
159   comment_length = strlen (comment);
160   in_len  = strlen (in);
161
162   /* First pass calculates the length, second pass does the actual
163      copying.  */
164   out = NULL;
165   out_len = 0;
166   for (pass=0; pass < 2; pass++)
167     {
168       special = 0;
169       for (i = 0; i < in_len; i++)
170         {
171           if (special)
172             {
173               special = 0;
174               switch (in[i])
175                 {
176                 case '%':
177                   if (out)
178                     *out++ = '%';
179                   else
180                     out_len++;
181                   break;
182
183                 case 'c': /* Comment.  */
184                   if (out)
185                     {
186                       memcpy (out, comment, comment_length);
187                       out += comment_length;
188                     }
189                   else
190                     out_len += comment_length;
191                   break;
192
193                 default: /* Invalid special sequences are kept as they are. */
194                   if (out)
195                     {
196                       *out++ = '%';
197                       *out++ = in[i];
198                     }
199                   else
200                     out_len+=2;
201                   break;
202                 }
203             }
204           else if (in[i] == '%')
205             special = 1;
206           else
207             {
208               if (out)
209                 *out++ = in[i];
210               else
211                 out_len++;
212             }
213         }
214       
215       if (!pass)
216         {
217           *result = out = xtrymalloc (out_len + 1);
218           if (!out)
219             return gpg_error_from_syserror ();
220         }
221     }
222
223   *out = 0;
224   assert (*result + out_len == out);
225   return 0;
226 }
227
228   
229
230 /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
231    should be the hex encoded keygrip of that key to be used with the
232    caching mechanism. DESC_TEXT may be set to override the default
233    description used for the pinentry. */
234 static int
235 unprotect (ctrl_t ctrl, const char *desc_text,
236            unsigned char **keybuf, const unsigned char *grip, 
237            cache_mode_t cache_mode)
238 {
239   struct pin_entry_info_s *pi;
240   struct try_unprotect_arg_s arg;
241   int rc, i;
242   unsigned char *result;
243   size_t resultlen;
244   char hexgrip[40+1];
245   
246   for (i=0; i < 20; i++)
247     sprintf (hexgrip+2*i, "%02X", grip[i]);
248   hexgrip[40] = 0;
249
250   /* First try to get it from the cache - if there is none or we can't
251      unprotect it, we fall back to ask the user */
252   if (cache_mode != CACHE_MODE_IGNORE)
253     {
254       void *cache_marker;
255       const char *pw;
256       
257     retry:
258       pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
259       if (pw)
260         {
261           rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
262           agent_unlock_cache_entry (&cache_marker);
263           if (!rc)
264             {
265               xfree (*keybuf);
266               *keybuf = result;
267               return 0;
268             }
269           rc  = 0;
270         }
271
272       /* If the pinentry is currently in use, we wait up to 60 seconds
273          for it close and check the cache again.  This solves a common
274          situation where several requests for unprotecting a key have
275          been made but the user is still entering the passphrase for
276          the first request.  Because all requests to agent_askpin are
277          serialized they would then pop up one after the other to
278          request the passphrase - despite that the user has already
279          entered it and is then available in the cache.  This
280          implementation is not race free but in the worst case the
281          user has to enter the passphrase only once more. */
282       if (pinentry_active_p (ctrl, 0))
283         {
284           /* Active - wait */
285           if (!pinentry_active_p (ctrl, 60))
286             {
287               /* We need to give the other thread a chance to actually put
288                  it into the cache. */
289               pth_sleep (1); 
290               goto retry;
291             }
292           /* Timeout - better call pinentry now the plain way. */
293         }
294     }
295   
296   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
297   if (!pi)
298     return gpg_error_from_syserror ();
299   pi->max_length = 100;
300   pi->min_digits = 0;  /* we want a real passphrase */
301   pi->max_digits = 8;
302   pi->max_tries = 3;
303   pi->check_cb = try_unprotect_cb;
304   arg.protected_key = *keybuf;
305   arg.unprotected_key = NULL;
306   pi->check_cb_arg = &arg;
307
308   rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
309   if (!rc)
310     {
311       assert (arg.unprotected_key);
312       agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
313       xfree (*keybuf);
314       *keybuf = arg.unprotected_key;
315     }
316   xfree (pi);
317   return rc;
318 }
319
320
321 /* Read the key identified by GRIP from the private key directory and
322    return it as an gcrypt S-expression object in RESULT.  On failure
323    returns an error code and stores NULL at RESULT. */
324 static gpg_error_t
325 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
326 {
327   int i, rc;
328   char *fname;
329   FILE *fp;
330   struct stat st;
331   unsigned char *buf;
332   size_t buflen, erroff;
333   gcry_sexp_t s_skey;
334   char hexgrip[40+4+1];
335   
336   *result = NULL;
337
338   for (i=0; i < 20; i++)
339     sprintf (hexgrip+2*i, "%02X", grip[i]);
340   strcpy (hexgrip+40, ".key");
341
342   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
343   fp = fopen (fname, "rb");
344   if (!fp)
345     {
346       rc = gpg_error_from_syserror ();
347       log_error ("can't open `%s': %s\n", fname, strerror (errno));
348       xfree (fname);
349       return rc;
350     }
351   
352   if (fstat (fileno(fp), &st))
353     {
354       rc = gpg_error_from_syserror ();
355       log_error ("can't stat `%s': %s\n", fname, strerror (errno));
356       xfree (fname);
357       fclose (fp);
358       return rc;
359     }
360
361   buflen = st.st_size;
362   buf = xtrymalloc (buflen+1);
363   if (!buf || fread (buf, buflen, 1, fp) != 1)
364     {
365       rc = gpg_error_from_syserror ();
366       log_error ("error reading `%s': %s\n", fname, strerror (errno));
367       xfree (fname);
368       fclose (fp);
369       xfree (buf);
370       return rc;
371     }
372
373   /* Convert the file into a gcrypt S-expression object.  */
374   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
375   xfree (fname);
376   fclose (fp);
377   xfree (buf);
378   if (rc)
379     {
380       log_error ("failed to build S-Exp (off=%u): %s\n",
381                  (unsigned int)erroff, gpg_strerror (rc));
382       return rc;
383     }
384   *result = s_skey;
385   return 0;
386 }
387
388
389 /* Return the secret key as an S-Exp in RESULT after locating it using
390    the grip.  Returns NULL in RESULT if the operation should be
391    diverted to a token; SHADOW_INFO will point then to an allocated
392    S-Expression with the shadow_info part from the file.  CACHE_MODE
393    defines now the cache shall be used.  DESC_TEXT may be set to
394    present a custom description for the pinentry. */
395 gpg_error_t
396 agent_key_from_file (ctrl_t ctrl, const char *desc_text,
397                      const unsigned char *grip, unsigned char **shadow_info,
398                      cache_mode_t cache_mode, gcry_sexp_t *result)
399 {
400   int rc;
401   unsigned char *buf;
402   size_t len, buflen, erroff;
403   gcry_sexp_t s_skey;
404   int got_shadow_info = 0;
405   
406   *result = NULL;
407   if (shadow_info)
408       *shadow_info = NULL;
409
410   rc = read_key_file (grip, &s_skey);
411   if (rc)
412     return rc;
413
414   /* For use with the protection functions we also need the key as an
415      canonical encoded S-expression in abuffer.  Create this buffer
416      now.  */
417   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
418   assert (len);
419   buf = xtrymalloc (len);
420   if (!buf)
421     {
422       rc = gpg_error_from_syserror ();
423       gcry_sexp_release (s_skey);
424       return rc;
425     }
426   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
427   assert (len);
428
429
430   switch (agent_private_key_type (buf))
431     {
432     case PRIVATE_KEY_CLEAR:
433       break; /* no unprotection needed */
434     case PRIVATE_KEY_PROTECTED:
435       {
436         gcry_sexp_t comment_sexp;
437         size_t comment_length;
438         char *desc_text_final;
439         const char *comment = NULL;
440
441         /* Note, that we will take the comment as a C string for
442            display purposes; i.e. all stuff beyond a Nul character is
443            ignored.  */
444         comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
445         if (comment_sexp)
446           comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
447         if (!comment)
448           {
449             comment = "";
450             comment_length = 0;
451           }
452
453         desc_text_final = NULL;
454         if (desc_text)
455           {
456             if (comment[comment_length])
457               {
458                 /* Not a C-string; create one.  We might here allocate
459                    more than actually displayed but well, that
460                    shouldn't be a problem.  */
461                 char *tmp = xtrymalloc (comment_length+1);
462                 if (!tmp)
463                   rc = gpg_error_from_syserror ();
464                 else
465                   {
466                     memcpy (tmp, comment, comment_length);
467                     tmp[comment_length] = 0;
468                     rc = modify_description (desc_text, tmp, &desc_text_final);
469                     xfree (tmp);
470                   }
471               }
472             else
473               rc = modify_description (desc_text, comment, &desc_text_final);
474           }
475
476         if (!rc)
477           {
478             rc = unprotect (ctrl, desc_text_final, &buf, grip, cache_mode);
479             if (rc)
480               log_error ("failed to unprotect the secret key: %s\n",
481                          gpg_strerror (rc));
482           }
483         
484         gcry_sexp_release (comment_sexp);
485         xfree (desc_text_final);
486       }
487       break;
488     case PRIVATE_KEY_SHADOWED:
489       if (shadow_info)
490         {
491           const unsigned char *s;
492           size_t n;
493
494           rc = agent_get_shadow_info (buf, &s);
495           if (!rc)
496             {
497               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
498               assert (n);
499               *shadow_info = xtrymalloc (n);
500               if (!*shadow_info)
501                 rc = out_of_core ();
502               else
503                 {
504                   memcpy (*shadow_info, s, n);
505                   rc = 0;
506                   got_shadow_info = 1;
507                 }
508             }
509           if (rc)
510             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
511         }
512       else
513         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
514       break;
515     default:
516       log_error ("invalid private key format\n");
517       rc = gpg_error (GPG_ERR_BAD_SECKEY);
518       break;
519     }
520   gcry_sexp_release (s_skey);
521   s_skey = NULL;
522   if (rc || got_shadow_info)
523     {
524       xfree (buf);
525       return rc;
526     }
527
528   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
529   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
530   wipememory (buf, buflen);
531   xfree (buf);
532   if (rc)
533     {
534       log_error ("failed to build S-Exp (off=%u): %s\n",
535                  (unsigned int)erroff, gpg_strerror (rc));
536       return rc;
537     }
538
539   *result = s_skey;
540   return 0;
541 }
542
543
544
545 /* Return the public key for the keygrip GRIP.  The result is stored
546    at RESULT.  This function extracts the public key from the private
547    key database.  On failure an error code is returned and NULL stored
548    at RESULT. */
549 gpg_error_t
550 agent_public_key_from_file (ctrl_t ctrl, 
551                             const unsigned char *grip,
552                             gcry_sexp_t *result)
553 {
554   int i, idx, rc;
555   gcry_sexp_t s_skey;
556   const char *algoname;
557   gcry_sexp_t uri_sexp, comment_sexp;
558   const char *uri, *comment;
559   size_t uri_length, comment_length;
560   char *format, *p;
561   void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
562                            for comment + end-of-list.  */
563   int argidx;
564   gcry_sexp_t list, l2;
565   const char *name;
566   const char *s;
567   size_t n;
568   const char *elems;
569   gcry_mpi_t *array;
570
571   *result = NULL;
572
573   rc = read_key_file (grip, &s_skey);
574   if (rc)
575     return rc;
576
577   list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
578   if (!list)
579     list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
580   if (!list)
581     list = gcry_sexp_find_token (s_skey, "private-key", 0 );
582   if (!list)
583     {
584       log_error ("invalid private key format\n");
585       gcry_sexp_release (s_skey);
586       return gpg_error (GPG_ERR_BAD_SECKEY);
587     }
588
589   l2 = gcry_sexp_cadr (list);
590   gcry_sexp_release (list);
591   list = l2;
592   name = gcry_sexp_nth_data (list, 0, &n);
593   if (n==3 && !memcmp (name, "rsa", 3))
594     {
595       algoname = "rsa";
596       elems = "ne";
597     }
598   else if (n==3 && !memcmp (name, "dsa", 3))
599     {
600       algoname = "dsa";
601       elems = "pqgy";
602     }
603   else if (n==3 && !memcmp (name, "elg", 3))
604     {
605       algoname = "elg";
606       elems = "pgy";
607     }
608   else
609     {
610       log_error ("unknown private key algorithm\n");
611       gcry_sexp_release (list);
612       gcry_sexp_release (s_skey);
613       return gpg_error (GPG_ERR_BAD_SECKEY);
614     }
615
616   /* Allocate an array for the parameters and copy them out of the
617      secret key.   FIXME: We should have a generic copy function. */
618   array = xtrycalloc (strlen(elems) + 1, sizeof *array);
619   if (!array)
620     {
621       rc = gpg_error_from_syserror ();
622       gcry_sexp_release (list);
623       gcry_sexp_release (s_skey);
624       return rc;
625     }
626
627   for (idx=0, s=elems; *s; s++, idx++ ) 
628     {
629       l2 = gcry_sexp_find_token (list, s, 1);
630       if (!l2)
631         {
632           /* Required parameter not found.  */
633           for (i=0; i<idx; i++)
634             gcry_mpi_release (array[i]);
635           xfree (array);
636           gcry_sexp_release (list);
637           gcry_sexp_release (s_skey);
638           return gpg_error (GPG_ERR_BAD_SECKEY);
639         }
640       array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
641       gcry_sexp_release (l2);
642       if (!array[idx])
643         {
644           /* Required parameter is invalid. */
645           for (i=0; i<idx; i++)
646             gcry_mpi_release (array[i]);
647           xfree (array);
648           gcry_sexp_release (list);
649           gcry_sexp_release (s_skey);
650           return gpg_error (GPG_ERR_BAD_SECKEY);
651         }
652     }
653   gcry_sexp_release (list);
654   list = NULL;
655
656   uri = NULL;
657   uri_length = 0;
658   uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
659   if (uri_sexp)
660     uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
661
662   comment = NULL;
663   comment_length = 0;
664   comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
665   if (comment_sexp)
666     comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
667
668   gcry_sexp_release (s_skey);
669   s_skey = NULL;
670
671
672   /* FIXME: The following thing is pretty ugly code; we should
673      investigate how to make it cleaner. Probably code to handle
674      canonical S-expressions in a memory buffer is better suioted for
675      such a task.  After all that is what we do in protect.c.  Neeed
676      to find common patterns and write a straightformward API to use
677      them.  */
678   assert (sizeof (size_t) <= sizeof (void*));
679
680   format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
681   if (!format)
682     {
683       rc = gpg_error_from_syserror ();
684       for (i=0; array[i]; i++)
685         gcry_mpi_release (array[i]);
686       xfree (array);
687       gcry_sexp_release (uri_sexp);
688       gcry_sexp_release (comment_sexp);
689       return rc;
690     }
691
692   argidx = 0;
693   p = stpcpy (stpcpy (format, "(public-key("), algoname);
694   for (idx=0, s=elems; *s; s++, idx++ ) 
695     {
696       *p++ = '(';
697       *p++ = *s;
698       p = stpcpy (p, " %m)");
699       assert (argidx < DIM (args));
700       args[argidx++] = &array[idx];
701     }
702   *p++ = ')';
703   if (uri)
704     {
705       p = stpcpy (p, "(uri %b)");
706       assert (argidx+1 < DIM (args));
707       args[argidx++] = (void *)uri_length;
708       args[argidx++] = (void *)uri;
709     }
710   if (comment)
711     {
712       p = stpcpy (p, "(comment %b)");
713       assert (argidx+1 < DIM (args));
714       args[argidx++] = (void *)comment_length;
715       args[argidx++] = (void*)comment;
716     }
717   *p++ = ')';
718   *p = 0;
719   assert (argidx < DIM (args));
720   args[argidx] = NULL;
721     
722   rc = gcry_sexp_build_array (&list, NULL, format, args);
723   xfree (format);
724   for (i=0; array[i]; i++)
725     gcry_mpi_release (array[i]);
726   xfree (array);
727   gcry_sexp_release (uri_sexp);
728   gcry_sexp_release (comment_sexp);
729
730   if (!rc)
731     *result = list;
732   return rc;
733 }
734
735
736
737 /* Return the secret key as an S-Exp after locating it using the grip.
738    Returns NULL if key is not available. 0 = key is available */
739 int
740 agent_key_available (const unsigned char *grip)
741 {
742   int i;
743   char *fname;
744   char hexgrip[40+4+1];
745   
746   for (i=0; i < 20; i++)
747     sprintf (hexgrip+2*i, "%02X", grip[i]);
748   strcpy (hexgrip+40, ".key");
749
750   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
751   i = !access (fname, R_OK)? 0 : -1;
752   xfree (fname);
753   return i;
754 }
755
756
757