agent: fix two bugs.
[gnupg.git] / agent / findkey.c
1 /* findkey.c - Locate the secret key
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
3  *               2010, 2011 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 <npth.h> /* (we use pth_sleep) */
33
34 #include "agent.h"
35 #include "i18n.h"
36 #include "../common/ssh-utils.h"
37
38 #ifndef O_BINARY
39 #define O_BINARY 0
40 #endif
41
42 /* Helper to pass data to the check callback of the unprotect function. */
43 struct try_unprotect_arg_s
44 {
45   ctrl_t ctrl;
46   const unsigned char *protected_key;
47   unsigned char *unprotected_key;
48   int change_required; /* Set by the callback to indicate that the
49                           user should chnage the passphrase.  */
50 };
51
52
53 /* Write an S-expression formatted key to our key storage.  With FORCE
54    passed as true an existing key with the given GRIP will get
55    overwritten.  */
56 int
57 agent_write_private_key (const unsigned char *grip,
58                          const void *buffer, size_t length, int force)
59 {
60   char *fname;
61   estream_t fp;
62   char hexgrip[40+4+1];
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_EEXIST);
74     }
75
76   fp = es_fopen (fname, force? "wb,mode=-rw" : "wbx,mode=-rw");
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 passphrase 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                    || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
175             err = 0;
176         }
177       xfree (desc);
178     }
179
180   return 0;
181 }
182
183
184 /* Modify a Key description, replacing certain special format
185    characters.  List of currently supported replacements:
186
187    %% - Replaced by a single %
188    %c - Replaced by the content of COMMENT.
189    %F - Replaced by an ssh style fingerprint computed from KEY.
190
191    The functions returns 0 on success or an error code.  On success a
192    newly allocated string is stored at the address of RESULT.
193  */
194 static gpg_error_t
195 modify_description (const char *in, const char *comment, const gcry_sexp_t key,
196                     char **result)
197 {
198   size_t comment_length;
199   size_t in_len;
200   size_t out_len;
201   char *out;
202   size_t i;
203   int special, pass;
204   char *ssh_fpr = NULL;
205
206   comment_length = strlen (comment);
207   in_len  = strlen (in);
208
209   /* First pass calculates the length, second pass does the actual
210      copying.  */
211   out = NULL;
212   out_len = 0;
213   for (pass=0; pass < 2; pass++)
214     {
215       special = 0;
216       for (i = 0; i < in_len; i++)
217         {
218           if (special)
219             {
220               special = 0;
221               switch (in[i])
222                 {
223                 case '%':
224                   if (out)
225                     *out++ = '%';
226                   else
227                     out_len++;
228                   break;
229
230                 case 'c': /* Comment.  */
231                   if (out)
232                     {
233                       memcpy (out, comment, comment_length);
234                       out += comment_length;
235                     }
236                   else
237                     out_len += comment_length;
238                   break;
239
240                 case 'F': /* SSH style fingerprint.  */
241                   if (!ssh_fpr && key)
242                     ssh_get_fingerprint_string (key, &ssh_fpr);
243                   if (ssh_fpr)
244                     {
245                       if (out)
246                         out = stpcpy (out, ssh_fpr);
247                       else
248                         out_len += strlen (ssh_fpr);
249                     }
250                   break;
251
252                 default: /* Invalid special sequences are kept as they are. */
253                   if (out)
254                     {
255                       *out++ = '%';
256                       *out++ = in[i];
257                     }
258                   else
259                     out_len+=2;
260                   break;
261                 }
262             }
263           else if (in[i] == '%')
264             special = 1;
265           else
266             {
267               if (out)
268                 *out++ = in[i];
269               else
270                 out_len++;
271             }
272         }
273
274       if (!pass)
275         {
276           *result = out = xtrymalloc (out_len + 1);
277           if (!out)
278             {
279               xfree (ssh_fpr);
280               return gpg_error_from_syserror ();
281             }
282         }
283     }
284
285   *out = 0;
286   assert (*result + out_len == out);
287   xfree (ssh_fpr);
288   return 0;
289 }
290
291
292
293 /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
294    should be the hex encoded keygrip of that key to be used with the
295    caching mechanism. DESC_TEXT may be set to override the default
296    description used for the pinentry.  If LOOKUP_TTL is given this
297    function is used to lookup the default ttl.  If R_PASSPHRASE is not
298    NULL, the function succeeded and the key was protected the used
299    passphrase (entered or from the cache) is stored there; if not NULL
300    will be stored.  The caller needs to free the returned
301    passphrase. */
302 static int
303 unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
304            unsigned char **keybuf, const unsigned char *grip,
305            cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
306            char **r_passphrase)
307 {
308   struct pin_entry_info_s *pi;
309   struct try_unprotect_arg_s arg;
310   int rc;
311   unsigned char *result;
312   size_t resultlen;
313   char hexgrip[40+1];
314
315   if (r_passphrase)
316     *r_passphrase = NULL;
317
318   bin2hex (grip, 20, hexgrip);
319
320   /* Initially try to get it using a cache nonce.  */
321   if (cache_nonce)
322     {
323       char *pw;
324
325       pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
326       if (pw)
327         {
328           rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
329           if (!rc)
330             {
331               if (r_passphrase)
332                 *r_passphrase = pw;
333               else
334                 xfree (pw);
335               xfree (*keybuf);
336               *keybuf = result;
337               return 0;
338             }
339           xfree (pw);
340         }
341     }
342
343   /* First try to get it from the cache - if there is none or we can't
344      unprotect it, we fall back to ask the user */
345   if (cache_mode != CACHE_MODE_IGNORE)
346     {
347       char *pw;
348
349     retry:
350       pw = agent_get_cache (hexgrip, cache_mode);
351       if (pw)
352         {
353           rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
354           if (!rc)
355             {
356               if (r_passphrase)
357                 *r_passphrase = pw;
358               else
359                 xfree (pw);
360               xfree (*keybuf);
361               *keybuf = result;
362               return 0;
363             }
364           xfree (pw);
365           rc  = 0;
366         }
367
368       /* If the pinentry is currently in use, we wait up to 60 seconds
369          for it to close and check the cache again.  This solves a common
370          situation where several requests for unprotecting a key have
371          been made but the user is still entering the passphrase for
372          the first request.  Because all requests to agent_askpin are
373          serialized they would then pop up one after the other to
374          request the passphrase - despite that the user has already
375          entered it and is then available in the cache.  This
376          implementation is not race free but in the worst case the
377          user has to enter the passphrase only once more. */
378       if (pinentry_active_p (ctrl, 0))
379         {
380           /* Active - wait */
381           if (!pinentry_active_p (ctrl, 60))
382             {
383               /* We need to give the other thread a chance to actually put
384                  it into the cache. */
385               npth_sleep (1);
386               goto retry;
387             }
388           /* Timeout - better call pinentry now the plain way. */
389         }
390     }
391
392   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
393   if (!pi)
394     return gpg_error_from_syserror ();
395   pi->max_length = 100;
396   pi->min_digits = 0;  /* we want a real passphrase */
397   pi->max_digits = 16;
398   pi->max_tries = 3;
399   pi->check_cb = try_unprotect_cb;
400   arg.ctrl = ctrl;
401   arg.protected_key = *keybuf;
402   arg.unprotected_key = NULL;
403   arg.change_required = 0;
404   pi->check_cb_arg = &arg;
405
406   rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
407   if (!rc)
408     {
409       assert (arg.unprotected_key);
410       if (arg.change_required)
411         {
412           size_t canlen, erroff;
413           gcry_sexp_t s_skey;
414
415           assert (arg.unprotected_key);
416           canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
417           rc = gcry_sexp_sscan (&s_skey, &erroff,
418                                 (char*)arg.unprotected_key, canlen);
419           if (rc)
420             {
421               log_error ("failed to build S-Exp (off=%u): %s\n",
422                          (unsigned int)erroff, gpg_strerror (rc));
423               wipememory (arg.unprotected_key, canlen);
424               xfree (arg.unprotected_key);
425               xfree (pi);
426               return rc;
427             }
428           rc = agent_protect_and_store (ctrl, s_skey, NULL);
429           gcry_sexp_release (s_skey);
430           if (rc)
431             {
432               log_error ("changing the passphrase failed: %s\n",
433                          gpg_strerror (rc));
434               wipememory (arg.unprotected_key, canlen);
435               xfree (arg.unprotected_key);
436               xfree (pi);
437               return rc;
438             }
439         }
440       else
441         {
442           agent_put_cache (hexgrip, cache_mode, pi->pin,
443                            lookup_ttl? lookup_ttl (hexgrip) : 0);
444           if (r_passphrase && *pi->pin)
445             *r_passphrase = xtrystrdup (pi->pin);
446         }
447       xfree (*keybuf);
448       *keybuf = arg.unprotected_key;
449     }
450   xfree (pi);
451   return rc;
452 }
453
454
455 /* Read the key identified by GRIP from the private key directory and
456    return it as an gcrypt S-expression object in RESULT.  On failure
457    returns an error code and stores NULL at RESULT. */
458 static gpg_error_t
459 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
460 {
461   int rc;
462   char *fname;
463   estream_t fp;
464   struct stat st;
465   unsigned char *buf;
466   size_t buflen, erroff;
467   gcry_sexp_t s_skey;
468   char hexgrip[40+4+1];
469
470   *result = NULL;
471
472   bin2hex (grip, 20, hexgrip);
473   strcpy (hexgrip+40, ".key");
474
475   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
476   fp = es_fopen (fname, "rb");
477   if (!fp)
478     {
479       rc = gpg_error_from_syserror ();
480       if (gpg_err_code (rc) != GPG_ERR_ENOENT)
481         log_error ("can't open '%s': %s\n", fname, strerror (errno));
482       xfree (fname);
483       return rc;
484     }
485
486   if (fstat (es_fileno (fp), &st))
487     {
488       rc = gpg_error_from_syserror ();
489       log_error ("can't stat '%s': %s\n", fname, strerror (errno));
490       xfree (fname);
491       es_fclose (fp);
492       return rc;
493     }
494
495   buflen = st.st_size;
496   buf = xtrymalloc (buflen+1);
497   if (!buf)
498     {
499       rc = gpg_error_from_syserror ();
500       log_error ("error allocating %zu bytes for '%s': %s\n",
501                  buflen, fname, strerror (errno));
502       xfree (fname);
503       es_fclose (fp);
504       xfree (buf);
505       return rc;
506
507     }
508
509   if (es_fread (buf, buflen, 1, fp) != 1)
510     {
511       rc = gpg_error_from_syserror ();
512       log_error ("error reading %zu bytes from '%s': %s\n",
513                  buflen, fname, strerror (errno));
514       xfree (fname);
515       es_fclose (fp);
516       xfree (buf);
517       return rc;
518     }
519
520   /* Convert the file into a gcrypt S-expression object.  */
521   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
522   xfree (fname);
523   es_fclose (fp);
524   xfree (buf);
525   if (rc)
526     {
527       log_error ("failed to build S-Exp (off=%u): %s\n",
528                  (unsigned int)erroff, gpg_strerror (rc));
529       return rc;
530     }
531   *result = s_skey;
532   return 0;
533 }
534
535
536 /* Return the secret key as an S-Exp in RESULT after locating it using
537    the GRIP.  Stores NULL at RESULT if the operation shall be diverted
538    to a token; in this case an allocated S-expression with the
539    shadow_info part from the file is stored at SHADOW_INFO.
540    CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
541    set to present a custom description for the pinentry.  LOOKUP_TTL
542    is an optional function to convey a TTL to the cache manager; we do
543    not simply pass the TTL value because the value is only needed if
544    an unprotect action was needed and looking up the TTL may have some
545    overhead (e.g. scanning the sshcontrol file).  If a CACHE_NONCE is
546    given that cache item is first tried to get a passphrase.  If
547    R_PASSPHRASE is not NULL, the function succeeded and the key was
548    protected the used passphrase (entered or from the cache) is stored
549    there; if not NULL will be stored.  The caller needs to free the
550    returned passphrase.   */
551 gpg_error_t
552 agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
553                      const char *desc_text,
554                      const unsigned char *grip, unsigned char **shadow_info,
555                      cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
556                      gcry_sexp_t *result, char **r_passphrase)
557 {
558   int rc;
559   unsigned char *buf;
560   size_t len, buflen, erroff;
561   gcry_sexp_t s_skey;
562   int got_shadow_info = 0;
563
564   *result = NULL;
565   if (shadow_info)
566     *shadow_info = NULL;
567   if (r_passphrase)
568     *r_passphrase = NULL;
569
570   rc = read_key_file (grip, &s_skey);
571   if (rc)
572     return rc;
573
574   /* For use with the protection functions we also need the key as an
575      canonical encoded S-expression in a buffer.  Create this buffer
576      now.  */
577   rc = make_canon_sexp (s_skey, &buf, &len);
578   if (rc)
579     return rc;
580
581   switch (agent_private_key_type (buf))
582     {
583     case PRIVATE_KEY_CLEAR:
584       break; /* no unprotection needed */
585     case PRIVATE_KEY_PROTECTED:
586       {
587         char *desc_text_final;
588         char *comment = NULL;
589
590         /* Note, that we will take the comment as a C string for
591            display purposes; i.e. all stuff beyond a Nul character is
592            ignored.  */
593         {
594           gcry_sexp_t comment_sexp;
595
596           comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
597           if (comment_sexp)
598             comment = gcry_sexp_nth_string (comment_sexp, 1);
599           gcry_sexp_release (comment_sexp);
600         }
601
602         desc_text_final = NULL;
603         if (desc_text)
604           rc = modify_description (desc_text, comment? comment:"", s_skey,
605                                    &desc_text_final);
606         gcry_free (comment);
607
608         if (!rc)
609           {
610             rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
611                             cache_mode, lookup_ttl, r_passphrase);
612             if (rc)
613               log_error ("failed to unprotect the secret key: %s\n",
614                          gpg_strerror (rc));
615           }
616
617         xfree (desc_text_final);
618       }
619       break;
620     case PRIVATE_KEY_SHADOWED:
621       if (shadow_info)
622         {
623           const unsigned char *s;
624           size_t n;
625
626           rc = agent_get_shadow_info (buf, &s);
627           if (!rc)
628             {
629               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
630               assert (n);
631               *shadow_info = xtrymalloc (n);
632               if (!*shadow_info)
633                 rc = out_of_core ();
634               else
635                 {
636                   memcpy (*shadow_info, s, n);
637                   rc = 0;
638                   got_shadow_info = 1;
639                 }
640             }
641           if (rc)
642             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
643         }
644       else
645         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
646       break;
647     default:
648       log_error ("invalid private key format\n");
649       rc = gpg_error (GPG_ERR_BAD_SECKEY);
650       break;
651     }
652   gcry_sexp_release (s_skey);
653   s_skey = NULL;
654   if (rc || got_shadow_info)
655     {
656       xfree (buf);
657       if (r_passphrase)
658         {
659           xfree (*r_passphrase);
660           *r_passphrase = NULL;
661         }
662       return rc;
663     }
664
665   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
666   rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
667   wipememory (buf, buflen);
668   xfree (buf);
669   if (rc)
670     {
671       log_error ("failed to build S-Exp (off=%u): %s\n",
672                  (unsigned int)erroff, gpg_strerror (rc));
673       if (r_passphrase)
674         {
675           xfree (*r_passphrase);
676           *r_passphrase = NULL;
677         }
678       return rc;
679     }
680
681   *result = s_skey;
682   return 0;
683 }
684
685
686 /* Return the string name from the S-expression S_KEY as well as a
687    string describing the names of the parameters.  ALGONAMESIZE and
688    ELEMSSIZE give the allocated size of the provided buffers.  The
689    buffers may be NULL if not required.  If R_LIST is not NULL the top
690    level list will be stored tehre; the caller needs to release it in
691    this case.  */
692 static gpg_error_t
693 key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
694                      char *r_algoname, size_t algonamesize,
695                      char *r_elems, size_t elemssize)
696 {
697   gcry_sexp_t list, l2;
698   const char *name, *algoname, *elems;
699   size_t n;
700
701   if (r_list)
702     *r_list = NULL;
703
704   list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
705   if (!list)
706     list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
707   if (!list)
708     list = gcry_sexp_find_token (s_key, "private-key", 0 );
709   if (!list)
710     {
711       log_error ("invalid private key format\n");
712       return gpg_error (GPG_ERR_BAD_SECKEY);
713     }
714
715   l2 = gcry_sexp_cadr (list);
716   gcry_sexp_release (list);
717   list = l2;
718   name = gcry_sexp_nth_data (list, 0, &n);
719   if (n==3 && !memcmp (name, "rsa", 3))
720     {
721       algoname = "rsa";
722       elems = "ne";
723     }
724   else if (n==3 && !memcmp (name, "dsa", 3))
725     {
726       algoname = "dsa";
727       elems = "pqgy";
728     }
729   else if (n==5 && !memcmp (name, "ecdsa", 5))
730     {
731       algoname = "ecdsa";
732       elems = "pabgnq";
733     }
734   else if (n==4 && !memcmp (name, "ecdh", 4))
735     {
736       algoname = "ecdh";
737       elems = "pabgnq";
738     }
739   else if (n==3 && !memcmp (name, "elg", 3))
740     {
741       algoname = "elg";
742       elems = "pgy";
743     }
744   else
745     {
746       log_error ("unknown private key algorithm\n");
747       gcry_sexp_release (list);
748       return gpg_error (GPG_ERR_BAD_SECKEY);
749     }
750
751   if (r_algoname)
752     {
753       if (strlen (algoname) >= algonamesize)
754         return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
755       strcpy (r_algoname, algoname);
756     }
757   if (r_elems)
758     {
759       if (strlen (elems) >= elemssize)
760         return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
761       strcpy (r_elems, elems);
762     }
763
764   if (r_list)
765     *r_list = list;
766   else
767     gcry_sexp_release (list);
768
769   return 0;
770 }
771
772
773 /* Return the public key algorithm number if S_KEY is a DSA style key.
774    If it is not a DSA style key, return 0.  */
775 int
776 agent_is_dsa_key (gcry_sexp_t s_key)
777 {
778   char algoname[6];
779
780   if (!s_key)
781     return 0;
782
783   if (key_parms_from_sexp (s_key, NULL, algoname, sizeof algoname, NULL, 0))
784     return 0; /* Error - assume it is not an DSA key.  */
785
786   if (!strcmp (algoname, "dsa"))
787     return GCRY_PK_DSA;
788   else if (!strcmp (algoname, "ecdsa"))
789     return GCRY_PK_ECDSA;
790   else
791     return 0;
792 }
793
794
795
796 /* Return the key for the keygrip GRIP.  The result is stored at
797    RESULT.  This function extracts the key from the private key
798    database and returns it as an S-expression object as it is.  On
799    failure an error code is returned and NULL stored at RESULT. */
800 gpg_error_t
801 agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
802                          gcry_sexp_t *result)
803 {
804   gpg_error_t err;
805   gcry_sexp_t s_skey;
806
807   (void)ctrl;
808
809   *result = NULL;
810
811   err = read_key_file (grip, &s_skey);
812   if (!err)
813     *result = s_skey;
814   return err;
815 }
816
817
818 /* Return the public key for the keygrip GRIP.  The result is stored
819    at RESULT.  This function extracts the public key from the private
820    key database.  On failure an error code is returned and NULL stored
821    at RESULT. */
822 gpg_error_t
823 agent_public_key_from_file (ctrl_t ctrl,
824                             const unsigned char *grip,
825                             gcry_sexp_t *result)
826 {
827   gpg_error_t err;
828   int i, idx;
829   gcry_sexp_t s_skey;
830   char algoname[6];
831   char elems[7];
832   gcry_sexp_t uri_sexp, comment_sexp;
833   const char *uri, *comment;
834   size_t uri_length, comment_length;
835   char *format, *p;
836   void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
837                            for comment + end-of-list.  */
838   int argidx;
839   gcry_sexp_t list, l2;
840   const char *s;
841   gcry_mpi_t *array;
842
843   (void)ctrl;
844
845   *result = NULL;
846
847   err = read_key_file (grip, &s_skey);
848   if (err)
849     return err;
850
851   err = key_parms_from_sexp (s_skey, &list,
852                             algoname, sizeof algoname,
853                             elems, sizeof elems);
854   if (err)
855     {
856       gcry_sexp_release (s_skey);
857       return err;
858     }
859
860   /* Allocate an array for the parameters and copy them out of the
861      secret key.   FIXME: We should have a generic copy function. */
862   array = xtrycalloc (strlen(elems) + 1, sizeof *array);
863   if (!array)
864     {
865       err = gpg_error_from_syserror ();
866       gcry_sexp_release (list);
867       gcry_sexp_release (s_skey);
868       return err;
869     }
870
871   for (idx=0, s=elems; *s; s++, idx++ )
872     {
873       l2 = gcry_sexp_find_token (list, s, 1);
874       if (!l2)
875         {
876           /* Required parameter not found.  */
877           for (i=0; i<idx; i++)
878             gcry_mpi_release (array[i]);
879           xfree (array);
880           gcry_sexp_release (list);
881           gcry_sexp_release (s_skey);
882           return gpg_error (GPG_ERR_BAD_SECKEY);
883         }
884       array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
885       gcry_sexp_release (l2);
886       if (!array[idx])
887         {
888           /* Required parameter is invalid. */
889           for (i=0; i<idx; i++)
890             gcry_mpi_release (array[i]);
891           xfree (array);
892           gcry_sexp_release (list);
893           gcry_sexp_release (s_skey);
894           return gpg_error (GPG_ERR_BAD_SECKEY);
895         }
896     }
897   gcry_sexp_release (list);
898   list = NULL;
899
900   uri = NULL;
901   uri_length = 0;
902   uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
903   if (uri_sexp)
904     uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
905
906   comment = NULL;
907   comment_length = 0;
908   comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
909   if (comment_sexp)
910     comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
911
912   gcry_sexp_release (s_skey);
913   s_skey = NULL;
914
915
916   /* FIXME: The following thing is pretty ugly code; we should
917      investigate how to make it cleaner.  Probably code to handle
918      canonical S-expressions in a memory buffer is better suited for
919      such a task.  After all that is what we do in protect.c.  Neeed
920      to find common patterns and write a straightformward API to use
921      them.  */
922   assert (sizeof (size_t) <= sizeof (void*));
923
924   format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
925   if (!format)
926     {
927       err = gpg_error_from_syserror ();
928       for (i=0; array[i]; i++)
929         gcry_mpi_release (array[i]);
930       xfree (array);
931       gcry_sexp_release (uri_sexp);
932       gcry_sexp_release (comment_sexp);
933       return err;
934     }
935
936   argidx = 0;
937   p = stpcpy (stpcpy (format, "(public-key("), algoname);
938   for (idx=0, s=elems; *s; s++, idx++ )
939     {
940       *p++ = '(';
941       *p++ = *s;
942       p = stpcpy (p, " %m)");
943       assert (argidx < DIM (args));
944       args[argidx++] = &array[idx];
945     }
946   *p++ = ')';
947   if (uri)
948     {
949       p = stpcpy (p, "(uri %b)");
950       assert (argidx+1 < DIM (args));
951       args[argidx++] = (void *)&uri_length;
952       args[argidx++] = (void *)&uri;
953     }
954   if (comment)
955     {
956       p = stpcpy (p, "(comment %b)");
957       assert (argidx+1 < DIM (args));
958       args[argidx++] = (void *)&comment_length;
959       args[argidx++] = (void*)&comment;
960     }
961   *p++ = ')';
962   *p = 0;
963   assert (argidx < DIM (args));
964   args[argidx] = NULL;
965
966   err = gcry_sexp_build_array (&list, NULL, format, args);
967   xfree (format);
968   for (i=0; array[i]; i++)
969     gcry_mpi_release (array[i]);
970   xfree (array);
971   gcry_sexp_release (uri_sexp);
972   gcry_sexp_release (comment_sexp);
973
974   if (!err)
975     *result = list;
976   return err;
977 }
978
979
980
981 /* Check whether the the secret key identified by GRIP is available.
982    Returns 0 is the key is available.  */
983 int
984 agent_key_available (const unsigned char *grip)
985 {
986   int result;
987   char *fname;
988   char hexgrip[40+4+1];
989
990   bin2hex (grip, 20, hexgrip);
991   strcpy (hexgrip+40, ".key");
992
993   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
994   result = !access (fname, R_OK)? 0 : -1;
995   xfree (fname);
996   return result;
997 }
998
999
1000
1001 /* Return the information about the secret key specified by the binary
1002    keygrip GRIP.  If the key is a shadowed one the shadow information
1003    will be stored at the address R_SHADOW_INFO as an allocated
1004    S-expression.  */
1005 gpg_error_t
1006 agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
1007                           int *r_keytype, unsigned char **r_shadow_info)
1008 {
1009   gpg_error_t err;
1010   unsigned char *buf;
1011   size_t len;
1012   int keytype;
1013
1014   (void)ctrl;
1015
1016   if (r_keytype)
1017     *r_keytype = PRIVATE_KEY_UNKNOWN;
1018   if (r_shadow_info)
1019     *r_shadow_info = NULL;
1020
1021   {
1022     gcry_sexp_t sexp;
1023
1024     err = read_key_file (grip, &sexp);
1025     if (err)
1026       {
1027         if (gpg_err_code (err) == GPG_ERR_ENOENT)
1028           return gpg_error (GPG_ERR_NOT_FOUND);
1029         else
1030           return err;
1031       }
1032     err = make_canon_sexp (sexp, &buf, &len);
1033     gcry_sexp_release (sexp);
1034     if (err)
1035       return err;
1036   }
1037
1038   keytype = agent_private_key_type (buf);
1039   switch (keytype)
1040     {
1041     case PRIVATE_KEY_CLEAR:
1042       break;
1043     case PRIVATE_KEY_PROTECTED:
1044       /* If we ever require it we could retrieve the comment fields
1045          from such a key. */
1046       break;
1047     case PRIVATE_KEY_SHADOWED:
1048       if (r_shadow_info)
1049         {
1050           const unsigned char *s;
1051           size_t n;
1052
1053           err = agent_get_shadow_info (buf, &s);
1054           if (!err)
1055             {
1056               n = gcry_sexp_canon_len (s, 0, NULL, NULL);
1057               assert (n);
1058               *r_shadow_info = xtrymalloc (n);
1059               if (!*r_shadow_info)
1060                 err = gpg_error_from_syserror ();
1061               else
1062                 memcpy (*r_shadow_info, s, n);
1063             }
1064         }
1065       break;
1066     default:
1067       err = gpg_error (GPG_ERR_BAD_SECKEY);
1068       break;
1069     }
1070
1071   if (!err && r_keytype)
1072     *r_keytype = keytype;
1073
1074   xfree (buf);
1075   return err;
1076 }