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