5fe735242b2f038aee3ea5ba9d690b4b46f78ea3
[gnupg.git] / agent / findkey.c
1 /* findkey.c - Locate the secret key
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2007  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
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 #include <pth.h> /* (we use pth_sleep) */
33
34 #include "agent.h"
35 #include "i18n.h"
36
37 #ifndef O_BINARY
38 #define O_BINARY 0
39 #endif
40
41 /* Helper to pass data to the check callback of the unprotect function. */
42 struct try_unprotect_arg_s 
43 {
44   ctrl_t ctrl;
45   const unsigned char *protected_key;
46   unsigned char *unprotected_key;
47   int change_required; /* Set by the callback to indicate that the
48                           user should chnage the passphrase.  */
49 };
50
51
52 /* Write an S-expression formatted key to our key storage.  With FORCE
53    passed as true an existing key with the given GRIP will get
54    overwritten.  */
55 int
56 agent_write_private_key (const unsigned char *grip,
57                          const void *buffer, size_t length, int force)
58 {
59   char *fname;
60   FILE *fp;
61   char hexgrip[40+4+1];
62   int fd;
63   
64   bin2hex (grip, 20, hexgrip);
65   strcpy (hexgrip+40, ".key");
66
67   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
68
69   if (!force && !access (fname, F_OK))
70     {
71       log_error ("secret key file `%s' already exists\n", fname);
72       xfree (fname);
73       return gpg_error (GPG_ERR_GENERAL);
74     }
75
76   /* In FORCE mode we would like to create FNAME but only if it does
77      not already exist.  We cannot make this guarantee just using
78      POSIX (GNU provides the "x" opentype for fopen, however, this is
79      not portable).  Thus, we use the more flexible open function and
80      then use fdopen to obtain a stream. */
81   fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY | O_BINARY)
82                          : (O_CREAT | O_EXCL | O_WRONLY | O_BINARY),
83              S_IRUSR | S_IWUSR 
84 #ifndef HAVE_W32_SYSTEM
85                  | S_IRGRP 
86 #endif
87                  );
88   if (fd < 0)
89     fp = NULL;
90   else
91     {
92       fp = fdopen (fd, "wb");
93       if (!fp)
94         { 
95           int save_e = errno;
96           close (fd);
97           errno = save_e;
98         }
99     }
100
101   if (!fp) 
102     { 
103       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
104       log_error ("can't create `%s': %s\n", fname, strerror (errno));
105       xfree (fname);
106       return tmperr;
107     }
108
109   if (fwrite (buffer, length, 1, fp) != 1)
110     {
111       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
112       log_error ("error writing `%s': %s\n", fname, strerror (errno));
113       fclose (fp);
114       remove (fname);
115       xfree (fname);
116       return tmperr;
117     }
118   if ( fclose (fp) )
119     {
120       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
121       log_error ("error closing `%s': %s\n", fname, strerror (errno));
122       remove (fname);
123       xfree (fname);
124       return tmperr;
125     }
126   bump_key_eventcounter ();
127   xfree (fname);
128   return 0;
129 }
130
131
132 /* Callback function to try the unprotection from the passpharse query
133    code. */
134 static int
135 try_unprotect_cb (struct pin_entry_info_s *pi)
136 {
137   struct try_unprotect_arg_s *arg = pi->check_cb_arg;
138   size_t dummy;
139   gpg_error_t err;
140   gnupg_isotime_t now, protected_at, tmptime;
141   char *desc = NULL;
142
143   assert (!arg->unprotected_key);
144
145   arg->change_required = 0;
146   err = agent_unprotect (arg->protected_key, pi->pin, protected_at,
147                          &arg->unprotected_key, &dummy);
148   if (err)
149     return err;
150   if (!opt.max_passphrase_days || arg->ctrl->in_passwd)
151     return 0;  /* No regular passphrase change required.  */
152
153   if (!*protected_at)
154     {
155       /* No protection date known - must force passphrase change.  */
156       desc = xtrystrdup (_("Note: This passphrase has never been changed.%0A"
157                            "Please change it now."));
158       if (!desc)
159         return gpg_error_from_syserror ();
160     }
161   else
162     {
163       gnupg_get_isotime (now);
164       gnupg_copy_time (tmptime, protected_at);
165       err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
166       if (err)
167         return err;
168       if (strcmp (now, tmptime) > 0 )
169         {
170           /* Passphrase "expired".  */
171           desc = xtryasprintf 
172             (_("This passphrase has not been changed%%0A"
173                "since %.4s-%.2s-%.2s.  Please change it now."),
174              protected_at, protected_at+4, protected_at+6);
175           if (!desc)
176             return gpg_error_from_syserror ();
177         }
178     }
179
180   if (desc)
181     {
182       /* Change required.  */
183       if (opt.enforce_passphrase_constraints)
184         {
185           err = agent_get_confirmation (arg->ctrl, desc,
186                                         _("Change passphrase"), NULL);
187           if (!err)
188             arg->change_required = 1;
189         }
190       else
191         {
192           err = agent_get_confirmation (arg->ctrl, desc,
193                                         _("Change passphrase"),
194                                         _("I'll change it later"));
195           if (!err)
196             arg->change_required = 1;
197           else if (gpg_err_code (err) == GPG_ERR_CANCELED)
198             err = 0;
199         }
200       xfree (desc);
201     }
202
203   return 0;
204 }
205
206
207 /* Modify a Key description, replacing certain special format
208    characters.  List of currently supported replacements:
209
210    %% - Replaced by a single %
211    %c - Replaced by the content of COMMENT.
212
213    The functions returns 0 on success or an error code.  On success a
214    newly allocated string is stored at the address of RESULT.
215  */
216 static gpg_error_t
217 modify_description (const char *in, const char *comment, char **result)
218 {
219   size_t comment_length;
220   size_t in_len;
221   size_t out_len;
222   char *out;
223   size_t i;
224   int special, pass;
225
226   comment_length = strlen (comment);
227   in_len  = strlen (in);
228
229   /* First pass calculates the length, second pass does the actual
230      copying.  */
231   out = NULL;
232   out_len = 0;
233   for (pass=0; pass < 2; pass++)
234     {
235       special = 0;
236       for (i = 0; i < in_len; i++)
237         {
238           if (special)
239             {
240               special = 0;
241               switch (in[i])
242                 {
243                 case '%':
244                   if (out)
245                     *out++ = '%';
246                   else
247                     out_len++;
248                   break;
249
250                 case 'c': /* Comment.  */
251                   if (out)
252                     {
253                       memcpy (out, comment, comment_length);
254                       out += comment_length;
255                     }
256                   else
257                     out_len += comment_length;
258                   break;
259
260                 default: /* Invalid special sequences are kept as they are. */
261                   if (out)
262                     {
263                       *out++ = '%';
264                       *out++ = in[i];
265                     }
266                   else
267                     out_len+=2;
268                   break;
269                 }
270             }
271           else if (in[i] == '%')
272             special = 1;
273           else
274             {
275               if (out)
276                 *out++ = in[i];
277               else
278                 out_len++;
279             }
280         }
281       
282       if (!pass)
283         {
284           *result = out = xtrymalloc (out_len + 1);
285           if (!out)
286             return gpg_error_from_syserror ();
287         }
288     }
289
290   *out = 0;
291   assert (*result + out_len == out);
292   return 0;
293 }
294
295   
296
297 /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
298    should be the hex encoded keygrip of that key to be used with the
299    caching mechanism. DESC_TEXT may be set to override the default
300    description used for the pinentry.  If LOOKUP_TTL is given this
301    function is used to lookup the default ttl. */
302 static int
303 unprotect (ctrl_t ctrl, const char *desc_text,
304            unsigned char **keybuf, const unsigned char *grip, 
305            cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
306 {
307   struct pin_entry_info_s *pi;
308   struct try_unprotect_arg_s arg;
309   int rc;
310   unsigned char *result;
311   size_t resultlen;
312   char hexgrip[40+1];
313   
314   bin2hex (grip, 20, hexgrip);
315
316   /* First try to get it from the cache - if there is none or we can't
317      unprotect it, we fall back to ask the user */
318   if (cache_mode != CACHE_MODE_IGNORE)
319     {
320       void *cache_marker;
321       const char *pw;
322       
323     retry:
324       pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
325       if (pw)
326         {
327           rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
328           agent_unlock_cache_entry (&cache_marker);
329           if (!rc)
330             {
331               xfree (*keybuf);
332               *keybuf = result;
333               return 0;
334             }
335           rc  = 0;
336         }
337
338       /* If the pinentry is currently in use, we wait up to 60 seconds
339          for it to close and check the cache again.  This solves a common
340          situation where several requests for unprotecting a key have
341          been made but the user is still entering the passphrase for
342          the first request.  Because all requests to agent_askpin are
343          serialized they would then pop up one after the other to
344          request the passphrase - despite that the user has already
345          entered it and is then available in the cache.  This
346          implementation is not race free but in the worst case the
347          user has to enter the passphrase only once more. */
348       if (pinentry_active_p (ctrl, 0))
349         {
350           /* Active - wait */
351           if (!pinentry_active_p (ctrl, 60))
352             {
353               /* We need to give the other thread a chance to actually put
354                  it into the cache. */
355               pth_sleep (1); 
356               goto retry;
357             }
358           /* Timeout - better call pinentry now the plain way. */
359         }
360     }
361
362   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
363   if (!pi)
364     return gpg_error_from_syserror ();
365   pi->max_length = 100;
366   pi->min_digits = 0;  /* we want a real passphrase */
367   pi->max_digits = 16;
368   pi->max_tries = 3;
369   pi->check_cb = try_unprotect_cb;
370   arg.ctrl = ctrl;
371   arg.protected_key = *keybuf;
372   arg.unprotected_key = NULL;
373   arg.change_required = 0;
374   pi->check_cb_arg = &arg;
375
376   rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
377   if (!rc)
378     {
379       assert (arg.unprotected_key);
380       if (arg.change_required)
381         {
382           size_t canlen, erroff;
383           gcry_sexp_t s_skey;
384           
385           assert (arg.unprotected_key);
386           canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
387           rc = gcry_sexp_sscan (&s_skey, &erroff,
388                                 (char*)arg.unprotected_key, canlen);
389           if (rc)
390             {
391               log_error ("failed to build S-Exp (off=%u): %s\n",
392                          (unsigned int)erroff, gpg_strerror (rc));
393               wipememory (arg.unprotected_key, canlen);
394               xfree (arg.unprotected_key);
395               xfree (pi);
396               return rc;
397             }
398           rc = agent_protect_and_store (ctrl, s_skey);
399           gcry_sexp_release (s_skey);
400           if (rc)
401             {
402               log_error ("changing the passphrase failed: %s\n", 
403                          gpg_strerror (rc));
404               wipememory (arg.unprotected_key, canlen);
405               xfree (arg.unprotected_key);
406               xfree (pi);
407               return rc;
408             }
409         }
410       agent_put_cache (hexgrip, cache_mode, pi->pin, 
411                        lookup_ttl? lookup_ttl (hexgrip) : 0);
412       xfree (*keybuf);
413       *keybuf = arg.unprotected_key;
414     }
415   xfree (pi);
416   return rc;
417 }
418
419
420 /* Read the key identified by GRIP from the private key directory and
421    return it as an gcrypt S-expression object in RESULT.  On failure
422    returns an error code and stores NULL at RESULT. */
423 static gpg_error_t
424 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
425 {
426   int rc;
427   char *fname;
428   FILE *fp;
429   struct stat st;
430   unsigned char *buf;
431   size_t buflen, erroff;
432   gcry_sexp_t s_skey;
433   char hexgrip[40+4+1];
434   
435   *result = NULL;
436
437   bin2hex (grip, 20, hexgrip);
438   strcpy (hexgrip+40, ".key");
439
440   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
441   fp = fopen (fname, "rb");
442   if (!fp)
443     {
444       rc = gpg_error_from_syserror ();
445       if (gpg_err_code (rc) != GPG_ERR_ENOENT)
446         log_error ("can't open `%s': %s\n", fname, strerror (errno));
447       xfree (fname);
448       return rc;
449     }
450   
451   if (fstat (fileno(fp), &st))
452     {
453       rc = gpg_error_from_syserror ();
454       log_error ("can't stat `%s': %s\n", fname, strerror (errno));
455       xfree (fname);
456       fclose (fp);
457       return rc;
458     }
459
460   buflen = st.st_size;
461   buf = xtrymalloc (buflen+1);
462   if (!buf || fread (buf, buflen, 1, fp) != 1)
463     {
464       rc = gpg_error_from_syserror ();
465       log_error ("error reading `%s': %s\n", fname, strerror (errno));
466       xfree (fname);
467       fclose (fp);
468       xfree (buf);
469       return rc;
470     }
471
472   /* Convert the file into a gcrypt S-expression object.  */
473   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
474   xfree (fname);
475   fclose (fp);
476   xfree (buf);
477   if (rc)
478     {
479       log_error ("failed to build S-Exp (off=%u): %s\n",
480                  (unsigned int)erroff, gpg_strerror (rc));
481       return rc;
482     }
483   *result = s_skey;
484   return 0;
485 }
486
487
488 /* Return the secret key as an S-Exp in RESULT after locating it using
489    the GRIP.  Stores NULL at RESULT if the operation shall be diverted
490    to a token; in this case an allocated S-expression with the
491    shadow_info part from the file is stored at SHADOW_INFO.
492    CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
493    set to present a custom description for the pinentry.  LOOKUP_TTL
494    is an optional function to convey a TTL to the cache manager; we do
495    not simply pass the TTL value because the value is only needed if an
496    unprotect action was needed and looking up the TTL may have some
497    overhead (e.g. scanning the sshcontrol file). */
498 gpg_error_t
499 agent_key_from_file (ctrl_t ctrl, const char *desc_text,
500                      const unsigned char *grip, unsigned char **shadow_info,
501                      cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
502                      gcry_sexp_t *result)
503 {
504   int rc;
505   unsigned char *buf;
506   size_t len, buflen, erroff;
507   gcry_sexp_t s_skey;
508   int got_shadow_info = 0;
509   
510   *result = NULL;
511   if (shadow_info)
512     *shadow_info = NULL;
513
514   rc = read_key_file (grip, &s_skey);
515   if (rc)
516     return rc;
517
518   /* For use with the protection functions we also need the key as an
519      canonical encoded S-expression in a buffer.  Create this buffer
520      now.  */
521   rc = make_canon_sexp (s_skey, &buf, &len);
522   if (rc)
523     return rc;
524
525   switch (agent_private_key_type (buf))
526     {
527     case PRIVATE_KEY_CLEAR:
528       break; /* no unprotection needed */
529     case PRIVATE_KEY_PROTECTED:
530       {
531         gcry_sexp_t comment_sexp;
532         size_t comment_length;
533         char *desc_text_final;
534         const char *comment = NULL;
535
536         /* Note, that we will take the comment as a C string for
537            display purposes; i.e. all stuff beyond a Nul character is
538            ignored.  */
539         comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
540         if (comment_sexp)
541           comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
542         if (!comment)
543           {
544             comment = "";
545             comment_length = 0;
546           }
547
548         desc_text_final = NULL;
549         if (desc_text)
550           {
551             if (comment[comment_length])
552               {
553                 /* Not a C-string; create one.  We might here allocate
554                    more than actually displayed but well, that
555                    shouldn't be a problem.  */
556                 char *tmp = xtrymalloc (comment_length+1);
557                 if (!tmp)
558                   rc = gpg_error_from_syserror ();
559                 else
560                   {
561                     memcpy (tmp, comment, comment_length);
562                     tmp[comment_length] = 0;
563                     rc = modify_description (desc_text, tmp, &desc_text_final);
564                     xfree (tmp);
565                   }
566               }
567             else
568               rc = modify_description (desc_text, comment, &desc_text_final);
569           }
570
571         if (!rc)
572           {
573             rc = unprotect (ctrl, desc_text_final, &buf, grip,
574                             cache_mode, lookup_ttl);
575             if (rc)
576               log_error ("failed to unprotect the secret key: %s\n",
577                          gpg_strerror (rc));
578           }
579         
580         gcry_sexp_release (comment_sexp);
581         xfree (desc_text_final);
582       }
583       break;
584     case PRIVATE_KEY_SHADOWED:
585       if (shadow_info)
586         {
587           const unsigned char *s;
588           size_t n;
589
590           rc = agent_get_shadow_info (buf, &s);
591           if (!rc)
592             {
593               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
594               assert (n);
595               *shadow_info = xtrymalloc (n);
596               if (!*shadow_info)
597                 rc = out_of_core ();
598               else
599                 {
600                   memcpy (*shadow_info, s, n);
601                   rc = 0;
602                   got_shadow_info = 1;
603                 }
604             }
605           if (rc)
606             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
607         }
608       else
609         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
610       break;
611     default:
612       log_error ("invalid private key format\n");
613       rc = gpg_error (GPG_ERR_BAD_SECKEY);
614       break;
615     }
616   gcry_sexp_release (s_skey);
617   s_skey = NULL;
618   if (rc || got_shadow_info)
619     {
620       xfree (buf);
621       return rc;
622     }
623
624   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
625   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
626   wipememory (buf, buflen);
627   xfree (buf);
628   if (rc)
629     {
630       log_error ("failed to build S-Exp (off=%u): %s\n",
631                  (unsigned int)erroff, gpg_strerror (rc));
632       return rc;
633     }
634
635   *result = s_skey;
636   return 0;
637 }
638
639
640
641 /* Return the public key for the keygrip GRIP.  The result is stored
642    at RESULT.  This function extracts the public key from the private
643    key database.  On failure an error code is returned and NULL stored
644    at RESULT. */
645 gpg_error_t
646 agent_public_key_from_file (ctrl_t ctrl, 
647                             const unsigned char *grip,
648                             gcry_sexp_t *result)
649 {
650   int i, idx, rc;
651   gcry_sexp_t s_skey;
652   const char *algoname;
653   gcry_sexp_t uri_sexp, comment_sexp;
654   const char *uri, *comment;
655   size_t uri_length, comment_length;
656   char *format, *p;
657   void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
658                            for comment + end-of-list.  */
659   int argidx;
660   gcry_sexp_t list, l2;
661   const char *name;
662   const char *s;
663   size_t n;
664   const char *elems;
665   gcry_mpi_t *array;
666
667   (void)ctrl;
668
669   *result = NULL;
670
671   rc = read_key_file (grip, &s_skey);
672   if (rc)
673     return rc;
674
675   list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
676   if (!list)
677     list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
678   if (!list)
679     list = gcry_sexp_find_token (s_skey, "private-key", 0 );
680   if (!list)
681     {
682       log_error ("invalid private key format\n");
683       gcry_sexp_release (s_skey);
684       return gpg_error (GPG_ERR_BAD_SECKEY);
685     }
686
687   l2 = gcry_sexp_cadr (list);
688   gcry_sexp_release (list);
689   list = l2;
690   name = gcry_sexp_nth_data (list, 0, &n);
691   if (n==3 && !memcmp (name, "rsa", 3))
692     {
693       algoname = "rsa";
694       elems = "ne";
695     }
696   else if (n==3 && !memcmp (name, "dsa", 3))
697     {
698       algoname = "dsa";
699       elems = "pqgy";
700     }
701   else if (n==3 && !memcmp (name, "elg", 3))
702     {
703       algoname = "elg";
704       elems = "pgy";
705     }
706   else
707     {
708       log_error ("unknown private key algorithm\n");
709       gcry_sexp_release (list);
710       gcry_sexp_release (s_skey);
711       return gpg_error (GPG_ERR_BAD_SECKEY);
712     }
713
714   /* Allocate an array for the parameters and copy them out of the
715      secret key.   FIXME: We should have a generic copy function. */
716   array = xtrycalloc (strlen(elems) + 1, sizeof *array);
717   if (!array)
718     {
719       rc = gpg_error_from_syserror ();
720       gcry_sexp_release (list);
721       gcry_sexp_release (s_skey);
722       return rc;
723     }
724
725   for (idx=0, s=elems; *s; s++, idx++ ) 
726     {
727       l2 = gcry_sexp_find_token (list, s, 1);
728       if (!l2)
729         {
730           /* Required parameter not found.  */
731           for (i=0; i<idx; i++)
732             gcry_mpi_release (array[i]);
733           xfree (array);
734           gcry_sexp_release (list);
735           gcry_sexp_release (s_skey);
736           return gpg_error (GPG_ERR_BAD_SECKEY);
737         }
738       array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
739       gcry_sexp_release (l2);
740       if (!array[idx])
741         {
742           /* Required parameter is invalid. */
743           for (i=0; i<idx; i++)
744             gcry_mpi_release (array[i]);
745           xfree (array);
746           gcry_sexp_release (list);
747           gcry_sexp_release (s_skey);
748           return gpg_error (GPG_ERR_BAD_SECKEY);
749         }
750     }
751   gcry_sexp_release (list);
752   list = NULL;
753
754   uri = NULL;
755   uri_length = 0;
756   uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
757   if (uri_sexp)
758     uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
759
760   comment = NULL;
761   comment_length = 0;
762   comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
763   if (comment_sexp)
764     comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
765
766   gcry_sexp_release (s_skey);
767   s_skey = NULL;
768
769
770   /* FIXME: The following thing is pretty ugly code; we should
771      investigate how to make it cleaner. Probably code to handle
772      canonical S-expressions in a memory buffer is better suioted for
773      such a task.  After all that is what we do in protect.c.  Neeed
774      to find common patterns and write a straightformward API to use
775      them.  */
776   assert (sizeof (size_t) <= sizeof (void*));
777
778   format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
779   if (!format)
780     {
781       rc = gpg_error_from_syserror ();
782       for (i=0; array[i]; i++)
783         gcry_mpi_release (array[i]);
784       xfree (array);
785       gcry_sexp_release (uri_sexp);
786       gcry_sexp_release (comment_sexp);
787       return rc;
788     }
789
790   argidx = 0;
791   p = stpcpy (stpcpy (format, "(public-key("), algoname);
792   for (idx=0, s=elems; *s; s++, idx++ ) 
793     {
794       *p++ = '(';
795       *p++ = *s;
796       p = stpcpy (p, " %m)");
797       assert (argidx < DIM (args));
798       args[argidx++] = &array[idx];
799     }
800   *p++ = ')';
801   if (uri)
802     {
803       p = stpcpy (p, "(uri %b)");
804       assert (argidx+1 < DIM (args));
805       args[argidx++] = (void *)uri_length;
806       args[argidx++] = (void *)uri;
807     }
808   if (comment)
809     {
810       p = stpcpy (p, "(comment %b)");
811       assert (argidx+1 < DIM (args));
812       args[argidx++] = (void *)comment_length;
813       args[argidx++] = (void*)comment;
814     }
815   *p++ = ')';
816   *p = 0;
817   assert (argidx < DIM (args));
818   args[argidx] = NULL;
819     
820   rc = gcry_sexp_build_array (&list, NULL, format, args);
821   xfree (format);
822   for (i=0; array[i]; i++)
823     gcry_mpi_release (array[i]);
824   xfree (array);
825   gcry_sexp_release (uri_sexp);
826   gcry_sexp_release (comment_sexp);
827
828   if (!rc)
829     *result = list;
830   return rc;
831 }
832
833
834
835 /* Return the secret key as an S-Exp after locating it using the grip.
836    Returns NULL if key is not available. 0 = key is available */
837 int
838 agent_key_available (const unsigned char *grip)
839 {
840   int result;
841   char *fname;
842   char hexgrip[40+4+1];
843   
844   bin2hex (grip, 20, hexgrip);
845   strcpy (hexgrip+40, ".key");
846
847   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
848   result = !access (fname, R_OK)? 0 : -1;
849   xfree (fname);
850   return result;
851 }
852
853
854
855 /* Return the information about the secret key specified by the binary
856    keygrip GRIP.  If the key is a shadowed one the shadow information
857    will be stored at the address R_SHADOW_INFO as an allocated
858    S-expression.  */
859 gpg_error_t
860 agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
861                           int *r_keytype, unsigned char **r_shadow_info)
862 {
863   gpg_error_t err;
864   unsigned char *buf;
865   size_t len;
866   int keytype;
867
868   (void)ctrl;
869   
870   if (r_keytype)
871     *r_keytype = PRIVATE_KEY_UNKNOWN;
872   if (r_shadow_info)
873     *r_shadow_info = NULL;
874
875   {
876     gcry_sexp_t sexp;
877     
878     err = read_key_file (grip, &sexp);
879     if (err)
880       {
881         if (gpg_err_code (err) == GPG_ERR_ENOENT)
882           return gpg_error (GPG_ERR_NOT_FOUND);
883         else
884           return err;
885       }
886     err = make_canon_sexp (sexp, &buf, &len);
887     gcry_sexp_release (sexp);
888     if (err)
889       return err;
890   }
891   
892   keytype = agent_private_key_type (buf);
893   switch (keytype)
894     {
895     case PRIVATE_KEY_CLEAR:
896       break; 
897     case PRIVATE_KEY_PROTECTED:
898       /* If we ever require it we could retrieve the comment fields
899          from such a key. */
900       break;
901     case PRIVATE_KEY_SHADOWED:
902       if (r_shadow_info)
903         {
904           const unsigned char *s;
905           size_t n;
906
907           err = agent_get_shadow_info (buf, &s);
908           if (!err)
909             {
910               n = gcry_sexp_canon_len (s, 0, NULL, NULL);
911               assert (n);
912               *r_shadow_info = xtrymalloc (n);
913               if (!*r_shadow_info)
914                 err = gpg_error_from_syserror ();
915               else
916                 memcpy (*r_shadow_info, s, n);
917             }
918         }
919       break;
920     default:
921       err = gpg_error (GPG_ERR_BAD_SECKEY);
922       break;
923     }
924
925   if (!err && r_keytype)
926     *r_keytype = keytype;
927
928   xfree (buf);
929   return err;
930 }