1 /* findkey.c - locate the secret key
2 * Copyright (C) 2001, 2002, 2003, 2004 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
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
;
44 agent_write_private_key (const unsigned char *grip
,
45 const void *buffer
, size_t length
, int force
)
52 for (i
=0; i
< 20; i
++)
53 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
54 strcpy (hexgrip
+40, ".key");
56 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
58 fp
= fopen (fname
, "wb");
63 if (!access (fname
, F_OK
))
65 log_error ("secret key file `%s' already exists\n", fname
);
67 return gpg_error (GPG_ERR_GENERAL
);
70 /* We would like to create FNAME but only if it does not already
71 exist. We cannot make this guarantee just using POSIX (GNU
72 provides the "x" opentype for fopen, however, this is not
73 portable). Thus, we use the more flexible open function and
74 then use fdopen to obtain a stream.
76 The mode parameter to open is what fopen uses. It will be
77 combined with the process' umask automatically. */
78 fd
= open (fname
, O_CREAT
| O_EXCL
| O_RDWR
,
79 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
84 fp
= fdopen (fd
, "wb");
96 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
97 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
102 if (fwrite (buffer
, length
, 1, fp
) != 1)
104 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
105 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
113 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
114 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
125 /* Callback function to try the unprotection from the passpharse query
128 try_unprotect_cb (struct pin_entry_info_s
*pi
)
130 struct try_unprotect_arg_s
*arg
= pi
->check_cb_arg
;
133 assert (!arg
->unprotected_key
);
134 return agent_unprotect (arg
->protected_key
, pi
->pin
,
135 &arg
->unprotected_key
, &dummy
);
139 /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
140 should be the hex encoded keygrip of that key to be used with the
141 caching mechanism. DESC_TEXT may be set to override the default
142 description used for the pinentry. */
144 unprotect (CTRL ctrl
, const char *desc_text
,
145 unsigned char **keybuf
, const unsigned char *grip
, int ignore_cache
)
147 struct pin_entry_info_s
*pi
;
148 struct try_unprotect_arg_s arg
;
150 unsigned char *result
;
154 for (i
=0; i
< 20; i
++)
155 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
158 /* First try to get it from the cache - if there is none or we can't
159 unprotect it, we fall back to ask the user */
163 const char *pw
= agent_get_cache (hexgrip
, &cache_marker
);
166 rc
= agent_unprotect (*keybuf
, pw
, &result
, &resultlen
);
167 agent_unlock_cache_entry (&cache_marker
);
178 pi
= gcry_calloc_secure (1, sizeof (*pi
) + 100);
179 pi
->max_length
= 100;
180 pi
->min_digits
= 0; /* we want a real passphrase */
183 pi
->check_cb
= try_unprotect_cb
;
184 arg
.protected_key
= *keybuf
;
185 arg
.unprotected_key
= NULL
;
186 pi
->check_cb_arg
= &arg
;
188 rc
= agent_askpin (ctrl
, desc_text
, NULL
, pi
);
191 assert (arg
.unprotected_key
);
192 agent_put_cache (hexgrip
, pi
->pin
, 0);
194 *keybuf
= arg
.unprotected_key
;
202 /* Return the secret key as an S-Exp in RESULT after locating it using
203 the grip. Returns NULL in RESULT if the operation should be
204 diverted to a token; SHADOW_INFO will point then to an allocated
205 S-Expression with the shadow_info part from the file. With
206 IGNORE_CACHE passed as true the passphrase is not taken from the
207 cache. DESC_TEXT may be set to present a custom description for the
210 agent_key_from_file (CTRL ctrl
, const char *desc_text
,
211 const unsigned char *grip
, unsigned char **shadow_info
,
212 int ignore_cache
, gcry_sexp_t
*result
)
219 size_t len
, buflen
, erroff
;
221 char hexgrip
[40+4+1];
222 int got_shadow_info
= 0;
228 for (i
=0; i
< 20; i
++)
229 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
230 strcpy (hexgrip
+40, ".key");
232 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
233 fp
= fopen (fname
, "rb");
236 rc
= gpg_error_from_errno (errno
);
237 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
242 if (fstat (fileno(fp
), &st
))
244 rc
= gpg_error_from_errno (errno
);
245 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
252 buf
= xmalloc (buflen
+1);
253 if (fread (buf
, buflen
, 1, fp
) != 1)
255 rc
= gpg_error_from_errno (errno
);
256 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
263 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, buf
, buflen
);
269 log_error ("failed to build S-Exp (off=%u): %s\n",
270 (unsigned int)erroff
, gpg_strerror (rc
));
273 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, NULL
, 0);
275 buf
= xtrymalloc (len
);
279 gcry_sexp_release (s_skey
);
282 len
= gcry_sexp_sprint (s_skey
, GCRYSEXP_FMT_CANON
, buf
, len
);
284 gcry_sexp_release (s_skey
);
286 switch (agent_private_key_type (buf
))
288 case PRIVATE_KEY_CLEAR
:
289 break; /* no unprotection needed */
290 case PRIVATE_KEY_PROTECTED
:
291 rc
= unprotect (ctrl
, desc_text
, &buf
, grip
, ignore_cache
);
293 log_error ("failed to unprotect the secret key: %s\n",
296 case PRIVATE_KEY_SHADOWED
:
299 const unsigned char *s
;
302 rc
= agent_get_shadow_info (buf
, &s
);
305 n
= gcry_sexp_canon_len (s
, 0, NULL
,NULL
);
307 *shadow_info
= xtrymalloc (n
);
312 memcpy (*shadow_info
, s
, n
);
318 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc
));
321 rc
= gpg_error (GPG_ERR_UNUSABLE_SECKEY
);
324 log_error ("invalid private key format\n");
325 rc
= gpg_error (GPG_ERR_BAD_SECKEY
);
328 if (rc
|| got_shadow_info
)
334 buflen
= gcry_sexp_canon_len (buf
, 0, NULL
, NULL
);
335 rc
= gcry_sexp_sscan (&s_skey
, &erroff
, buf
, buflen
);
336 wipememory (buf
, buflen
);
340 log_error ("failed to build S-Exp (off=%u): %s\n",
341 (unsigned int)erroff
, gpg_strerror (rc
));
349 /* Return the secret key as an S-Exp after locating it using the grip.
350 Returns NULL if key is not available. 0 = key is available */
352 agent_key_available (const unsigned char *grip
)
356 char hexgrip
[40+4+1];
358 for (i
=0; i
< 20; i
++)
359 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
360 strcpy (hexgrip
+40, ".key");
362 fname
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
363 i
= !access (fname
, R_OK
)? 0 : -1;