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