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/>.
32 #include <pth.h> /* (we use pth_sleep) */
41 /* Helper to pass data to the check callback of the unprotect function. */
42 struct try_unprotect_arg_s
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
56 agent_write_private_key (const unsigned char *grip
,
57 const void *buffer
, size_t length
, int force
)
65 for (i
=0; i
< 20; i
++)
66 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
67 strcpy (hexgrip
+40, ".key");
69 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
71 if (!force
&& !access (fname
, F_OK
))
73 log_error ("secret key file `%s' already exists\n", fname
);
75 return gpg_error (GPG_ERR_GENERAL
);
78 /* In FORCE mode we would like to create FNAME but only if it does
79 not already exist. We cannot make this guarantee just using
80 POSIX (GNU provides the "x" opentype for fopen, however, this is
81 not portable). Thus, we use the more flexible open function and
82 then use fdopen to obtain a stream. */
83 fd
= open (fname
, force
? (O_CREAT
| O_TRUNC
| O_WRONLY
| O_BINARY
)
84 : (O_CREAT
| O_EXCL
| O_WRONLY
| O_BINARY
),
86 #ifndef HAVE_W32_SYSTEM
94 fp
= fdopen (fd
, "wb");
105 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
106 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
111 if (fwrite (buffer
, length
, 1, fp
) != 1)
113 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
114 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
122 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
123 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
128 bump_key_eventcounter ();
134 /* Callback function to try the unprotection from the passpharse query
137 try_unprotect_cb (struct pin_entry_info_s
*pi
)
139 struct try_unprotect_arg_s
*arg
= pi
->check_cb_arg
;
142 gnupg_isotime_t now
, protected_at
, tmptime
;
145 assert (!arg
->unprotected_key
);
147 arg
->change_required
= 0;
148 err
= agent_unprotect (arg
->protected_key
, pi
->pin
, protected_at
,
149 &arg
->unprotected_key
, &dummy
);
152 if (!opt
.max_passphrase_days
|| arg
->ctrl
->in_passwd
)
153 return 0; /* No regular passphrase change required. */
157 /* No protection date known - must force passphrase change. */
158 desc
= xtrystrdup (_("Note: This passphrase has never been changed.%0A"
159 "Please change it now."));
161 return gpg_error_from_syserror ();
165 gnupg_get_isotime (now
);
166 gnupg_copy_time (tmptime
, protected_at
);
167 err
= add_days_to_isotime (tmptime
, opt
.max_passphrase_days
);
170 if (strcmp (now
, tmptime
) > 0 )
172 /* Passphrase "expired". */
174 (_("This passphrase has not been changed%%0A"
175 "since %.4s-%.2s-%.2s. Please change it now."),
176 protected_at
, protected_at
+4, protected_at
+6);
178 return gpg_error_from_syserror ();
184 /* Change required. */
185 if (opt
.enforce_passphrase_constraints
)
187 err
= agent_get_confirmation (arg
->ctrl
, desc
,
188 _("Change passphrase"), NULL
);
190 arg
->change_required
= 1;
194 err
= agent_get_confirmation (arg
->ctrl
, desc
,
195 _("Change passphrase"),
196 _("I'll change it later"));
198 arg
->change_required
= 1;
199 else if (gpg_err_code (err
) == GPG_ERR_CANCELED
)
209 /* Modify a Key description, replacing certain special format
210 characters. List of currently supported replacements:
212 %% - Replaced by a single %
213 %c - Replaced by the content of COMMENT.
215 The functions returns 0 on success or an error code. On success a
216 newly allocated string is stored at the address of RESULT.
219 modify_description (const char *in
, const char *comment
, char **result
)
221 size_t comment_length
;
228 comment_length
= strlen (comment
);
229 in_len
= strlen (in
);
231 /* First pass calculates the length, second pass does the actual
235 for (pass
=0; pass
< 2; pass
++)
238 for (i
= 0; i
< in_len
; i
++)
252 case 'c': /* Comment. */
255 memcpy (out
, comment
, comment_length
);
256 out
+= comment_length
;
259 out_len
+= comment_length
;
262 default: /* Invalid special sequences are kept as they are. */
273 else if (in
[i
] == '%')
286 *result
= out
= xtrymalloc (out_len
+ 1);
288 return gpg_error_from_syserror ();
293 assert (*result
+ out_len
== out
);
299 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
300 should be the hex encoded keygrip of that key to be used with the
301 caching mechanism. DESC_TEXT may be set to override the default
302 description used for the pinentry. */
304 unprotect (ctrl_t ctrl
, const char *desc_text
,
305 unsigned char **keybuf
, const unsigned char *grip
,
306 cache_mode_t cache_mode
)
308 struct pin_entry_info_s
*pi
;
309 struct try_unprotect_arg_s arg
;
311 unsigned char *result
;
315 for (i
=0; i
< 20; i
++)
316 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
319 /* First try to get it from the cache - if there is none or we can't
320 unprotect it, we fall back to ask the user */
321 if (cache_mode
!= CACHE_MODE_IGNORE
)
327 pw
= agent_get_cache (hexgrip
, cache_mode
, &cache_marker
);
330 rc
= agent_unprotect (*keybuf
, pw
, NULL
, &result
, &resultlen
);
331 agent_unlock_cache_entry (&cache_marker
);
341 /* If the pinentry is currently in use, we wait up to 60 seconds
342 for it to close and check the cache again. This solves a common
343 situation where several requests for unprotecting a key have
344 been made but the user is still entering the passphrase for
345 the first request. Because all requests to agent_askpin are
346 serialized they would then pop up one after the other to
347 request the passphrase - despite that the user has already
348 entered it and is then available in the cache. This
349 implementation is not race free but in the worst case the
350 user has to enter the passphrase only once more. */
351 if (pinentry_active_p (ctrl
, 0))
354 if (!pinentry_active_p (ctrl
, 60))
356 /* We need to give the other thread a chance to actually put
357 it into the cache. */
361 /* Timeout - better call pinentry now the plain way. */
365 pi
= gcry_calloc_secure (1, sizeof (*pi
) + 100);
367 return gpg_error_from_syserror ();
368 pi
->max_length
= 100;
369 pi
->min_digits
= 0; /* we want a real passphrase */
372 pi
->check_cb
= try_unprotect_cb
;
374 arg
.protected_key
= *keybuf
;
375 arg
.unprotected_key
= NULL
;
376 arg
.change_required
= 0;
377 pi
->check_cb_arg
= &arg
;
379 rc
= agent_askpin (ctrl
, desc_text
, NULL
, NULL
, pi
);
382 assert (arg
.unprotected_key
);
383 if (arg
.change_required
)
385 size_t canlen
, erroff
;
388 assert (arg
.unprotected_key
);
389 canlen
= gcry_sexp_canon_len (arg
.unprotected_key
, 0, NULL
, NULL
);
390 rc
= gcry_sexp_sscan (&s_skey
, &erroff
,
391 (char*)arg
.unprotected_key
, canlen
);
394 log_error ("failed to build S-Exp (off=%u): %s\n",
395 (unsigned int)erroff
, gpg_strerror (rc
));
396 wipememory (arg
.unprotected_key
, canlen
);
397 xfree (arg
.unprotected_key
);
401 rc
= agent_protect_and_store (ctrl
, s_skey
);
402 gcry_sexp_release (s_skey
);
405 log_error ("changing the passphrase failed: %s\n",
407 wipememory (arg
.unprotected_key
, canlen
);
408 xfree (arg
.unprotected_key
);
413 agent_put_cache (hexgrip
, cache_mode
, pi
->pin
, 0);
415 *keybuf
= arg
.unprotected_key
;
422 /* Read the key identified by GRIP from the private key directory and
423 return it as an gcrypt S-expression object in RESULT. On failure
424 returns an error code and stores NULL at RESULT. */
426 read_key_file (const unsigned char *grip
, gcry_sexp_t
*result
)
433 size_t buflen
, erroff
;
435 char hexgrip
[40+4+1];
439 for (i
=0; i
< 20; i
++)
440 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
441 strcpy (hexgrip
+40, ".key");
443 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
444 fp
= fopen (fname
, "rb");
447 rc
= gpg_error_from_syserror ();
448 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
453 if (fstat (fileno(fp
), &st
))
455 rc
= gpg_error_from_syserror ();
456 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
463 buf
= xtrymalloc (buflen
+1);
464 if (!buf
|| fread (buf
, buflen
, 1, fp
) != 1)
466 rc
= gpg_error_from_syserror ();
467 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
474 /* Convert the file into a gcrypt S-expression object. */
475 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, (char*)buf
, buflen
);
481 log_error ("failed to build S-Exp (off=%u): %s\n",
482 (unsigned int)erroff
, gpg_strerror (rc
));
490 /* Return the secret key as an S-Exp in RESULT after locating it using
491 the grip. Returns NULL in RESULT if the operation should be
492 diverted to a token; SHADOW_INFO will point then to an allocated
493 S-Expression with the shadow_info part from the file. CACHE_MODE
494 defines now the cache shall be used. DESC_TEXT may be set to
495 present a custom description for the pinentry. */
497 agent_key_from_file (ctrl_t ctrl
, const char *desc_text
,
498 const unsigned char *grip
, unsigned char **shadow_info
,
499 cache_mode_t cache_mode
, gcry_sexp_t
*result
)
503 size_t len
, buflen
, erroff
;
505 int got_shadow_info
= 0;
511 rc
= read_key_file (grip
, &s_skey
);
515 /* For use with the protection functions we also need the key as an
516 canonical encoded S-expression in abuffer. Create this buffer
518 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, NULL
, 0);
520 buf
= xtrymalloc (len
);
523 rc
= gpg_error_from_syserror ();
524 gcry_sexp_release (s_skey
);
527 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, buf
, len
);
531 switch (agent_private_key_type (buf
))
533 case PRIVATE_KEY_CLEAR
:
534 break; /* no unprotection needed */
535 case PRIVATE_KEY_PROTECTED
:
537 gcry_sexp_t comment_sexp
;
538 size_t comment_length
;
539 char *desc_text_final
;
540 const char *comment
= NULL
;
542 /* Note, that we will take the comment as a C string for
543 display purposes; i.e. all stuff beyond a Nul character is
545 comment_sexp
= gcry_sexp_find_token (s_skey
, "comment", 0);
547 comment
= gcry_sexp_nth_data (comment_sexp
, 1, &comment_length
);
554 desc_text_final
= NULL
;
557 if (comment
[comment_length
])
559 /* Not a C-string; create one. We might here allocate
560 more than actually displayed but well, that
561 shouldn't be a problem. */
562 char *tmp
= xtrymalloc (comment_length
+1);
564 rc
= gpg_error_from_syserror ();
567 memcpy (tmp
, comment
, comment_length
);
568 tmp
[comment_length
] = 0;
569 rc
= modify_description (desc_text
, tmp
, &desc_text_final
);
574 rc
= modify_description (desc_text
, comment
, &desc_text_final
);
579 rc
= unprotect (ctrl
, desc_text_final
, &buf
, grip
, cache_mode
);
581 log_error ("failed to unprotect the secret key: %s\n",
585 gcry_sexp_release (comment_sexp
);
586 xfree (desc_text_final
);
589 case PRIVATE_KEY_SHADOWED
:
592 const unsigned char *s
;
595 rc
= agent_get_shadow_info (buf
, &s
);
598 n
= gcry_sexp_canon_len (s
, 0, NULL
,NULL
);
600 *shadow_info
= xtrymalloc (n
);
605 memcpy (*shadow_info
, s
, n
);
611 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc
));
614 rc
= gpg_error (GPG_ERR_UNUSABLE_SECKEY
);
617 log_error ("invalid private key format\n");
618 rc
= gpg_error (GPG_ERR_BAD_SECKEY
);
621 gcry_sexp_release (s_skey
);
623 if (rc
|| got_shadow_info
)
629 buflen
= gcry_sexp_canon_len (buf
, 0, NULL
, NULL
);
630 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, (char*)buf
, buflen
);
631 wipememory (buf
, buflen
);
635 log_error ("failed to build S-Exp (off=%u): %s\n",
636 (unsigned int)erroff
, gpg_strerror (rc
));
646 /* Return the public key for the keygrip GRIP. The result is stored
647 at RESULT. This function extracts the public key from the private
648 key database. On failure an error code is returned and NULL stored
651 agent_public_key_from_file (ctrl_t ctrl
,
652 const unsigned char *grip
,
657 const char *algoname
;
658 gcry_sexp_t uri_sexp
, comment_sexp
;
659 const char *uri
, *comment
;
660 size_t uri_length
, comment_length
;
662 void *args
[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
663 for comment + end-of-list. */
665 gcry_sexp_t list
, l2
;
676 rc
= read_key_file (grip
, &s_skey
);
680 list
= gcry_sexp_find_token (s_skey
, "shadowed-private-key", 0 );
682 list
= gcry_sexp_find_token (s_skey
, "protected-private-key", 0 );
684 list
= gcry_sexp_find_token (s_skey
, "private-key", 0 );
687 log_error ("invalid private key format\n");
688 gcry_sexp_release (s_skey
);
689 return gpg_error (GPG_ERR_BAD_SECKEY
);
692 l2
= gcry_sexp_cadr (list
);
693 gcry_sexp_release (list
);
695 name
= gcry_sexp_nth_data (list
, 0, &n
);
696 if (n
==3 && !memcmp (name
, "rsa", 3))
701 else if (n
==3 && !memcmp (name
, "dsa", 3))
706 else if (n
==3 && !memcmp (name
, "elg", 3))
713 log_error ("unknown private key algorithm\n");
714 gcry_sexp_release (list
);
715 gcry_sexp_release (s_skey
);
716 return gpg_error (GPG_ERR_BAD_SECKEY
);
719 /* Allocate an array for the parameters and copy them out of the
720 secret key. FIXME: We should have a generic copy function. */
721 array
= xtrycalloc (strlen(elems
) + 1, sizeof *array
);
724 rc
= gpg_error_from_syserror ();
725 gcry_sexp_release (list
);
726 gcry_sexp_release (s_skey
);
730 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
732 l2
= gcry_sexp_find_token (list
, s
, 1);
735 /* Required parameter not found. */
736 for (i
=0; i
<idx
; i
++)
737 gcry_mpi_release (array
[i
]);
739 gcry_sexp_release (list
);
740 gcry_sexp_release (s_skey
);
741 return gpg_error (GPG_ERR_BAD_SECKEY
);
743 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
744 gcry_sexp_release (l2
);
747 /* Required parameter is invalid. */
748 for (i
=0; i
<idx
; i
++)
749 gcry_mpi_release (array
[i
]);
751 gcry_sexp_release (list
);
752 gcry_sexp_release (s_skey
);
753 return gpg_error (GPG_ERR_BAD_SECKEY
);
756 gcry_sexp_release (list
);
761 uri_sexp
= gcry_sexp_find_token (s_skey
, "uri", 0);
763 uri
= gcry_sexp_nth_data (uri_sexp
, 1, &uri_length
);
767 comment_sexp
= gcry_sexp_find_token (s_skey
, "comment", 0);
769 comment
= gcry_sexp_nth_data (comment_sexp
, 1, &comment_length
);
771 gcry_sexp_release (s_skey
);
775 /* FIXME: The following thing is pretty ugly code; we should
776 investigate how to make it cleaner. Probably code to handle
777 canonical S-expressions in a memory buffer is better suioted for
778 such a task. After all that is what we do in protect.c. Neeed
779 to find common patterns and write a straightformward API to use
781 assert (sizeof (size_t) <= sizeof (void*));
783 format
= xtrymalloc (15+7*strlen (elems
)+10+15+1+1);
786 rc
= gpg_error_from_syserror ();
787 for (i
=0; array
[i
]; i
++)
788 gcry_mpi_release (array
[i
]);
790 gcry_sexp_release (uri_sexp
);
791 gcry_sexp_release (comment_sexp
);
796 p
= stpcpy (stpcpy (format
, "(public-key("), algoname
);
797 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
801 p
= stpcpy (p
, " %m)");
802 assert (argidx
< DIM (args
));
803 args
[argidx
++] = &array
[idx
];
808 p
= stpcpy (p
, "(uri %b)");
809 assert (argidx
+1 < DIM (args
));
810 args
[argidx
++] = (void *)uri_length
;
811 args
[argidx
++] = (void *)uri
;
815 p
= stpcpy (p
, "(comment %b)");
816 assert (argidx
+1 < DIM (args
));
817 args
[argidx
++] = (void *)comment_length
;
818 args
[argidx
++] = (void*)comment
;
822 assert (argidx
< DIM (args
));
825 rc
= gcry_sexp_build_array (&list
, NULL
, format
, args
);
827 for (i
=0; array
[i
]; i
++)
828 gcry_mpi_release (array
[i
]);
830 gcry_sexp_release (uri_sexp
);
831 gcry_sexp_release (comment_sexp
);
840 /* Return the secret key as an S-Exp after locating it using the grip.
841 Returns NULL if key is not available. 0 = key is available */
843 agent_key_available (const unsigned char *grip
)
847 char hexgrip
[40+4+1];
849 for (i
=0; i
< 20; i
++)
850 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
851 strcpy (hexgrip
+40, ".key");
853 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
854 i
= !access (fname
, R_OK
)? 0 : -1;