Move password repetition from gpg to gpg-agent.
[gnupg.git] / agent / findkey.c
blob5bea198dcb17df9d115d8d7f5f13d6c36efb696a
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 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)
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. */
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)
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];
313 bin2hex (grip, 20, hexgrip);
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)
319 void *cache_marker;
320 const char *pw;
322 retry:
323 pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
324 if (pw)
326 rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
327 agent_unlock_cache_entry (&cache_marker);
328 if (!rc)
330 xfree (*keybuf);
331 *keybuf = result;
332 return 0;
334 rc = 0;
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))
349 /* Active - wait */
350 if (!pinentry_active_p (ctrl, 60))
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;
357 /* Timeout - better call pinentry now the plain way. */
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;
375 rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
376 if (!rc)
378 assert (arg.unprotected_key);
379 if (arg.change_required)
381 size_t canlen, erroff;
382 gcry_sexp_t s_skey;
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)
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;
397 rc = agent_protect_and_store (ctrl, s_skey);
398 gcry_sexp_release (s_skey);
399 if (rc)
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;
409 agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
410 xfree (*keybuf);
411 *keybuf = arg.unprotected_key;
413 xfree (pi);
414 return rc;
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)
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];
433 *result = NULL;
435 bin2hex (grip, 20, hexgrip);
436 strcpy (hexgrip+40, ".key");
438 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
439 fp = fopen (fname, "rb");
440 if (!fp)
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;
449 if (fstat (fileno(fp), &st))
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;
458 buflen = st.st_size;
459 buf = xtrymalloc (buflen+1);
460 if (!buf || fread (buf, buflen, 1, fp) != 1)
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;
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)
477 log_error ("failed to build S-Exp (off=%u): %s\n",
478 (unsigned int)erroff, gpg_strerror (rc));
479 return rc;
481 *result = s_skey;
482 return 0;
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)
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;
503 *result = NULL;
504 if (shadow_info)
505 *shadow_info = NULL;
507 rc = read_key_file (grip, &s_skey);
508 if (rc)
509 return rc;
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;
518 switch (agent_private_key_type (buf))
520 case PRIVATE_KEY_CLEAR:
521 break; /* no unprotection needed */
522 case PRIVATE_KEY_PROTECTED:
524 gcry_sexp_t comment_sexp;
525 size_t comment_length;
526 char *desc_text_final;
527 const char *comment = NULL;
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)
537 comment = "";
538 comment_length = 0;
541 desc_text_final = NULL;
542 if (desc_text)
544 if (comment[comment_length])
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
554 memcpy (tmp, comment, comment_length);
555 tmp[comment_length] = 0;
556 rc = modify_description (desc_text, tmp, &desc_text_final);
557 xfree (tmp);
560 else
561 rc = modify_description (desc_text, comment, &desc_text_final);
564 if (!rc)
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));
572 gcry_sexp_release (comment_sexp);
573 xfree (desc_text_final);
575 break;
576 case PRIVATE_KEY_SHADOWED:
577 if (shadow_info)
579 const unsigned char *s;
580 size_t n;
582 rc = agent_get_shadow_info (buf, &s);
583 if (!rc)
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
592 memcpy (*shadow_info, s, n);
593 rc = 0;
594 got_shadow_info = 1;
597 if (rc)
598 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
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;
608 gcry_sexp_release (s_skey);
609 s_skey = NULL;
610 if (rc || got_shadow_info)
612 xfree (buf);
613 return rc;
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)
622 log_error ("failed to build S-Exp (off=%u): %s\n",
623 (unsigned int)erroff, gpg_strerror (rc));
624 return rc;
627 *result = s_skey;
628 return 0;
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)
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;
659 (void)ctrl;
661 *result = NULL;
663 rc = read_key_file (grip, &s_skey);
664 if (rc)
665 return rc;
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)
674 log_error ("invalid private key format\n");
675 gcry_sexp_release (s_skey);
676 return gpg_error (GPG_ERR_BAD_SECKEY);
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))
685 algoname = "rsa";
686 elems = "ne";
688 else if (n==3 && !memcmp (name, "dsa", 3))
690 algoname = "dsa";
691 elems = "pqgy";
693 else if (n==3 && !memcmp (name, "elg", 3))
695 algoname = "elg";
696 elems = "pgy";
698 else
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);
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)
711 rc = gpg_error_from_syserror ();
712 gcry_sexp_release (list);
713 gcry_sexp_release (s_skey);
714 return rc;
717 for (idx=0, s=elems; *s; s++, idx++ )
719 l2 = gcry_sexp_find_token (list, s, 1);
720 if (!l2)
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);
730 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
731 gcry_sexp_release (l2);
732 if (!array[idx])
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);
743 gcry_sexp_release (list);
744 list = NULL;
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);
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);
758 gcry_sexp_release (s_skey);
759 s_skey = NULL;
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*));
770 format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
771 if (!format)
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;
782 argidx = 0;
783 p = stpcpy (stpcpy (format, "(public-key("), algoname);
784 for (idx=0, s=elems; *s; s++, idx++ )
786 *p++ = '(';
787 *p++ = *s;
788 p = stpcpy (p, " %m)");
789 assert (argidx < DIM (args));
790 args[argidx++] = &array[idx];
792 *p++ = ')';
793 if (uri)
795 p = stpcpy (p, "(uri %b)");
796 assert (argidx+1 < DIM (args));
797 args[argidx++] = (void *)uri_length;
798 args[argidx++] = (void *)uri;
800 if (comment)
802 p = stpcpy (p, "(comment %b)");
803 assert (argidx+1 < DIM (args));
804 args[argidx++] = (void *)comment_length;
805 args[argidx++] = (void*)comment;
807 *p++ = ')';
808 *p = 0;
809 assert (argidx < DIM (args));
810 args[argidx] = NULL;
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);
820 if (!rc)
821 *result = list;
822 return rc;
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 */
830 agent_key_available (const unsigned char *grip)
832 int result;
833 char *fname;
834 char hexgrip[40+4+1];
836 bin2hex (grip, 20, hexgrip);
837 strcpy (hexgrip+40, ".key");
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;
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)
855 gpg_error_t err;
856 unsigned char *buf;
857 size_t len;
858 int keytype;
860 (void)ctrl;
862 if (r_keytype)
863 *r_keytype = PRIVATE_KEY_UNKNOWN;
864 if (r_shadow_info)
865 *r_shadow_info = NULL;
868 gcry_sexp_t sexp;
870 err = read_key_file (grip, &sexp);
871 if (err)
873 if (gpg_err_code (err) == GPG_ERR_ENOENT)
874 return gpg_error (GPG_ERR_NOT_FOUND);
875 else
876 return err;
878 err = make_canon_sexp (sexp, &buf, &len);
879 gcry_sexp_release (sexp);
880 if (err)
881 return err;
884 keytype = agent_private_key_type (buf);
885 switch (keytype)
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)
896 const unsigned char *s;
897 size_t n;
899 err = agent_get_shadow_info (buf, &s);
900 if (!err)
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);
911 break;
912 default:
913 err = gpg_error (GPG_ERR_BAD_SECKEY);
914 break;
917 if (!err && r_keytype)
918 *r_keytype = keytype;
920 xfree (buf);
921 return err;