1 /* findkey.c - locate the secret key
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
33 #include <pth.h> /* (we use pth_sleep) */
37 /* Helper to pass data to the check callback of the unprotect function. */
38 struct try_unprotect_arg_s
{
39 const unsigned char *protected_key
;
40 unsigned char *unprotected_key
;
44 /* Write an S-expression formatted key to our key storage. With FORCE
45 pased as true an existing key with the given GRIP will get
48 agent_write_private_key (const unsigned char *grip
,
49 const void *buffer
, size_t length
, int force
)
57 for (i
=0; i
< 20; i
++)
58 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
59 strcpy (hexgrip
+40, ".key");
61 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
63 if (!force
&& !access (fname
, F_OK
))
65 log_error ("secret key file `%s' already exists\n", fname
);
67 return gpg_error (GPG_ERR_GENERAL
);
70 /* In FORCE mode we would like to create FNAME but only if it does
71 not already exist. We cannot make this guarantee just using
72 POSIX (GNU provides the "x" opentype for fopen, however, this is
73 not portable). Thus, we use the more flexible open function and
74 then use fdopen to obtain a stream. */
75 fd
= open (fname
, force
? (O_CREAT
| O_TRUNC
| O_WRONLY
)
76 : (O_CREAT
| O_EXCL
| O_WRONLY
),
78 #ifndef HAVE_W32_SYSTEM
86 fp
= fdopen (fd
, "wb");
97 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
98 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
103 if (fwrite (buffer
, length
, 1, fp
) != 1)
105 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
106 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
114 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
115 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
120 bump_key_eventcounter ();
126 /* Callback function to try the unprotection from the passpharse query
129 try_unprotect_cb (struct pin_entry_info_s
*pi
)
131 struct try_unprotect_arg_s
*arg
= pi
->check_cb_arg
;
134 assert (!arg
->unprotected_key
);
135 return agent_unprotect (arg
->protected_key
, pi
->pin
,
136 &arg
->unprotected_key
, &dummy
);
140 /* Modify a Key description, replacing certain special format
141 characters. List of currently supported replacements:
143 %% - Replaced by a single %
144 %c - Replaced by the content of COMMENT.
146 The functions returns 0 on success or an error code. On success a
147 newly allocated string is stored at the address of RESULT.
150 modify_description (const char *in
, const char *comment
, char **result
)
152 size_t comment_length
;
159 comment_length
= strlen (comment
);
160 in_len
= strlen (in
);
162 /* First pass calculates the length, second pass does the actual
166 for (pass
=0; pass
< 2; pass
++)
169 for (i
= 0; i
< in_len
; i
++)
183 case 'c': /* Comment. */
186 memcpy (out
, comment
, comment_length
);
187 out
+= comment_length
;
190 out_len
+= comment_length
;
193 default: /* Invalid special sequences are kept as they are. */
204 else if (in
[i
] == '%')
217 *result
= out
= xtrymalloc (out_len
+ 1);
219 return gpg_error_from_syserror ();
224 assert (*result
+ out_len
== out
);
230 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
231 should be the hex encoded keygrip of that key to be used with the
232 caching mechanism. DESC_TEXT may be set to override the default
233 description used for the pinentry. */
235 unprotect (ctrl_t ctrl
, const char *desc_text
,
236 unsigned char **keybuf
, const unsigned char *grip
,
237 cache_mode_t cache_mode
)
239 struct pin_entry_info_s
*pi
;
240 struct try_unprotect_arg_s arg
;
242 unsigned char *result
;
246 for (i
=0; i
< 20; i
++)
247 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
250 /* First try to get it from the cache - if there is none or we can't
251 unprotect it, we fall back to ask the user */
252 if (cache_mode
!= CACHE_MODE_IGNORE
)
258 pw
= agent_get_cache (hexgrip
, cache_mode
, &cache_marker
);
261 rc
= agent_unprotect (*keybuf
, pw
, &result
, &resultlen
);
262 agent_unlock_cache_entry (&cache_marker
);
272 /* If the pinentry is currently in use, we wait up to 60 seconds
273 for it close and check the cache again. This solves a common
274 situation where several requests for unprotecting a key have
275 been made but the user is still entering the passphrase for
276 the first request. Because all requests to agent_askpin are
277 serialized they would then pop up one after the other to
278 request the passphrase - despite that the user has already
279 entered it and is then available in the cache. This
280 implementation is not race free but in the worst case the
281 user has to enter the passphrase only once more. */
282 if (pinentry_active_p (ctrl
, 0))
285 if (!pinentry_active_p (ctrl
, 60))
287 /* We need to give the other thread a chance to actually put
288 it into the cache. */
292 /* Timeout - better call pinentry now the plain way. */
296 pi
= gcry_calloc_secure (1, sizeof (*pi
) + 100);
298 return gpg_error_from_syserror ();
299 pi
->max_length
= 100;
300 pi
->min_digits
= 0; /* we want a real passphrase */
303 pi
->check_cb
= try_unprotect_cb
;
304 arg
.protected_key
= *keybuf
;
305 arg
.unprotected_key
= NULL
;
306 pi
->check_cb_arg
= &arg
;
308 rc
= agent_askpin (ctrl
, desc_text
, NULL
, NULL
, pi
);
311 assert (arg
.unprotected_key
);
312 agent_put_cache (hexgrip
, cache_mode
, pi
->pin
, 0);
314 *keybuf
= arg
.unprotected_key
;
321 /* Read the key identified by GRIP from the private key directory and
322 return it as an gcrypt S-expression object in RESULT. On failure
323 returns an error code and stores NULL at RESULT. */
325 read_key_file (const unsigned char *grip
, gcry_sexp_t
*result
)
332 size_t buflen
, erroff
;
334 char hexgrip
[40+4+1];
338 for (i
=0; i
< 20; i
++)
339 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
340 strcpy (hexgrip
+40, ".key");
342 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
343 fp
= fopen (fname
, "rb");
346 rc
= gpg_error_from_syserror ();
347 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
352 if (fstat (fileno(fp
), &st
))
354 rc
= gpg_error_from_syserror ();
355 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
362 buf
= xtrymalloc (buflen
+1);
363 if (!buf
|| fread (buf
, buflen
, 1, fp
) != 1)
365 rc
= gpg_error_from_syserror ();
366 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
373 /* Convert the file into a gcrypt S-expression object. */
374 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, (char*)buf
, buflen
);
380 log_error ("failed to build S-Exp (off=%u): %s\n",
381 (unsigned int)erroff
, gpg_strerror (rc
));
389 /* Return the secret key as an S-Exp in RESULT after locating it using
390 the grip. Returns NULL in RESULT if the operation should be
391 diverted to a token; SHADOW_INFO will point then to an allocated
392 S-Expression with the shadow_info part from the file. CACHE_MODE
393 defines now the cache shall be used. DESC_TEXT may be set to
394 present a custom description for the pinentry. */
396 agent_key_from_file (ctrl_t ctrl
, const char *desc_text
,
397 const unsigned char *grip
, unsigned char **shadow_info
,
398 cache_mode_t cache_mode
, gcry_sexp_t
*result
)
402 size_t len
, buflen
, erroff
;
404 int got_shadow_info
= 0;
410 rc
= read_key_file (grip
, &s_skey
);
414 /* For use with the protection functions we also need the key as an
415 canonical encoded S-expression in abuffer. Create this buffer
417 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, NULL
, 0);
419 buf
= xtrymalloc (len
);
422 rc
= gpg_error_from_syserror ();
423 gcry_sexp_release (s_skey
);
426 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, buf
, len
);
430 switch (agent_private_key_type (buf
))
432 case PRIVATE_KEY_CLEAR
:
433 break; /* no unprotection needed */
434 case PRIVATE_KEY_PROTECTED
:
436 gcry_sexp_t comment_sexp
;
437 size_t comment_length
;
438 char *desc_text_final
;
439 const char *comment
= NULL
;
441 /* Note, that we will take the comment as a C string for
442 display purposes; i.e. all stuff beyond a Nul character is
444 comment_sexp
= gcry_sexp_find_token (s_skey
, "comment", 0);
446 comment
= gcry_sexp_nth_data (comment_sexp
, 1, &comment_length
);
453 desc_text_final
= NULL
;
456 if (comment
[comment_length
])
458 /* Not a C-string; create one. We might here allocate
459 more than actually displayed but well, that
460 shouldn't be a problem. */
461 char *tmp
= xtrymalloc (comment_length
+1);
463 rc
= gpg_error_from_syserror ();
466 memcpy (tmp
, comment
, comment_length
);
467 tmp
[comment_length
] = 0;
468 rc
= modify_description (desc_text
, tmp
, &desc_text_final
);
473 rc
= modify_description (desc_text
, comment
, &desc_text_final
);
478 rc
= unprotect (ctrl
, desc_text_final
, &buf
, grip
, cache_mode
);
480 log_error ("failed to unprotect the secret key: %s\n",
484 gcry_sexp_release (comment_sexp
);
485 xfree (desc_text_final
);
488 case PRIVATE_KEY_SHADOWED
:
491 const unsigned char *s
;
494 rc
= agent_get_shadow_info (buf
, &s
);
497 n
= gcry_sexp_canon_len (s
, 0, NULL
,NULL
);
499 *shadow_info
= xtrymalloc (n
);
504 memcpy (*shadow_info
, s
, n
);
510 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc
));
513 rc
= gpg_error (GPG_ERR_UNUSABLE_SECKEY
);
516 log_error ("invalid private key format\n");
517 rc
= gpg_error (GPG_ERR_BAD_SECKEY
);
520 gcry_sexp_release (s_skey
);
522 if (rc
|| got_shadow_info
)
528 buflen
= gcry_sexp_canon_len (buf
, 0, NULL
, NULL
);
529 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, (char*)buf
, buflen
);
530 wipememory (buf
, buflen
);
534 log_error ("failed to build S-Exp (off=%u): %s\n",
535 (unsigned int)erroff
, gpg_strerror (rc
));
545 /* Return the public key for the keygrip GRIP. The result is stored
546 at RESULT. This function extracts the public key from the private
547 key database. On failure an error code is returned and NULL stored
550 agent_public_key_from_file (ctrl_t ctrl
,
551 const unsigned char *grip
,
556 const char *algoname
;
557 gcry_sexp_t uri_sexp
, comment_sexp
;
558 const char *uri
, *comment
;
559 size_t uri_length
, comment_length
;
561 void *args
[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
562 for comment + end-of-list. */
564 gcry_sexp_t list
, l2
;
573 rc
= read_key_file (grip
, &s_skey
);
577 list
= gcry_sexp_find_token (s_skey
, "shadowed-private-key", 0 );
579 list
= gcry_sexp_find_token (s_skey
, "protected-private-key", 0 );
581 list
= gcry_sexp_find_token (s_skey
, "private-key", 0 );
584 log_error ("invalid private key format\n");
585 gcry_sexp_release (s_skey
);
586 return gpg_error (GPG_ERR_BAD_SECKEY
);
589 l2
= gcry_sexp_cadr (list
);
590 gcry_sexp_release (list
);
592 name
= gcry_sexp_nth_data (list
, 0, &n
);
593 if (n
==3 && !memcmp (name
, "rsa", 3))
598 else if (n
==3 && !memcmp (name
, "dsa", 3))
603 else if (n
==3 && !memcmp (name
, "elg", 3))
610 log_error ("unknown private key algorithm\n");
611 gcry_sexp_release (list
);
612 gcry_sexp_release (s_skey
);
613 return gpg_error (GPG_ERR_BAD_SECKEY
);
616 /* Allocate an array for the parameters and copy them out of the
617 secret key. FIXME: We should have a generic copy function. */
618 array
= xtrycalloc (strlen(elems
) + 1, sizeof *array
);
621 rc
= gpg_error_from_syserror ();
622 gcry_sexp_release (list
);
623 gcry_sexp_release (s_skey
);
627 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
629 l2
= gcry_sexp_find_token (list
, s
, 1);
632 /* Required parameter not found. */
633 for (i
=0; i
<idx
; i
++)
634 gcry_mpi_release (array
[i
]);
636 gcry_sexp_release (list
);
637 gcry_sexp_release (s_skey
);
638 return gpg_error (GPG_ERR_BAD_SECKEY
);
640 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
641 gcry_sexp_release (l2
);
644 /* Required parameter is invalid. */
645 for (i
=0; i
<idx
; i
++)
646 gcry_mpi_release (array
[i
]);
648 gcry_sexp_release (list
);
649 gcry_sexp_release (s_skey
);
650 return gpg_error (GPG_ERR_BAD_SECKEY
);
653 gcry_sexp_release (list
);
658 uri_sexp
= gcry_sexp_find_token (s_skey
, "uri", 0);
660 uri
= gcry_sexp_nth_data (uri_sexp
, 1, &uri_length
);
664 comment_sexp
= gcry_sexp_find_token (s_skey
, "comment", 0);
666 comment
= gcry_sexp_nth_data (comment_sexp
, 1, &comment_length
);
668 gcry_sexp_release (s_skey
);
672 /* FIXME: The following thing is pretty ugly code; we should
673 investigate how to make it cleaner. Probably code to handle
674 canonical S-expressions in a memory buffer is better suioted for
675 such a task. After all that is what we do in protect.c. Neeed
676 to find common patterns and write a straightformward API to use
678 assert (sizeof (size_t) <= sizeof (void*));
680 format
= xtrymalloc (15+7*strlen (elems
)+10+15+1+1);
683 rc
= gpg_error_from_syserror ();
684 for (i
=0; array
[i
]; i
++)
685 gcry_mpi_release (array
[i
]);
687 gcry_sexp_release (uri_sexp
);
688 gcry_sexp_release (comment_sexp
);
693 p
= stpcpy (stpcpy (format
, "(public-key("), algoname
);
694 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
698 p
= stpcpy (p
, " %m)");
699 assert (argidx
< DIM (args
));
700 args
[argidx
++] = &array
[idx
];
705 p
= stpcpy (p
, "(uri %b)");
706 assert (argidx
+1 < DIM (args
));
707 args
[argidx
++] = (void *)uri_length
;
708 args
[argidx
++] = (void *)uri
;
712 p
= stpcpy (p
, "(comment %b)");
713 assert (argidx
+1 < DIM (args
));
714 args
[argidx
++] = (void *)comment_length
;
715 args
[argidx
++] = (void*)comment
;
719 assert (argidx
< DIM (args
));
722 rc
= gcry_sexp_build_array (&list
, NULL
, format
, args
);
724 for (i
=0; array
[i
]; i
++)
725 gcry_mpi_release (array
[i
]);
727 gcry_sexp_release (uri_sexp
);
728 gcry_sexp_release (comment_sexp
);
737 /* Return the secret key as an S-Exp after locating it using the grip.
738 Returns NULL if key is not available. 0 = key is available */
740 agent_key_available (const unsigned char *grip
)
744 char hexgrip
[40+4+1];
746 for (i
=0; i
< 20; i
++)
747 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
748 strcpy (hexgrip
+40, ".key");
750 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
751 i
= !access (fname
, R_OK
)? 0 : -1;