Line data Source code
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
5 : *
6 : * This file is part of GnuPG.
7 : *
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.
12 : *
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.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <config.h>
23 : #include <errno.h>
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 : #include <ctype.h>
28 : #include <fcntl.h>
29 : #include <assert.h>
30 : #include <unistd.h>
31 : #include <sys/stat.h>
32 : #include <assert.h>
33 : #include <npth.h> /* (we use pth_sleep) */
34 :
35 : #include "agent.h"
36 : #include "i18n.h"
37 : #include "../common/ssh-utils.h"
38 : #include "../common/name-value.h"
39 :
40 : #ifndef O_BINARY
41 : #define O_BINARY 0
42 : #endif
43 :
44 : /* Helper to pass data to the check callback of the unprotect function. */
45 : struct try_unprotect_arg_s
46 : {
47 : ctrl_t ctrl;
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. */
52 : };
53 :
54 :
55 : static gpg_error_t
56 0 : write_extended_private_key (char *fname, estream_t fp,
57 : const void *buf, size_t len)
58 : {
59 : gpg_error_t err;
60 0 : nvc_t pk = NULL;
61 0 : gcry_sexp_t key = NULL;
62 0 : int remove = 0;
63 : int line;
64 :
65 0 : err = nvc_parse_private_key (&pk, &line, fp);
66 0 : if (err)
67 : {
68 0 : log_error ("error parsing '%s' line %d: %s\n",
69 : fname, line, gpg_strerror (err));
70 0 : goto leave;
71 : }
72 :
73 0 : err = gcry_sexp_sscan (&key, NULL, buf, len);
74 0 : if (err)
75 0 : goto leave;
76 :
77 0 : err = nvc_set_private_key (pk, key);
78 0 : if (err)
79 0 : goto leave;
80 :
81 0 : err = es_fseek (fp, 0, SEEK_SET);
82 0 : if (err)
83 0 : goto leave;
84 :
85 0 : err = nvc_write (pk, fp);
86 0 : if (err)
87 : {
88 0 : log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
89 0 : remove = 1;
90 0 : goto leave;
91 : }
92 :
93 0 : if (ftruncate (es_fileno (fp), es_ftello (fp)))
94 : {
95 0 : err = gpg_error_from_syserror ();
96 0 : log_error ("error truncating '%s': %s\n", fname, gpg_strerror (err));
97 0 : remove = 1;
98 0 : goto leave;
99 : }
100 :
101 0 : if (es_fclose (fp))
102 : {
103 0 : err = gpg_error_from_syserror ();
104 0 : log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
105 0 : remove = 1;
106 0 : goto leave;
107 : }
108 : else
109 0 : fp = NULL;
110 :
111 0 : bump_key_eventcounter ();
112 :
113 : leave:
114 0 : if (fp)
115 0 : es_fclose (fp);
116 0 : if (remove)
117 0 : gnupg_remove (fname);
118 0 : xfree (fname);
119 0 : gcry_sexp_release (key);
120 0 : nvc_release (pk);
121 0 : return err;
122 : }
123 :
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
126 : overwritten. */
127 : int
128 34 : agent_write_private_key (const unsigned char *grip,
129 : const void *buffer, size_t length, int force)
130 : {
131 : char *fname;
132 : estream_t fp;
133 : char hexgrip[40+4+1];
134 :
135 34 : bin2hex (grip, 20, hexgrip);
136 34 : strcpy (hexgrip+40, ".key");
137 :
138 34 : fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
139 : hexgrip, NULL);
140 :
141 : /* FIXME: Write to a temp file first so that write failures during
142 : key updates won't lead to a key loss. */
143 :
144 34 : if (!force && !access (fname, F_OK))
145 : {
146 0 : log_error ("secret key file '%s' already exists\n", fname);
147 0 : xfree (fname);
148 0 : return gpg_error (GPG_ERR_EEXIST);
149 : }
150 :
151 34 : fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw");
152 34 : if (!fp)
153 : {
154 0 : gpg_error_t tmperr = gpg_error_from_syserror ();
155 0 : log_error ("can't create '%s': %s\n", fname, gpg_strerror (tmperr));
156 0 : xfree (fname);
157 0 : return tmperr;
158 : }
159 :
160 : /* See if an existing key is in extended format. */
161 34 : if (force)
162 : {
163 : gpg_error_t rc;
164 : char first;
165 :
166 8 : if (es_fread (&first, 1, 1, fp) != 1)
167 : {
168 0 : rc = gpg_error_from_syserror ();
169 0 : log_error ("error reading first byte from '%s': %s\n",
170 0 : fname, strerror (errno));
171 0 : xfree (fname);
172 0 : es_fclose (fp);
173 0 : return rc;
174 : }
175 :
176 8 : rc = es_fseek (fp, 0, SEEK_SET);
177 8 : if (rc)
178 : {
179 0 : log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
180 0 : xfree (fname);
181 0 : es_fclose (fp);
182 0 : return rc;
183 : }
184 :
185 8 : if (first != '(')
186 : {
187 : /* Key is in extended format. */
188 0 : return write_extended_private_key (fname, fp, buffer, length);
189 : }
190 : }
191 :
192 34 : if (es_fwrite (buffer, length, 1, fp) != 1)
193 : {
194 0 : gpg_error_t tmperr = gpg_error_from_syserror ();
195 0 : log_error ("error writing '%s': %s\n", fname, gpg_strerror (tmperr));
196 0 : es_fclose (fp);
197 0 : gnupg_remove (fname);
198 0 : xfree (fname);
199 0 : return tmperr;
200 : }
201 :
202 : /* When force is given, the file might have to be truncated. */
203 34 : if (force && ftruncate (es_fileno (fp), es_ftello (fp)))
204 : {
205 0 : gpg_error_t tmperr = gpg_error_from_syserror ();
206 0 : log_error ("error truncating '%s': %s\n", fname, gpg_strerror (tmperr));
207 0 : es_fclose (fp);
208 0 : gnupg_remove (fname);
209 0 : xfree (fname);
210 0 : return tmperr;
211 : }
212 :
213 34 : if (es_fclose (fp))
214 : {
215 0 : gpg_error_t tmperr = gpg_error_from_syserror ();
216 0 : log_error ("error closing '%s': %s\n", fname, gpg_strerror (tmperr));
217 0 : gnupg_remove (fname);
218 0 : xfree (fname);
219 0 : return tmperr;
220 : }
221 34 : bump_key_eventcounter ();
222 34 : xfree (fname);
223 34 : return 0;
224 : }
225 :
226 :
227 : /* Callback function to try the unprotection from the passphrase query
228 : code. */
229 : static gpg_error_t
230 1 : try_unprotect_cb (struct pin_entry_info_s *pi)
231 : {
232 1 : struct try_unprotect_arg_s *arg = pi->check_cb_arg;
233 1 : ctrl_t ctrl = arg->ctrl;
234 : size_t dummy;
235 : gpg_error_t err;
236 : gnupg_isotime_t now, protected_at, tmptime;
237 1 : char *desc = NULL;
238 :
239 1 : assert (!arg->unprotected_key);
240 :
241 1 : arg->change_required = 0;
242 1 : err = agent_unprotect (ctrl, arg->protected_key, pi->pin, protected_at,
243 : &arg->unprotected_key, &dummy);
244 1 : if (err)
245 0 : return err;
246 1 : if (!opt.max_passphrase_days || ctrl->in_passwd)
247 1 : return 0; /* No regular passphrase change required. */
248 :
249 0 : if (!*protected_at)
250 : {
251 : /* No protection date known - must force passphrase change. */
252 0 : desc = xtrystrdup (L_("Note: This passphrase has never been changed.%0A"
253 : "Please change it now."));
254 0 : if (!desc)
255 0 : return gpg_error_from_syserror ();
256 : }
257 : else
258 : {
259 0 : gnupg_get_isotime (now);
260 0 : gnupg_copy_time (tmptime, protected_at);
261 0 : err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
262 0 : if (err)
263 0 : return err;
264 0 : if (strcmp (now, tmptime) > 0 )
265 : {
266 : /* Passphrase "expired". */
267 0 : desc = xtryasprintf
268 : (L_("This passphrase has not been changed%%0A"
269 : "since %.4s-%.2s-%.2s. Please change it now."),
270 : protected_at, protected_at+4, protected_at+6);
271 0 : if (!desc)
272 0 : return gpg_error_from_syserror ();
273 : }
274 : }
275 :
276 0 : if (desc)
277 : {
278 : /* Change required. */
279 0 : if (opt.enforce_passphrase_constraints)
280 : {
281 0 : err = agent_get_confirmation (ctrl, desc,
282 : L_("Change passphrase"), NULL, 0);
283 0 : if (!err)
284 0 : arg->change_required = 1;
285 : }
286 : else
287 : {
288 0 : err = agent_get_confirmation (ctrl, desc,
289 : L_("Change passphrase"),
290 : L_("I'll change it later"), 0);
291 0 : if (!err)
292 0 : arg->change_required = 1;
293 0 : else if (gpg_err_code (err) == GPG_ERR_CANCELED
294 0 : || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
295 0 : err = 0;
296 : }
297 0 : xfree (desc);
298 : }
299 :
300 0 : return 0;
301 : }
302 :
303 :
304 : /* Modify a Key description, replacing certain special format
305 : characters. List of currently supported replacements:
306 :
307 : %% - Replaced by a single %
308 : %c - Replaced by the content of COMMENT.
309 : %C - Same as %c but put into parentheses.
310 : %F - Replaced by an ssh style fingerprint computed from KEY.
311 :
312 : The functions returns 0 on success or an error code. On success a
313 : newly allocated string is stored at the address of RESULT.
314 : */
315 : static gpg_error_t
316 137 : modify_description (const char *in, const char *comment, const gcry_sexp_t key,
317 : char **result)
318 : {
319 : size_t comment_length;
320 : size_t in_len;
321 : size_t out_len;
322 : char *out;
323 : size_t i;
324 : int special, pass;
325 137 : char *ssh_fpr = NULL;
326 :
327 137 : comment_length = strlen (comment);
328 137 : in_len = strlen (in);
329 :
330 : /* First pass calculates the length, second pass does the actual
331 : copying. */
332 137 : out = NULL;
333 137 : out_len = 0;
334 411 : for (pass=0; pass < 2; pass++)
335 : {
336 274 : special = 0;
337 49814 : for (i = 0; i < in_len; i++)
338 : {
339 49540 : if (special)
340 : {
341 1644 : special = 0;
342 1644 : switch (in[i])
343 : {
344 : case '%':
345 0 : if (out)
346 0 : *out++ = '%';
347 : else
348 0 : out_len++;
349 0 : break;
350 :
351 : case 'c': /* Comment. */
352 0 : if (out)
353 : {
354 0 : memcpy (out, comment, comment_length);
355 0 : out += comment_length;
356 : }
357 : else
358 0 : out_len += comment_length;
359 0 : break;
360 :
361 : case 'C': /* Comment. */
362 0 : if (!comment_length)
363 : ;
364 0 : else if (out)
365 : {
366 0 : *out++ = '(';
367 0 : memcpy (out, comment, comment_length);
368 0 : out += comment_length;
369 0 : *out++ = ')';
370 : }
371 : else
372 0 : out_len += comment_length + 2;
373 0 : break;
374 :
375 : case 'F': /* SSH style fingerprint. */
376 0 : if (!ssh_fpr && key)
377 0 : ssh_get_fingerprint_string (key, &ssh_fpr);
378 0 : if (ssh_fpr)
379 : {
380 0 : if (out)
381 0 : out = stpcpy (out, ssh_fpr);
382 : else
383 0 : out_len += strlen (ssh_fpr);
384 : }
385 0 : break;
386 :
387 : default: /* Invalid special sequences are kept as they are. */
388 1644 : if (out)
389 : {
390 822 : *out++ = '%';
391 822 : *out++ = in[i];
392 : }
393 : else
394 822 : out_len+=2;
395 1644 : break;
396 : }
397 : }
398 47896 : else if (in[i] == '%')
399 1644 : special = 1;
400 : else
401 : {
402 46252 : if (out)
403 23126 : *out++ = in[i];
404 : else
405 23126 : out_len++;
406 : }
407 : }
408 :
409 274 : if (!pass)
410 : {
411 137 : *result = out = xtrymalloc (out_len + 1);
412 137 : if (!out)
413 : {
414 0 : xfree (ssh_fpr);
415 0 : return gpg_error_from_syserror ();
416 : }
417 : }
418 : }
419 :
420 137 : *out = 0;
421 137 : assert (*result + out_len == out);
422 137 : xfree (ssh_fpr);
423 137 : return 0;
424 : }
425 :
426 :
427 :
428 : /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
429 : should be the hex encoded keygrip of that key to be used with the
430 : caching mechanism. DESC_TEXT may be set to override the default
431 : description used for the pinentry. If LOOKUP_TTL is given this
432 : function is used to lookup the default ttl. If R_PASSPHRASE is not
433 : NULL, the function succeeded and the key was protected the used
434 : passphrase (entered or from the cache) is stored there; if not NULL
435 : will be stored. The caller needs to free the returned
436 : passphrase. */
437 : static int
438 137 : unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
439 : unsigned char **keybuf, const unsigned char *grip,
440 : cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
441 : char **r_passphrase)
442 : {
443 : struct pin_entry_info_s *pi;
444 : struct try_unprotect_arg_s arg;
445 : int rc;
446 : unsigned char *result;
447 : size_t resultlen;
448 : char hexgrip[40+1];
449 :
450 137 : if (r_passphrase)
451 2 : *r_passphrase = NULL;
452 :
453 137 : bin2hex (grip, 20, hexgrip);
454 :
455 : /* Initially try to get it using a cache nonce. */
456 137 : if (cache_nonce)
457 : {
458 : char *pw;
459 :
460 1 : pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
461 1 : if (pw)
462 : {
463 1 : rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
464 1 : if (!rc)
465 : {
466 1 : if (r_passphrase)
467 1 : *r_passphrase = pw;
468 : else
469 0 : xfree (pw);
470 1 : xfree (*keybuf);
471 1 : *keybuf = result;
472 1 : return 0;
473 : }
474 0 : xfree (pw);
475 : }
476 : }
477 :
478 : /* First try to get it from the cache - if there is none or we can't
479 : unprotect it, we fall back to ask the user */
480 136 : if (cache_mode != CACHE_MODE_IGNORE)
481 : {
482 : char *pw;
483 :
484 : retry:
485 135 : pw = agent_get_cache (hexgrip, cache_mode);
486 135 : if (pw)
487 : {
488 135 : rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
489 135 : if (!rc)
490 : {
491 135 : if (cache_mode == CACHE_MODE_NORMAL)
492 135 : agent_store_cache_hit (hexgrip);
493 135 : if (r_passphrase)
494 0 : *r_passphrase = pw;
495 : else
496 135 : xfree (pw);
497 135 : xfree (*keybuf);
498 135 : *keybuf = result;
499 135 : return 0;
500 : }
501 0 : xfree (pw);
502 0 : rc = 0;
503 : }
504 0 : else if (cache_mode == CACHE_MODE_NORMAL)
505 : {
506 : /* The standard use of GPG keys is to have a signing and an
507 : encryption subkey. Commonly both use the same
508 : passphrase. We try to help the user to enter the
509 : passphrase only once by silently trying the last
510 : correctly entered passphrase. Checking one additional
511 : passphrase should be acceptable; despite the S2K
512 : introduced delays. The assumed workflow is:
513 :
514 : 1. Read encrypted message in a MUA and thus enter a
515 : passphrase for the encryption subkey.
516 :
517 : 2. Reply to that mail with an encrypted and signed
518 : mail, thus entering the passphrase for the signing
519 : subkey.
520 :
521 : We can often avoid the passphrase entry in the second
522 : step. We do this only in normal mode, so not to
523 : interfere with unrelated cache entries. */
524 0 : pw = agent_get_cache (NULL, cache_mode);
525 0 : if (pw)
526 : {
527 0 : rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
528 : &result, &resultlen);
529 0 : if (!rc)
530 : {
531 0 : if (r_passphrase)
532 0 : *r_passphrase = pw;
533 : else
534 0 : xfree (pw);
535 0 : xfree (*keybuf);
536 0 : *keybuf = result;
537 0 : return 0;
538 : }
539 0 : xfree (pw);
540 0 : rc = 0;
541 : }
542 : }
543 :
544 : /* If the pinentry is currently in use, we wait up to 60 seconds
545 : for it to close and check the cache again. This solves a common
546 : situation where several requests for unprotecting a key have
547 : been made but the user is still entering the passphrase for
548 : the first request. Because all requests to agent_askpin are
549 : serialized they would then pop up one after the other to
550 : request the passphrase - despite that the user has already
551 : entered it and is then available in the cache. This
552 : implementation is not race free but in the worst case the
553 : user has to enter the passphrase only once more. */
554 0 : if (pinentry_active_p (ctrl, 0))
555 : {
556 : /* Active - wait */
557 0 : if (!pinentry_active_p (ctrl, 60))
558 : {
559 : /* We need to give the other thread a chance to actually put
560 : it into the cache. */
561 0 : npth_sleep (1);
562 0 : goto retry;
563 : }
564 : /* Timeout - better call pinentry now the plain way. */
565 : }
566 : }
567 :
568 1 : pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
569 1 : if (!pi)
570 0 : return gpg_error_from_syserror ();
571 1 : pi->max_length = MAX_PASSPHRASE_LEN + 1;
572 1 : pi->min_digits = 0; /* we want a real passphrase */
573 1 : pi->max_digits = 16;
574 1 : pi->max_tries = 3;
575 1 : pi->check_cb = try_unprotect_cb;
576 1 : arg.ctrl = ctrl;
577 1 : arg.protected_key = *keybuf;
578 1 : arg.unprotected_key = NULL;
579 1 : arg.change_required = 0;
580 1 : pi->check_cb_arg = &arg;
581 :
582 1 : rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
583 1 : if (!rc)
584 : {
585 1 : assert (arg.unprotected_key);
586 1 : if (arg.change_required)
587 : {
588 : /* The callback told as that the user should change their
589 : passphrase. Present the dialog to do. */
590 : size_t canlen, erroff;
591 : gcry_sexp_t s_skey;
592 :
593 0 : assert (arg.unprotected_key);
594 0 : canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
595 0 : rc = gcry_sexp_sscan (&s_skey, &erroff,
596 0 : (char*)arg.unprotected_key, canlen);
597 0 : if (rc)
598 : {
599 0 : log_error ("failed to build S-Exp (off=%u): %s\n",
600 : (unsigned int)erroff, gpg_strerror (rc));
601 0 : wipememory (arg.unprotected_key, canlen);
602 0 : xfree (arg.unprotected_key);
603 0 : xfree (pi);
604 0 : return rc;
605 : }
606 0 : rc = agent_protect_and_store (ctrl, s_skey, NULL);
607 0 : gcry_sexp_release (s_skey);
608 0 : if (rc)
609 : {
610 0 : log_error ("changing the passphrase failed: %s\n",
611 : gpg_strerror (rc));
612 0 : wipememory (arg.unprotected_key, canlen);
613 0 : xfree (arg.unprotected_key);
614 0 : xfree (pi);
615 0 : return rc;
616 : }
617 : }
618 : else
619 : {
620 : /* Passphrase is fine. */
621 1 : agent_put_cache (hexgrip, cache_mode, pi->pin,
622 : lookup_ttl? lookup_ttl (hexgrip) : 0);
623 1 : agent_store_cache_hit (hexgrip);
624 1 : if (r_passphrase && *pi->pin)
625 1 : *r_passphrase = xtrystrdup (pi->pin);
626 : }
627 1 : xfree (*keybuf);
628 1 : *keybuf = arg.unprotected_key;
629 : }
630 1 : xfree (pi);
631 1 : return rc;
632 : }
633 :
634 :
635 : /* Read the key identified by GRIP from the private key directory and
636 : return it as an gcrypt S-expression object in RESULT. On failure
637 : returns an error code and stores NULL at RESULT. */
638 : static gpg_error_t
639 440 : read_key_file (const unsigned char *grip, gcry_sexp_t *result)
640 : {
641 : int rc;
642 : char *fname;
643 : estream_t fp;
644 : struct stat st;
645 : unsigned char *buf;
646 : size_t buflen, erroff;
647 : gcry_sexp_t s_skey;
648 : char hexgrip[40+4+1];
649 : char first;
650 :
651 440 : *result = NULL;
652 :
653 440 : bin2hex (grip, 20, hexgrip);
654 440 : strcpy (hexgrip+40, ".key");
655 :
656 440 : fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
657 : hexgrip, NULL);
658 440 : fp = es_fopen (fname, "rb");
659 440 : if (!fp)
660 : {
661 0 : rc = gpg_error_from_syserror ();
662 0 : if (gpg_err_code (rc) != GPG_ERR_ENOENT)
663 0 : log_error ("can't open '%s': %s\n", fname, strerror (errno));
664 0 : xfree (fname);
665 0 : return rc;
666 : }
667 :
668 440 : if (es_fread (&first, 1, 1, fp) != 1)
669 : {
670 0 : rc = gpg_error_from_syserror ();
671 0 : log_error ("error reading first byte from '%s': %s\n",
672 0 : fname, strerror (errno));
673 0 : xfree (fname);
674 0 : es_fclose (fp);
675 0 : return rc;
676 : }
677 :
678 440 : rc = es_fseek (fp, 0, SEEK_SET);
679 440 : if (rc)
680 : {
681 0 : log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
682 0 : xfree (fname);
683 0 : es_fclose (fp);
684 0 : return rc;
685 : }
686 :
687 440 : if (first != '(')
688 : {
689 : /* Key is in extended format. */
690 : nvc_t pk;
691 : int line;
692 :
693 0 : rc = nvc_parse_private_key (&pk, &line, fp);
694 0 : es_fclose (fp);
695 :
696 0 : if (rc)
697 0 : log_error ("error parsing '%s' line %d: %s\n",
698 : fname, line, gpg_strerror (rc));
699 : else
700 : {
701 0 : rc = nvc_get_private_key (pk, result);
702 0 : nvc_release (pk);
703 0 : if (rc)
704 0 : log_error ("error getting private key from '%s': %s\n",
705 : fname, gpg_strerror (rc));
706 : }
707 :
708 0 : xfree (fname);
709 0 : return rc;
710 : }
711 :
712 440 : if (fstat (es_fileno (fp), &st))
713 : {
714 0 : rc = gpg_error_from_syserror ();
715 0 : log_error ("can't stat '%s': %s\n", fname, strerror (errno));
716 0 : xfree (fname);
717 0 : es_fclose (fp);
718 0 : return rc;
719 : }
720 :
721 440 : buflen = st.st_size;
722 440 : buf = xtrymalloc (buflen+1);
723 440 : if (!buf)
724 : {
725 0 : rc = gpg_error_from_syserror ();
726 0 : log_error ("error allocating %zu bytes for '%s': %s\n",
727 0 : buflen, fname, strerror (errno));
728 0 : xfree (fname);
729 0 : es_fclose (fp);
730 0 : xfree (buf);
731 0 : return rc;
732 :
733 : }
734 :
735 440 : if (es_fread (buf, buflen, 1, fp) != 1)
736 : {
737 0 : rc = gpg_error_from_syserror ();
738 0 : log_error ("error reading %zu bytes from '%s': %s\n",
739 0 : buflen, fname, strerror (errno));
740 0 : xfree (fname);
741 0 : es_fclose (fp);
742 0 : xfree (buf);
743 0 : return rc;
744 : }
745 :
746 : /* Convert the file into a gcrypt S-expression object. */
747 440 : rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
748 440 : xfree (fname);
749 440 : es_fclose (fp);
750 440 : xfree (buf);
751 440 : if (rc)
752 : {
753 0 : log_error ("failed to build S-Exp (off=%u): %s\n",
754 : (unsigned int)erroff, gpg_strerror (rc));
755 0 : return rc;
756 : }
757 440 : *result = s_skey;
758 440 : return 0;
759 : }
760 :
761 :
762 : /* Remove the key identified by GRIP from the private key directory. */
763 : static gpg_error_t
764 0 : remove_key_file (const unsigned char *grip)
765 : {
766 0 : gpg_error_t err = 0;
767 : char *fname;
768 : char hexgrip[40+4+1];
769 :
770 0 : bin2hex (grip, 20, hexgrip);
771 0 : strcpy (hexgrip+40, ".key");
772 0 : fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
773 : hexgrip, NULL);
774 0 : if (gnupg_remove (fname))
775 0 : err = gpg_error_from_syserror ();
776 0 : xfree (fname);
777 0 : return err;
778 : }
779 :
780 :
781 : /* Return the secret key as an S-Exp in RESULT after locating it using
782 : the GRIP. If the operation shall be diverted to a token, an
783 : allocated S-expression with the shadow_info part from the file is
784 : stored at SHADOW_INFO; if not NULL will be stored at SHADOW_INFO.
785 : CACHE_MODE defines now the cache shall be used. DESC_TEXT may be
786 : set to present a custom description for the pinentry. LOOKUP_TTL
787 : is an optional function to convey a TTL to the cache manager; we do
788 : not simply pass the TTL value because the value is only needed if
789 : an unprotect action was needed and looking up the TTL may have some
790 : overhead (e.g. scanning the sshcontrol file). If a CACHE_NONCE is
791 : given that cache item is first tried to get a passphrase. If
792 : R_PASSPHRASE is not NULL, the function succeeded and the key was
793 : protected the used passphrase (entered or from the cache) is stored
794 : there; if not NULL will be stored. The caller needs to free the
795 : returned passphrase. */
796 : gpg_error_t
797 400 : agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
798 : const char *desc_text,
799 : const unsigned char *grip, unsigned char **shadow_info,
800 : cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
801 : gcry_sexp_t *result, char **r_passphrase)
802 : {
803 : int rc;
804 : unsigned char *buf;
805 : size_t len, buflen, erroff;
806 : gcry_sexp_t s_skey;
807 :
808 400 : *result = NULL;
809 400 : if (shadow_info)
810 400 : *shadow_info = NULL;
811 400 : if (r_passphrase)
812 2 : *r_passphrase = NULL;
813 :
814 400 : rc = read_key_file (grip, &s_skey);
815 400 : if (rc)
816 : {
817 0 : if (gpg_err_code (rc) == GPG_ERR_ENOENT)
818 0 : rc = gpg_error (GPG_ERR_NO_SECKEY);
819 0 : return rc;
820 : }
821 :
822 : /* For use with the protection functions we also need the key as an
823 : canonical encoded S-expression in a buffer. Create this buffer
824 : now. */
825 400 : rc = make_canon_sexp (s_skey, &buf, &len);
826 400 : if (rc)
827 0 : return rc;
828 :
829 400 : switch (agent_private_key_type (buf))
830 : {
831 : case PRIVATE_KEY_CLEAR:
832 261 : break; /* no unprotection needed */
833 : case PRIVATE_KEY_OPENPGP_NONE:
834 : {
835 : unsigned char *buf_new;
836 : size_t buf_newlen;
837 :
838 2 : rc = agent_unprotect (ctrl, buf, "", NULL, &buf_new, &buf_newlen);
839 2 : if (rc)
840 0 : log_error ("failed to convert unprotected openpgp key: %s\n",
841 : gpg_strerror (rc));
842 : else
843 : {
844 2 : xfree (buf);
845 2 : buf = buf_new;
846 : }
847 : }
848 2 : break;
849 : case PRIVATE_KEY_PROTECTED:
850 : {
851 : char *desc_text_final;
852 137 : char *comment = NULL;
853 :
854 : /* Note, that we will take the comment as a C string for
855 : display purposes; i.e. all stuff beyond a Nul character is
856 : ignored. */
857 : {
858 : gcry_sexp_t comment_sexp;
859 :
860 137 : comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
861 137 : if (comment_sexp)
862 0 : comment = gcry_sexp_nth_string (comment_sexp, 1);
863 137 : gcry_sexp_release (comment_sexp);
864 : }
865 :
866 137 : desc_text_final = NULL;
867 137 : if (desc_text)
868 137 : rc = modify_description (desc_text, comment? comment:"", s_skey,
869 : &desc_text_final);
870 137 : gcry_free (comment);
871 :
872 137 : if (!rc)
873 : {
874 137 : rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
875 : cache_mode, lookup_ttl, r_passphrase);
876 137 : if (rc)
877 0 : log_error ("failed to unprotect the secret key: %s\n",
878 : gpg_strerror (rc));
879 : }
880 :
881 137 : xfree (desc_text_final);
882 : }
883 137 : break;
884 : case PRIVATE_KEY_SHADOWED:
885 0 : if (shadow_info)
886 : {
887 : const unsigned char *s;
888 : size_t n;
889 :
890 0 : rc = agent_get_shadow_info (buf, &s);
891 0 : if (!rc)
892 : {
893 0 : n = gcry_sexp_canon_len (s, 0, NULL,NULL);
894 0 : assert (n);
895 0 : *shadow_info = xtrymalloc (n);
896 0 : if (!*shadow_info)
897 0 : rc = out_of_core ();
898 : else
899 : {
900 0 : memcpy (*shadow_info, s, n);
901 0 : rc = 0;
902 : }
903 : }
904 0 : if (rc)
905 0 : log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
906 : }
907 : else
908 0 : rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
909 0 : break;
910 : default:
911 0 : log_error ("invalid private key format\n");
912 0 : rc = gpg_error (GPG_ERR_BAD_SECKEY);
913 0 : break;
914 : }
915 400 : gcry_sexp_release (s_skey);
916 400 : s_skey = NULL;
917 400 : if (rc)
918 : {
919 0 : xfree (buf);
920 0 : if (r_passphrase)
921 : {
922 0 : xfree (*r_passphrase);
923 0 : *r_passphrase = NULL;
924 : }
925 0 : return rc;
926 : }
927 :
928 400 : buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
929 400 : rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
930 400 : wipememory (buf, buflen);
931 400 : xfree (buf);
932 400 : if (rc)
933 : {
934 0 : log_error ("failed to build S-Exp (off=%u): %s\n",
935 : (unsigned int)erroff, gpg_strerror (rc));
936 0 : if (r_passphrase)
937 : {
938 0 : xfree (*r_passphrase);
939 0 : *r_passphrase = NULL;
940 : }
941 0 : return rc;
942 : }
943 :
944 400 : *result = s_skey;
945 400 : return 0;
946 : }
947 :
948 :
949 : /* Return the string name from the S-expression S_KEY as well as a
950 : string describing the names of the parameters. ALGONAMESIZE and
951 : ELEMSSIZE give the allocated size of the provided buffers. The
952 : buffers may be NULL if not required. If R_LIST is not NULL the top
953 : level list will be stored there; the caller needs to release it in
954 : this case. */
955 : static gpg_error_t
956 272 : key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
957 : char *r_algoname, size_t algonamesize,
958 : char *r_elems, size_t elemssize)
959 : {
960 : gcry_sexp_t list, l2;
961 : const char *name, *algoname, *elems;
962 : size_t n;
963 :
964 272 : if (r_list)
965 272 : *r_list = NULL;
966 :
967 272 : list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
968 272 : if (!list)
969 272 : list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
970 272 : if (!list)
971 272 : list = gcry_sexp_find_token (s_key, "private-key", 0 );
972 272 : if (!list)
973 : {
974 0 : log_error ("invalid private key format\n");
975 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
976 : }
977 :
978 272 : l2 = gcry_sexp_cadr (list);
979 272 : gcry_sexp_release (list);
980 272 : list = l2;
981 272 : name = gcry_sexp_nth_data (list, 0, &n);
982 272 : if (n==3 && !memcmp (name, "rsa", 3))
983 : {
984 36 : algoname = "rsa";
985 36 : elems = "ne";
986 : }
987 236 : else if (n==3 && !memcmp (name, "dsa", 3))
988 : {
989 194 : algoname = "dsa";
990 194 : elems = "pqgy";
991 : }
992 42 : else if (n==3 && !memcmp (name, "ecc", 3))
993 : {
994 42 : algoname = "ecc";
995 42 : elems = "pabgnq";
996 : }
997 0 : else if (n==5 && !memcmp (name, "ecdsa", 5))
998 : {
999 0 : algoname = "ecdsa";
1000 0 : elems = "pabgnq";
1001 : }
1002 0 : else if (n==4 && !memcmp (name, "ecdh", 4))
1003 : {
1004 0 : algoname = "ecdh";
1005 0 : elems = "pabgnq";
1006 : }
1007 0 : else if (n==3 && !memcmp (name, "elg", 3))
1008 : {
1009 0 : algoname = "elg";
1010 0 : elems = "pgy";
1011 : }
1012 : else
1013 : {
1014 0 : log_error ("unknown private key algorithm\n");
1015 0 : gcry_sexp_release (list);
1016 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
1017 : }
1018 :
1019 272 : if (r_algoname)
1020 : {
1021 272 : if (strlen (algoname) >= algonamesize)
1022 0 : return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1023 272 : strcpy (r_algoname, algoname);
1024 : }
1025 272 : if (r_elems)
1026 : {
1027 0 : if (strlen (elems) >= elemssize)
1028 0 : return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1029 0 : strcpy (r_elems, elems);
1030 : }
1031 :
1032 272 : if (r_list)
1033 272 : *r_list = list;
1034 : else
1035 0 : gcry_sexp_release (list);
1036 :
1037 272 : return 0;
1038 : }
1039 :
1040 :
1041 : /* Return true if KEYPARMS holds an EdDSA key. */
1042 : static int
1043 42 : is_eddsa (gcry_sexp_t keyparms)
1044 : {
1045 42 : int result = 0;
1046 : gcry_sexp_t list;
1047 : const char *s;
1048 : size_t n;
1049 : int i;
1050 :
1051 42 : list = gcry_sexp_find_token (keyparms, "flags", 0);
1052 42 : for (i = list ? gcry_sexp_length (list)-1 : 0; i > 0; i--)
1053 : {
1054 0 : s = gcry_sexp_nth_data (list, i, &n);
1055 0 : if (!s)
1056 0 : continue; /* Not a data element. */
1057 :
1058 0 : if (n == 5 && !memcmp (s, "eddsa", 5))
1059 : {
1060 0 : result = 1;
1061 0 : break;
1062 : }
1063 : }
1064 42 : gcry_sexp_release (list);
1065 42 : return result;
1066 : }
1067 :
1068 :
1069 : /* Return the public key algorithm number if S_KEY is a DSA style key.
1070 : If it is not a DSA style key, return 0. */
1071 : int
1072 136 : agent_is_dsa_key (gcry_sexp_t s_key)
1073 : {
1074 : int result;
1075 : gcry_sexp_t list;
1076 : char algoname[6];
1077 :
1078 136 : if (!s_key)
1079 0 : return 0;
1080 :
1081 136 : if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
1082 0 : return 0; /* Error - assume it is not an DSA key. */
1083 :
1084 136 : if (!strcmp (algoname, "dsa"))
1085 97 : result = GCRY_PK_DSA;
1086 39 : else if (!strcmp (algoname, "ecc"))
1087 : {
1088 21 : if (is_eddsa (list))
1089 0 : result = 0;
1090 : else
1091 21 : result = GCRY_PK_ECDSA;
1092 : }
1093 18 : else if (!strcmp (algoname, "ecdsa"))
1094 0 : result = GCRY_PK_ECDSA;
1095 : else
1096 18 : result = 0;
1097 :
1098 136 : gcry_sexp_release (list);
1099 136 : return result;
1100 : }
1101 :
1102 :
1103 : /* Return true if S_KEY is an EdDSA key as used with curve Ed25519. */
1104 : int
1105 136 : agent_is_eddsa_key (gcry_sexp_t s_key)
1106 : {
1107 : int result;
1108 : gcry_sexp_t list;
1109 : char algoname[6];
1110 :
1111 136 : if (!s_key)
1112 0 : return 0;
1113 :
1114 136 : if (key_parms_from_sexp (s_key, &list, algoname, sizeof algoname, NULL, 0))
1115 0 : return 0; /* Error - assume it is not an EdDSA key. */
1116 :
1117 136 : if (!strcmp (algoname, "ecc") && is_eddsa (list))
1118 0 : result = 1;
1119 136 : else if (!strcmp (algoname, "eddsa")) /* backward compatibility. */
1120 0 : result = 1;
1121 : else
1122 136 : result = 0;
1123 :
1124 136 : gcry_sexp_release (list);
1125 136 : return result;
1126 : }
1127 :
1128 :
1129 : /* Return the key for the keygrip GRIP. The result is stored at
1130 : RESULT. This function extracts the key from the private key
1131 : database and returns it as an S-expression object as it is. On
1132 : failure an error code is returned and NULL stored at RESULT. */
1133 : gpg_error_t
1134 0 : agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
1135 : gcry_sexp_t *result)
1136 : {
1137 : gpg_error_t err;
1138 : gcry_sexp_t s_skey;
1139 :
1140 : (void)ctrl;
1141 :
1142 0 : *result = NULL;
1143 :
1144 0 : err = read_key_file (grip, &s_skey);
1145 0 : if (!err)
1146 0 : *result = s_skey;
1147 0 : return err;
1148 : }
1149 :
1150 :
1151 : /* Return the public key for the keygrip GRIP. The result is stored
1152 : at RESULT. This function extracts the public key from the private
1153 : key database. On failure an error code is returned and NULL stored
1154 : at RESULT. */
1155 : gpg_error_t
1156 11 : agent_public_key_from_file (ctrl_t ctrl,
1157 : const unsigned char *grip,
1158 : gcry_sexp_t *result)
1159 : {
1160 : gpg_error_t err;
1161 : int i, idx;
1162 : gcry_sexp_t s_skey;
1163 : const char *algoname, *elems;
1164 : int npkey;
1165 : gcry_mpi_t array[10];
1166 11 : gcry_sexp_t curve = NULL;
1167 11 : gcry_sexp_t flags = NULL;
1168 : gcry_sexp_t uri_sexp, comment_sexp;
1169 : const char *uri, *comment;
1170 : size_t uri_length, comment_length;
1171 : char *format, *p;
1172 : void *args[2+7+2+2+1]; /* Size is 2 + max. # of elements + 2 for uri + 2
1173 : for comment + end-of-list. */
1174 : int argidx;
1175 11 : gcry_sexp_t list = NULL;
1176 : const char *s;
1177 :
1178 : (void)ctrl;
1179 :
1180 11 : *result = NULL;
1181 :
1182 11 : err = read_key_file (grip, &s_skey);
1183 11 : if (err)
1184 0 : return err;
1185 :
1186 121 : for (i=0; i < DIM (array); i++)
1187 110 : array[i] = NULL;
1188 :
1189 11 : err = extract_private_key (s_skey, 0, &algoname, &npkey, NULL, &elems,
1190 : array, DIM (array), &curve, &flags);
1191 11 : if (err)
1192 : {
1193 0 : gcry_sexp_release (s_skey);
1194 0 : return err;
1195 : }
1196 :
1197 11 : uri = NULL;
1198 11 : uri_length = 0;
1199 11 : uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
1200 11 : if (uri_sexp)
1201 0 : uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
1202 :
1203 11 : comment = NULL;
1204 11 : comment_length = 0;
1205 11 : comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
1206 11 : if (comment_sexp)
1207 11 : comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
1208 :
1209 11 : gcry_sexp_release (s_skey);
1210 11 : s_skey = NULL;
1211 :
1212 :
1213 : /* FIXME: The following thing is pretty ugly code; we should
1214 : investigate how to make it cleaner. Probably code to handle
1215 : canonical S-expressions in a memory buffer is better suited for
1216 : such a task. After all that is what we do in protect.c. Neeed
1217 : to find common patterns and write a straightformward API to use
1218 : them. */
1219 : assert (sizeof (size_t) <= sizeof (void*));
1220 :
1221 11 : format = xtrymalloc (15+4+7*npkey+10+15+1+1);
1222 11 : if (!format)
1223 : {
1224 0 : err = gpg_error_from_syserror ();
1225 0 : for (i=0; array[i]; i++)
1226 0 : gcry_mpi_release (array[i]);
1227 0 : gcry_sexp_release (curve);
1228 0 : gcry_sexp_release (flags);
1229 0 : gcry_sexp_release (uri_sexp);
1230 0 : gcry_sexp_release (comment_sexp);
1231 0 : return err;
1232 : }
1233 :
1234 11 : argidx = 0;
1235 11 : p = stpcpy (stpcpy (format, "(public-key("), algoname);
1236 11 : p = stpcpy (p, "%S%S"); /* curve name and flags. */
1237 11 : args[argidx++] = &curve;
1238 11 : args[argidx++] = &flags;
1239 38 : for (idx=0, s=elems; idx < npkey; idx++)
1240 : {
1241 27 : *p++ = '(';
1242 27 : *p++ = *s++;
1243 27 : p = stpcpy (p, " %m)");
1244 27 : assert (argidx < DIM (args));
1245 27 : args[argidx++] = &array[idx];
1246 : }
1247 11 : *p++ = ')';
1248 11 : if (uri)
1249 : {
1250 0 : p = stpcpy (p, "(uri %b)");
1251 0 : assert (argidx+1 < DIM (args));
1252 0 : args[argidx++] = (void *)&uri_length;
1253 0 : args[argidx++] = (void *)&uri;
1254 : }
1255 11 : if (comment)
1256 : {
1257 11 : p = stpcpy (p, "(comment %b)");
1258 11 : assert (argidx+1 < DIM (args));
1259 11 : args[argidx++] = (void *)&comment_length;
1260 11 : args[argidx++] = (void*)&comment;
1261 : }
1262 11 : *p++ = ')';
1263 11 : *p = 0;
1264 11 : assert (argidx < DIM (args));
1265 11 : args[argidx] = NULL;
1266 :
1267 11 : err = gcry_sexp_build_array (&list, NULL, format, args);
1268 11 : xfree (format);
1269 38 : for (i=0; array[i]; i++)
1270 27 : gcry_mpi_release (array[i]);
1271 11 : gcry_sexp_release (curve);
1272 11 : gcry_sexp_release (flags);
1273 11 : gcry_sexp_release (uri_sexp);
1274 11 : gcry_sexp_release (comment_sexp);
1275 :
1276 11 : if (!err)
1277 11 : *result = list;
1278 11 : return err;
1279 : }
1280 :
1281 :
1282 :
1283 : /* Check whether the the secret key identified by GRIP is available.
1284 : Returns 0 is the key is available. */
1285 : int
1286 1022 : agent_key_available (const unsigned char *grip)
1287 : {
1288 : int result;
1289 : char *fname;
1290 : char hexgrip[40+4+1];
1291 :
1292 1022 : bin2hex (grip, 20, hexgrip);
1293 1022 : strcpy (hexgrip+40, ".key");
1294 :
1295 1022 : fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
1296 : hexgrip, NULL);
1297 1022 : result = !access (fname, R_OK)? 0 : -1;
1298 1022 : xfree (fname);
1299 1022 : return result;
1300 : }
1301 :
1302 :
1303 :
1304 : /* Return the information about the secret key specified by the binary
1305 : keygrip GRIP. If the key is a shadowed one the shadow information
1306 : will be stored at the address R_SHADOW_INFO as an allocated
1307 : S-expression. */
1308 : gpg_error_t
1309 29 : agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
1310 : int *r_keytype, unsigned char **r_shadow_info)
1311 : {
1312 : gpg_error_t err;
1313 : unsigned char *buf;
1314 : size_t len;
1315 : int keytype;
1316 :
1317 : (void)ctrl;
1318 :
1319 29 : if (r_keytype)
1320 29 : *r_keytype = PRIVATE_KEY_UNKNOWN;
1321 29 : if (r_shadow_info)
1322 29 : *r_shadow_info = NULL;
1323 :
1324 : {
1325 : gcry_sexp_t sexp;
1326 :
1327 29 : err = read_key_file (grip, &sexp);
1328 29 : if (err)
1329 : {
1330 0 : if (gpg_err_code (err) == GPG_ERR_ENOENT)
1331 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1332 : else
1333 0 : return err;
1334 : }
1335 29 : err = make_canon_sexp (sexp, &buf, &len);
1336 29 : gcry_sexp_release (sexp);
1337 29 : if (err)
1338 0 : return err;
1339 : }
1340 :
1341 29 : keytype = agent_private_key_type (buf);
1342 29 : switch (keytype)
1343 : {
1344 : case PRIVATE_KEY_CLEAR:
1345 : case PRIVATE_KEY_OPENPGP_NONE:
1346 17 : break;
1347 : case PRIVATE_KEY_PROTECTED:
1348 : /* If we ever require it we could retrieve the comment fields
1349 : from such a key. */
1350 12 : break;
1351 : case PRIVATE_KEY_SHADOWED:
1352 0 : if (r_shadow_info)
1353 : {
1354 : const unsigned char *s;
1355 : size_t n;
1356 :
1357 0 : err = agent_get_shadow_info (buf, &s);
1358 0 : if (!err)
1359 : {
1360 0 : n = gcry_sexp_canon_len (s, 0, NULL, NULL);
1361 0 : assert (n);
1362 0 : *r_shadow_info = xtrymalloc (n);
1363 0 : if (!*r_shadow_info)
1364 0 : err = gpg_error_from_syserror ();
1365 : else
1366 0 : memcpy (*r_shadow_info, s, n);
1367 : }
1368 : }
1369 0 : break;
1370 : default:
1371 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
1372 0 : break;
1373 : }
1374 :
1375 29 : if (!err && r_keytype)
1376 29 : *r_keytype = keytype;
1377 :
1378 29 : xfree (buf);
1379 29 : return err;
1380 : }
1381 :
1382 :
1383 :
1384 : /* Delete the key with GRIP from the disk after having asked for
1385 : confirmation using DESC_TEXT. If FORCE is set the function won't
1386 : require a confirmation via Pinentry or warns if the key is also
1387 : used by ssh.
1388 :
1389 : Common error codes are:
1390 : GPG_ERR_NO_SECKEY
1391 : GPG_ERR_KEY_ON_CARD
1392 : GPG_ERR_NOT_CONFIRMED
1393 : */
1394 : gpg_error_t
1395 0 : agent_delete_key (ctrl_t ctrl, const char *desc_text,
1396 : const unsigned char *grip, int force)
1397 : {
1398 : gpg_error_t err;
1399 0 : gcry_sexp_t s_skey = NULL;
1400 0 : unsigned char *buf = NULL;
1401 : size_t len;
1402 0 : char *desc_text_final = NULL;
1403 0 : char *comment = NULL;
1404 0 : ssh_control_file_t cf = NULL;
1405 : char hexgrip[40+4+1];
1406 0 : char *default_desc = NULL;
1407 :
1408 0 : err = read_key_file (grip, &s_skey);
1409 0 : if (gpg_err_code (err) == GPG_ERR_ENOENT)
1410 0 : err = gpg_error (GPG_ERR_NO_SECKEY);
1411 0 : if (err)
1412 0 : goto leave;
1413 :
1414 0 : err = make_canon_sexp (s_skey, &buf, &len);
1415 0 : if (err)
1416 0 : goto leave;
1417 :
1418 0 : switch (agent_private_key_type (buf))
1419 : {
1420 : case PRIVATE_KEY_CLEAR:
1421 : case PRIVATE_KEY_OPENPGP_NONE:
1422 : case PRIVATE_KEY_PROTECTED:
1423 0 : bin2hex (grip, 20, hexgrip);
1424 0 : if (!force)
1425 : {
1426 0 : if (!desc_text)
1427 : {
1428 0 : default_desc = xtryasprintf
1429 : (L_("Do you really want to delete the key identified by keygrip%%0A"
1430 : " %s%%0A %%C%%0A?"), hexgrip);
1431 0 : desc_text = default_desc;
1432 : }
1433 :
1434 : /* Note, that we will take the comment as a C string for
1435 : display purposes; i.e. all stuff beyond a Nul character is
1436 : ignored. */
1437 : {
1438 : gcry_sexp_t comment_sexp;
1439 :
1440 0 : comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
1441 0 : if (comment_sexp)
1442 0 : comment = gcry_sexp_nth_string (comment_sexp, 1);
1443 0 : gcry_sexp_release (comment_sexp);
1444 : }
1445 :
1446 0 : if (desc_text)
1447 0 : err = modify_description (desc_text, comment? comment:"", s_skey,
1448 : &desc_text_final);
1449 0 : if (err)
1450 0 : goto leave;
1451 :
1452 0 : err = agent_get_confirmation (ctrl, desc_text_final,
1453 : L_("Delete key"), L_("No"), 0);
1454 0 : if (err)
1455 0 : goto leave;
1456 :
1457 0 : cf = ssh_open_control_file ();
1458 0 : if (cf)
1459 : {
1460 0 : if (!ssh_search_control_file (cf, hexgrip, NULL, NULL, NULL))
1461 : {
1462 0 : err = agent_get_confirmation
1463 : (ctrl,
1464 : L_("Warning: This key is also listed for use with SSH!\n"
1465 : "Deleting the key might remove your ability to "
1466 : "access remote machines."),
1467 : L_("Delete key"), L_("No"), 0);
1468 0 : if (err)
1469 0 : goto leave;
1470 : }
1471 : }
1472 : }
1473 0 : err = remove_key_file (grip);
1474 0 : break;
1475 :
1476 : case PRIVATE_KEY_SHADOWED:
1477 0 : err = remove_key_file (grip);
1478 0 : break;
1479 :
1480 : default:
1481 0 : log_error ("invalid private key format\n");
1482 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
1483 0 : break;
1484 : }
1485 :
1486 : leave:
1487 0 : ssh_close_control_file (cf);
1488 0 : gcry_free (comment);
1489 0 : xfree (desc_text_final);
1490 0 : xfree (default_desc);
1491 0 : xfree (buf);
1492 0 : gcry_sexp_release (s_skey);
1493 0 : return err;
1494 : }
|