1 /* protect-tool.c - A tool to test the secret key protection
2 * Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
34 #ifdef HAVE_LANGINFO_CODESET
37 #ifdef HAVE_DOSISH_SYSTEM
38 #include <fcntl.h> /* for setmode() */
43 #include "get-passphrase.h"
45 #include "../common/init.h"
48 enum cmd_and_opt_values
77 struct rsa_secret_key_s
79 gcry_mpi_t n; /* public modulus */
80 gcry_mpi_t e; /* public exponent */
81 gcry_mpi_t d; /* exponent */
82 gcry_mpi_t p; /* prime p. */
83 gcry_mpi_t q; /* prime q. */
84 gcry_mpi_t u; /* inverse of p mod q. */
88 static const char *opt_homedir;
90 static int opt_canonical;
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;
100 static char *get_passphrase (int promptno);
101 static void release_passphrase (char *pw);
104 static ARGPARSE_OPTS opts[] = {
105 ARGPARSE_group (300, N_("@Commands:\n ")),
107 ARGPARSE_c (oProtect, "protect", "protect a private key"),
108 ARGPARSE_c (oUnprotect, "unprotect", "unprotect a private key"),
109 ARGPARSE_c (oShadow, "shadow", "create a shadow entry for a public key"),
110 ARGPARSE_c (oShowShadowInfo, "show-shadow-info", "return the shadow info"),
111 ARGPARSE_c (oShowKeygrip, "show-keygrip", "show the \"keygrip\""),
112 ARGPARSE_c (oS2Kcalibration, "s2k-calibration", "@"),
114 ARGPARSE_group (301, N_("@\nOptions:\n ")),
116 ARGPARSE_s_n (oVerbose, "verbose", "verbose"),
117 ARGPARSE_s_n (oArmor, "armor", "write output in advanced format"),
118 ARGPARSE_s_n (oCanonical, "canonical", "write output in canonical format"),
120 ARGPARSE_s_s (oPassphrase, "passphrase", "|STRING|use passphrase STRING"),
121 ARGPARSE_s_n (oHaveCert, "have-cert",
122 "certificate to export provided on STDIN"),
123 ARGPARSE_s_n (oStore, "store",
124 "store the created key in the appropriate place"),
125 ARGPARSE_s_n (oForce, "force",
126 "force overwriting"),
127 ARGPARSE_s_n (oNoFailOnExist, "no-fail-on-exist", "@"),
128 ARGPARSE_s_s (oHomedir, "homedir", "@"),
129 ARGPARSE_s_s (oPrompt, "prompt",
130 "|ESCSTRING|use ESCSTRING as prompt in pinentry"),
131 ARGPARSE_s_n (oStatusMsg, "enable-status-msg", "@"),
133 ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
139 my_strusage (int level)
144 case 11: p = "gpg-protect-tool (" GNUPG_NAME ")";
146 case 13: p = VERSION; break;
147 case 17: p = PRINTABLE_OS_NAME; break;
148 case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
151 case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n");
153 case 41: p = _("Syntax: gpg-protect-tool [options] [args]\n"
154 "Secret key maintenance tool\n");
164 /* print_mpi (const char *text, gcry_mpi_t a) */
167 /* void *bufaddr = &buf; */
170 /* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
172 /* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */
175 /* log_info ("%s: %s\n", text, buf); */
176 /* gcry_free (buf); */
182 static unsigned char *
183 make_canonical (const char *fname, const char *buf, size_t buflen)
188 unsigned char *result;
190 rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
193 log_error ("invalid S-Expression in '%s' (off=%u): %s\n",
194 fname, (unsigned int)erroff, gpg_strerror (rc));
197 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
199 result = xmalloc (len);
200 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
202 gcry_sexp_release (sexp);
207 make_advanced (const unsigned char *buf, size_t buflen)
214 rc = gcry_sexp_sscan (&sexp, &erroff, (const char*)buf, buflen);
217 log_error ("invalid canonical S-Expression (off=%u): %s\n",
218 (unsigned int)erroff, gpg_strerror (rc));
221 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
223 result = xmalloc (len);
224 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
226 gcry_sexp_release (sexp);
232 read_file (const char *fname, size_t *r_length)
238 if (!strcmp (fname, "-"))
240 size_t nread, bufsize = 0;
243 #ifdef HAVE_DOSISH_SYSTEM
244 setmode ( fileno(fp) , O_BINARY );
253 buf = xmalloc (bufsize);
255 buf = xrealloc (buf, bufsize);
257 nread = fread (buf+buflen, 1, NCHUNK, fp);
258 if (nread < NCHUNK && ferror (fp))
260 log_error ("error reading '[stdin]': %s\n", strerror (errno));
266 while (nread == NCHUNK);
274 fp = fopen (fname, "rb");
277 log_error ("can't open '%s': %s\n", fname, strerror (errno));
281 if (fstat (fileno(fp), &st))
283 log_error ("can't stat '%s': %s\n", fname, strerror (errno));
289 buf = xmalloc (buflen+1);
290 if (fread (buf, buflen, 1, fp) != 1)
292 log_error ("error reading '%s': %s\n", fname, strerror (errno));
305 static unsigned char *
306 read_key (const char *fname)
312 buf = read_file (fname, &buflen);
315 key = make_canonical (fname, buf, buflen);
323 read_and_protect (const char *fname)
327 unsigned char *result;
331 key = read_key (fname);
335 pw = get_passphrase (1);
336 rc = agent_protect (key, pw, &result, &resultlen, 0);
337 release_passphrase (pw);
341 log_error ("protecting the key failed: %s\n", gpg_strerror (rc));
347 char *p = make_advanced (result, resultlen);
351 result = (unsigned char*)p;
352 resultlen = strlen (p);
355 fwrite (result, resultlen, 1, stdout);
361 read_and_unprotect (const char *fname)
365 unsigned char *result;
368 gnupg_isotime_t protected_at;
370 key = read_key (fname);
374 rc = agent_unprotect (NULL, key, (pw=get_passphrase (1)),
375 protected_at, &result, &resultlen);
376 release_passphrase (pw);
381 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
382 log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc));
386 log_info ("key protection done at %.4s-%.2s-%.2s %.2s:%.2s:%s\n",
387 protected_at, protected_at+4, protected_at+6,
388 protected_at+9, protected_at+11, protected_at+13);
393 char *p = make_advanced (result, resultlen);
397 result = (unsigned char*)p;
398 resultlen = strlen (p);
401 fwrite (result, resultlen, 1, stdout);
408 read_and_shadow (const char *fname)
412 unsigned char *result;
414 unsigned char dummy_info[] = "(8:313233342:43)";
416 key = read_key (fname);
420 rc = agent_shadow_key (key, dummy_info, &result);
424 log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
427 resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
432 char *p = make_advanced (result, resultlen);
436 result = (unsigned char*)p;
437 resultlen = strlen (p);
440 fwrite (result, resultlen, 1, stdout);
445 show_shadow_info (const char *fname)
449 const unsigned char *info;
452 key = read_key (fname);
456 rc = agent_get_shadow_info (key, &info);
460 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
463 infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
468 char *p = make_advanced (info, infolen);
471 fwrite (p, strlen (p), 1, stdout);
475 fwrite (info, infolen, 1, stdout);
480 show_file (const char *fname)
486 key = read_key (fname);
490 keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
495 fwrite (key, keylen, 1, stdout);
499 p = make_advanced (key, keylen);
502 fwrite (p, strlen (p), 1, stdout);
510 show_keygrip (const char *fname)
514 unsigned char grip[20];
517 key = read_key (fname);
521 if (gcry_sexp_new (&private, key, 0, 0))
523 log_error ("gcry_sexp_new failed\n");
528 if (!gcry_pk_get_keygrip (private, grip))
530 log_error ("can't calculate keygrip\n");
533 gcry_sexp_release (private);
535 for (i=0; i < 20; i++)
536 printf ("%02X", grip[i]);
545 main (int argc, char **argv )
551 early_system_init ();
552 set_strusage (my_strusage);
553 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
554 log_set_prefix ("gpg-protect-tool", 1);
556 /* Make sure that our subsystems are ready. */
558 init_common_subsystems (&argc, &argv);
560 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
562 log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
563 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
566 setup_libgcrypt_logging ();
567 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
570 opt_homedir = default_homedir ();
575 pargs.flags= 1; /* (do not remove the args) */
576 while (arg_parse (&pargs, opts) )
580 case oVerbose: opt.verbose++; break;
581 case oArmor: opt_armor=1; break;
582 case oCanonical: opt_canonical=1; break;
583 case oHomedir: opt_homedir = pargs.r.ret_str; break;
585 case oAgentProgram: opt_agent_program = pargs.r.ret_str; break;
587 case oProtect: cmd = oProtect; break;
588 case oUnprotect: cmd = oUnprotect; break;
589 case oShadow: cmd = oShadow; break;
590 case oShowShadowInfo: cmd = oShowShadowInfo; break;
591 case oShowKeygrip: cmd = oShowKeygrip; break;
592 case oS2Kcalibration: cmd = oS2Kcalibration; break;
594 case oPassphrase: opt_passphrase = pargs.r.ret_str; break;
595 case oStore: opt_store = 1; break;
596 case oForce: opt_force = 1; break;
597 case oNoFailOnExist: opt_no_fail_on_exist = 1; break;
598 case oHaveCert: opt_have_cert = 1; break;
599 case oPrompt: opt_prompt = pargs.r.ret_str; break;
600 case oStatusMsg: opt_status_msg = 1; break;
602 default: pargs.err = ARGPARSE_PRINT_ERROR; break;
605 if (log_get_errorcount (0))
614 /* Set the information which can't be taken from envvars. */
615 gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT,
622 opt_prompt = percent_plus_unescape (opt_prompt, 0);
625 read_and_protect (fname);
626 else if (cmd == oUnprotect)
627 read_and_unprotect (fname);
628 else if (cmd == oShadow)
629 read_and_shadow (fname);
630 else if (cmd == oShowShadowInfo)
631 show_shadow_info (fname);
632 else if (cmd == oShowKeygrip)
633 show_keygrip (fname);
634 else if (cmd == oS2Kcalibration)
637 opt.verbose++; /* We need to see something. */
638 get_standard_s2k_count ();
644 return 8; /*NOTREACHED*/
650 rc = rc? rc : log_get_errorcount(0)? 2 : 0;
655 /* Return the passphrase string and ask the agent if it has not been
656 set from the command line PROMPTNO select the prompt to display:
658 1 = taken from the option --prompt
659 2 = for unprotecting a pkcs#12 object
660 3 = for protecting a new pkcs#12 object
661 4 = for protecting an imported pkcs#12 in our system
664 get_passphrase (int promptno)
673 return xstrdup (opt_passphrase);
675 orig_codeset = i18n_switchto_utf8 ();
677 if (promptno == 1 && opt_prompt)
681 else if (promptno == 2)
683 desc = _("Please enter the passphrase to unprotect the "
686 else if (promptno == 3)
688 desc = _("Please enter the passphrase to protect the "
689 "new PKCS#12 object.");
692 else if (promptno == 4)
694 desc = _("Please enter the passphrase to protect the "
695 "imported object within the GnuPG system.");
699 desc = _("Please enter the passphrase or the PIN\n"
700 "needed to complete this operation.");
702 i18n_switchback (orig_codeset);
704 err = gnupg_get_passphrase (NULL, NULL, _("Passphrase:"), desc,
705 repeat, repeat, 1, &pw);
708 if (gpg_err_code (err) == GPG_ERR_CANCELED
709 || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
710 log_info (_("cancelled\n"));
712 log_error (_("error while asking for the passphrase: %s\n"),
723 release_passphrase (char *pw)
727 wipememory (pw, strlen (pw));
735 convert_from_openpgp_native (gcry_sexp_t s_pgp, const char *passphrase,
736 unsigned char **r_key)
741 return gpg_error (GPG_ERR_BUG);