1 /* findkey.c - Locate the secret key
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
3 * 2010, 2011 Free Software Foundation, Inc.
4 * Copyright (C) 2014 Werner Koch
6 * This file is part of GnuPG.
8 * GnuPG is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GnuPG is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <https://www.gnu.org/licenses/>.
33 #include <npth.h> /* (we use pth_sleep) */
37 #include "../common/ssh-utils.h"
38 #include "../common/name-value.h"
44 /* Helper to pass data to the check callback of the unprotect function. */
45 struct try_unprotect_arg_s
48 const unsigned char *protected_key;
49 unsigned char *unprotected_key;
50 int change_required; /* Set by the callback to indicate that the
51 user should change the passphrase. */
56 write_extended_private_key (char *fname, estream_t fp,
57 const void *buf, size_t len)
61 gcry_sexp_t key = NULL;
65 err = nvc_parse_private_key (&pk, &line, fp);
68 log_error ("error parsing '%s' line %d: %s\n",
69 fname, line, gpg_strerror (err));
73 err = gcry_sexp_sscan (&key, NULL, buf, len);
77 err = nvc_set_private_key (pk, key);
81 err = es_fseek (fp, 0, SEEK_SET);
85 err = nvc_write (pk, fp);
88 log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
93 if (ftruncate (es_fileno (fp), es_ftello (fp)))
95 err = gpg_error_from_syserror ();
96 log_error ("error truncating '%s': %s\n", fname, gpg_strerror (err));
103 err = gpg_error_from_syserror ();
104 log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
111 bump_key_eventcounter ();
117 gnupg_remove (fname);
119 gcry_sexp_release (key);
124 /* Write an S-expression formatted key to our key storage. With FORCE
125 passed as true an existing key with the given GRIP will get
128 agent_write_private_key (const unsigned char *grip,
129 const void *buffer, size_t length, int force)
133 char hexgrip[40+4+1];
135 bin2hex (grip, 20, hexgrip);
136 strcpy (hexgrip+40, ".key");
138 fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
141 /* FIXME: Write to a temp file first so that write failures during
142 key updates won't lead to a key loss. */
144 if (!force && !access (fname, F_OK))
146 log_error ("secret key file '%s' already exists\n", fname);
148 return gpg_error (GPG_ERR_EEXIST);
151 fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw");
154 gpg_error_t tmperr = gpg_error_from_syserror ();
156 if (force && gpg_err_code (tmperr) == GPG_ERR_ENOENT)
158 fp = es_fopen (fname, "wbx,mode=-rw");
160 tmperr = gpg_error_from_syserror ();
164 log_error ("can't create '%s': %s\n", fname, gpg_strerror (tmperr));
174 /* See if an existing key is in extended format. */
175 if (es_fread (&first, 1, 1, fp) != 1)
177 rc = gpg_error_from_syserror ();
178 log_error ("error reading first byte from '%s': %s\n",
179 fname, strerror (errno));
185 rc = es_fseek (fp, 0, SEEK_SET);
188 log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
196 /* Key is in extended format. */
197 return write_extended_private_key (fname, fp, buffer, length);
201 if (es_fwrite (buffer, length, 1, fp) != 1)
203 gpg_error_t tmperr = gpg_error_from_syserror ();
204 log_error ("error writing '%s': %s\n", fname, gpg_strerror (tmperr));
206 gnupg_remove (fname);
211 /* When force is given, the file might have to be truncated. */
212 if (force && ftruncate (es_fileno (fp), es_ftello (fp)))
214 gpg_error_t tmperr = gpg_error_from_syserror ();
215 log_error ("error truncating '%s': %s\n", fname, gpg_strerror (tmperr));
217 gnupg_remove (fname);
224 gpg_error_t tmperr = gpg_error_from_syserror ();
225 log_error ("error closing '%s': %s\n", fname, gpg_strerror (tmperr));
226 gnupg_remove (fname);
230 bump_key_eventcounter ();
236 /* Callback function to try the unprotection from the passphrase query
239 try_unprotect_cb (struct pin_entry_info_s *pi)
241 struct try_unprotect_arg_s *arg = pi->check_cb_arg;
242 ctrl_t ctrl = arg->ctrl;
245 gnupg_isotime_t now, protected_at, tmptime;
248 assert (!arg->unprotected_key);
250 arg->change_required = 0;
251 err = agent_unprotect (ctrl, arg->protected_key, pi->pin, protected_at,
252 &arg->unprotected_key, &dummy);
255 if (!opt.max_passphrase_days || ctrl->in_passwd)
256 return 0; /* No regular passphrase change required. */
260 /* No protection date known - must force passphrase change. */
261 desc = xtrystrdup (L_("Note: This passphrase has never been changed.%0A"
262 "Please change it now."));
264 return gpg_error_from_syserror ();
268 gnupg_get_isotime (now);
269 gnupg_copy_time (tmptime, protected_at);
270 err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
273 if (strcmp (now, tmptime) > 0 )
275 /* Passphrase "expired". */
277 (L_("This passphrase has not been changed%%0A"
278 "since %.4s-%.2s-%.2s. Please change it now."),
279 protected_at, protected_at+4, protected_at+6);
281 return gpg_error_from_syserror ();
287 /* Change required. */
288 if (opt.enforce_passphrase_constraints)
290 err = agent_get_confirmation (ctrl, desc,
291 L_("Change passphrase"), NULL, 0);
293 arg->change_required = 1;
297 err = agent_get_confirmation (ctrl, desc,
298 L_("Change passphrase"),
299 L_("I'll change it later"), 0);
301 arg->change_required = 1;
302 else if (gpg_err_code (err) == GPG_ERR_CANCELED
303 || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
313 /* Modify a Key description, replacing certain special format
314 characters. List of currently supported replacements:
316 %% - Replaced by a single %
317 %c - Replaced by the content of COMMENT.
318 %C - Same as %c but put into parentheses.
319 %F - Replaced by an ssh style fingerprint computed from KEY.
321 The functions returns 0 on success or an error code. On success a
322 newly allocated string is stored at the address of RESULT.
325 modify_description (const char *in, const char *comment, const gcry_sexp_t key,
328 size_t comment_length;
334 char *ssh_fpr = NULL;
336 comment_length = strlen (comment);
337 in_len = strlen (in);
339 /* First pass calculates the length, second pass does the actual
343 for (pass=0; pass < 2; pass++)
346 for (i = 0; i < in_len; i++)
360 case 'c': /* Comment. */
363 memcpy (out, comment, comment_length);
364 out += comment_length;
367 out_len += comment_length;
370 case 'C': /* Comment. */
376 memcpy (out, comment, comment_length);
377 out += comment_length;
381 out_len += comment_length + 2;
384 case 'F': /* SSH style fingerprint. */
386 ssh_get_fingerprint_string (key, &ssh_fpr);
390 out = stpcpy (out, ssh_fpr);
392 out_len += strlen (ssh_fpr);
396 default: /* Invalid special sequences are kept as they are. */
407 else if (in[i] == '%')
420 *result = out = xtrymalloc (out_len + 1);
424 return gpg_error_from_syserror ();
430 assert (*result + out_len == out);
437 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
438 should be the hex encoded keygrip of that key to be used with the
439 caching mechanism. DESC_TEXT may be set to override the default
440 description used for the pinentry. If LOOKUP_TTL is given this
441 function is used to lookup the default ttl. If R_PASSPHRASE is not
442 NULL, the function succeeded and the key was protected the used
443 passphrase (entered or from the cache) is stored there; if not NULL
444 will be stored. The caller needs to free the returned
447 unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
448 unsigned char **keybuf, const unsigned char *grip,
449 cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
452 struct pin_entry_info_s *pi;
453 struct try_unprotect_arg_s arg;
455 unsigned char *result;
460 *r_passphrase = NULL;
462 bin2hex (grip, 20, hexgrip);
464 /* Initially try to get it using a cache nonce. */
469 pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
472 rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
487 /* First try to get it from the cache - if there is none or we can't
488 unprotect it, we fall back to ask the user */
489 if (cache_mode != CACHE_MODE_IGNORE)
494 pw = agent_get_cache (hexgrip, cache_mode);
497 rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
500 if (cache_mode == CACHE_MODE_NORMAL)
501 agent_store_cache_hit (hexgrip);
513 else if (cache_mode == CACHE_MODE_NORMAL)
515 /* The standard use of GPG keys is to have a signing and an
516 encryption subkey. Commonly both use the same
517 passphrase. We try to help the user to enter the
518 passphrase only once by silently trying the last
519 correctly entered passphrase. Checking one additional
520 passphrase should be acceptable; despite the S2K
521 introduced delays. The assumed workflow is:
523 1. Read encrypted message in a MUA and thus enter a
524 passphrase for the encryption subkey.
526 2. Reply to that mail with an encrypted and signed
527 mail, thus entering the passphrase for the signing
530 We can often avoid the passphrase entry in the second
531 step. We do this only in normal mode, so not to
532 interfere with unrelated cache entries. */
533 pw = agent_get_cache (NULL, cache_mode);
536 rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
537 &result, &resultlen);
553 /* If the pinentry is currently in use, we wait up to 60 seconds
554 for it to close and check the cache again. This solves a common
555 situation where several requests for unprotecting a key have
556 been made but the user is still entering the passphrase for
557 the first request. Because all requests to agent_askpin are
558 serialized they would then pop up one after the other to
559 request the passphrase - despite that the user has already
560 entered it and is then available in the cache. This
561 implementation is not race free but in the worst case the
562 user has to enter the passphrase only once more. */
563 if (pinentry_active_p (ctrl, 0))
566 if (!pinentry_active_p (ctrl, 60))
568 /* We need to give the other thread a chance to actually put
569 it into the cache. */
573 /* Timeout - better call pinentry now the plain way. */
577 pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
579 return gpg_error_from_syserror ();
580 pi->max_length = MAX_PASSPHRASE_LEN + 1;
581 pi->min_digits = 0; /* we want a real passphrase */
584 pi->check_cb = try_unprotect_cb;
586 arg.protected_key = *keybuf;
587 arg.unprotected_key = NULL;
588 arg.change_required = 0;
589 pi->check_cb_arg = &arg;
591 rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
594 assert (arg.unprotected_key);
595 if (arg.change_required)
597 /* The callback told as that the user should change their
598 passphrase. Present the dialog to do. */
599 size_t canlen, erroff;
602 assert (arg.unprotected_key);
603 canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
604 rc = gcry_sexp_sscan (&s_skey, &erroff,
605 (char*)arg.unprotected_key, canlen);
608 log_error ("failed to build S-Exp (off=%u): %s\n",
609 (unsigned int)erroff, gpg_strerror (rc));
610 wipememory (arg.unprotected_key, canlen);
611 xfree (arg.unprotected_key);
615 rc = agent_protect_and_store (ctrl, s_skey, NULL);
616 gcry_sexp_release (s_skey);
619 log_error ("changing the passphrase failed: %s\n",
621 wipememory (arg.unprotected_key, canlen);
622 xfree (arg.unprotected_key);
629 /* Passphrase is fine. */
630 agent_put_cache (hexgrip, cache_mode, pi->pin,
631 lookup_ttl? lookup_ttl (hexgrip) : 0);
632 agent_store_cache_hit (hexgrip);
633 if (r_passphrase && *pi->pin)
634 *r_passphrase = xtrystrdup (pi->pin);
637 *keybuf = arg.unprotected_key;
644 /* Read the key identified by GRIP from the private key directory and
645 return it as an gcrypt S-expression object in RESULT. On failure
646 returns an error code and stores NULL at RESULT. */
648 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
655 size_t buflen, erroff;
657 char hexgrip[40+4+1];
662 bin2hex (grip, 20, hexgrip);
663 strcpy (hexgrip+40, ".key");
665 fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
667 fp = es_fopen (fname, "rb");
670 rc = gpg_error_from_syserror ();
671 if (gpg_err_code (rc) != GPG_ERR_ENOENT)
672 log_error ("can't open '%s': %s\n", fname, strerror (errno));
677 if (es_fread (&first, 1, 1, fp) != 1)
679 rc = gpg_error_from_syserror ();
680 log_error ("error reading first byte from '%s': %s\n",
681 fname, strerror (errno));
687 rc = es_fseek (fp, 0, SEEK_SET);
690 log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
698 /* Key is in extended format. */
702 rc = nvc_parse_private_key (&pk, &line, fp);
706 log_error ("error parsing '%s' line %d: %s\n",
707 fname, line, gpg_strerror (rc));
710 rc = nvc_get_private_key (pk, result);
713 log_error ("error getting private key from '%s': %s\n",
714 fname, gpg_strerror (rc));
721 if (fstat (es_fileno (fp), &st))
723 rc = gpg_error_from_syserror ();
724 log_error ("can't stat '%s': %s\n", fname, strerror (errno));
731 buf = xtrymalloc (buflen+1);
734 rc = gpg_error_from_syserror ();
735 log_error ("error allocating %zu bytes for '%s': %s\n",
736 buflen, fname, strerror (errno));
744 if (es_fread (buf, buflen, 1, fp) != 1)
746 rc = gpg_error_from_syserror ();
747 log_error ("error reading %zu bytes from '%s': %s\n",
748 buflen, fname, strerror (errno));
755 /* Convert the file into a gcrypt S-expression object. */
756 rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
762 log_error ("failed to build S-Exp (off=%u): %s\n",
763 (unsigned int)erroff, gpg_strerror (rc));
771 /* Remove the key identified by GRIP from the private key directory. */
773 remove_key_file (const unsigned char *grip)
777 char hexgrip[40+4+1];
779 bin2hex (grip, 20, hexgrip);
780 strcpy (hexgrip+40, ".key");
781 fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
783 if (gnupg_remove (fname))
784 err = gpg_error_from_syserror ();
790 /* Return the secret key as an S-Exp in RESULT after locating it using
791 the GRIP. If the operation shall be diverted to a token, an
792 allocated S-expression with the shadow_info part from the file is
793 stored at SHADOW_INFO; if not NULL will be stored at SHADOW_INFO.
794 CACHE_MODE defines now the cache shall be used. DESC_TEXT may be
795 set to present a custom description for the pinentry. LOOKUP_TTL
796 is an optional function to convey a TTL to the cache manager; we do
797 not simply pass the TTL value because the value is only needed if
798 an unprotect action was needed and looking up the TTL may have some
799 overhead (e.g. scanning the sshcontrol file). If a CACHE_NONCE is
800 given that cache item is first tried to get a passphrase. If
801 R_PASSPHRASE is not NULL, the function succeeded and the key was
802 protected the used passphrase (entered or from the cache) is stored
803 there; if not NULL will be stored. The caller needs to free the
804 returned passphrase. */
806 agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
807 const char *desc_text,
808 const unsigned char *grip, unsigned char **shadow_info,
809 cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
810 gcry_sexp_t *result, char **r_passphrase)
814 size_t len, buflen, erroff;
821 *r_passphrase = NULL;
823 rc = read_key_file (grip, &s_skey);
826 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
827 rc = gpg_error (GPG_ERR_NO_SECKEY);
831 /* For use with the protection functions we also need the key as an
832 canonical encoded S-expression in a buffer. Create this buffer
834 rc = make_canon_sexp (s_skey, &buf, &len);
838 switch (agent_private_key_type (buf))
840 case PRIVATE_KEY_CLEAR:
841 break; /* no unprotection needed */
842 case PRIVATE_KEY_OPENPGP_NONE:
844 unsigned char *buf_new;
847 rc = agent_unprotect (ctrl, buf, "", NULL, &buf_new, &buf_newlen);
849 log_error ("failed to convert unprotected openpgp key: %s\n",
858 case PRIVATE_KEY_PROTECTED:
860 char *desc_text_final;
861 char *comment = NULL;
863 /* Note, that we will take the comment as a C string for
864 display purposes; i.e. all stuff beyond a Nul character is
867 gcry_sexp_t comment_sexp;
869 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
871 comment = gcry_sexp_nth_string (comment_sexp, 1);
872 gcry_sexp_release (comment_sexp);
875 desc_text_final = NULL;
877 rc = modify_description (desc_text, comment? comment:"", s_skey,
883 rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
884 cache_mode, lookup_ttl, r_passphrase);
886 log_error ("failed to unprotect the secret key: %s\n",
890 xfree (desc_text_final);
893 case PRIVATE_KEY_SHADOWED:
896 const unsigned char *s;
899 rc = agent_get_shadow_info (buf, &s);
902 n = gcry_sexp_canon_len (s, 0, NULL,NULL);
904 *shadow_info = xtrymalloc (n);
909 memcpy (*shadow_info, s, n);
914 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
917 rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
920 log_error ("invalid private key format\n");
921 rc = gpg_error (GPG_ERR_BAD_SECKEY);
924 gcry_sexp_release (s_skey);
931 xfree (*r_passphrase);
932 *r_passphrase = NULL;
937 buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
938 rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
939 wipememory (buf, buflen);
943 log_error ("failed to build S-Exp (off=%u): %s\n",
944 (unsigned int)erroff, gpg_strerror (rc));
947 xfree (*r_passphrase);
948 *r_passphrase = NULL;
958 /* Return the string name from the S-expression S_KEY as well as a
959 string describing the names of the parameters. ALGONAMESIZE and
960 ELEMSSIZE give the allocated size of the provided buffers. The
961 buffers may be NULL if not required. If R_LIST is not NULL the top
962 level list will be stored there; the caller needs to release it in
965 key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
966 char *r_algoname, size_t algonamesize,
967 char *r_elems, size_t elemssize)
969 gcry_sexp_t list, l2;
970 const char *name, *algoname, *elems;
976 list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
978 list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
980 list = gcry_sexp_find_token (s_key, "private-key", 0 );
983 log_error ("invalid private key format\n");
984 return gpg_error (GPG_ERR_BAD_SECKEY);
987 l2 = gcry_sexp_cadr (list);
988 gcry_sexp_release (list);
990 name = gcry_sexp_nth_data (list, 0, &n);
991 if (n==3 && !memcmp (name, "rsa", 3))
996 else if (n==3 && !memcmp (name, "dsa", 3))
1001 else if (n==3 && !memcmp (name, "ecc", 3))
1006 else if (n==5 && !memcmp (name, "ecdsa", 5))
1011 else if (n==4 && !memcmp (name, "ecdh", 4))
1016 else if (n==3 && !memcmp (name, "elg", 3))
1023 log_error ("unknown private key algorithm\n");
1024 gcry_sexp_release (list);
1025 return gpg_error (GPG_ERR_BAD_SECKEY);
1030 if (strlen (algoname) >= algonamesize)
1031 return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1032 strcpy (r_algoname, algoname);
1036 if (strlen (elems) >= elemssize)
1037 return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1038 strcpy (r_elems, elems);
1044 gcry_sexp_release (list);
1050 /* Return true if KEYPARMS holds an EdDSA key. */
1052 is_eddsa (gcry_sexp_t keyparms)
1060 list = gcry_sexp_find_token (keyparms, "flags", 0);
1061 for (i = list ? gcry_sexp_length (list)-1 : 0; i > 0; i--)
1063 s = gcry_sexp_nth_data (list, i, &n);
1065 continue; /* Not a data element. */
1067 if (n == 5 && !memcmp (s, "eddsa", 5))
1073 gcry_sexp_release (list);
1078 /* Return the public key algorithm number if S_KEY is a DSA style key.
1079 If it is not a DSA style key, return 0. */
1081 agent_is_dsa_key (gcry_sexp_t s_key)
1090 if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
1091 return 0; /* Error - assume it is not an DSA key. */
1093 if (!strcmp (algoname, "dsa"))
1094 result = GCRY_PK_DSA;
1095 else if (!strcmp (algoname, "ecc"))
1097 if (is_eddsa (list))
1100 result = GCRY_PK_ECDSA;
1102 else if (!strcmp (algoname, "ecdsa"))
1103 result = GCRY_PK_ECDSA;
1107 gcry_sexp_release (list);
1112 /* Return true if S_KEY is an EdDSA key as used with curve Ed25519. */
1114 agent_is_eddsa_key (gcry_sexp_t s_key)
1123 if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
1124 return 0; /* Error - assume it is not an EdDSA key. */
1126 if (!strcmp (algoname, "ecc") && is_eddsa (list))
1128 else if (!strcmp (algoname, "eddsa")) /* backward compatibility. */
1133 gcry_sexp_release (list);
1138 /* Return the key for the keygrip GRIP. The result is stored at
1139 RESULT. This function extracts the key from the private key
1140 database and returns it as an S-expression object as it is. On
1141 failure an error code is returned and NULL stored at RESULT. */
1143 agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
1144 gcry_sexp_t *result)
1153 err = read_key_file (grip, &s_skey);
1160 /* Return the public key for the keygrip GRIP. The result is stored
1161 at RESULT. This function extracts the public key from the private
1162 key database. On failure an error code is returned and NULL stored
1165 agent_public_key_from_file (ctrl_t ctrl,
1166 const unsigned char *grip,
1167 gcry_sexp_t *result)
1172 const char *algoname, *elems;
1174 gcry_mpi_t array[10];
1175 gcry_sexp_t curve = NULL;
1176 gcry_sexp_t flags = NULL;
1177 gcry_sexp_t uri_sexp, comment_sexp;
1178 const char *uri, *comment;
1179 size_t uri_length, comment_length;
1181 void *args[2+7+2+2+1]; /* Size is 2 + max. # of elements + 2 for uri + 2
1182 for comment + end-of-list. */
1184 gcry_sexp_t list = NULL;
1191 err = read_key_file (grip, &s_skey);
1195 for (i=0; i < DIM (array); i++)
1198 err = extract_private_key (s_skey, 0, &algoname, &npkey, NULL, &elems,
1199 array, DIM (array), &curve, &flags);
1202 gcry_sexp_release (s_skey);
1208 uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
1210 uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
1214 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
1216 comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
1218 gcry_sexp_release (s_skey);
1222 /* FIXME: The following thing is pretty ugly code; we should
1223 investigate how to make it cleaner. Probably code to handle
1224 canonical S-expressions in a memory buffer is better suited for
1225 such a task. After all that is what we do in protect.c. Neeed
1226 to find common patterns and write a straightformward API to use
1228 assert (sizeof (size_t) <= sizeof (void*));
1230 format = xtrymalloc (15+4+7*npkey+10+15+1+1);
1233 err = gpg_error_from_syserror ();
1234 for (i=0; array[i]; i++)
1235 gcry_mpi_release (array[i]);
1236 gcry_sexp_release (curve);
1237 gcry_sexp_release (flags);
1238 gcry_sexp_release (uri_sexp);
1239 gcry_sexp_release (comment_sexp);
1244 p = stpcpy (stpcpy (format, "(public-key("), algoname);
1245 p = stpcpy (p, "%S%S"); /* curve name and flags. */
1246 args[argidx++] = &curve;
1247 args[argidx++] = &flags;
1248 for (idx=0, s=elems; idx < npkey; idx++)
1252 p = stpcpy (p, " %m)");
1253 assert (argidx < DIM (args));
1254 args[argidx++] = &array[idx];
1259 p = stpcpy (p, "(uri %b)");
1260 assert (argidx+1 < DIM (args));
1261 args[argidx++] = (void *)&uri_length;
1262 args[argidx++] = (void *)&uri;
1266 p = stpcpy (p, "(comment %b)");
1267 assert (argidx+1 < DIM (args));
1268 args[argidx++] = (void *)&comment_length;
1269 args[argidx++] = (void*)&comment;
1273 assert (argidx < DIM (args));
1274 args[argidx] = NULL;
1276 err = gcry_sexp_build_array (&list, NULL, format, args);
1278 for (i=0; array[i]; i++)
1279 gcry_mpi_release (array[i]);
1280 gcry_sexp_release (curve);
1281 gcry_sexp_release (flags);
1282 gcry_sexp_release (uri_sexp);
1283 gcry_sexp_release (comment_sexp);
1292 /* Check whether the the secret key identified by GRIP is available.
1293 Returns 0 is the key is available. */
1295 agent_key_available (const unsigned char *grip)
1299 char hexgrip[40+4+1];
1301 bin2hex (grip, 20, hexgrip);
1302 strcpy (hexgrip+40, ".key");
1304 fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
1306 result = !access (fname, R_OK)? 0 : -1;
1313 /* Return the information about the secret key specified by the binary
1314 keygrip GRIP. If the key is a shadowed one the shadow information
1315 will be stored at the address R_SHADOW_INFO as an allocated
1318 agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
1319 int *r_keytype, unsigned char **r_shadow_info)
1329 *r_keytype = PRIVATE_KEY_UNKNOWN;
1331 *r_shadow_info = NULL;
1336 err = read_key_file (grip, &sexp);
1339 if (gpg_err_code (err) == GPG_ERR_ENOENT)
1340 return gpg_error (GPG_ERR_NOT_FOUND);
1344 err = make_canon_sexp (sexp, &buf, &len);
1345 gcry_sexp_release (sexp);
1350 keytype = agent_private_key_type (buf);
1353 case PRIVATE_KEY_CLEAR:
1354 case PRIVATE_KEY_OPENPGP_NONE:
1356 case PRIVATE_KEY_PROTECTED:
1357 /* If we ever require it we could retrieve the comment fields
1360 case PRIVATE_KEY_SHADOWED:
1363 const unsigned char *s;
1366 err = agent_get_shadow_info (buf, &s);
1369 n = gcry_sexp_canon_len (s, 0, NULL, NULL);
1371 *r_shadow_info = xtrymalloc (n);
1372 if (!*r_shadow_info)
1373 err = gpg_error_from_syserror ();
1375 memcpy (*r_shadow_info, s, n);
1380 err = gpg_error (GPG_ERR_BAD_SECKEY);
1384 if (!err && r_keytype)
1385 *r_keytype = keytype;
1393 /* Delete the key with GRIP from the disk after having asked for
1394 confirmation using DESC_TEXT. If FORCE is set the function won't
1395 require a confirmation via Pinentry or warns if the key is also
1398 Common error codes are:
1401 GPG_ERR_NOT_CONFIRMED
1404 agent_delete_key (ctrl_t ctrl, const char *desc_text,
1405 const unsigned char *grip, int force)
1408 gcry_sexp_t s_skey = NULL;
1409 unsigned char *buf = NULL;
1411 char *desc_text_final = NULL;
1412 char *comment = NULL;
1413 ssh_control_file_t cf = NULL;
1414 char hexgrip[40+4+1];
1415 char *default_desc = NULL;
1417 err = read_key_file (grip, &s_skey);
1418 if (gpg_err_code (err) == GPG_ERR_ENOENT)
1419 err = gpg_error (GPG_ERR_NO_SECKEY);
1423 err = make_canon_sexp (s_skey, &buf, &len);
1427 switch (agent_private_key_type (buf))
1429 case PRIVATE_KEY_CLEAR:
1430 case PRIVATE_KEY_OPENPGP_NONE:
1431 case PRIVATE_KEY_PROTECTED:
1432 bin2hex (grip, 20, hexgrip);
1437 default_desc = xtryasprintf
1438 (L_("Do you really want to delete the key identified by keygrip%%0A"
1439 " %s%%0A %%C%%0A?"), hexgrip);
1440 desc_text = default_desc;
1443 /* Note, that we will take the comment as a C string for
1444 display purposes; i.e. all stuff beyond a Nul character is
1447 gcry_sexp_t comment_sexp;
1449 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
1451 comment = gcry_sexp_nth_string (comment_sexp, 1);
1452 gcry_sexp_release (comment_sexp);
1456 err = modify_description (desc_text, comment? comment:"", s_skey,
1461 err = agent_get_confirmation (ctrl, desc_text_final,
1462 L_("Delete key"), L_("No"), 0);
1466 cf = ssh_open_control_file ();
1469 if (!ssh_search_control_file (cf, hexgrip, NULL, NULL, NULL))
1471 err = agent_get_confirmation
1473 L_("Warning: This key is also listed for use with SSH!\n"
1474 "Deleting the key might remove your ability to "
1475 "access remote machines."),
1476 L_("Delete key"), L_("No"), 0);
1482 err = remove_key_file (grip);
1485 case PRIVATE_KEY_SHADOWED:
1486 err = remove_key_file (grip);
1490 log_error ("invalid private key format\n");
1491 err = gpg_error (GPG_ERR_BAD_SECKEY);
1496 ssh_close_control_file (cf);
1497 gcry_free (comment);
1498 xfree (desc_text_final);
1499 xfree (default_desc);
1501 gcry_sexp_release (s_skey);
1506 /* Write an S-expression formatted shadow key to our key storage.
1507 Shadow key is created by an S-expression public key in PKBUF and
1508 card's SERIALNO and the IDSTRING. With FORCE passed as true an
1509 existing key with the given GRIP will get overwritten. */
1511 agent_write_shadow_key (const unsigned char *grip,
1512 const char *serialno, const char *keyid,
1513 const unsigned char *pkbuf, int force)
1516 unsigned char *shadow_info;
1517 unsigned char *shdkey;
1520 shadow_info = make_shadow_info (serialno, keyid);
1522 return gpg_error_from_syserror ();
1524 err = agent_shadow_key (pkbuf, shadow_info, &shdkey);
1525 xfree (shadow_info);
1528 log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
1532 len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
1533 err = agent_write_private_key (grip, shdkey, len, force);
1536 log_error ("error writing key: %s\n", gpg_strerror (err));