app-openpgp changes
[gnupg.git] / agent / findkey.c
blob5fe735242b2f038aee3ea5ba9d690b4b46f78ea3
1 /* findkey.c - Locate the secret key
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 * 2007 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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.
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.
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/>.
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) */
34 #include "agent.h"
35 #include "i18n.h"
37 #ifndef O_BINARY
38 #define O_BINARY 0
39 #endif
41 /* Helper to pass data to the check callback of the unprotect function. */
42 struct try_unprotect_arg_s
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. */
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)
59 char *fname;
60 FILE *fp;
61 char hexgrip[40+4+1];
62 int fd;
64 bin2hex (grip, 20, hexgrip);
65 strcpy (hexgrip+40, ".key");
67 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
69 if (!force && !access (fname, F_OK))
71 log_error ("secret key file `%s' already exists\n", fname);
72 xfree (fname);
73 return gpg_error (GPG_ERR_GENERAL);
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
88 if (fd < 0)
89 fp = NULL;
90 else
92 fp = fdopen (fd, "wb");
93 if (!fp)
95 int save_e = errno;
96 close (fd);
97 errno = save_e;
101 if (!fp)
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;
109 if (fwrite (buffer, length, 1, fp) != 1)
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;
118 if ( fclose (fp) )
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;
126 bump_key_eventcounter ();
127 xfree (fname);
128 return 0;
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)
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;
143 assert (!arg->unprotected_key);
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. */
153 if (!*protected_at)
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 ();
161 else
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 )
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 ();
180 if (desc)
182 /* Change required. */
183 if (opt.enforce_passphrase_constraints)
185 err = agent_get_confirmation (arg->ctrl, desc,
186 _("Change passphrase"), NULL);
187 if (!err)
188 arg->change_required = 1;
190 else
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;
200 xfree (desc);
203 return 0;
207 /* Modify a Key description, replacing certain special format
208 characters. List of currently supported replacements:
210 %% - Replaced by a single %
211 %c - Replaced by the content of COMMENT.
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.
216 static gpg_error_t
217 modify_description (const char *in, const char *comment, char **result)
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;
226 comment_length = strlen (comment);
227 in_len = strlen (in);
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++)
235 special = 0;
236 for (i = 0; i < in_len; i++)
238 if (special)
240 special = 0;
241 switch (in[i])
243 case '%':
244 if (out)
245 *out++ = '%';
246 else
247 out_len++;
248 break;
250 case 'c': /* Comment. */
251 if (out)
253 memcpy (out, comment, comment_length);
254 out += comment_length;
256 else
257 out_len += comment_length;
258 break;
260 default: /* Invalid special sequences are kept as they are. */
261 if (out)
263 *out++ = '%';
264 *out++ = in[i];
266 else
267 out_len+=2;
268 break;
271 else if (in[i] == '%')
272 special = 1;
273 else
275 if (out)
276 *out++ = in[i];
277 else
278 out_len++;
282 if (!pass)
284 *result = out = xtrymalloc (out_len + 1);
285 if (!out)
286 return gpg_error_from_syserror ();
290 *out = 0;
291 assert (*result + out_len == out);
292 return 0;
297 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
298 should be the hex encoded keygrip of that key to be used with the
299 caching mechanism. DESC_TEXT may be set to override the default
300 description used for the pinentry. If LOOKUP_TTL is given this
301 function is used to lookup the default ttl. */
302 static int
303 unprotect (ctrl_t ctrl, const char *desc_text,
304 unsigned char **keybuf, const unsigned char *grip,
305 cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
307 struct pin_entry_info_s *pi;
308 struct try_unprotect_arg_s arg;
309 int rc;
310 unsigned char *result;
311 size_t resultlen;
312 char hexgrip[40+1];
314 bin2hex (grip, 20, hexgrip);
316 /* First try to get it from the cache - if there is none or we can't
317 unprotect it, we fall back to ask the user */
318 if (cache_mode != CACHE_MODE_IGNORE)
320 void *cache_marker;
321 const char *pw;
323 retry:
324 pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
325 if (pw)
327 rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
328 agent_unlock_cache_entry (&cache_marker);
329 if (!rc)
331 xfree (*keybuf);
332 *keybuf = result;
333 return 0;
335 rc = 0;
338 /* If the pinentry is currently in use, we wait up to 60 seconds
339 for it to close and check the cache again. This solves a common
340 situation where several requests for unprotecting a key have
341 been made but the user is still entering the passphrase for
342 the first request. Because all requests to agent_askpin are
343 serialized they would then pop up one after the other to
344 request the passphrase - despite that the user has already
345 entered it and is then available in the cache. This
346 implementation is not race free but in the worst case the
347 user has to enter the passphrase only once more. */
348 if (pinentry_active_p (ctrl, 0))
350 /* Active - wait */
351 if (!pinentry_active_p (ctrl, 60))
353 /* We need to give the other thread a chance to actually put
354 it into the cache. */
355 pth_sleep (1);
356 goto retry;
358 /* Timeout - better call pinentry now the plain way. */
362 pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
363 if (!pi)
364 return gpg_error_from_syserror ();
365 pi->max_length = 100;
366 pi->min_digits = 0; /* we want a real passphrase */
367 pi->max_digits = 16;
368 pi->max_tries = 3;
369 pi->check_cb = try_unprotect_cb;
370 arg.ctrl = ctrl;
371 arg.protected_key = *keybuf;
372 arg.unprotected_key = NULL;
373 arg.change_required = 0;
374 pi->check_cb_arg = &arg;
376 rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
377 if (!rc)
379 assert (arg.unprotected_key);
380 if (arg.change_required)
382 size_t canlen, erroff;
383 gcry_sexp_t s_skey;
385 assert (arg.unprotected_key);
386 canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
387 rc = gcry_sexp_sscan (&s_skey, &erroff,
388 (char*)arg.unprotected_key, canlen);
389 if (rc)
391 log_error ("failed to build S-Exp (off=%u): %s\n",
392 (unsigned int)erroff, gpg_strerror (rc));
393 wipememory (arg.unprotected_key, canlen);
394 xfree (arg.unprotected_key);
395 xfree (pi);
396 return rc;
398 rc = agent_protect_and_store (ctrl, s_skey);
399 gcry_sexp_release (s_skey);
400 if (rc)
402 log_error ("changing the passphrase failed: %s\n",
403 gpg_strerror (rc));
404 wipememory (arg.unprotected_key, canlen);
405 xfree (arg.unprotected_key);
406 xfree (pi);
407 return rc;
410 agent_put_cache (hexgrip, cache_mode, pi->pin,
411 lookup_ttl? lookup_ttl (hexgrip) : 0);
412 xfree (*keybuf);
413 *keybuf = arg.unprotected_key;
415 xfree (pi);
416 return rc;
420 /* Read the key identified by GRIP from the private key directory and
421 return it as an gcrypt S-expression object in RESULT. On failure
422 returns an error code and stores NULL at RESULT. */
423 static gpg_error_t
424 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
426 int rc;
427 char *fname;
428 FILE *fp;
429 struct stat st;
430 unsigned char *buf;
431 size_t buflen, erroff;
432 gcry_sexp_t s_skey;
433 char hexgrip[40+4+1];
435 *result = NULL;
437 bin2hex (grip, 20, hexgrip);
438 strcpy (hexgrip+40, ".key");
440 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
441 fp = fopen (fname, "rb");
442 if (!fp)
444 rc = gpg_error_from_syserror ();
445 if (gpg_err_code (rc) != GPG_ERR_ENOENT)
446 log_error ("can't open `%s': %s\n", fname, strerror (errno));
447 xfree (fname);
448 return rc;
451 if (fstat (fileno(fp), &st))
453 rc = gpg_error_from_syserror ();
454 log_error ("can't stat `%s': %s\n", fname, strerror (errno));
455 xfree (fname);
456 fclose (fp);
457 return rc;
460 buflen = st.st_size;
461 buf = xtrymalloc (buflen+1);
462 if (!buf || fread (buf, buflen, 1, fp) != 1)
464 rc = gpg_error_from_syserror ();
465 log_error ("error reading `%s': %s\n", fname, strerror (errno));
466 xfree (fname);
467 fclose (fp);
468 xfree (buf);
469 return rc;
472 /* Convert the file into a gcrypt S-expression object. */
473 rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
474 xfree (fname);
475 fclose (fp);
476 xfree (buf);
477 if (rc)
479 log_error ("failed to build S-Exp (off=%u): %s\n",
480 (unsigned int)erroff, gpg_strerror (rc));
481 return rc;
483 *result = s_skey;
484 return 0;
488 /* Return the secret key as an S-Exp in RESULT after locating it using
489 the GRIP. Stores NULL at RESULT if the operation shall be diverted
490 to a token; in this case an allocated S-expression with the
491 shadow_info part from the file is stored at SHADOW_INFO.
492 CACHE_MODE defines now the cache shall be used. DESC_TEXT may be
493 set to present a custom description for the pinentry. LOOKUP_TTL
494 is an optional function to convey a TTL to the cache manager; we do
495 not simply pass the TTL value because the value is only needed if an
496 unprotect action was needed and looking up the TTL may have some
497 overhead (e.g. scanning the sshcontrol file). */
498 gpg_error_t
499 agent_key_from_file (ctrl_t ctrl, const char *desc_text,
500 const unsigned char *grip, unsigned char **shadow_info,
501 cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
502 gcry_sexp_t *result)
504 int rc;
505 unsigned char *buf;
506 size_t len, buflen, erroff;
507 gcry_sexp_t s_skey;
508 int got_shadow_info = 0;
510 *result = NULL;
511 if (shadow_info)
512 *shadow_info = NULL;
514 rc = read_key_file (grip, &s_skey);
515 if (rc)
516 return rc;
518 /* For use with the protection functions we also need the key as an
519 canonical encoded S-expression in a buffer. Create this buffer
520 now. */
521 rc = make_canon_sexp (s_skey, &buf, &len);
522 if (rc)
523 return rc;
525 switch (agent_private_key_type (buf))
527 case PRIVATE_KEY_CLEAR:
528 break; /* no unprotection needed */
529 case PRIVATE_KEY_PROTECTED:
531 gcry_sexp_t comment_sexp;
532 size_t comment_length;
533 char *desc_text_final;
534 const char *comment = NULL;
536 /* Note, that we will take the comment as a C string for
537 display purposes; i.e. all stuff beyond a Nul character is
538 ignored. */
539 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
540 if (comment_sexp)
541 comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
542 if (!comment)
544 comment = "";
545 comment_length = 0;
548 desc_text_final = NULL;
549 if (desc_text)
551 if (comment[comment_length])
553 /* Not a C-string; create one. We might here allocate
554 more than actually displayed but well, that
555 shouldn't be a problem. */
556 char *tmp = xtrymalloc (comment_length+1);
557 if (!tmp)
558 rc = gpg_error_from_syserror ();
559 else
561 memcpy (tmp, comment, comment_length);
562 tmp[comment_length] = 0;
563 rc = modify_description (desc_text, tmp, &desc_text_final);
564 xfree (tmp);
567 else
568 rc = modify_description (desc_text, comment, &desc_text_final);
571 if (!rc)
573 rc = unprotect (ctrl, desc_text_final, &buf, grip,
574 cache_mode, lookup_ttl);
575 if (rc)
576 log_error ("failed to unprotect the secret key: %s\n",
577 gpg_strerror (rc));
580 gcry_sexp_release (comment_sexp);
581 xfree (desc_text_final);
583 break;
584 case PRIVATE_KEY_SHADOWED:
585 if (shadow_info)
587 const unsigned char *s;
588 size_t n;
590 rc = agent_get_shadow_info (buf, &s);
591 if (!rc)
593 n = gcry_sexp_canon_len (s, 0, NULL,NULL);
594 assert (n);
595 *shadow_info = xtrymalloc (n);
596 if (!*shadow_info)
597 rc = out_of_core ();
598 else
600 memcpy (*shadow_info, s, n);
601 rc = 0;
602 got_shadow_info = 1;
605 if (rc)
606 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
608 else
609 rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
610 break;
611 default:
612 log_error ("invalid private key format\n");
613 rc = gpg_error (GPG_ERR_BAD_SECKEY);
614 break;
616 gcry_sexp_release (s_skey);
617 s_skey = NULL;
618 if (rc || got_shadow_info)
620 xfree (buf);
621 return rc;
624 buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
625 rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
626 wipememory (buf, buflen);
627 xfree (buf);
628 if (rc)
630 log_error ("failed to build S-Exp (off=%u): %s\n",
631 (unsigned int)erroff, gpg_strerror (rc));
632 return rc;
635 *result = s_skey;
636 return 0;
641 /* Return the public key for the keygrip GRIP. The result is stored
642 at RESULT. This function extracts the public key from the private
643 key database. On failure an error code is returned and NULL stored
644 at RESULT. */
645 gpg_error_t
646 agent_public_key_from_file (ctrl_t ctrl,
647 const unsigned char *grip,
648 gcry_sexp_t *result)
650 int i, idx, rc;
651 gcry_sexp_t s_skey;
652 const char *algoname;
653 gcry_sexp_t uri_sexp, comment_sexp;
654 const char *uri, *comment;
655 size_t uri_length, comment_length;
656 char *format, *p;
657 void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
658 for comment + end-of-list. */
659 int argidx;
660 gcry_sexp_t list, l2;
661 const char *name;
662 const char *s;
663 size_t n;
664 const char *elems;
665 gcry_mpi_t *array;
667 (void)ctrl;
669 *result = NULL;
671 rc = read_key_file (grip, &s_skey);
672 if (rc)
673 return rc;
675 list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
676 if (!list)
677 list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
678 if (!list)
679 list = gcry_sexp_find_token (s_skey, "private-key", 0 );
680 if (!list)
682 log_error ("invalid private key format\n");
683 gcry_sexp_release (s_skey);
684 return gpg_error (GPG_ERR_BAD_SECKEY);
687 l2 = gcry_sexp_cadr (list);
688 gcry_sexp_release (list);
689 list = l2;
690 name = gcry_sexp_nth_data (list, 0, &n);
691 if (n==3 && !memcmp (name, "rsa", 3))
693 algoname = "rsa";
694 elems = "ne";
696 else if (n==3 && !memcmp (name, "dsa", 3))
698 algoname = "dsa";
699 elems = "pqgy";
701 else if (n==3 && !memcmp (name, "elg", 3))
703 algoname = "elg";
704 elems = "pgy";
706 else
708 log_error ("unknown private key algorithm\n");
709 gcry_sexp_release (list);
710 gcry_sexp_release (s_skey);
711 return gpg_error (GPG_ERR_BAD_SECKEY);
714 /* Allocate an array for the parameters and copy them out of the
715 secret key. FIXME: We should have a generic copy function. */
716 array = xtrycalloc (strlen(elems) + 1, sizeof *array);
717 if (!array)
719 rc = gpg_error_from_syserror ();
720 gcry_sexp_release (list);
721 gcry_sexp_release (s_skey);
722 return rc;
725 for (idx=0, s=elems; *s; s++, idx++ )
727 l2 = gcry_sexp_find_token (list, s, 1);
728 if (!l2)
730 /* Required parameter not found. */
731 for (i=0; i<idx; i++)
732 gcry_mpi_release (array[i]);
733 xfree (array);
734 gcry_sexp_release (list);
735 gcry_sexp_release (s_skey);
736 return gpg_error (GPG_ERR_BAD_SECKEY);
738 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
739 gcry_sexp_release (l2);
740 if (!array[idx])
742 /* Required parameter is invalid. */
743 for (i=0; i<idx; i++)
744 gcry_mpi_release (array[i]);
745 xfree (array);
746 gcry_sexp_release (list);
747 gcry_sexp_release (s_skey);
748 return gpg_error (GPG_ERR_BAD_SECKEY);
751 gcry_sexp_release (list);
752 list = NULL;
754 uri = NULL;
755 uri_length = 0;
756 uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
757 if (uri_sexp)
758 uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
760 comment = NULL;
761 comment_length = 0;
762 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
763 if (comment_sexp)
764 comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
766 gcry_sexp_release (s_skey);
767 s_skey = NULL;
770 /* FIXME: The following thing is pretty ugly code; we should
771 investigate how to make it cleaner. Probably code to handle
772 canonical S-expressions in a memory buffer is better suioted for
773 such a task. After all that is what we do in protect.c. Neeed
774 to find common patterns and write a straightformward API to use
775 them. */
776 assert (sizeof (size_t) <= sizeof (void*));
778 format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
779 if (!format)
781 rc = gpg_error_from_syserror ();
782 for (i=0; array[i]; i++)
783 gcry_mpi_release (array[i]);
784 xfree (array);
785 gcry_sexp_release (uri_sexp);
786 gcry_sexp_release (comment_sexp);
787 return rc;
790 argidx = 0;
791 p = stpcpy (stpcpy (format, "(public-key("), algoname);
792 for (idx=0, s=elems; *s; s++, idx++ )
794 *p++ = '(';
795 *p++ = *s;
796 p = stpcpy (p, " %m)");
797 assert (argidx < DIM (args));
798 args[argidx++] = &array[idx];
800 *p++ = ')';
801 if (uri)
803 p = stpcpy (p, "(uri %b)");
804 assert (argidx+1 < DIM (args));
805 args[argidx++] = (void *)uri_length;
806 args[argidx++] = (void *)uri;
808 if (comment)
810 p = stpcpy (p, "(comment %b)");
811 assert (argidx+1 < DIM (args));
812 args[argidx++] = (void *)comment_length;
813 args[argidx++] = (void*)comment;
815 *p++ = ')';
816 *p = 0;
817 assert (argidx < DIM (args));
818 args[argidx] = NULL;
820 rc = gcry_sexp_build_array (&list, NULL, format, args);
821 xfree (format);
822 for (i=0; array[i]; i++)
823 gcry_mpi_release (array[i]);
824 xfree (array);
825 gcry_sexp_release (uri_sexp);
826 gcry_sexp_release (comment_sexp);
828 if (!rc)
829 *result = list;
830 return rc;
835 /* Return the secret key as an S-Exp after locating it using the grip.
836 Returns NULL if key is not available. 0 = key is available */
838 agent_key_available (const unsigned char *grip)
840 int result;
841 char *fname;
842 char hexgrip[40+4+1];
844 bin2hex (grip, 20, hexgrip);
845 strcpy (hexgrip+40, ".key");
847 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
848 result = !access (fname, R_OK)? 0 : -1;
849 xfree (fname);
850 return result;
855 /* Return the information about the secret key specified by the binary
856 keygrip GRIP. If the key is a shadowed one the shadow information
857 will be stored at the address R_SHADOW_INFO as an allocated
858 S-expression. */
859 gpg_error_t
860 agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
861 int *r_keytype, unsigned char **r_shadow_info)
863 gpg_error_t err;
864 unsigned char *buf;
865 size_t len;
866 int keytype;
868 (void)ctrl;
870 if (r_keytype)
871 *r_keytype = PRIVATE_KEY_UNKNOWN;
872 if (r_shadow_info)
873 *r_shadow_info = NULL;
876 gcry_sexp_t sexp;
878 err = read_key_file (grip, &sexp);
879 if (err)
881 if (gpg_err_code (err) == GPG_ERR_ENOENT)
882 return gpg_error (GPG_ERR_NOT_FOUND);
883 else
884 return err;
886 err = make_canon_sexp (sexp, &buf, &len);
887 gcry_sexp_release (sexp);
888 if (err)
889 return err;
892 keytype = agent_private_key_type (buf);
893 switch (keytype)
895 case PRIVATE_KEY_CLEAR:
896 break;
897 case PRIVATE_KEY_PROTECTED:
898 /* If we ever require it we could retrieve the comment fields
899 from such a key. */
900 break;
901 case PRIVATE_KEY_SHADOWED:
902 if (r_shadow_info)
904 const unsigned char *s;
905 size_t n;
907 err = agent_get_shadow_info (buf, &s);
908 if (!err)
910 n = gcry_sexp_canon_len (s, 0, NULL, NULL);
911 assert (n);
912 *r_shadow_info = xtrymalloc (n);
913 if (!*r_shadow_info)
914 err = gpg_error_from_syserror ();
915 else
916 memcpy (*r_shadow_info, s, n);
919 break;
920 default:
921 err = gpg_error (GPG_ERR_BAD_SECKEY);
922 break;
925 if (!err && r_keytype)
926 *r_keytype = keytype;
928 xfree (buf);
929 return err;