New gpg-agent command to list key information.
[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    pased 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. */
301 static int
302 unprotect (ctrl_t ctrl, const char *desc_text,
303            unsigned char **keybuf, const unsigned char *grip, 
304            cache_mode_t cache_mode)
305 {
306   struct pin_entry_info_s *pi;
307   struct try_unprotect_arg_s arg;
308   int rc;
309   unsigned char *result;
310   size_t resultlen;
311   char hexgrip[40+1];
312   
313   bin2hex (grip, 20, hexgrip);
314
315   /* First try to get it from the cache - if there is none or we can't
316      unprotect it, we fall back to ask the user */
317   if (cache_mode != CACHE_MODE_IGNORE)
318     {
319       void *cache_marker;
320       const char *pw;
321       
322     retry:
323       pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
324       if (pw)
325         {
326           rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
327           agent_unlock_cache_entry (&cache_marker);
328           if (!rc)
329             {
330               xfree (*keybuf);
331               *keybuf = result;
332               return 0;
333             }
334           rc  = 0;
335         }
336
337       /* If the pinentry is currently in use, we wait up to 60 seconds
338          for it to close and check the cache again.  This solves a common
339          situation where several requests for unprotecting a key have
340          been made but the user is still entering the passphrase for
341          the first request.  Because all requests to agent_askpin are
342          serialized they would then pop up one after the other to
343          request the passphrase - despite that the user has already
344          entered it and is then available in the cache.  This
345          implementation is not race free but in the worst case the
346          user has to enter the passphrase only once more. */
347       if (pinentry_active_p (ctrl, 0))
348         {
349           /* Active - wait */
350           if (!pinentry_active_p (ctrl, 60))
351             {
352               /* We need to give the other thread a chance to actually put
353                  it into the cache. */
354               pth_sleep (1); 
355               goto retry;
356             }
357           /* Timeout - better call pinentry now the plain way. */
358         }
359     }
360
361   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
362   if (!pi)
363     return gpg_error_from_syserror ();
364   pi->max_length = 100;
365   pi->min_digits = 0;  /* we want a real passphrase */
366   pi->max_digits = 16;
367   pi->max_tries = 3;
368   pi->check_cb = try_unprotect_cb;
369   arg.ctrl = ctrl;
370   arg.protected_key = *keybuf;
371   arg.unprotected_key = NULL;
372   arg.change_required = 0;
373   pi->check_cb_arg = &arg;
374
375   rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
376   if (!rc)
377     {
378       assert (arg.unprotected_key);
379       if (arg.change_required)
380         {
381           size_t canlen, erroff;
382           gcry_sexp_t s_skey;
383           
384           assert (arg.unprotected_key);
385           canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
386           rc = gcry_sexp_sscan (&s_skey, &erroff,
387                                 (char*)arg.unprotected_key, canlen);
388           if (rc)
389             {
390               log_error ("failed to build S-Exp (off=%u): %s\n",
391                          (unsigned int)erroff, gpg_strerror (rc));
392               wipememory (arg.unprotected_key, canlen);
393               xfree (arg.unprotected_key);
394               xfree (pi);
395               return rc;
396             }
397           rc = agent_protect_and_store (ctrl, s_skey);
398           gcry_sexp_release (s_skey);
399           if (rc)
400             {
401               log_error ("changing the passphrase failed: %s\n", 
402                          gpg_strerror (rc));
403               wipememory (arg.unprotected_key, canlen);
404               xfree (arg.unprotected_key);
405               xfree (pi);
406               return rc;
407             }
408         }
409       agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
410       xfree (*keybuf);
411       *keybuf = arg.unprotected_key;
412     }
413   xfree (pi);
414   return rc;
415 }
416
417
418 /* Read the key identified by GRIP from the private key directory and
419    return it as an gcrypt S-expression object in RESULT.  On failure
420    returns an error code and stores NULL at RESULT. */
421 static gpg_error_t
422 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
423 {
424   int rc;
425   char *fname;
426   FILE *fp;
427   struct stat st;
428   unsigned char *buf;
429   size_t buflen, erroff;
430   gcry_sexp_t s_skey;
431   char hexgrip[40+4+1];
432   
433   *result = NULL;
434
435   bin2hex (grip, 20, hexgrip);
436   strcpy (hexgrip+40, ".key");
437
438   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
439   fp = fopen (fname, "rb");
440   if (!fp)
441     {
442       rc = gpg_error_from_syserror ();
443       if (gpg_err_code (rc) != GPG_ERR_ENOENT)
444         log_error ("can't open `%s': %s\n", fname, strerror (errno));
445       xfree (fname);
446       return rc;
447     }
448   
449   if (fstat (fileno(fp), &st))
450     {
451       rc = gpg_error_from_syserror ();
452       log_error ("can't stat `%s': %s\n", fname, strerror (errno));
453       xfree (fname);
454       fclose (fp);
455       return rc;
456     }
457
458   buflen = st.st_size;
459   buf = xtrymalloc (buflen+1);
460   if (!buf || fread (buf, buflen, 1, fp) != 1)
461     {
462       rc = gpg_error_from_syserror ();
463       log_error ("error reading `%s': %s\n", fname, strerror (errno));
464       xfree (fname);
465       fclose (fp);
466       xfree (buf);
467       return rc;
468     }
469
470   /* Convert the file into a gcrypt S-expression object.  */
471   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
472   xfree (fname);
473   fclose (fp);
474   xfree (buf);
475   if (rc)
476     {
477       log_error ("failed to build S-Exp (off=%u): %s\n",
478                  (unsigned int)erroff, gpg_strerror (rc));
479       return rc;
480     }
481   *result = s_skey;
482   return 0;
483 }
484
485
486 /* Return the secret key as an S-Exp in RESULT after locating it using
487    the GRIP.  Stores NULL at RESULT if the operation shall be diverted
488    to a token; in this case an allocated S-expression with the
489    shadow_info part from the file is stored at SHADOW_INFO.
490    CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
491    set to present a custom description for the pinentry.  */
492 gpg_error_t
493 agent_key_from_file (ctrl_t ctrl, const char *desc_text,
494                      const unsigned char *grip, unsigned char **shadow_info,
495                      cache_mode_t cache_mode, gcry_sexp_t *result)
496 {
497   int rc;
498   unsigned char *buf;
499   size_t len, buflen, erroff;
500   gcry_sexp_t s_skey;
501   int got_shadow_info = 0;
502   
503   *result = NULL;
504   if (shadow_info)
505       *shadow_info = NULL;
506
507   rc = read_key_file (grip, &s_skey);
508   if (rc)
509     return rc;
510
511   /* For use with the protection functions we also need the key as an
512      canonical encoded S-expression in a buffer.  Create this buffer
513      now.  */
514   rc = make_canon_sexp (s_skey, &buf, &len);
515   if (rc)
516     return rc;
517
518   switch (agent_private_key_type (buf))
519     {
520     case PRIVATE_KEY_CLEAR:
521       break; /* no unprotection needed */
522     case PRIVATE_KEY_PROTECTED:
523       {
524         gcry_sexp_t comment_sexp;
525         size_t comment_length;
526         char *desc_text_final;
527         const char *comment = NULL;
528
529         /* Note, that we will take the comment as a C string for
530            display purposes; i.e. all stuff beyond a Nul character is
531            ignored.  */
532         comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
533         if (comment_sexp)
534           comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
535         if (!comment)
536           {
537             comment = "";
538             comment_length = 0;
539           }
540
541         desc_text_final = NULL;
542         if (desc_text)
543           {
544             if (comment[comment_length])
545               {
546                 /* Not a C-string; create one.  We might here allocate
547                    more than actually displayed but well, that
548                    shouldn't be a problem.  */
549                 char *tmp = xtrymalloc (comment_length+1);
550                 if (!tmp)
551                   rc = gpg_error_from_syserror ();
552                 else
553                   {
554                     memcpy (tmp, comment, comment_length);
555                     tmp[comment_length] = 0;
556                     rc = modify_description (desc_text, tmp, &desc_text_final);
557                     xfree (tmp);
558                   }
559               }
560             else
561               rc = modify_description (desc_text, comment, &desc_text_final);
562           }
563
564         if (!rc)
565           {
566             rc = unprotect (ctrl, desc_text_final, &buf, grip, cache_mode);
567             if (rc)
568               log_error ("failed to unprotect the secret key: %s\n",
569                          gpg_strerror (rc));
570           }
571         
572         gcry_sexp_release (comment_sexp);
573         xfree (desc_text_final);
574       }
575       break;
576     case PRIVATE_KEY_SHADOWED:
577       if (shadow_info)
578         {
579           const unsigned char *s;
580           size_t n;
581
582           rc = agent_get_shadow_info (buf, &s);
583           if (!rc)
584             {
585               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
586               assert (n);
587               *shadow_info = xtrymalloc (n);
588               if (!*shadow_info)
589                 rc = out_of_core ();
590               else
591                 {
592                   memcpy (*shadow_info, s, n);
593                   rc = 0;
594                   got_shadow_info = 1;
595                 }
596             }
597           if (rc)
598             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
599         }
600       else
601         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
602       break;
603     default:
604       log_error ("invalid private key format\n");
605       rc = gpg_error (GPG_ERR_BAD_SECKEY);
606       break;
607     }
608   gcry_sexp_release (s_skey);
609   s_skey = NULL;
610   if (rc || got_shadow_info)
611     {
612       xfree (buf);
613       return rc;
614     }
615
616   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
617   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
618   wipememory (buf, buflen);
619   xfree (buf);
620   if (rc)
621     {
622       log_error ("failed to build S-Exp (off=%u): %s\n",
623                  (unsigned int)erroff, gpg_strerror (rc));
624       return rc;
625     }
626
627   *result = s_skey;
628   return 0;
629 }
630
631
632
633 /* Return the public key for the keygrip GRIP.  The result is stored
634    at RESULT.  This function extracts the public key from the private
635    key database.  On failure an error code is returned and NULL stored
636    at RESULT. */
637 gpg_error_t
638 agent_public_key_from_file (ctrl_t ctrl, 
639                             const unsigned char *grip,
640                             gcry_sexp_t *result)
641 {
642   int i, idx, rc;
643   gcry_sexp_t s_skey;
644   const char *algoname;
645   gcry_sexp_t uri_sexp, comment_sexp;
646   const char *uri, *comment;
647   size_t uri_length, comment_length;
648   char *format, *p;
649   void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
650                            for comment + end-of-list.  */
651   int argidx;
652   gcry_sexp_t list, l2;
653   const char *name;
654   const char *s;
655   size_t n;
656   const char *elems;
657   gcry_mpi_t *array;
658
659   (void)ctrl;
660
661   *result = NULL;
662
663   rc = read_key_file (grip, &s_skey);
664   if (rc)
665     return rc;
666
667   list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
668   if (!list)
669     list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
670   if (!list)
671     list = gcry_sexp_find_token (s_skey, "private-key", 0 );
672   if (!list)
673     {
674       log_error ("invalid private key format\n");
675       gcry_sexp_release (s_skey);
676       return gpg_error (GPG_ERR_BAD_SECKEY);
677     }
678
679   l2 = gcry_sexp_cadr (list);
680   gcry_sexp_release (list);
681   list = l2;
682   name = gcry_sexp_nth_data (list, 0, &n);
683   if (n==3 && !memcmp (name, "rsa", 3))
684     {
685       algoname = "rsa";
686       elems = "ne";
687     }
688   else if (n==3 && !memcmp (name, "dsa", 3))
689     {
690       algoname = "dsa";
691       elems = "pqgy";
692     }
693   else if (n==3 && !memcmp (name, "elg", 3))
694     {
695       algoname = "elg";
696       elems = "pgy";
697     }
698   else
699     {
700       log_error ("unknown private key algorithm\n");
701       gcry_sexp_release (list);
702       gcry_sexp_release (s_skey);
703       return gpg_error (GPG_ERR_BAD_SECKEY);
704     }
705
706   /* Allocate an array for the parameters and copy them out of the
707      secret key.   FIXME: We should have a generic copy function. */
708   array = xtrycalloc (strlen(elems) + 1, sizeof *array);
709   if (!array)
710     {
711       rc = gpg_error_from_syserror ();
712       gcry_sexp_release (list);
713       gcry_sexp_release (s_skey);
714       return rc;
715     }
716
717   for (idx=0, s=elems; *s; s++, idx++ ) 
718     {
719       l2 = gcry_sexp_find_token (list, s, 1);
720       if (!l2)
721         {
722           /* Required parameter not found.  */
723           for (i=0; i<idx; i++)
724             gcry_mpi_release (array[i]);
725           xfree (array);
726           gcry_sexp_release (list);
727           gcry_sexp_release (s_skey);
728           return gpg_error (GPG_ERR_BAD_SECKEY);
729         }
730       array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
731       gcry_sexp_release (l2);
732       if (!array[idx])
733         {
734           /* Required parameter is invalid. */
735           for (i=0; i<idx; i++)
736             gcry_mpi_release (array[i]);
737           xfree (array);
738           gcry_sexp_release (list);
739           gcry_sexp_release (s_skey);
740           return gpg_error (GPG_ERR_BAD_SECKEY);
741         }
742     }
743   gcry_sexp_release (list);
744   list = NULL;
745
746   uri = NULL;
747   uri_length = 0;
748   uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
749   if (uri_sexp)
750     uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
751
752   comment = NULL;
753   comment_length = 0;
754   comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
755   if (comment_sexp)
756     comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
757
758   gcry_sexp_release (s_skey);
759   s_skey = NULL;
760
761
762   /* FIXME: The following thing is pretty ugly code; we should
763      investigate how to make it cleaner. Probably code to handle
764      canonical S-expressions in a memory buffer is better suioted for
765      such a task.  After all that is what we do in protect.c.  Neeed
766      to find common patterns and write a straightformward API to use
767      them.  */
768   assert (sizeof (size_t) <= sizeof (void*));
769
770   format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
771   if (!format)
772     {
773       rc = gpg_error_from_syserror ();
774       for (i=0; array[i]; i++)
775         gcry_mpi_release (array[i]);
776       xfree (array);
777       gcry_sexp_release (uri_sexp);
778       gcry_sexp_release (comment_sexp);
779       return rc;
780     }
781
782   argidx = 0;
783   p = stpcpy (stpcpy (format, "(public-key("), algoname);
784   for (idx=0, s=elems; *s; s++, idx++ ) 
785     {
786       *p++ = '(';
787       *p++ = *s;
788       p = stpcpy (p, " %m)");
789       assert (argidx < DIM (args));
790       args[argidx++] = &array[idx];
791     }
792   *p++ = ')';
793   if (uri)
794     {
795       p = stpcpy (p, "(uri %b)");
796       assert (argidx+1 < DIM (args));
797       args[argidx++] = (void *)uri_length;
798       args[argidx++] = (void *)uri;
799     }
800   if (comment)
801     {
802       p = stpcpy (p, "(comment %b)");
803       assert (argidx+1 < DIM (args));
804       args[argidx++] = (void *)comment_length;
805       args[argidx++] = (void*)comment;
806     }
807   *p++ = ')';
808   *p = 0;
809   assert (argidx < DIM (args));
810   args[argidx] = NULL;
811     
812   rc = gcry_sexp_build_array (&list, NULL, format, args);
813   xfree (format);
814   for (i=0; array[i]; i++)
815     gcry_mpi_release (array[i]);
816   xfree (array);
817   gcry_sexp_release (uri_sexp);
818   gcry_sexp_release (comment_sexp);
819
820   if (!rc)
821     *result = list;
822   return rc;
823 }
824
825
826
827 /* Return the secret key as an S-Exp after locating it using the grip.
828    Returns NULL if key is not available. 0 = key is available */
829 int
830 agent_key_available (const unsigned char *grip)
831 {
832   int result;
833   char *fname;
834   char hexgrip[40+4+1];
835   
836   bin2hex (grip, 20, hexgrip);
837   strcpy (hexgrip+40, ".key");
838
839   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
840   result = !access (fname, R_OK)? 0 : -1;
841   xfree (fname);
842   return result;
843 }
844
845
846
847 /* Return the information about the secret key specified by the binary
848    keygrip GRIP.  If the key is a shadowed one the shadow information
849    will be stored at the address R_SHADOW_INFO as an allocated
850    S-expression.  */
851 gpg_error_t
852 agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
853                           int *r_keytype, unsigned char **r_shadow_info)
854 {
855   gpg_error_t err;
856   unsigned char *buf;
857   size_t len;
858   int keytype;
859
860   (void)ctrl;
861   
862   if (r_keytype)
863     *r_keytype = PRIVATE_KEY_UNKNOWN;
864   if (r_shadow_info)
865     *r_shadow_info = NULL;
866
867   {
868     gcry_sexp_t sexp;
869     
870     err = read_key_file (grip, &sexp);
871     if (err)
872       {
873         if (gpg_err_code (err) == GPG_ERR_ENOENT)
874           return gpg_error (GPG_ERR_NOT_FOUND);
875         else
876           return err;
877       }
878     err = make_canon_sexp (sexp, &buf, &len);
879     gcry_sexp_release (sexp);
880     if (err)
881       return err;
882   }
883   
884   keytype = agent_private_key_type (buf);
885   switch (keytype)
886     {
887     case PRIVATE_KEY_CLEAR:
888       break; 
889     case PRIVATE_KEY_PROTECTED:
890       /* If we ever require it we could retrieve the comment fields
891          from such a key. */
892       break;
893     case PRIVATE_KEY_SHADOWED:
894       if (r_shadow_info)
895         {
896           const unsigned char *s;
897           size_t n;
898
899           err = agent_get_shadow_info (buf, &s);
900           if (!err)
901             {
902               n = gcry_sexp_canon_len (s, 0, NULL, NULL);
903               assert (n);
904               *r_shadow_info = xtrymalloc (n);
905               if (!*r_shadow_info)
906                 err = gpg_error_from_syserror ();
907               else
908                 memcpy (*r_shadow_info, s, n);
909             }
910         }
911       break;
912     default:
913       err = gpg_error (GPG_ERR_BAD_SECKEY);
914       break;
915     }
916
917   if (!err && r_keytype)
918     *r_keytype = keytype;
919
920   xfree (buf);
921   return err;
922 }