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