Line data Source code
1 : /* protect-tool.c - A tool to test the secret key protection
2 : * Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
6 : * GnuPG is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * GnuPG is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <stddef.h>
25 : #include <stdarg.h>
26 : #include <string.h>
27 : #include <errno.h>
28 : #include <assert.h>
29 : #include <sys/stat.h>
30 : #include <unistd.h>
31 : #ifdef HAVE_LOCALE_H
32 : #include <locale.h>
33 : #endif
34 : #ifdef HAVE_LANGINFO_CODESET
35 : #include <langinfo.h>
36 : #endif
37 : #ifdef HAVE_DOSISH_SYSTEM
38 : #include <fcntl.h> /* for setmode() */
39 : #endif
40 :
41 : #include "agent.h"
42 : #include "i18n.h"
43 : #include "get-passphrase.h"
44 : #include "sysutils.h"
45 : #include "../common/init.h"
46 :
47 :
48 : enum cmd_and_opt_values
49 : {
50 : aNull = 0,
51 : oVerbose = 'v',
52 : oArmor = 'a',
53 : oPassphrase = 'P',
54 :
55 : oProtect = 'p',
56 : oUnprotect = 'u',
57 :
58 : oNoVerbose = 500,
59 : oShadow,
60 : oShowShadowInfo,
61 : oShowKeygrip,
62 : oS2Kcalibration,
63 : oCanonical,
64 :
65 : oStore,
66 : oForce,
67 : oHaveCert,
68 : oNoFailOnExist,
69 : oHomedir,
70 : oPrompt,
71 : oStatusMsg,
72 : oDebugUseOCB,
73 :
74 : oAgentProgram
75 : };
76 :
77 :
78 : struct rsa_secret_key_s
79 : {
80 : gcry_mpi_t n; /* public modulus */
81 : gcry_mpi_t e; /* public exponent */
82 : gcry_mpi_t d; /* exponent */
83 : gcry_mpi_t p; /* prime p. */
84 : gcry_mpi_t q; /* prime q. */
85 : gcry_mpi_t u; /* inverse of p mod q. */
86 : };
87 :
88 :
89 : static int opt_armor;
90 : static int opt_canonical;
91 : static int opt_store;
92 : static int opt_force;
93 : static int opt_no_fail_on_exist;
94 : static int opt_have_cert;
95 : static const char *opt_passphrase;
96 : static char *opt_prompt;
97 : static int opt_status_msg;
98 : static const char *opt_agent_program;
99 : static int opt_debug_use_ocb;
100 :
101 : static char *get_passphrase (int promptno);
102 : static void release_passphrase (char *pw);
103 :
104 :
105 : static ARGPARSE_OPTS opts[] = {
106 : ARGPARSE_group (300, N_("@Commands:\n ")),
107 :
108 : ARGPARSE_c (oProtect, "protect", "protect a private key"),
109 : ARGPARSE_c (oUnprotect, "unprotect", "unprotect a private key"),
110 : ARGPARSE_c (oShadow, "shadow", "create a shadow entry for a public key"),
111 : ARGPARSE_c (oShowShadowInfo, "show-shadow-info", "return the shadow info"),
112 : ARGPARSE_c (oShowKeygrip, "show-keygrip", "show the \"keygrip\""),
113 : ARGPARSE_c (oS2Kcalibration, "s2k-calibration", "@"),
114 :
115 : ARGPARSE_group (301, N_("@\nOptions:\n ")),
116 :
117 : ARGPARSE_s_n (oVerbose, "verbose", "verbose"),
118 : ARGPARSE_s_n (oArmor, "armor", "write output in advanced format"),
119 : ARGPARSE_s_n (oCanonical, "canonical", "write output in canonical format"),
120 :
121 : ARGPARSE_s_s (oPassphrase, "passphrase", "|STRING|use passphrase STRING"),
122 : ARGPARSE_s_n (oHaveCert, "have-cert",
123 : "certificate to export provided on STDIN"),
124 : ARGPARSE_s_n (oStore, "store",
125 : "store the created key in the appropriate place"),
126 : ARGPARSE_s_n (oForce, "force",
127 : "force overwriting"),
128 : ARGPARSE_s_n (oNoFailOnExist, "no-fail-on-exist", "@"),
129 : ARGPARSE_s_s (oHomedir, "homedir", "@"),
130 : ARGPARSE_s_s (oPrompt, "prompt",
131 : "|ESCSTRING|use ESCSTRING as prompt in pinentry"),
132 : ARGPARSE_s_n (oStatusMsg, "enable-status-msg", "@"),
133 :
134 : ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
135 :
136 : ARGPARSE_s_n (oDebugUseOCB, "debug-use-ocb", "@"), /* For hacking only. */
137 :
138 : ARGPARSE_end ()
139 : };
140 :
141 : static const char *
142 0 : my_strusage (int level)
143 : {
144 : const char *p;
145 0 : switch (level)
146 : {
147 0 : case 11: p = "gpg-protect-tool (" GNUPG_NAME ")";
148 0 : break;
149 0 : case 13: p = VERSION; break;
150 0 : case 17: p = PRINTABLE_OS_NAME; break;
151 0 : case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
152 :
153 : case 1:
154 0 : case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n");
155 0 : break;
156 0 : case 41: p = _("Syntax: gpg-protect-tool [options] [args]\n"
157 : "Secret key maintenance tool\n");
158 0 : break;
159 :
160 0 : default: p = NULL;
161 : }
162 0 : return p;
163 : }
164 :
165 :
166 : /* static void */
167 : /* print_mpi (const char *text, gcry_mpi_t a) */
168 : /* { */
169 : /* char *buf; */
170 : /* void *bufaddr = &buf; */
171 : /* int rc; */
172 :
173 : /* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
174 : /* if (rc) */
175 : /* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */
176 : /* else */
177 : /* { */
178 : /* log_info ("%s: %s\n", text, buf); */
179 : /* gcry_free (buf); */
180 : /* } */
181 : /* } */
182 :
183 :
184 :
185 : static unsigned char *
186 0 : make_canonical (const char *fname, const char *buf, size_t buflen)
187 : {
188 : int rc;
189 : size_t erroff, len;
190 : gcry_sexp_t sexp;
191 : unsigned char *result;
192 :
193 0 : rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
194 0 : if (rc)
195 : {
196 0 : log_error ("invalid S-Expression in '%s' (off=%u): %s\n",
197 : fname, (unsigned int)erroff, gpg_strerror (rc));
198 0 : return NULL;
199 : }
200 0 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
201 0 : assert (len);
202 0 : result = xmalloc (len);
203 0 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
204 0 : assert (len);
205 0 : gcry_sexp_release (sexp);
206 0 : return result;
207 : }
208 :
209 : static char *
210 0 : make_advanced (const unsigned char *buf, size_t buflen)
211 : {
212 : int rc;
213 : size_t erroff, len;
214 : gcry_sexp_t sexp;
215 : char *result;
216 :
217 0 : rc = gcry_sexp_sscan (&sexp, &erroff, (const char*)buf, buflen);
218 0 : if (rc)
219 : {
220 0 : log_error ("invalid canonical S-Expression (off=%u): %s\n",
221 : (unsigned int)erroff, gpg_strerror (rc));
222 0 : return NULL;
223 : }
224 0 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
225 0 : assert (len);
226 0 : result = xmalloc (len);
227 0 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
228 0 : assert (len);
229 0 : gcry_sexp_release (sexp);
230 0 : return result;
231 : }
232 :
233 :
234 : static char *
235 0 : read_file (const char *fname, size_t *r_length)
236 : {
237 : FILE *fp;
238 : char *buf;
239 : size_t buflen;
240 :
241 0 : if (!strcmp (fname, "-"))
242 : {
243 0 : size_t nread, bufsize = 0;
244 :
245 0 : fp = stdin;
246 : #ifdef HAVE_DOSISH_SYSTEM
247 : setmode ( fileno(fp) , O_BINARY );
248 : #endif
249 0 : buf = NULL;
250 0 : buflen = 0;
251 : #define NCHUNK 8192
252 : do
253 : {
254 0 : bufsize += NCHUNK;
255 0 : if (!buf)
256 0 : buf = xmalloc (bufsize);
257 : else
258 0 : buf = xrealloc (buf, bufsize);
259 :
260 0 : nread = fread (buf+buflen, 1, NCHUNK, fp);
261 0 : if (nread < NCHUNK && ferror (fp))
262 : {
263 0 : log_error ("error reading '[stdin]': %s\n", strerror (errno));
264 0 : xfree (buf);
265 0 : return NULL;
266 : }
267 0 : buflen += nread;
268 : }
269 0 : while (nread == NCHUNK);
270 : #undef NCHUNK
271 :
272 : }
273 : else
274 : {
275 : struct stat st;
276 :
277 0 : fp = fopen (fname, "rb");
278 0 : if (!fp)
279 : {
280 0 : log_error ("can't open '%s': %s\n", fname, strerror (errno));
281 0 : return NULL;
282 : }
283 :
284 0 : if (fstat (fileno(fp), &st))
285 : {
286 0 : log_error ("can't stat '%s': %s\n", fname, strerror (errno));
287 0 : fclose (fp);
288 0 : return NULL;
289 : }
290 :
291 0 : buflen = st.st_size;
292 0 : buf = xmalloc (buflen+1);
293 0 : if (fread (buf, buflen, 1, fp) != 1)
294 : {
295 0 : log_error ("error reading '%s': %s\n", fname, strerror (errno));
296 0 : fclose (fp);
297 0 : xfree (buf);
298 0 : return NULL;
299 : }
300 0 : fclose (fp);
301 : }
302 :
303 0 : *r_length = buflen;
304 0 : return buf;
305 : }
306 :
307 :
308 : static unsigned char *
309 0 : read_key (const char *fname)
310 : {
311 : char *buf;
312 : size_t buflen;
313 : unsigned char *key;
314 :
315 0 : buf = read_file (fname, &buflen);
316 0 : if (!buf)
317 0 : return NULL;
318 0 : key = make_canonical (fname, buf, buflen);
319 0 : xfree (buf);
320 0 : return key;
321 : }
322 :
323 :
324 :
325 : static void
326 0 : read_and_protect (const char *fname)
327 : {
328 : int rc;
329 : unsigned char *key;
330 : unsigned char *result;
331 : size_t resultlen;
332 : char *pw;
333 :
334 0 : key = read_key (fname);
335 0 : if (!key)
336 0 : return;
337 :
338 0 : pw = get_passphrase (1);
339 0 : rc = agent_protect (key, pw, &result, &resultlen, 0,
340 0 : opt_debug_use_ocb? 1 : -1);
341 0 : release_passphrase (pw);
342 0 : xfree (key);
343 0 : if (rc)
344 : {
345 0 : log_error ("protecting the key failed: %s\n", gpg_strerror (rc));
346 0 : return;
347 : }
348 :
349 0 : if (opt_armor)
350 : {
351 0 : char *p = make_advanced (result, resultlen);
352 0 : xfree (result);
353 0 : if (!p)
354 0 : return;
355 0 : result = (unsigned char*)p;
356 0 : resultlen = strlen (p);
357 : }
358 :
359 0 : fwrite (result, resultlen, 1, stdout);
360 0 : xfree (result);
361 : }
362 :
363 :
364 : static void
365 0 : read_and_unprotect (ctrl_t ctrl, const char *fname)
366 : {
367 : int rc;
368 : unsigned char *key;
369 : unsigned char *result;
370 : size_t resultlen;
371 : char *pw;
372 : gnupg_isotime_t protected_at;
373 :
374 0 : key = read_key (fname);
375 0 : if (!key)
376 0 : return;
377 :
378 0 : rc = agent_unprotect (ctrl, key, (pw=get_passphrase (1)),
379 : protected_at, &result, &resultlen);
380 0 : release_passphrase (pw);
381 0 : xfree (key);
382 0 : if (rc)
383 : {
384 0 : if (opt_status_msg)
385 0 : log_info ("[PROTECT-TOOL:] bad-passphrase\n");
386 0 : log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc));
387 0 : return;
388 : }
389 0 : if (opt.verbose)
390 : {
391 0 : if (*protected_at)
392 0 : log_info ("key protection done at %.4s-%.2s-%.2s %.2s:%.2s:%s\n",
393 : protected_at, protected_at+4, protected_at+6,
394 : protected_at+9, protected_at+11, protected_at+13);
395 : else
396 0 : log_info ("key protection done at [unknown]\n");
397 : }
398 :
399 0 : if (opt_armor)
400 : {
401 0 : char *p = make_advanced (result, resultlen);
402 0 : xfree (result);
403 0 : if (!p)
404 0 : return;
405 0 : result = (unsigned char*)p;
406 0 : resultlen = strlen (p);
407 : }
408 :
409 0 : fwrite (result, resultlen, 1, stdout);
410 0 : xfree (result);
411 : }
412 :
413 :
414 :
415 : static void
416 0 : read_and_shadow (const char *fname)
417 : {
418 : int rc;
419 : unsigned char *key;
420 : unsigned char *result;
421 : size_t resultlen;
422 0 : unsigned char dummy_info[] = "(8:313233342:43)";
423 :
424 0 : key = read_key (fname);
425 0 : if (!key)
426 0 : return;
427 :
428 0 : rc = agent_shadow_key (key, dummy_info, &result);
429 0 : xfree (key);
430 0 : if (rc)
431 : {
432 0 : log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
433 0 : return;
434 : }
435 0 : resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
436 0 : assert (resultlen);
437 :
438 0 : if (opt_armor)
439 : {
440 0 : char *p = make_advanced (result, resultlen);
441 0 : xfree (result);
442 0 : if (!p)
443 0 : return;
444 0 : result = (unsigned char*)p;
445 0 : resultlen = strlen (p);
446 : }
447 :
448 0 : fwrite (result, resultlen, 1, stdout);
449 0 : xfree (result);
450 : }
451 :
452 : static void
453 0 : show_shadow_info (const char *fname)
454 : {
455 : int rc;
456 : unsigned char *key;
457 : const unsigned char *info;
458 : size_t infolen;
459 :
460 0 : key = read_key (fname);
461 0 : if (!key)
462 0 : return;
463 :
464 0 : rc = agent_get_shadow_info (key, &info);
465 0 : xfree (key);
466 0 : if (rc)
467 : {
468 0 : log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
469 0 : return;
470 : }
471 0 : infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
472 0 : assert (infolen);
473 :
474 0 : if (opt_armor)
475 : {
476 0 : char *p = make_advanced (info, infolen);
477 0 : if (!p)
478 0 : return;
479 0 : fwrite (p, strlen (p), 1, stdout);
480 0 : xfree (p);
481 : }
482 : else
483 0 : fwrite (info, infolen, 1, stdout);
484 : }
485 :
486 :
487 : static void
488 0 : show_file (const char *fname)
489 : {
490 : unsigned char *key;
491 : size_t keylen;
492 : char *p;
493 :
494 0 : key = read_key (fname);
495 0 : if (!key)
496 0 : return;
497 :
498 0 : keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
499 0 : assert (keylen);
500 :
501 0 : if (opt_canonical)
502 : {
503 0 : fwrite (key, keylen, 1, stdout);
504 : }
505 : else
506 : {
507 0 : p = make_advanced (key, keylen);
508 0 : if (p)
509 : {
510 0 : fwrite (p, strlen (p), 1, stdout);
511 0 : xfree (p);
512 : }
513 : }
514 0 : xfree (key);
515 : }
516 :
517 : static void
518 0 : show_keygrip (const char *fname)
519 : {
520 : unsigned char *key;
521 : gcry_sexp_t private;
522 : unsigned char grip[20];
523 : int i;
524 :
525 0 : key = read_key (fname);
526 0 : if (!key)
527 0 : return;
528 :
529 0 : if (gcry_sexp_new (&private, key, 0, 0))
530 : {
531 0 : log_error ("gcry_sexp_new failed\n");
532 0 : return;
533 : }
534 0 : xfree (key);
535 :
536 0 : if (!gcry_pk_get_keygrip (private, grip))
537 : {
538 0 : log_error ("can't calculate keygrip\n");
539 0 : return;
540 : }
541 0 : gcry_sexp_release (private);
542 :
543 0 : for (i=0; i < 20; i++)
544 0 : printf ("%02X", grip[i]);
545 0 : putchar ('\n');
546 : }
547 :
548 :
549 :
550 :
551 :
552 : int
553 0 : main (int argc, char **argv )
554 : {
555 : ARGPARSE_ARGS pargs;
556 0 : int cmd = 0;
557 : const char *fname;
558 : ctrl_t ctrl;
559 :
560 0 : early_system_init ();
561 0 : set_strusage (my_strusage);
562 0 : gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
563 0 : log_set_prefix ("gpg-protect-tool", GPGRT_LOG_WITH_PREFIX);
564 :
565 : /* Make sure that our subsystems are ready. */
566 0 : i18n_init ();
567 0 : init_common_subsystems (&argc, &argv);
568 :
569 0 : setup_libgcrypt_logging ();
570 0 : gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
571 :
572 0 : pargs.argc = &argc;
573 0 : pargs.argv = &argv;
574 0 : pargs.flags= 1; /* (do not remove the args) */
575 0 : while (arg_parse (&pargs, opts) )
576 : {
577 0 : switch (pargs.r_opt)
578 : {
579 0 : case oVerbose: opt.verbose++; break;
580 0 : case oArmor: opt_armor=1; break;
581 0 : case oCanonical: opt_canonical=1; break;
582 0 : case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
583 :
584 0 : case oAgentProgram: opt_agent_program = pargs.r.ret_str; break;
585 :
586 0 : case oProtect: cmd = oProtect; break;
587 0 : case oUnprotect: cmd = oUnprotect; break;
588 0 : case oShadow: cmd = oShadow; break;
589 0 : case oShowShadowInfo: cmd = oShowShadowInfo; break;
590 0 : case oShowKeygrip: cmd = oShowKeygrip; break;
591 0 : case oS2Kcalibration: cmd = oS2Kcalibration; break;
592 :
593 0 : case oPassphrase: opt_passphrase = pargs.r.ret_str; break;
594 0 : case oStore: opt_store = 1; break;
595 0 : case oForce: opt_force = 1; break;
596 0 : case oNoFailOnExist: opt_no_fail_on_exist = 1; break;
597 0 : case oHaveCert: opt_have_cert = 1; break;
598 0 : case oPrompt: opt_prompt = pargs.r.ret_str; break;
599 0 : case oStatusMsg: opt_status_msg = 1; break;
600 0 : case oDebugUseOCB: opt_debug_use_ocb = 1; break;
601 :
602 0 : default: pargs.err = ARGPARSE_PRINT_ERROR; break;
603 : }
604 : }
605 0 : if (log_get_errorcount (0))
606 0 : exit (2);
607 :
608 0 : fname = "-";
609 0 : if (argc == 1)
610 0 : fname = *argv;
611 0 : else if (argc > 1)
612 0 : usage (1);
613 :
614 : /* Allocate an CTRL object. An empty object should sufficent. */
615 0 : ctrl = xtrycalloc (1, sizeof *ctrl);
616 0 : if (!ctrl)
617 : {
618 0 : log_error ("error allocating connection control data: %s\n",
619 0 : strerror (errno));
620 0 : agent_exit (1);
621 : }
622 :
623 : /* Set the information which can't be taken from envvars. */
624 0 : gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT,
625 : opt.verbose,
626 : opt_agent_program,
627 : NULL, NULL, NULL);
628 :
629 0 : if (opt_prompt)
630 0 : opt_prompt = percent_plus_unescape (opt_prompt, 0);
631 :
632 0 : if (cmd == oProtect)
633 0 : read_and_protect (fname);
634 0 : else if (cmd == oUnprotect)
635 0 : read_and_unprotect (ctrl, fname);
636 0 : else if (cmd == oShadow)
637 0 : read_and_shadow (fname);
638 0 : else if (cmd == oShowShadowInfo)
639 0 : show_shadow_info (fname);
640 0 : else if (cmd == oShowKeygrip)
641 0 : show_keygrip (fname);
642 0 : else if (cmd == oS2Kcalibration)
643 : {
644 0 : if (!opt.verbose)
645 0 : opt.verbose++; /* We need to see something. */
646 0 : get_standard_s2k_count ();
647 : }
648 : else
649 0 : show_file (fname);
650 :
651 0 : xfree (ctrl);
652 :
653 0 : agent_exit (0);
654 : return 8; /*NOTREACHED*/
655 : }
656 :
657 : void
658 0 : agent_exit (int rc)
659 : {
660 0 : rc = rc? rc : log_get_errorcount(0)? 2 : 0;
661 0 : exit (rc);
662 : }
663 :
664 :
665 : /* Return the passphrase string and ask the agent if it has not been
666 : set from the command line PROMPTNO select the prompt to display:
667 : 0 = default
668 : 1 = taken from the option --prompt
669 : 2 = for unprotecting a pkcs#12 object
670 : 3 = for protecting a new pkcs#12 object
671 : 4 = for protecting an imported pkcs#12 in our system
672 : */
673 : static char *
674 0 : get_passphrase (int promptno)
675 : {
676 : char *pw;
677 : int err;
678 : const char *desc;
679 : char *orig_codeset;
680 0 : int repeat = 0;
681 :
682 0 : if (opt_passphrase)
683 0 : return xstrdup (opt_passphrase);
684 :
685 0 : orig_codeset = i18n_switchto_utf8 ();
686 :
687 0 : if (promptno == 1 && opt_prompt)
688 : {
689 0 : desc = opt_prompt;
690 : }
691 0 : else if (promptno == 2)
692 : {
693 0 : desc = _("Please enter the passphrase to unprotect the "
694 : "PKCS#12 object.");
695 : }
696 0 : else if (promptno == 3)
697 : {
698 0 : desc = _("Please enter the passphrase to protect the "
699 : "new PKCS#12 object.");
700 0 : repeat = 1;
701 : }
702 0 : else if (promptno == 4)
703 : {
704 0 : desc = _("Please enter the passphrase to protect the "
705 : "imported object within the GnuPG system.");
706 0 : repeat = 1;
707 : }
708 : else
709 0 : desc = _("Please enter the passphrase or the PIN\n"
710 : "needed to complete this operation.");
711 :
712 0 : i18n_switchback (orig_codeset);
713 :
714 0 : err = gnupg_get_passphrase (NULL, NULL, _("Passphrase:"), desc,
715 : repeat, repeat, 1, &pw);
716 0 : if (err)
717 : {
718 0 : if (gpg_err_code (err) == GPG_ERR_CANCELED
719 0 : || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
720 0 : log_info (_("cancelled\n"));
721 : else
722 0 : log_error (_("error while asking for the passphrase: %s\n"),
723 : gpg_strerror (err));
724 0 : agent_exit (0);
725 : }
726 0 : assert (pw);
727 :
728 0 : return pw;
729 : }
730 :
731 :
732 : static void
733 0 : release_passphrase (char *pw)
734 : {
735 0 : if (pw)
736 : {
737 0 : wipememory (pw, strlen (pw));
738 0 : xfree (pw);
739 : }
740 0 : }
741 :
742 :
743 : /* Stub function. */
744 : int
745 0 : agent_key_available (const unsigned char *grip)
746 : {
747 : (void)grip;
748 0 : return -1; /* Not available. */
749 : }
750 :
751 : char *
752 0 : agent_get_cache (const char *key, cache_mode_t cache_mode)
753 : {
754 : (void)key;
755 : (void)cache_mode;
756 0 : return NULL;
757 : }
758 :
759 : gpg_error_t
760 0 : agent_askpin (ctrl_t ctrl,
761 : const char *desc_text, const char *prompt_text,
762 : const char *initial_errtext,
763 : struct pin_entry_info_s *pininfo,
764 : const char *keyinfo, cache_mode_t cache_mode)
765 : {
766 : gpg_error_t err;
767 : unsigned char *passphrase;
768 : size_t size;
769 :
770 : (void)ctrl;
771 : (void)desc_text;
772 : (void)prompt_text;
773 : (void)initial_errtext;
774 : (void)keyinfo;
775 : (void)cache_mode;
776 :
777 0 : *pininfo->pin = 0; /* Reset the PIN. */
778 0 : passphrase = get_passphrase (0);
779 0 : size = strlen (passphrase);
780 0 : if (size >= pininfo->max_length)
781 0 : return gpg_error (GPG_ERR_TOO_LARGE);
782 :
783 0 : memcpy (&pininfo->pin, passphrase, size);
784 0 : xfree (passphrase);
785 0 : pininfo->pin[size] = 0;
786 0 : if (pininfo->check_cb)
787 : {
788 : /* More checks by utilizing the optional callback. */
789 0 : pininfo->cb_errtext = NULL;
790 0 : err = pininfo->check_cb (pininfo);
791 : }
792 : else
793 0 : err = 0;
794 0 : return err;
795 : }
796 :
797 : /* Replacement for the function in findkey.c. Here we write the key
798 : * to stdout. */
799 : int
800 0 : agent_write_private_key (const unsigned char *grip,
801 : const void *buffer, size_t length, int force)
802 : {
803 : char hexgrip[40+4+1];
804 : char *p;
805 :
806 : (void)force;
807 :
808 0 : bin2hex (grip, 20, hexgrip);
809 0 : strcpy (hexgrip+40, ".key");
810 0 : p = make_advanced (buffer, length);
811 0 : if (p)
812 : {
813 0 : printf ("# Begin dump of %s\n%s%s# End dump of %s\n",
814 0 : hexgrip, p, (*p && p[strlen(p)-1] == '\n')? "":"\n", hexgrip);
815 0 : xfree (p);
816 : }
817 :
818 0 : return 0;
819 : }
|