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