2005-04-11 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / agent / findkey.c
blob0b5816bf5e7a6a7e0fa2e3acb1bd751f4f7247ce
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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>
33 #include "agent.h"
35 /* Helper to pass data to the check callback of the unprotect function. */
36 struct try_unprotect_arg_s {
37 const unsigned char *protected_key;
38 unsigned char *unprotected_key;
42 /* Write an S-expression formatted key to our key storage. With FORCE
43 pased as true an existsing key with the given GRIP will get
44 overwritten. */
45 int
46 agent_write_private_key (const unsigned char *grip,
47 const void *buffer, size_t length, int force)
49 int i;
50 char *fname;
51 FILE *fp;
52 char hexgrip[40+4+1];
53 int fd;
55 for (i=0; i < 20; i++)
56 sprintf (hexgrip+2*i, "%02X", grip[i]);
57 strcpy (hexgrip+40, ".key");
59 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
61 if (!force && !access (fname, F_OK))
63 log_error ("secret key file `%s' already exists\n", fname);
64 xfree (fname);
65 return gpg_error (GPG_ERR_GENERAL);
68 /* In FORCE mode we would like to create FNAME but only if it does
69 not already exist. We cannot make this guarantee just using
70 POSIX (GNU provides the "x" opentype for fopen, however, this is
71 not portable). Thus, we use the more flexible open function and
72 then use fdopen to obtain a stream. */
73 fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY)
74 : (O_CREAT | O_EXCL | O_WRONLY),
75 S_IRUSR | S_IWUSR
76 #ifndef HAVE_W32_SYSTEM
77 | S_IRGRP
78 #endif
80 if (fd < 0)
81 fp = NULL;
82 else
84 fp = fdopen (fd, "wb");
85 if (!fp)
87 int save_e = errno;
88 close (fd);
89 errno = save_e;
93 if (!fp)
95 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
96 log_error ("can't create `%s': %s\n", fname, strerror (errno));
97 xfree (fname);
98 return tmperr;
101 if (fwrite (buffer, length, 1, fp) != 1)
103 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
104 log_error ("error writing `%s': %s\n", fname, strerror (errno));
105 fclose (fp);
106 remove (fname);
107 xfree (fname);
108 return tmperr;
110 if ( fclose (fp) )
112 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
113 log_error ("error closing `%s': %s\n", fname, strerror (errno));
114 remove (fname);
115 xfree (fname);
116 return tmperr;
119 xfree (fname);
120 return 0;
124 /* Callback function to try the unprotection from the passpharse query
125 code. */
126 static int
127 try_unprotect_cb (struct pin_entry_info_s *pi)
129 struct try_unprotect_arg_s *arg = pi->check_cb_arg;
130 size_t dummy;
132 assert (!arg->unprotected_key);
133 return agent_unprotect (arg->protected_key, pi->pin,
134 &arg->unprotected_key, &dummy);
138 /* Modify a Key description, replacing certain special format
139 characters. List of currently supported replacements:
141 %% - Replaced by a single %
142 %c - Replaced by the content of COMMENT.
144 The functions returns 0 on success or an error code. On success a
145 newly allocated string is stored at the address of RESULT.
147 static gpg_error_t
148 modify_description (const char *in, const char *comment, char **result)
150 size_t comment_length;
151 size_t in_len;
152 size_t out_len;
153 char *out;
154 size_t i;
155 int special, pass;
157 comment_length = strlen (comment);
158 in_len = strlen (in);
160 /* First pass calculates the length, second pass does the actual
161 copying. */
162 out = NULL;
163 out_len = 0;
164 for (pass=0; pass < 2; pass++)
166 special = 0;
167 for (i = 0; i < in_len; i++)
169 if (special)
171 special = 0;
172 switch (in[i])
174 case '%':
175 if (out)
176 *out++ = '%';
177 else
178 out_len++;
179 break;
181 case 'c': /* Comment. */
182 if (out)
184 memcpy (out, comment, comment_length);
185 out += comment_length;
187 else
188 out_len += comment_length;
189 break;
191 default: /* Invalid special sequences are kept as they are. */
192 if (out)
194 *out++ = '%';
195 *out++ = in[i];
197 else
198 out_len+=2;
199 break;
202 else if (in[i] == '%')
203 special = 1;
204 else
206 if (out)
207 *out++ = in[i];
208 else
209 out_len++;
213 if (!pass)
215 *result = out = xtrymalloc (out_len + 1);
216 if (!out)
217 return gpg_error_from_errno (errno);
221 *out = 0;
222 assert (*result + out_len == out);
223 return 0;
228 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
229 should be the hex encoded keygrip of that key to be used with the
230 caching mechanism. DESC_TEXT may be set to override the default
231 description used for the pinentry. */
232 static int
233 unprotect (CTRL ctrl, const char *desc_text,
234 unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
236 struct pin_entry_info_s *pi;
237 struct try_unprotect_arg_s arg;
238 int rc, i;
239 unsigned char *result;
240 size_t resultlen;
241 char hexgrip[40+1];
243 for (i=0; i < 20; i++)
244 sprintf (hexgrip+2*i, "%02X", grip[i]);
245 hexgrip[40] = 0;
247 /* First try to get it from the cache - if there is none or we can't
248 unprotect it, we fall back to ask the user */
249 if (!ignore_cache)
251 void *cache_marker;
252 const char *pw = agent_get_cache (hexgrip, &cache_marker);
253 if (pw)
255 rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
256 agent_unlock_cache_entry (&cache_marker);
257 if (!rc)
259 xfree (*keybuf);
260 *keybuf = result;
261 return 0;
263 rc = 0;
267 pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
268 if (!pi)
269 return gpg_error_from_errno (errno);
270 pi->max_length = 100;
271 pi->min_digits = 0; /* we want a real passphrase */
272 pi->max_digits = 8;
273 pi->max_tries = 3;
274 pi->check_cb = try_unprotect_cb;
275 arg.protected_key = *keybuf;
276 arg.unprotected_key = NULL;
277 pi->check_cb_arg = &arg;
279 rc = agent_askpin (ctrl, desc_text, NULL, pi);
280 if (!rc)
282 assert (arg.unprotected_key);
283 agent_put_cache (hexgrip, pi->pin, 0);
284 xfree (*keybuf);
285 *keybuf = arg.unprotected_key;
287 xfree (pi);
288 return rc;
292 /* Read the key identified by GRIP from the private key directory and
293 return it as an gcrypt S-expression object in RESULT. On failure
294 returns an error code and stores NULL at RESULT. */
295 static gpg_error_t
296 read_key_file (const unsigned char *grip, gcry_sexp_t *result)
298 int i, rc;
299 char *fname;
300 FILE *fp;
301 struct stat st;
302 unsigned char *buf;
303 size_t buflen, erroff;
304 gcry_sexp_t s_skey;
305 char hexgrip[40+4+1];
307 *result = NULL;
309 for (i=0; i < 20; i++)
310 sprintf (hexgrip+2*i, "%02X", grip[i]);
311 strcpy (hexgrip+40, ".key");
313 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
314 fp = fopen (fname, "rb");
315 if (!fp)
317 rc = gpg_error_from_errno (errno);
318 log_error ("can't open `%s': %s\n", fname, strerror (errno));
319 xfree (fname);
320 return rc;
323 if (fstat (fileno(fp), &st))
325 rc = gpg_error_from_errno (errno);
326 log_error ("can't stat `%s': %s\n", fname, strerror (errno));
327 xfree (fname);
328 fclose (fp);
329 return rc;
332 buflen = st.st_size;
333 buf = xtrymalloc (buflen+1);
334 if (!buf || fread (buf, buflen, 1, fp) != 1)
336 rc = gpg_error_from_errno (errno);
337 log_error ("error reading `%s': %s\n", fname, strerror (errno));
338 xfree (fname);
339 fclose (fp);
340 xfree (buf);
341 return rc;
344 /* Convert the file into a gcrypt S-expression object. */
345 rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
346 xfree (fname);
347 fclose (fp);
348 xfree (buf);
349 if (rc)
351 log_error ("failed to build S-Exp (off=%u): %s\n",
352 (unsigned int)erroff, gpg_strerror (rc));
353 return rc;
355 *result = s_skey;
356 return 0;
360 /* Return the secret key as an S-Exp in RESULT after locating it using
361 the grip. Returns NULL in RESULT if the operation should be
362 diverted to a token; SHADOW_INFO will point then to an allocated
363 S-Expression with the shadow_info part from the file. With
364 IGNORE_CACHE passed as true the passphrase is not taken from the
365 cache. DESC_TEXT may be set to present a custom description for the
366 pinentry. */
367 gpg_error_t
368 agent_key_from_file (ctrl_t ctrl, const char *desc_text,
369 const unsigned char *grip, unsigned char **shadow_info,
370 int ignore_cache, gcry_sexp_t *result)
372 int rc;
373 unsigned char *buf;
374 size_t len, buflen, erroff;
375 gcry_sexp_t s_skey;
376 int got_shadow_info = 0;
378 *result = NULL;
379 if (shadow_info)
380 *shadow_info = NULL;
382 rc = read_key_file (grip, &s_skey);
383 if (rc)
384 return rc;
386 /* For use with the protection functions we also need the key as an
387 canonical encoded S-expression in abuffer. Create this buffer
388 now. */
389 len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
390 assert (len);
391 buf = xtrymalloc (len);
392 if (!buf)
394 rc = gpg_error_from_errno (errno);
395 gcry_sexp_release (s_skey);
396 return rc;
398 len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
399 assert (len);
402 switch (agent_private_key_type (buf))
404 case PRIVATE_KEY_CLEAR:
405 break; /* no unprotection needed */
406 case PRIVATE_KEY_PROTECTED:
408 gcry_sexp_t comment_sexp;
409 size_t comment_length;
410 char *desc_text_final;
411 const char *comment = NULL;
413 /* Note, that we will take the comment as a C string for
414 display purposes; i.e. all stuff beyond a Nul character is
415 ignored. */
416 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
417 if (comment_sexp)
418 comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
419 if (!comment)
421 comment = "";
422 comment_length = 0;
425 desc_text_final = NULL;
426 if (desc_text)
428 if (comment[comment_length])
430 /* Not a C-string; create one. We might here allocate
431 more than actually displayed but well, that
432 shouldn't be a problem. */
433 char *tmp = xtrymalloc (comment_length+1);
434 if (!tmp)
435 rc = gpg_error_from_errno (errno);
436 else
438 memcpy (tmp, comment, comment_length);
439 tmp[comment_length] = 0;
440 rc = modify_description (desc_text, tmp, &desc_text_final);
441 xfree (tmp);
444 else
445 rc = modify_description (desc_text, comment, &desc_text_final);
448 if (!rc)
450 rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache);
451 if (rc)
452 log_error ("failed to unprotect the secret key: %s\n",
453 gpg_strerror (rc));
456 gcry_sexp_release (comment_sexp);
457 xfree (desc_text_final);
459 break;
460 case PRIVATE_KEY_SHADOWED:
461 if (shadow_info)
463 const unsigned char *s;
464 size_t n;
466 rc = agent_get_shadow_info (buf, &s);
467 if (!rc)
469 n = gcry_sexp_canon_len (s, 0, NULL,NULL);
470 assert (n);
471 *shadow_info = xtrymalloc (n);
472 if (!*shadow_info)
473 rc = out_of_core ();
474 else
476 memcpy (*shadow_info, s, n);
477 rc = 0;
478 got_shadow_info = 1;
481 if (rc)
482 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
484 else
485 rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
486 break;
487 default:
488 log_error ("invalid private key format\n");
489 rc = gpg_error (GPG_ERR_BAD_SECKEY);
490 break;
492 gcry_sexp_release (s_skey);
493 s_skey = NULL;
494 if (rc || got_shadow_info)
496 xfree (buf);
497 return rc;
500 buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
501 rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
502 wipememory (buf, buflen);
503 xfree (buf);
504 if (rc)
506 log_error ("failed to build S-Exp (off=%u): %s\n",
507 (unsigned int)erroff, gpg_strerror (rc));
508 return rc;
511 *result = s_skey;
512 return 0;
517 /* Return the public key for the keygrip GRIP. The result is stored
518 at RESULT. This function extracts the public key from the private
519 key database. On failure an error code is returned and NULL stored
520 at RESULT. */
521 gpg_error_t
522 agent_public_key_from_file (ctrl_t ctrl,
523 const unsigned char *grip,
524 gcry_sexp_t *result)
526 int i, idx, rc;
527 gcry_sexp_t s_skey;
528 const char *algoname;
529 gcry_sexp_t uri_sexp, comment_sexp;
530 const char *uri, *comment;
531 size_t uri_length, comment_length;
532 char *format, *p;
533 void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
534 for comment + end-of-list. */
535 int argidx;
536 gcry_sexp_t list, l2;
537 const char *name;
538 const char *s;
539 size_t n;
540 const char *elems;
541 gcry_mpi_t *array;
543 *result = NULL;
545 rc = read_key_file (grip, &s_skey);
546 if (rc)
547 return rc;
549 list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
550 if (!list)
551 list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
552 if (!list)
553 list = gcry_sexp_find_token (s_skey, "private-key", 0 );
554 if (!list)
556 log_error ("invalid private key format\n");
557 gcry_sexp_release (s_skey);
558 return gpg_error (GPG_ERR_BAD_SECKEY);
561 l2 = gcry_sexp_cadr (list);
562 gcry_sexp_release (list);
563 list = l2;
564 name = gcry_sexp_nth_data (list, 0, &n);
565 if (n==3 && !memcmp (name, "rsa", 3))
567 algoname = "rsa";
568 elems = "ne";
570 else if (n==3 && !memcmp (name, "dsa", 3))
572 algoname = "dsa";
573 elems = "pqgy";
575 else if (n==3 && !memcmp (name, "elg", 3))
577 algoname = "elg";
578 elems = "pgy";
580 else
582 log_error ("unknown private key algorithm\n");
583 gcry_sexp_release (list);
584 gcry_sexp_release (s_skey);
585 return gpg_error (GPG_ERR_BAD_SECKEY);
588 /* Allocate an array for the parameters and copy them out of the
589 secret key. FIXME: We should have a generic copy function. */
590 array = xtrycalloc (strlen(elems) + 1, sizeof *array);
591 if (!array)
593 rc = gpg_error_from_errno (errno);
594 gcry_sexp_release (list);
595 gcry_sexp_release (s_skey);
596 return rc;
599 for (idx=0, s=elems; *s; s++, idx++ )
601 l2 = gcry_sexp_find_token (list, s, 1);
602 if (!l2)
604 /* Required parameter not found. */
605 for (i=0; i<idx; i++)
606 gcry_mpi_release (array[i]);
607 xfree (array);
608 gcry_sexp_release (list);
609 gcry_sexp_release (s_skey);
610 return gpg_error (GPG_ERR_BAD_SECKEY);
612 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
613 gcry_sexp_release (l2);
614 if (!array[idx])
616 /* Required parameter is invalid. */
617 for (i=0; i<idx; i++)
618 gcry_mpi_release (array[i]);
619 xfree (array);
620 gcry_sexp_release (list);
621 gcry_sexp_release (s_skey);
622 return gpg_error (GPG_ERR_BAD_SECKEY);
625 gcry_sexp_release (list);
626 list = NULL;
628 uri = NULL;
629 uri_length = 0;
630 uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
631 if (uri_sexp)
632 uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
634 comment = NULL;
635 comment_length = 0;
636 comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
637 if (comment_sexp)
638 comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
640 gcry_sexp_release (s_skey);
641 s_skey = NULL;
644 /* FIXME: The following thing is pretty ugly code; we should
645 investigate how to make it cleaner. Probably code to handle
646 canonical S-expressions in a memory buffer is better suioted for
647 such a task. After all that is what we do in protect.c. Neeed
648 to find common patterns and write a straightformward API to use
649 them. */
650 assert (sizeof (size_t) <= sizeof (void*));
652 format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
653 if (!format)
655 rc = gpg_error_from_errno (errno);
656 for (i=0; array[i]; i++)
657 gcry_mpi_release (array[i]);
658 xfree (array);
659 gcry_sexp_release (uri_sexp);
660 gcry_sexp_release (comment_sexp);
661 return rc;
664 argidx = 0;
665 p = stpcpy (stpcpy (format, "(public-key("), algoname);
666 for (idx=0, s=elems; *s; s++, idx++ )
668 *p++ = '(';
669 *p++ = *s;
670 p = stpcpy (p, " %m)");
671 assert (argidx < DIM (args));
672 args[argidx++] = array[idx];
674 *p++ = ')';
675 if (uri)
677 p = stpcpy (p, "(uri %b)");
678 assert (argidx+1 < DIM (args));
679 args[argidx++] = (void *)uri_length;
680 args[argidx++] = (void *)uri;
682 if (comment)
684 p = stpcpy (p, "(comment %b)");
685 assert (argidx+1 < DIM (args));
686 args[argidx++] = (void *)comment_length;
687 args[argidx++] = (void*)comment;
689 *p++ = ')';
690 *p = 0;
691 assert (argidx < DIM (args));
692 args[argidx] = NULL;
694 rc = gcry_sexp_build_array (&list, NULL, format, args);
695 xfree (format);
696 for (i=0; array[i]; i++)
697 gcry_mpi_release (array[i]);
698 xfree (array);
699 gcry_sexp_release (uri_sexp);
700 gcry_sexp_release (comment_sexp);
702 if (!rc)
703 *result = list;
704 return rc;
709 /* Return the secret key as an S-Exp after locating it using the grip.
710 Returns NULL if key is not available. 0 = key is available */
712 agent_key_available (const unsigned char *grip)
714 int i;
715 char *fname;
716 char hexgrip[40+4+1];
718 for (i=0; i < 20; i++)
719 sprintf (hexgrip+2*i, "%02X", grip[i]);
720 strcpy (hexgrip+40, ".key");
722 fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
723 i = !access (fname, R_OK)? 0 : -1;
724 xfree (fname);
725 return i;