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